very minor code police. also fix a possible but unlikely missed cpu_boost(false)
[Rockbox.git] / apps / plugins / test_disk.c
blob7638fbf831fb274e2c839cf3f7025b6d05dcf443
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2007 Jens Arnold
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
22 #include "plugin.h"
23 #include "oldmenuapi.h"
24 #include "helper.h"
26 PLUGIN_HEADER
28 #define TESTBASEDIR "/__TEST__"
29 #define TEST_FILE TESTBASEDIR "/test_disk.tmp"
30 #define FRND_SEED 0x78C3 /* arbirary */
32 #ifdef HAVE_MMC
33 #define TEST_SIZE (20*1024*1024)
34 #else
35 #define TEST_SIZE (300*1024*1024)
36 #endif
37 #define TEST_TIME 10 /* in seconds */
39 static const struct plugin_api* rb;
40 static unsigned char* audiobuf;
41 static ssize_t audiobuflen;
43 static unsigned short frnd_buffer;
44 static int line = 0;
45 static int max_line = 0;
46 static int log_fd;
47 static char logfilename[MAX_PATH];
48 static const char testbasedir[] = TESTBASEDIR;
50 static void mem_fill_frnd(unsigned char *addr, int len)
52 unsigned char *end = addr + len;
53 unsigned random = frnd_buffer;
55 while (addr < end)
57 random = 75 * random + 74;
58 *addr++ = random >> 8;
60 frnd_buffer = random;
63 static bool mem_cmp_frnd(unsigned char *addr, int len)
65 unsigned char *end = addr + len;
66 unsigned random = frnd_buffer;
68 while (addr < end)
70 random = 75 * random + 74;
71 if (*addr++ != ((random >> 8) & 0xff))
72 return false;
74 frnd_buffer = random;
75 return true;
78 static bool log_init(void)
80 int h;
82 rb->lcd_getstringsize("A", NULL, &h);
83 max_line = LCD_HEIGHT / h;
84 line = 0;
85 rb->lcd_clear_display();
86 rb->lcd_update();
88 rb->create_numbered_filename(logfilename, "/", "test_disk_log_", ".txt",
89 2 IF_CNFN_NUM_(, NULL));
90 log_fd = rb->open(logfilename, O_RDWR|O_CREAT|O_TRUNC);
91 return log_fd >= 0;
94 static void log_text(char *text, bool advance)
96 rb->lcd_puts(0, line, text);
97 rb->lcd_update();
98 if (advance)
100 if (++line >= max_line)
101 line = 0;
102 rb->fdprintf(log_fd, "%s\n", text);
106 static void log_close(void)
108 rb->close(log_fd);
111 static bool test_fs(void)
113 unsigned char text_buf[32];
114 int total, current, align;
115 int fd;
117 log_init();
118 log_text("test_disk WRITE&VERIFY", true);
119 #ifndef SIMULATOR
120 rb->snprintf(text_buf, sizeof(text_buf), "CPU clock: %ld Hz",
121 *rb->cpu_frequency);
122 log_text(text_buf, true);
123 #endif
124 log_text("----------------------", true);
125 rb->snprintf(text_buf, sizeof text_buf, "Data size: %dKB", (TEST_SIZE>>10));
126 log_text(text_buf, true);
128 fd = rb->creat(TEST_FILE);
129 if (fd < 0)
131 rb->splash(HZ, "creat() failed.");
132 goto error;
135 frnd_buffer = FRND_SEED;
136 total = TEST_SIZE;
137 while (total > 0)
139 current = rb->rand() % (audiobuflen - 4);
140 current = MIN(current, total);
141 align = rb->rand() & 3;
142 rb->snprintf(text_buf, sizeof text_buf, "Wrt %dKB, %dKB left",
143 current >> 10, total >> 10);
144 log_text(text_buf, false);
146 mem_fill_frnd(audiobuf + align, current);
147 if (current != rb->write(fd, audiobuf + align, current))
149 rb->splash(0, "write() failed.");
150 rb->close(fd);
151 goto error;
153 total -= current;
155 rb->close(fd);
157 fd = rb->open(TEST_FILE, O_RDONLY);
158 if (fd < 0)
160 rb->splash(0, "open() failed.");
161 goto error;
164 frnd_buffer = FRND_SEED;
165 total = TEST_SIZE;
166 while (total > 0)
168 current = rb->rand() % (audiobuflen - 4);
169 current = MIN(current, total);
170 align = rb->rand() & 3;
171 rb->snprintf(text_buf, sizeof text_buf, "Cmp %dKB, %dKB left",
172 current >> 10, total >> 10);
173 log_text(text_buf, false);
175 if (current != rb->read(fd, audiobuf + align, current))
177 rb->splash(0, "read() failed.");
178 rb->close(fd);
179 goto error;
181 if (!mem_cmp_frnd(audiobuf + align, current))
183 log_text(text_buf, true);
184 log_text("Compare error.", true);
185 rb->close(fd);
186 goto error;
188 total -= current;
190 rb->close(fd);
191 log_text(text_buf, true);
192 log_text("Test passed.", true);
194 error:
195 log_close();
196 rb->remove(TEST_FILE);
197 rb->button_clear_queue();
198 rb->button_get(true);
200 return false;
203 static bool file_speed(int chunksize, bool align)
205 unsigned char text_buf[64];
206 int fd;
207 long filesize = 0;
208 long size, time;
210 if (chunksize >= audiobuflen)
211 return false;
213 log_text("--------------------", true);
215 /* File creation write speed */
216 fd = rb->creat(TEST_FILE);
217 if (fd < 0)
219 rb->splash(HZ, "creat() failed.");
220 goto error;
222 time = *rb->current_tick;
223 while (TIME_BEFORE(*rb->current_tick, time + TEST_TIME*HZ))
225 if (chunksize != rb->write(fd, audiobuf + (align ? 0 : 1), chunksize))
227 rb->splash(HZ, "write() failed.");
228 rb->close(fd);
229 goto error;
231 filesize += chunksize;
233 time = *rb->current_tick - time;
234 rb->close(fd);
235 rb->snprintf(text_buf, sizeof text_buf, "Create (%d,%c): %ld KB/s",
236 chunksize, align ? 'A' : 'U', (25 * (filesize>>8) / time) );
237 log_text(text_buf, true);
239 /* Existing file write speed */
240 fd = rb->open(TEST_FILE, O_WRONLY);
241 if (fd < 0)
243 rb->splash(0, "open() failed.");
244 goto error;
246 time = *rb->current_tick;
247 for (size = filesize; size > 0; size -= chunksize)
249 if (chunksize != rb->write(fd, audiobuf + (align ? 0 : 1), chunksize))
251 rb->splash(0, "write() failed.");
252 rb->close(fd);
253 goto error;
256 time = *rb->current_tick - time;
257 rb->close(fd);
258 rb->snprintf(text_buf, sizeof text_buf, "Write (%d,%c): %ld KB/s",
259 chunksize, align ? 'A' : 'U', (25 * (filesize>>8) / time) );
260 log_text(text_buf, true);
262 /* File read speed */
263 fd = rb->open(TEST_FILE, O_RDONLY);
264 if (fd < 0)
266 rb->splash(0, "open() failed.");
267 goto error;
269 time = *rb->current_tick;
270 for (size = filesize; size > 0; size -= chunksize)
272 if (chunksize != rb->read(fd, audiobuf + (align ? 0 : 1), chunksize))
274 rb->splash(0, "read() failed.");
275 rb->close(fd);
276 goto error;
279 time = *rb->current_tick - time;
280 rb->close(fd);
281 rb->snprintf(text_buf, sizeof text_buf, "Read (%d,%c): %ld KB/s",
282 chunksize, align ? 'A' : 'U', (25 * (filesize>>8) / time) );
283 log_text(text_buf, true);
284 rb->remove(TEST_FILE);
285 return true;
287 error:
288 rb->remove(TEST_FILE);
289 return false;
292 static bool test_speed(void)
294 unsigned char text_buf[64];
295 DIR *dir = NULL;
296 struct dirent *entry = NULL;
297 int fd, last_file;
298 int i, n;
299 long time;
301 rb->memset(audiobuf, 'T', audiobuflen);
302 log_init();
303 log_text("test_disk SPEED TEST", true);
304 #ifndef SIMULATOR
305 rb->snprintf(text_buf, sizeof(text_buf), "CPU clock: %ld Hz",
306 *rb->cpu_frequency);
307 log_text(text_buf, true);
308 #endif
309 log_text("--------------------", true);
311 /* File creation speed */
312 time = *rb->current_tick + TEST_TIME*HZ;
313 for (i = 0; TIME_BEFORE(*rb->current_tick, time); i++)
315 rb->snprintf(text_buf, sizeof(text_buf), TESTBASEDIR "/%08x.tmp", i);
316 fd = rb->creat(text_buf);
317 if (fd < 0)
319 last_file = i;
320 rb->splash(HZ, "creat() failed.");
321 goto error;
323 rb->close(fd);
325 last_file = i;
326 rb->snprintf(text_buf, sizeof(text_buf), "Create: %d files/s",
327 last_file / TEST_TIME);
328 log_text(text_buf, true);
330 /* File open speed */
331 time = *rb->current_tick + TEST_TIME*HZ;
332 for (n = 0, i = 0; TIME_BEFORE(*rb->current_tick, time); n++, i++)
334 if (i >= last_file)
335 i = 0;
336 rb->snprintf(text_buf, sizeof(text_buf), TESTBASEDIR "/%08x.tmp", i);
337 fd = rb->open(text_buf, O_RDONLY);
338 if (fd < 0)
340 rb->splash(HZ, "open() failed.");
341 goto error;
343 rb->close(fd);
345 rb->snprintf(text_buf, sizeof(text_buf), "Open: %d files/s", n / TEST_TIME);
346 log_text(text_buf, true);
348 /* Directory scan speed */
349 time = *rb->current_tick + TEST_TIME*HZ;
350 for (n = 0; TIME_BEFORE(*rb->current_tick, time); n++)
352 if (entry == NULL)
354 if (dir != NULL)
355 rb->closedir(dir);
356 dir = rb->opendir(testbasedir);
357 if (dir == NULL)
359 rb->splash(HZ, "opendir() failed.");
360 goto error;
363 entry = rb->readdir(dir);
365 rb->closedir(dir);
366 rb->snprintf(text_buf, sizeof(text_buf), "Dirscan: %d files/s", n / TEST_TIME);
367 log_text(text_buf, true);
369 /* File delete speed */
370 time = *rb->current_tick;
371 for (i = 0; i < last_file; i++)
373 rb->snprintf(text_buf, sizeof(text_buf), TESTBASEDIR "/%08x.tmp", i);
374 rb->remove(text_buf);
376 rb->snprintf(text_buf, sizeof(text_buf), "Delete: %ld files/s",
377 last_file * HZ / (*rb->current_tick - time));
378 log_text(text_buf, true);
380 if (file_speed(512, true)
381 && file_speed(512, false)
382 && file_speed(4096, true)
383 && file_speed(4096, false)
384 && file_speed(1048576, true))
385 file_speed(1048576, false);
387 log_text("DONE", false);
388 log_close();
389 rb->button_clear_queue();
390 rb->button_get(true);
391 return false;
393 error:
394 for (i = 0; i < last_file; i++)
396 rb->snprintf(text_buf, sizeof(text_buf), TESTBASEDIR "/%08x.tmp", i);
397 rb->remove(text_buf);
399 log_text("DONE", false);
400 log_close();
401 rb->button_clear_queue();
402 rb->button_get(true);
403 return false;
407 /* this is the plugin entry point */
408 enum plugin_status plugin_start(const struct plugin_api* api, const void* parameter)
410 static const struct menu_item items[] = {
411 { "Disk speed", test_speed },
412 { "Write & verify", test_fs },
414 int m;
415 int align;
416 DIR *dir;
418 (void)parameter;
419 rb = api;
421 if ((dir = rb->opendir(testbasedir)) == NULL)
423 if (rb->mkdir(testbasedir) < 0)
425 rb->splash(HZ*2, "Can't create test directory.");
426 return PLUGIN_ERROR;
429 else
431 rb->closedir(dir);
434 audiobuf = rb->plugin_get_audio_buffer((size_t *)&audiobuflen);
435 /* align start and length to 32 bit */
436 align = (-(int)audiobuf) & 3;
437 audiobuf += align;
438 audiobuflen = (audiobuflen - align) & ~3;
440 rb->srand(*rb->current_tick);
442 /* Turn off backlight timeout */
443 backlight_force_on(rb); /* backlight control in lib/helper.c */
445 m = menu_init(rb, items, sizeof(items) / sizeof(*items), NULL,
446 NULL, NULL, NULL);
447 menu_run(m);
448 menu_exit(m);
450 /* Turn on backlight timeout (revert to settings) */
451 backlight_use_settings(rb); /* backlight control in lib/helper.c */
453 rb->rmdir(testbasedir);
455 return PLUGIN_OK;