Hide symbols by default on 64 bit sim buildsto avoid clashing, fixes crashing on...
[kugel-rb.git] / apps / plugins / test_disk.c
blob216ef733bd8fc10b1e0c5bdaf39190c3f594d863
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2007 Jens Arnold
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
18 ****************************************************************************/
20 #include "plugin.h"
21 #include "oldmenuapi.h"
22 #include "helper.h"
24 PLUGIN_HEADER
26 #define TESTBASEDIR "/__TEST__"
27 #define TEST_FILE TESTBASEDIR "/test_disk.tmp"
28 #define FRND_SEED 0x78C3 /* arbirary */
30 #ifdef HAVE_MMC
31 #define TEST_SIZE (20*1024*1024)
32 #else
33 #define TEST_SIZE (300*1024*1024)
34 #endif
35 #define TEST_TIME 10 /* in seconds */
37 static struct plugin_api* rb;
38 static unsigned char* audiobuf;
39 static ssize_t audiobuflen;
41 static unsigned short frnd_buffer;
42 static int line = 0;
43 static int max_line = 0;
44 static int log_fd;
45 static char logfilename[MAX_PATH];
46 static const char testbasedir[] = TESTBASEDIR;
48 static void mem_fill_frnd(unsigned char *addr, int len)
50 unsigned char *end = addr + len;
51 unsigned random = frnd_buffer;
53 while (addr < end)
55 random = 75 * random + 74;
56 *addr++ = random >> 8;
58 frnd_buffer = random;
61 static bool mem_cmp_frnd(unsigned char *addr, int len)
63 unsigned char *end = addr + len;
64 unsigned random = frnd_buffer;
66 while (addr < end)
68 random = 75 * random + 74;
69 if (*addr++ != ((random >> 8) & 0xff))
70 return false;
72 frnd_buffer = random;
73 return true;
76 static bool log_init(void)
78 int h;
80 rb->lcd_setmargins(0, 0);
81 rb->lcd_getstringsize("A", NULL, &h);
82 max_line = LCD_HEIGHT / h;
83 line = 0;
84 rb->lcd_clear_display();
85 rb->lcd_update();
87 rb->create_numbered_filename(logfilename, "/", "test_disk_log_", ".txt",
88 2 IF_CNFN_NUM_(, NULL));
89 log_fd = rb->open(logfilename, O_RDWR|O_CREAT|O_TRUNC);
90 return log_fd >= 0;
93 static void log_text(char *text, bool advance)
95 rb->lcd_puts(0, line, text);
96 rb->lcd_update();
97 if (advance)
99 if (++line >= max_line)
100 line = 0;
101 rb->fdprintf(log_fd, "%s\n", text);
105 static void log_close(void)
107 rb->close(log_fd);
110 static bool test_fs(void)
112 unsigned char text_buf[32];
113 int total, current, align;
114 int fd;
116 log_init();
117 log_text("test_disk WRITE&VERIFY", true);
118 #ifndef SIMULATOR
119 rb->snprintf(text_buf, sizeof(text_buf), "CPU clock: %ld Hz",
120 *rb->cpu_frequency);
121 log_text(text_buf, true);
122 #endif
123 log_text("----------------------", true);
124 rb->snprintf(text_buf, sizeof text_buf, "Data size: %dKB", (TEST_SIZE>>10));
125 log_text(text_buf, true);
127 fd = rb->creat(TEST_FILE);
128 if (fd < 0)
130 rb->splash(HZ, "creat() failed.");
131 goto error;
134 frnd_buffer = FRND_SEED;
135 total = TEST_SIZE;
136 while (total > 0)
138 current = rb->rand() % (audiobuflen - 4);
139 current = MIN(current, total);
140 align = rb->rand() & 3;
141 rb->snprintf(text_buf, sizeof text_buf, "Wrt %dKB, %dKB left",
142 current >> 10, total >> 10);
143 log_text(text_buf, false);
145 mem_fill_frnd(audiobuf + align, current);
146 if (current != rb->write(fd, audiobuf + align, current))
148 rb->splash(0, "write() failed.");
149 rb->close(fd);
150 goto error;
152 total -= current;
154 rb->close(fd);
156 fd = rb->open(TEST_FILE, O_RDONLY);
157 if (fd < 0)
159 rb->splash(0, "open() failed.");
160 goto error;
163 frnd_buffer = FRND_SEED;
164 total = TEST_SIZE;
165 while (total > 0)
167 current = rb->rand() % (audiobuflen - 4);
168 current = MIN(current, total);
169 align = rb->rand() & 3;
170 rb->snprintf(text_buf, sizeof text_buf, "Cmp %dKB, %dKB left",
171 current >> 10, total >> 10);
172 log_text(text_buf, false);
174 if (current != rb->read(fd, audiobuf + align, current))
176 rb->splash(0, "read() failed.");
177 rb->close(fd);
178 goto error;
180 if (!mem_cmp_frnd(audiobuf + align, current))
182 log_text(text_buf, true);
183 log_text("Compare error.", true);
184 rb->close(fd);
185 goto error;
187 total -= current;
189 rb->close(fd);
190 log_text(text_buf, true);
191 log_text("Test passed.", true);
193 error:
194 log_close();
195 rb->remove(TEST_FILE);
196 rb->button_clear_queue();
197 rb->button_get(true);
199 return false;
202 static bool file_speed(int chunksize, bool align)
204 unsigned char text_buf[64];
205 int fd;
206 long filesize = 0;
207 long size, time;
209 if (chunksize >= audiobuflen)
210 return false;
212 log_text("--------------------", true);
214 /* File creation write speed */
215 fd = rb->creat(TEST_FILE);
216 if (fd < 0)
218 rb->splash(HZ, "creat() failed.");
219 goto error;
221 time = *rb->current_tick;
222 while (TIME_BEFORE(*rb->current_tick, time + TEST_TIME*HZ))
224 if (chunksize != rb->write(fd, audiobuf + (align ? 0 : 1), chunksize))
226 rb->splash(HZ, "write() failed.");
227 rb->close(fd);
228 goto error;
230 filesize += chunksize;
232 time = *rb->current_tick - time;
233 rb->close(fd);
234 rb->snprintf(text_buf, sizeof text_buf, "Create (%d,%c): %ld KB/s",
235 chunksize, align ? 'A' : 'U', (25 * filesize / time) >> 8);
236 log_text(text_buf, true);
238 /* Existing file write speed */
239 fd = rb->open(TEST_FILE, O_WRONLY);
240 if (fd < 0)
242 rb->splash(0, "open() failed.");
243 goto error;
245 time = *rb->current_tick;
246 for (size = filesize; size > 0; size -= chunksize)
248 if (chunksize != rb->write(fd, audiobuf + (align ? 0 : 1), chunksize))
250 rb->splash(0, "write() failed.");
251 rb->close(fd);
252 goto error;
255 time = *rb->current_tick - time;
256 rb->close(fd);
257 rb->snprintf(text_buf, sizeof text_buf, "Write (%d,%c): %ld KB/s",
258 chunksize, align ? 'A' : 'U', (25 * filesize / time) >> 8);
259 log_text(text_buf, true);
261 /* File read speed */
262 fd = rb->open(TEST_FILE, O_RDONLY);
263 if (fd < 0)
265 rb->splash(0, "open() failed.");
266 goto error;
268 time = *rb->current_tick;
269 for (size = filesize; size > 0; size -= chunksize)
271 if (chunksize != rb->read(fd, audiobuf + (align ? 0 : 1), chunksize))
273 rb->splash(0, "read() failed.");
274 rb->close(fd);
275 goto error;
278 time = *rb->current_tick - time;
279 rb->close(fd);
280 rb->snprintf(text_buf, sizeof text_buf, "Read (%d,%c): %ld KB/s",
281 chunksize, align ? 'A' : 'U', (25 * filesize / time) >> 8);
282 log_text(text_buf, true);
283 rb->remove(TEST_FILE);
284 return true;
286 error:
287 rb->remove(TEST_FILE);
288 return false;
291 static bool test_speed(void)
293 unsigned char text_buf[64];
294 DIR *dir = NULL;
295 struct dirent *entry = NULL;
296 int fd, last_file;
297 int i, n;
298 long time;
300 rb->memset(audiobuf, 'T', audiobuflen);
301 log_init();
302 log_text("test_disk SPEED TEST", true);
303 #ifndef SIMULATOR
304 rb->snprintf(text_buf, sizeof(text_buf), "CPU clock: %ld Hz",
305 *rb->cpu_frequency);
306 log_text(text_buf, true);
307 #endif
308 log_text("--------------------", true);
310 /* File creation speed */
311 time = *rb->current_tick + TEST_TIME*HZ;
312 for (i = 0; TIME_BEFORE(*rb->current_tick, time); i++)
314 rb->snprintf(text_buf, sizeof(text_buf), TESTBASEDIR "/%08x.tmp", i);
315 fd = rb->creat(text_buf);
316 if (fd < 0)
318 last_file = i;
319 rb->splash(HZ, "creat() failed.");
320 goto error;
322 rb->close(fd);
324 last_file = i;
325 rb->snprintf(text_buf, sizeof(text_buf), "Create: %d files/s",
326 last_file / TEST_TIME);
327 log_text(text_buf, true);
329 /* File open speed */
330 time = *rb->current_tick + TEST_TIME*HZ;
331 for (n = 0, i = 0; TIME_BEFORE(*rb->current_tick, time); n++, i++)
333 if (i >= last_file)
334 i = 0;
335 rb->snprintf(text_buf, sizeof(text_buf), TESTBASEDIR "/%08x.tmp", i);
336 fd = rb->open(text_buf, O_RDONLY);
337 if (fd < 0)
339 rb->splash(HZ, "open() failed.");
340 goto error;
342 rb->close(fd);
344 rb->snprintf(text_buf, sizeof(text_buf), "Open: %d files/s", n / TEST_TIME);
345 log_text(text_buf, true);
347 /* Directory scan speed */
348 time = *rb->current_tick + TEST_TIME*HZ;
349 for (n = 0; TIME_BEFORE(*rb->current_tick, time); n++)
351 if (entry == NULL)
353 if (dir != NULL)
354 rb->closedir(dir);
355 dir = rb->opendir(testbasedir);
356 if (dir == NULL)
358 rb->splash(HZ, "opendir() failed.");
359 goto error;
362 entry = rb->readdir(dir);
364 rb->closedir(dir);
365 rb->snprintf(text_buf, sizeof(text_buf), "Dirscan: %d files/s", n / TEST_TIME);
366 log_text(text_buf, true);
368 /* File delete speed */
369 time = *rb->current_tick;
370 for (i = 0; i < last_file; i++)
372 rb->snprintf(text_buf, sizeof(text_buf), TESTBASEDIR "/%08x.tmp", i);
373 rb->remove(text_buf);
375 rb->snprintf(text_buf, sizeof(text_buf), "Delete: %ld files/s",
376 last_file * HZ / (*rb->current_tick - time));
377 log_text(text_buf, true);
379 if (file_speed(512, true)
380 && file_speed(512, false)
381 && file_speed(4096, true)
382 && file_speed(4096, false)
383 && file_speed(1048576, true))
384 file_speed(1048576, false);
386 log_text("DONE", false);
387 log_close();
388 rb->button_clear_queue();
389 rb->button_get(true);
390 return false;
392 error:
393 for (i = 0; i < last_file; i++)
395 rb->snprintf(text_buf, sizeof(text_buf), TESTBASEDIR "/%08x.tmp", i);
396 rb->remove(text_buf);
398 log_text("DONE", false);
399 log_close();
400 rb->button_clear_queue();
401 rb->button_get(true);
402 return false;
406 /* this is the plugin entry point */
407 enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
409 static const struct menu_item items[] = {
410 { "Disk speed", test_speed },
411 { "Write & verify", test_fs },
413 int m;
414 int align;
415 DIR *dir;
417 (void)parameter;
418 rb = api;
420 if ((dir = rb->opendir(testbasedir)) == NULL)
422 if (rb->mkdir(testbasedir) < 0)
424 rb->splash(HZ*2, "Can't create test directory.");
425 return PLUGIN_ERROR;
428 else
430 rb->closedir(dir);
433 audiobuf = rb->plugin_get_audio_buffer((size_t *)&audiobuflen);
434 /* align start and length to 32 bit */
435 align = (-(int)audiobuf) & 3;
436 audiobuf += align;
437 audiobuflen = (audiobuflen - align) & ~3;
439 rb->srand(*rb->current_tick);
441 /* Turn off backlight timeout */
442 backlight_force_on(rb); /* backlight control in lib/helper.c */
444 m = menu_init(rb, items, sizeof(items) / sizeof(*items), NULL,
445 NULL, NULL, NULL);
446 menu_run(m);
447 menu_exit(m);
449 /* Turn on backlight timeout (revert to settings) */
450 backlight_use_settings(rb); /* backlight control in lib/helper.c */
452 rb->rmdir(testbasedir);
454 return PLUGIN_OK;