Make open() posix compliant api-wise. A few calls (those with O_CREAT) need the addit...
[kugel-rb.git] / apps / plugins / test_disk.c
blobc83fb7e1d20e9f2768c5508371868cf7304b154e
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 "lib/helper.h"
25 PLUGIN_HEADER
27 #define TESTBASEDIR "/__TEST__"
28 #define TEST_FILE TESTBASEDIR "/test_disk.tmp"
29 #define FRND_SEED 0x78C3 /* arbirary */
31 #if (CONFIG_STORAGE & STORAGE_MMC)
32 #define TEST_SIZE (20*1024*1024)
33 #else
34 #define TEST_SIZE (300*1024*1024)
35 #endif
36 #define TEST_TIME 10 /* in seconds */
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_getstringsize("A", NULL, &h);
81 max_line = LCD_HEIGHT / h;
82 line = 0;
83 rb->lcd_clear_display();
84 rb->lcd_update();
86 rb->create_numbered_filename(logfilename, "/", "test_disk_log_", ".txt",
87 2 IF_CNFN_NUM_(, NULL));
88 log_fd = rb->open(logfilename, O_RDWR|O_CREAT|O_TRUNC, 0666);
89 return log_fd >= 0;
92 static void log_text(char *text, bool advance)
94 rb->lcd_puts(0, line, text);
95 rb->lcd_update();
96 if (advance)
98 if (++line >= max_line)
99 line = 0;
100 rb->fdprintf(log_fd, "%s\n", text);
104 static void log_close(void)
106 rb->close(log_fd);
109 static bool test_fs(void)
111 unsigned char text_buf[32];
112 int total, current, align;
113 int fd;
115 log_init();
116 log_text("test_disk WRITE&VERIFY", true);
117 #ifndef SIMULATOR
118 rb->snprintf(text_buf, sizeof(text_buf), "CPU clock: %ld Hz",
119 *rb->cpu_frequency);
120 log_text(text_buf, true);
121 #endif
122 log_text("----------------------", true);
123 rb->snprintf(text_buf, sizeof text_buf, "Data size: %dKB", (TEST_SIZE>>10));
124 log_text(text_buf, true);
126 fd = rb->creat(TEST_FILE, 0666);
127 if (fd < 0)
129 rb->splash(HZ, "creat() failed.");
130 goto error;
133 frnd_buffer = FRND_SEED;
134 total = TEST_SIZE;
135 while (total > 0)
137 align = rb->rand() & 0xf;
138 current = rb->rand() % (audiobuflen - align);
139 current = MIN(current, total);
140 rb->snprintf(text_buf, sizeof text_buf, "Wrt %dKB, %dKB left",
141 current >> 10, total >> 10);
142 log_text(text_buf, false);
144 mem_fill_frnd(audiobuf + align, current);
145 if (current != rb->write(fd, audiobuf + align, current))
147 rb->splash(0, "write() failed.");
148 rb->close(fd);
149 goto error;
151 total -= current;
153 rb->close(fd);
155 fd = rb->open(TEST_FILE, O_RDONLY);
156 if (fd < 0)
158 rb->splash(0, "open() failed.");
159 goto error;
162 frnd_buffer = FRND_SEED;
163 total = TEST_SIZE;
164 while (total > 0)
166 align = rb->rand() & 0xf;
167 current = rb->rand() % (audiobuflen - align);
168 current = MIN(current, total);
169 rb->snprintf(text_buf, sizeof text_buf, "Cmp %dKB, %dKB left",
170 current >> 10, total >> 10);
171 log_text(text_buf, false);
173 if (current != rb->read(fd, audiobuf + align, current))
175 rb->splash(0, "read() failed.");
176 rb->close(fd);
177 goto error;
179 if (!mem_cmp_frnd(audiobuf + align, current))
181 log_text(text_buf, true);
182 log_text("Compare error.", true);
183 rb->close(fd);
184 goto error;
186 total -= current;
188 rb->close(fd);
189 log_text(text_buf, true);
190 log_text("Test passed.", true);
192 error:
193 log_close();
194 rb->remove(TEST_FILE);
195 rb->button_clear_queue();
196 rb->button_get(true);
198 return false;
201 static bool file_speed(int chunksize, bool align)
203 unsigned char text_buf[64];
204 int fd;
205 long filesize = 0;
206 long size, time;
208 if (chunksize >= audiobuflen)
209 return false;
211 log_text("--------------------", true);
213 /* File creation write speed */
214 fd = rb->creat(TEST_FILE, 0666);
215 if (fd < 0)
217 rb->splash(HZ, "creat() failed.");
218 goto error;
220 time = *rb->current_tick;
221 while (TIME_BEFORE(*rb->current_tick, time + TEST_TIME*HZ))
223 if (chunksize != rb->write(fd, audiobuf + (align ? 0 : 1), chunksize))
225 rb->splash(HZ, "write() failed.");
226 rb->close(fd);
227 goto error;
229 filesize += chunksize;
231 time = *rb->current_tick - time;
232 rb->close(fd);
233 rb->snprintf(text_buf, sizeof text_buf, "Create (%d,%c): %ld KB/s",
234 chunksize, align ? 'A' : 'U', (25 * (filesize>>8) / time) );
235 log_text(text_buf, true);
237 /* Existing file write speed */
238 fd = rb->open(TEST_FILE, O_WRONLY);
239 if (fd < 0)
241 rb->splash(0, "open() failed.");
242 goto error;
244 time = *rb->current_tick;
245 for (size = filesize; size > 0; size -= chunksize)
247 if (chunksize != rb->write(fd, audiobuf + (align ? 0 : 1), chunksize))
249 rb->splash(0, "write() failed.");
250 rb->close(fd);
251 goto error;
254 time = *rb->current_tick - time;
255 rb->close(fd);
256 rb->snprintf(text_buf, sizeof text_buf, "Write (%d,%c): %ld KB/s",
257 chunksize, align ? 'A' : 'U', (25 * (filesize>>8) / time) );
258 log_text(text_buf, true);
260 /* File read speed */
261 fd = rb->open(TEST_FILE, O_RDONLY);
262 if (fd < 0)
264 rb->splash(0, "open() failed.");
265 goto error;
267 time = *rb->current_tick;
268 for (size = filesize; size > 0; size -= chunksize)
270 if (chunksize != rb->read(fd, audiobuf + (align ? 0 : 1), chunksize))
272 rb->splash(0, "read() failed.");
273 rb->close(fd);
274 goto error;
277 time = *rb->current_tick - time;
278 rb->close(fd);
279 rb->snprintf(text_buf, sizeof text_buf, "Read (%d,%c): %ld KB/s",
280 chunksize, align ? 'A' : 'U', (25 * (filesize>>8) / time) );
281 log_text(text_buf, true);
282 rb->remove(TEST_FILE);
283 return true;
285 error:
286 rb->remove(TEST_FILE);
287 return false;
290 static bool test_speed(void)
292 unsigned char text_buf[64];
293 DIR *dir = NULL;
294 struct dirent *entry = NULL;
295 int fd, last_file;
296 int i, n;
297 long time;
299 rb->memset(audiobuf, 'T', audiobuflen);
300 log_init();
301 log_text("test_disk SPEED TEST", true);
302 #ifndef SIMULATOR
303 rb->snprintf(text_buf, sizeof(text_buf), "CPU clock: %ld Hz",
304 *rb->cpu_frequency);
305 log_text(text_buf, true);
306 #endif
307 log_text("--------------------", true);
309 /* File creation speed */
310 time = *rb->current_tick + TEST_TIME*HZ;
311 for (i = 0; TIME_BEFORE(*rb->current_tick, time); i++)
313 rb->snprintf(text_buf, sizeof(text_buf), TESTBASEDIR "/%08x.tmp", i);
314 fd = rb->creat(text_buf, 0666);
315 if (fd < 0)
317 last_file = i;
318 rb->splash(HZ, "creat() failed.");
319 goto error;
321 rb->close(fd);
323 last_file = i;
324 rb->snprintf(text_buf, sizeof(text_buf), "Create: %d files/s",
325 last_file / TEST_TIME);
326 log_text(text_buf, true);
328 /* File open speed */
329 time = *rb->current_tick + TEST_TIME*HZ;
330 for (n = 0, i = 0; TIME_BEFORE(*rb->current_tick, time); n++, i++)
332 if (i >= last_file)
333 i = 0;
334 rb->snprintf(text_buf, sizeof(text_buf), TESTBASEDIR "/%08x.tmp", i);
335 fd = rb->open(text_buf, O_RDONLY);
336 if (fd < 0)
338 rb->splash(HZ, "open() failed.");
339 goto error;
341 rb->close(fd);
343 rb->snprintf(text_buf, sizeof(text_buf), "Open: %d files/s", n / TEST_TIME);
344 log_text(text_buf, true);
346 /* Directory scan speed */
347 time = *rb->current_tick + TEST_TIME*HZ;
348 for (n = 0; TIME_BEFORE(*rb->current_tick, time); n++)
350 if (entry == NULL)
352 if (dir != NULL)
353 rb->closedir(dir);
354 dir = rb->opendir(testbasedir);
355 if (dir == NULL)
357 rb->splash(HZ, "opendir() failed.");
358 goto error;
361 entry = rb->readdir(dir);
363 rb->closedir(dir);
364 rb->snprintf(text_buf, sizeof(text_buf), "Dirscan: %d files/s", n / TEST_TIME);
365 log_text(text_buf, true);
367 /* File delete speed */
368 time = *rb->current_tick;
369 for (i = 0; i < last_file; i++)
371 rb->snprintf(text_buf, sizeof(text_buf), TESTBASEDIR "/%08x.tmp", i);
372 rb->remove(text_buf);
374 rb->snprintf(text_buf, sizeof(text_buf), "Delete: %ld files/s",
375 last_file * HZ / (*rb->current_tick - time));
376 log_text(text_buf, true);
378 if (file_speed(512, true)
379 && file_speed(512, false)
380 && file_speed(4096, true)
381 && file_speed(4096, false)
382 && file_speed(1048576, true))
383 file_speed(1048576, false);
385 log_text("DONE", false);
386 log_close();
387 rb->button_clear_queue();
388 rb->button_get(true);
389 return false;
391 error:
392 for (i = 0; i < last_file; i++)
394 rb->snprintf(text_buf, sizeof(text_buf), TESTBASEDIR "/%08x.tmp", i);
395 rb->remove(text_buf);
397 log_text("DONE", false);
398 log_close();
399 rb->button_clear_queue();
400 rb->button_get(true);
401 return false;
405 /* this is the plugin entry point */
406 enum plugin_status plugin_start(const void* parameter)
408 MENUITEM_STRINGLIST(menu, "Test Disk Menu", NULL,
409 "Disk speed", "Write & verify");
410 int selected=0;
411 bool quit = false;
412 int align;
413 DIR *dir;
415 (void)parameter;
417 if ((dir = rb->opendir(testbasedir)) == NULL)
419 if (rb->mkdir(testbasedir) < 0)
421 rb->splash(HZ*2, "Can't create test directory.");
422 return PLUGIN_ERROR;
425 else
427 rb->closedir(dir);
430 audiobuf = rb->plugin_get_audio_buffer((size_t *)&audiobuflen);
431 /* align start and length to 32 bit */
432 align = (-(int)audiobuf) & 3;
433 audiobuf += align;
434 audiobuflen = (audiobuflen - align) & ~3;
436 rb->srand(*rb->current_tick);
438 /* Turn off backlight timeout */
439 backlight_force_on(); /* backlight control in lib/helper.c */
441 while(!quit)
443 switch(rb->do_menu(&menu, &selected, NULL, false))
445 case 0:
446 test_speed();
447 break;
448 case 1:
449 test_fs();
450 break;
451 default:
452 quit = true;
453 break;
457 /* Turn on backlight timeout (revert to settings) */
458 backlight_use_settings(); /* backlight control in lib/helper.c */
460 rb->rmdir(testbasedir);
462 return PLUGIN_OK;