1 /* ScummVM - Graphic Adventure Engine
2 *
3 * ScummVM is the legal property of its developers, whose names
4 * are too numerous to list here. Please refer to the COPYRIGHT
5 * file distributed with this source distribution.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 *
21 */
22
23 // PSP speed and unit tests. Activate in tests.h
24 // You may also want to build without any engines.
25
26 #include "backends/platform/psp/tests.h"
27
28 #if defined(PSP_ENABLE_UNIT_TESTS) || defined(PSP_ENABLE_SPEED_TESTS)
29
30 #include "common/scummsys.h"
31 #include <pspiofilemgr_fcntl.h>
32 #include <pspiofilemgr_stat.h>
33 #include <pspiofilemgr.h>
34 #include <pspthreadman.h>
35 #include <pspsdk.h>
36 #include <psprtc.h>
37 #include <stdlib.h>
38 #include <stdio.h>
39 #include <psputils.h>
40 #include "backends/platform/psp/rtc.h"
41 #include "backends/platform/psp/thread.h"
42 #include "backends/platform/psp/memory.h"
43 #include "common/stream.h"
44 #include "common/file.h"
45 #include "common/fs.h"
46
47 #define UNCACHED(x) ((byte *)(((uint32)(x)) | 0x40000000)) /* make an uncached access */
48 #define CACHED(x) ((byte *)(((uint32)(x)) & 0xBFFFFFFF)) /* make an uncached access into a cached one */
49
50 //#define __PSP_DEBUG_FUNCS__
51 //#define __PSP_DEBUG_PRINT__
52
53 // Results: (333Mhz/222Mhz)
54 // Getting a tick: 1-2 us
55 // Getting a time structure: 9/14us
56 // ie. using a tick and just dividing by 1000 saves us time.
57
58 #include "backends/platform/psp/trace.h"
59
60 class PspSpeedTests {
61 public:
62 void tickSpeed();
63 void getMicrosSpeed();
64 void seekSpeed();
65 void msReadSpeed();
66 void threadFunctionsSpeed();
67 void semaphoreSpeed();
68 static int threadFunc(SceSize args, void *argp);
69 void semaphoreManyThreadSpeed();
70 void fastCopySpeed();
71
72 private:
73 enum {
74 MEMCPY_BUFFER_SIZE = 8192
75 };
76 static PspSemaphore _sem; // semaphore
77
78 void readAndTime(uint32 bytes, char *buffer, FILE *file);
79 void seekAndTime(int bytes, int origin, FILE *file);
80 void fastCopySpecificSize(byte *dst, byte *src, uint32 bytes);
81 void fastCopyDifferentSizes(byte *dst, byte *src);
82 int getThreadIdSpeed();
83 void getPrioritySpeed();
84 void changePrioritySpeed(int id, int priority);
85 };
86
87 PspSemaphore PspSpeedTests::_sem(0);
88
tickSpeed()89 void PspSpeedTests::tickSpeed() {
90 uint32 ticksPerSecond = sceRtcGetTickResolution();
91 PSP_INFO_PRINT("ticksPerSecond[%d]\n", ticksPerSecond);
92
93 uint32 currentTicks1[2];
94 uint32 currentTicks2[2];
95
96 sceRtcGetCurrentTick((u64 *)currentTicks1);
97 sceRtcGetCurrentTick((u64 *)currentTicks2);
98 PSP_INFO_PRINT("current tick[%x %x][%u %u]\n", currentTicks1[0], currentTicks1[1], currentTicks1[0], currentTicks1[1]);
99 PSP_INFO_PRINT("current tick[%x %x][%u %u]\n", currentTicks2[0], currentTicks2[1], currentTicks2[0], currentTicks2[1]);
100
101 pspTime time;
102 sceRtcSetTick(&time, (u64 *)currentTicks2);
103 PSP_INFO_PRINT("current tick in time, year[%d] month[%d] day[%d] hour[%d] minutes[%d] seconds[%d] us[%d]\n", time.year, time.month, time.day, time.hour, time.minutes, time.seconds, time.microseconds);
104
105 pspTime time1;
106 pspTime time2;
107 sceRtcGetCurrentClockLocalTime(&time1);
108 sceRtcGetCurrentClockLocalTime(&time2);
109 PSP_INFO_PRINT("time1, year[%d] month[%d] day[%d] hour[%d] minutes[%d] seconds[%d] us[%d]\n", time1.year, time1.month, time1.day, time1.hour, time1.minutes, time1.seconds, time1.microseconds);
110 PSP_INFO_PRINT("time2, year[%d] month[%d] day[%d] hour[%d] minutes[%d] seconds[%d] us[%d]\n", time2.year, time2.month, time2.day, time2.hour, time2.minutes, time2.seconds, time2.microseconds);
111 }
112
getMicrosSpeed()113 void PspSpeedTests::getMicrosSpeed() {
114 uint32 time1, time2, time3, time4;
115 time1 = PspRtc::instance().getMicros();
116 time2 = PspRtc::instance().getMicros();
117 time3 = PspRtc::instance().getMicros();
118 time4 = PspRtc::instance().getMicros();
119
120 PSP_INFO_PRINT("getMicros() times: %d, %d, %d\n", time4-time3, time3-time2, time2-time1);
121 }
122
readAndTime(uint32 bytes,char * buffer,FILE * file)123 void PspSpeedTests::readAndTime(uint32 bytes, char *buffer, FILE *file) {
124 uint32 time1 = PspRtc::instance().getMicros();
125 // test minimal read
126 fread(buffer, bytes, 1, file);
127 uint32 time2 = PspRtc::instance().getMicros();
128
129 PSP_INFO_PRINT("Reading %d byte takes %dus\n", bytes, time2-time1);
130 }
131
132 /*
133 333MHz/222MHz
134 Reading 1 byte takes 2590us / 3167
135 Reading 10 byte takes 8us / 9
136 Reading 50 byte takes 8us / 11
137 Reading 100 byte takes 8us / 11
138 Reading 1000 byte takes 915us / 1131
139 Reading 2000 byte takes 1806us / 2,284
140 Reading 3000 byte takes 2697us / 3,374
141 Reading 5000 byte takes 4551us / 5,544
142 Reading 6000 byte takes 5356us / 6,676
143 Reading 7000 byte takes 6800us / 8,358
144 Reading 8000 byte takes 6794us / 8,454
145 Reading 9000 byte takes 6782us / 8,563
146 Reading 10000 byte takes 8497us / 10,631
147 Reading 30000 byte takes 25995us / 32,473
148 Reading 80000 byte takes 68457us / 85,291
149 Reading 100000 byte takes 85103us / 106,163
150 */
151 // Function to test the impact of MS reads
152 // These tests can't be done from shell - the cache screws them up
msReadSpeed()153 void PspSpeedTests::msReadSpeed() {
154 FILE *file;
155 file = fopen("ms0:/psp/music/track1.mp3", "r");
156
157 char *buffer = (char *)malloc(2 * 1024 * 1024);
158
159 readAndTime(1, buffer, file);
160 readAndTime(10, buffer, file);
161 readAndTime(50, buffer, file);
162 readAndTime(100, buffer, file);
163 readAndTime(1000, buffer, file);
164 readAndTime(2000, buffer, file);
165 readAndTime(3000, buffer, file);
166 readAndTime(5000, buffer, file);
167 readAndTime(6000, buffer, file);
168 readAndTime(7000, buffer, file);
169 readAndTime(8000, buffer, file);
170 readAndTime(9000, buffer, file);
171 readAndTime(10000, buffer, file);
172 readAndTime(30000, buffer, file);
173 readAndTime(50000, buffer, file);
174 readAndTime(80000, buffer, file);
175 readAndTime(100000, buffer, file);
176
177 fclose(file);
178 free(buffer);
179 }
180
seekAndTime(int bytes,int origin,FILE * file)181 void PspSpeedTests::seekAndTime(int bytes, int origin, FILE *file) {
182 char buffer[1000];
183
184 uint32 time1 = PspRtc::instance().getMicros();
185 // test minimal read
186 fseek(file, bytes, origin);
187 uint32 time2 = PspRtc::instance().getMicros();
188
189 PSP_INFO_PRINT("Seeking %d byte from %d took %dus\n", bytes, origin, time2-time1);
190
191 time1 = PspRtc::instance().getMicros();
192 // test minimal read
193 fread(buffer, 1000, 1, file);
194 time2 = PspRtc::instance().getMicros();
195
196 PSP_INFO_PRINT("Reading 1000 bytes took %dus\n", time2-time1);
197 }
198
199 /*
200 333MHz
201 Seeking 0 byte from 0 took 946us
202 Reading 1000 bytes took 1781us
203 Seeking 5 byte from 0 took 6us
204 Reading 1000 bytes took 19us
205 Seeking 1000 byte from 0 took 5us
206 Reading 1000 bytes took 913us
207 Seeking 100 byte from 0 took 955us
208 Reading 1000 bytes took 906us
209 Seeking 10000 byte from 0 took 963us
210 Reading 1000 bytes took 905us
211 Seeking -5 byte from 1 took 1022us
212 Reading 1000 bytes took 949us
213 Seeking -100 byte from 1 took 1040us
214 Reading 1000 bytes took 907us
215 Seeking 100 byte from 1 took 1044us
216 Reading 1000 bytes took 930us
217 Seeking 0 byte from 2 took 7211us
218 Reading 1000 bytes took 80us
219 Seeking 10000 byte from 2 took 3636us
220 Reading 1000 bytes took 110us
221 */
222
seekSpeed()223 void PspSpeedTests::seekSpeed() {
224 FILE *file;
225 file = fopen("ms0:/psp/music/track1.mp3", "r");
226
227 seekAndTime(0, SEEK_SET, file);
228 seekAndTime(5, SEEK_SET, file);
229 seekAndTime(1000, SEEK_SET, file);
230 seekAndTime(100, SEEK_SET, file);
231 seekAndTime(10000, SEEK_SET, file);
232 seekAndTime(-5, SEEK_CUR, file);
233 seekAndTime(-100, SEEK_CUR, file);
234 seekAndTime(100, SEEK_CUR, file);
235 seekAndTime(0, SEEK_END, file);
236 seekAndTime(-10000, SEEK_END, file);
237
238 fclose(file);
239 }
240
241 // 222: 5-7us
getThreadIdSpeed()242 int PspSpeedTests::getThreadIdSpeed() {
243 uint32 time1 = PspRtc::instance().getMicros();
244 int threadId = sceKernelGetThreadId();
245 uint32 time2 = PspRtc::instance().getMicros();
246
247 PSP_INFO_PRINT("Getting thread ID %d took %dus\n", threadId, time2-time1);
248
249 return threadId;
250 }
251
252 // 222: 4-5us
getPrioritySpeed()253 void PspSpeedTests::getPrioritySpeed() {
254 uint32 time1 = PspRtc::instance().getMicros();
255 int priority = sceKernelGetThreadCurrentPriority();
256 uint32 time2 = PspRtc::instance().getMicros();
257
258 PSP_INFO_PRINT("Getting thread priority %d took %dus\n", priority, time2-time1);
259 }
260
261 // 222: 9-10us
changePrioritySpeed(int id,int priority)262 void PspSpeedTests::changePrioritySpeed(int id, int priority) {
263 uint32 time1 = PspRtc::instance().getMicros();
264 sceKernelChangeThreadPriority(id, priority);
265 uint32 time2 = PspRtc::instance().getMicros();
266
267 PSP_INFO_PRINT("Changing thread priority to %d for id %d took %dus\n", priority, id, time2-time1);
268 }
269
threadFunctionsSpeed()270 void PspSpeedTests::threadFunctionsSpeed() {
271 // very unscientific -- just ballpark
272 int id;
273 id = getThreadIdSpeed();
274 getThreadIdSpeed();
275 getPrioritySpeed();
276 getPrioritySpeed();
277 changePrioritySpeed(id, 30);
278 changePrioritySpeed(id, 35);
279 changePrioritySpeed(id, 25);
280
281 // test context switch time
282 for (int i=0; i<10; i++) {
283 uint time1 = PspRtc::instance().getMicros();
284 PspThread::delayMicros(0);
285 uint time2 = PspRtc::instance().getMicros();
286 PSP_INFO_PRINT("poll %d. context switch Time = %dus\n", i, time2-time1); // 10-15us
287 }
288 }
289
semaphoreSpeed()290 void PspSpeedTests::semaphoreSpeed() {
291 PspSemaphore sem(1);
292
293 uint32 time1 = PspRtc::instance().getMicros();
294
295 sem.take();
296
297 uint32 time2 = PspRtc::instance().getMicros();
298
299 PSP_INFO_PRINT("taking semaphore took %d us\n", time2-time1); // 10us
300
301 uint32 time3 = PspRtc::instance().getMicros();
302
303 sem.give();
304
305 uint32 time4 = PspRtc::instance().getMicros();
306 PSP_INFO_PRINT("releasing semaphore took %d us\n", time4-time3); //10us-55us
307 }
308
threadFunc(SceSize args,void * argp)309 int PspSpeedTests::threadFunc(SceSize args, void *argp) {
310 PSP_INFO_PRINT("thread %x created.\n", sceKernelGetThreadId());
311
312 _sem.take();
313
314 PSP_INFO_PRINT("grabbed semaphore. Quitting thread\n");
315
316 return 0;
317 }
318
semaphoreManyThreadSpeed()319 void PspSpeedTests::semaphoreManyThreadSpeed() {
320
321 // create 4 threads
322 for (int i=0; i<4; i++) {
323 int thid = sceKernelCreateThread("my_thread", PspSpeedTests::threadFunc, 0x18, 0x10000, THREAD_ATTR_USER, NULL);
324 sceKernelStartThread(thid, 0, 0);
325 }
326
327 PSP_INFO_PRINT("main thread. created threads\n");
328
329 uint32 threads = _sem.numOfWaitingThreads();
330 while (threads < 4) {
331 threads = _sem.numOfWaitingThreads();
332 PSP_INFO_PRINT("main thread: waiting threads[%d]\n", threads);
333 }
334
335 PSP_INFO_PRINT("main: semaphore value[%d]\n", _sem.getValue());
336 PSP_INFO_PRINT("main thread: waiting threads[%d]\n", _sem.numOfWaitingThreads());
337
338 _sem.give(4);
339 }
340
fastCopySpecificSize(byte * dst,byte * src,uint32 bytes)341 void PspSpeedTests::fastCopySpecificSize(byte *dst, byte *src, uint32 bytes) {
342 uint32 time1, time2;
343 uint32 fastcopyTime, memcpyTime;
344 const int iterations = 2000;
345 int intc;
346
347 intc = pspSdkDisableInterrupts();
348
349 time1 = PspRtc::instance().getMicros();
350 for (int i=0; i<iterations; i++) {
351 PspMemory::fastCopy(dst, src, bytes);
352 }
353 time2 = PspRtc::instance().getMicros();
354
355 pspSdkEnableInterrupts(intc);
356
357 fastcopyTime = time2-time1;
358
359 intc = pspSdkDisableInterrupts();
360
361 time1 = PspRtc::instance().getMicros();
362 for (int i=0; i<iterations; i++) {
363 memcpy(dst, src, bytes);
364 }
365 time2 = PspRtc::instance().getMicros();
366
367 pspSdkEnableInterrupts(intc);
368
369 memcpyTime = time2-time1;
370
371 PSP_INFO_PRINT("%d bytes. memcpy[%d], fastcopy[%d]\n", bytes, memcpyTime, fastcopyTime);
372 }
373
fastCopyDifferentSizes(byte * dst,byte * src)374 void PspSpeedTests::fastCopyDifferentSizes(byte *dst, byte *src) {
375 PSP_INFO_PRINT("\nsrc[%p], dst[%p]\n", src, dst);
376 fastCopySpecificSize(dst, src, 1);
377 fastCopySpecificSize(dst, src, 2);
378 fastCopySpecificSize(dst, src, 3);
379 fastCopySpecificSize(dst, src, 4);
380 fastCopySpecificSize(dst, src, 5);
381 fastCopySpecificSize(dst, src, 8);
382 fastCopySpecificSize(dst, src, 10);
383 fastCopySpecificSize(dst, src, 16);
384 fastCopySpecificSize(dst, src, 32);
385 fastCopySpecificSize(dst, src, 50);
386 fastCopySpecificSize(dst, src, 100);
387 fastCopySpecificSize(dst, src, 500);
388 fastCopySpecificSize(dst, src, 1024);
389 fastCopySpecificSize(dst, src, 2048);
390 }
391
fastCopySpeed()392 void PspSpeedTests::fastCopySpeed() {
393 PSP_INFO_PRINT("running fastCopy speed test\n");
394
395 uint32 *bufferSrc32 = (uint32 *)memalign(16, MEMCPY_BUFFER_SIZE);
396 uint32 *bufferDst32 = (uint32 *)memalign(16, MEMCPY_BUFFER_SIZE);
397
398 // fill buffer 1
399 for (int i=0; i<MEMCPY_BUFFER_SIZE/4; i++)
400 bufferSrc32[i] = i | (((MEMCPY_BUFFER_SIZE/4)-i)<<16);
401
402 // print buffer
403 for (int i=0; i<50; i++)
404 PSP_INFO_PRINT("%x ", bufferSrc32[i]);
405 PSP_INFO_PRINT("\n");
406
407 byte *bufferSrc = ((byte *)bufferSrc32);
408 byte *bufferDst = ((byte *)bufferDst32);
409
410 PSP_INFO_PRINT("\n\ndst and src cached: -----------------\n");
411 fastCopyDifferentSizes(bufferDst, bufferSrc);
412 fastCopyDifferentSizes(bufferDst+1, bufferSrc+1);
413 fastCopyDifferentSizes(bufferDst, bufferSrc+1);
414 fastCopyDifferentSizes(bufferDst+1, bufferSrc);
415
416 PSP_INFO_PRINT("\n\ndst cached, src uncached: -----------------\n");
417 bufferSrc = UNCACHED(bufferSrc);
418 fastCopyDifferentSizes(bufferDst, bufferSrc);
419 fastCopyDifferentSizes(bufferDst+1, bufferSrc+1);
420 fastCopyDifferentSizes(bufferDst, bufferSrc+1);
421 fastCopyDifferentSizes(bufferDst+1, bufferSrc);
422
423 PSP_INFO_PRINT("\n\ndst uncached, src uncached: --------------\n");
424 bufferDst = UNCACHED(bufferDst);
425 fastCopyDifferentSizes(bufferDst, bufferSrc);
426 fastCopyDifferentSizes(bufferDst+1, bufferSrc+1);
427 fastCopyDifferentSizes(bufferDst, bufferSrc+1);
428 fastCopyDifferentSizes(bufferDst+1, bufferSrc);
429
430 PSP_INFO_PRINT("\n\ndst uncached, src cached: -------------------\n");
431 bufferSrc = CACHED(bufferSrc);
432 fastCopyDifferentSizes(bufferDst, bufferSrc);
433 fastCopyDifferentSizes(bufferDst+1, bufferSrc+1);
434 fastCopyDifferentSizes(bufferDst, bufferSrc+1);
435 fastCopyDifferentSizes(bufferDst+1, bufferSrc);
436
437
438 free(bufferSrc32);
439 free(bufferDst32);
440 }
441
442 //-------Unit Tests -------------------------------
443
444 class PspUnitTests {
445 public:
446 void testFastCopy();
447 bool testFileSystem();
448
449 private:
450 enum {
451 MEMCPY_BUFFER_SIZE = 8192
452 };
453
454 void fastCopySpecificSize(byte *dst, byte *src, uint32 bytes, bool swap = false);
455 void fastCopyDifferentSizes(byte *dst, byte *src, bool swap = false);
456
457 };
458
testFastCopy()459 void PspUnitTests::testFastCopy() {
460 PSP_INFO_PRINT("running fastcopy unit test ***********\n");
461 PSP_INFO_PRINT("this test requires the test flag to be on in fastCopy\n\n");
462
463 uint32 *bufferSrc32 = (uint32 *)memalign(16, MEMCPY_BUFFER_SIZE);
464 uint32 *bufferDst32 = (uint32 *)memalign(16, MEMCPY_BUFFER_SIZE);
465
466 // fill buffer 1
467 for (int i=0; i<MEMCPY_BUFFER_SIZE/4; i++)
468 bufferSrc32[i] = i | (((MEMCPY_BUFFER_SIZE/4)-i)<<16);
469
470 // print buffer
471 for (int i=0; i<50; i++)
472 PSP_INFO_PRINT("%x ", bufferSrc32[i]);
473 PSP_INFO_PRINT("\n");
474
475 byte *bufferSrc = ((byte *)bufferSrc32);
476 byte *bufferDst = ((byte *)bufferDst32);
477
478 fastCopyDifferentSizes(bufferDst, bufferSrc, true);
479 fastCopyDifferentSizes(bufferDst+1, bufferSrc+1);
480 fastCopyDifferentSizes(bufferDst+2, bufferSrc+2, true);
481 fastCopyDifferentSizes(bufferDst+3, bufferSrc+3);
482 fastCopyDifferentSizes(bufferDst, bufferSrc+1);
483 fastCopyDifferentSizes(bufferDst, bufferSrc+2, true);
484 fastCopyDifferentSizes(bufferDst+2, bufferSrc, true);
485 fastCopyDifferentSizes(bufferDst, bufferSrc+3);
486 fastCopyDifferentSizes(bufferDst+1, bufferSrc+2);
487 fastCopyDifferentSizes(bufferDst+1, bufferSrc+3);
488 fastCopyDifferentSizes(bufferDst+2, bufferSrc+1);
489 fastCopyDifferentSizes(bufferDst+2, bufferSrc+3);
490 fastCopyDifferentSizes(bufferDst+3, bufferSrc+1);
491 fastCopyDifferentSizes(bufferDst+3, bufferSrc+2);
492
493 free(bufferSrc32);
494 free(bufferDst32);
495 }
496
fastCopyDifferentSizes(byte * dst,byte * src,bool swap)497 void PspUnitTests::fastCopyDifferentSizes(byte *dst, byte *src, bool swap) {
498 fastCopySpecificSize(dst, src, 1);
499 fastCopySpecificSize(dst, src, 2, swap);
500 fastCopySpecificSize(dst, src, 4, swap);
501 fastCopySpecificSize(dst, src, 6, swap);
502 fastCopySpecificSize(dst, src, 8, swap);
503 fastCopySpecificSize(dst, src, 9);
504 fastCopySpecificSize(dst, src, 10, swap);
505 fastCopySpecificSize(dst, src, 11);
506 fastCopySpecificSize(dst, src, 12, swap);
507 fastCopySpecificSize(dst, src, 13);
508 fastCopySpecificSize(dst, src, 14, swap);
509 fastCopySpecificSize(dst, src, 15);
510 fastCopySpecificSize(dst, src, 16, swap);
511 fastCopySpecificSize(dst, src, 17);
512 fastCopySpecificSize(dst, src, 18, swap);
513 fastCopySpecificSize(dst, src, 19);
514 fastCopySpecificSize(dst, src, 20, swap);
515 fastCopySpecificSize(dst, src, 32, swap);
516 fastCopySpecificSize(dst, src, 33);
517 fastCopySpecificSize(dst, src, 34, swap);
518 fastCopySpecificSize(dst, src, 35);
519 fastCopySpecificSize(dst, src, 36, swap);
520 fastCopySpecificSize(dst, src, 50, swap);
521 fastCopySpecificSize(dst, src, 100, swap);
522 fastCopySpecificSize(dst, src, 500, swap);
523 fastCopySpecificSize(dst, src, 1000, swap);
524 }
525
fastCopySpecificSize(byte * dst,byte * src,uint32 bytes,bool swap)526 void PspUnitTests::fastCopySpecificSize(byte *dst, byte *src, uint32 bytes, bool swap) {
527 memset(dst, 0, bytes);
528 PspMemory::fastCopy(dst, src, bytes);
529
530 if (swap) { // test swap also
531 memset(dst, 0, bytes);
532
533 // pixelformat for swap
534 PSPPixelFormat format;
535 format.set(PSPPixelFormat::Type_4444, true);
536
537 PspMemory::fastSwap(dst, src, bytes, format);
538 }
539 }
540
541 // This function leaks. For now I don't care
testFileSystem()542 bool PspUnitTests::testFileSystem() {
543 // create memory
544 const uint32 BufSize = 32 * 1024;
545 char* buffer = new char[BufSize];
546 int i;
547 Common::WriteStream *wrStream;
548 Common::SeekableReadStream *rdStream;
549
550 PSP_INFO_PRINT("testing fileSystem...\n");
551
552 // fill buffer
553 for (i=0; i<(int)BufSize; i += 4) {
554 buffer[i] = 'A';
555 buffer[i + 1] = 'B';
556 buffer[i + 2] = 'C';
557 buffer[i + 3] = 'D';
558 }
559
560 // create a file
561 const char *path = "./file.test";
562 Common::FSNode file(path);
563
564 PSP_INFO_PRINT("creating write stream...\n");
565
566 wrStream = file.createWriteStream();
567 if (!wrStream) {
568 PSP_ERROR("%s couldn't be created.\n", path);
569 delete[] buffer;
570 return false;
571 }
572
573 // write contents
574 char* index = buffer;
575 int32 totalLength = BufSize;
576 int32 curLength = 50;
577
578 PSP_INFO_PRINT("writing...\n");
579
580 while(totalLength - curLength > 0) {
581 if ((int)wrStream->write(index, curLength) != curLength) {
582 PSP_ERROR("couldn't write %d bytes\n", curLength);
583 delete[] buffer;
584 delete wrStream;
585 return false;
586 }
587 totalLength -= curLength;
588 index += curLength;
589 //curLength *= 2;
590 //PSP_INFO_PRINT("write\n");
591 }
592
593 // write the rest
594 if ((int)wrStream->write(index, totalLength) != totalLength) {
595 PSP_ERROR("couldn't write %d bytes\n", curLength);
596 delete[] buffer;
597 delete wrStream;
598 return false;
599 }
600
601 delete wrStream;
602
603 PSP_INFO_PRINT("reading...\n");
604
605 rdStream = file.createReadStream();
606 if (!rdStream) {
607 PSP_ERROR("%s couldn't be created.\n", path);
608 delete[] buffer;
609 return false;
610 }
611
612 // seek to beginning
613 if (!rdStream->seek(0, SEEK_SET)) {
614 PSP_ERROR("couldn't seek to the beginning after writing the file\n");
615 delete[] buffer;
616 delete rdStream;
617 return false;
618 }
619
620 // read the contents
621 char *readBuffer = new char[BufSize + 4];
622 memset(readBuffer, 0, (BufSize + 4));
623 index = readBuffer;
624 while (rdStream->read(index, 100) == 100) {
625 index += 100;
626 }
627
628 if (!rdStream->eos()) {
629 PSP_ERROR("didn't find EOS at end of stream\n");
630 delete[] buffer;
631 delete rdStream;
632 delete[] readBuffer;
633 return false;
634 }
635
636 // compare
637 for (i=0; i<(int)BufSize; i++)
638 if (buffer[i] != readBuffer[i]) {
639 PSP_ERROR("reading/writing mistake at %x. Got %x instead of %x\n", i, readBuffer[i], buffer[i]);
640 delete[] buffer;
641 delete rdStream;
642 delete[] readBuffer;
643 return false;
644 }
645
646 // Check for exceeding limit
647 for (i=0; i<4; i++) {
648 if (readBuffer[BufSize + i]) {
649 PSP_ERROR("read exceeded limits. %d = %x\n", BufSize + i, readBuffer[BufSize + i]);
650 }
651 }
652
653 delete[] buffer;
654 delete rdStream;
655 delete[] readBuffer;
656
657 PSP_INFO_PRINT("writing...\n");
658
659 wrStream = file.createWriteStream();
660 if (!wrStream) {
661 PSP_ERROR("%s couldn't be created.\n", path);
662 return false;
663 }
664
665 const char *phrase = "Jello is really fabulous";
666 uint32 phraseLen = strlen(phrase);
667
668 int ret;
669 if ((ret = wrStream->write(phrase, phraseLen)) != (int)phraseLen) {
670 PSP_ERROR("couldn't write phrase. Got %d instead of %d\n", ret, phraseLen);
671 delete wrStream;
672 return false;
673 }
674
675 PSP_INFO_PRINT("reading...\n");
676
677 delete wrStream;
678
679 rdStream = file.createReadStream();
680 if (!rdStream) {
681 PSP_ERROR("%s couldn't be created.\n", path);
682 return false;
683 }
684
685 char *readPhrase = new char[phraseLen + 2];
686 memset(readPhrase, 0, phraseLen + 2);
687
688 if ((ret = rdStream->read(readPhrase, phraseLen) != phraseLen)) {
689 PSP_ERROR("read error on phrase. Got %d instead of %d\n", ret, phraseLen);
690 delete rdStream;
691 delete[] readPhrase;
692 return false;
693 }
694
695 for (i=0; i<(int)phraseLen; i++) {
696 if (readPhrase[i] != phrase[i]) {
697 PSP_ERROR("bad read/write in phrase. At %d, %x != %x\n", i, readPhrase[i], phrase[i]);
698 delete rdStream;
699 delete[] readPhrase;
700 return false;
701 }
702 }
703
704 // check for exceeding
705 if (readPhrase[i] != 0) {
706 PSP_ERROR("found excessive copy in phrase. %c at %d\n", readPhrase[i], i);
707 delete rdStream;
708 delete[] readPhrase;
709 return false;
710 }
711
712 PSP_INFO_PRINT("trying to read end...\n");
713
714 // seek to end
715 if (!rdStream->seek(0, SEEK_END)) {
716 PSP_ERROR("couldn't seek to end for append\n");
717 delete rdStream;
718 delete[] readPhrase;
719 return false;
720 };
721
722 // try to read
723 if (rdStream->read(readPhrase, 2) || !rdStream->eos()) {
724 PSP_ERROR("was able to read at end of file\n");
725 delete rdStream;
726 delete[] readPhrase;
727 return false;
728 }
729
730 delete rdStream;
731 delete[] readPhrase;
732
733 PSP_INFO_PRINT("ok\n");
734 return true;
735 }
736
psp_tests()737 void psp_tests() {
738 PSP_INFO_PRINT("in tests\n");
739
740 #ifdef PSP_ENABLE_SPEED_TESTS
741 // Speed tests
742 PspSpeedTests speedTests;
743 speedTests.tickSpeed();
744 speedTests.getMicrosSpeed();
745 speedTests.msReadSpeed();
746 speedTests.seekSpeed();
747 speedTests.msReadSpeed();
748 speedTests.threadFunctionsSpeed();
749 speedTests.semaphoreSpeed();
750 speedTests.semaphoreManyThreadSpeed();
751 speedTests.fastCopySpeed();
752 #endif
753
754 #ifdef PSP_ENABLE_UNIT_TESTS
755 // Unit tests
756 PspUnitTests unitTests;
757
758 //unitTests.testFastCopy();
759 unitTests.testFileSystem();
760 #endif
761 }
762
763 #endif /* (PSP_ENABLE_UNIT_TESTS) || defined(PSP_ENABLE_SPEED_TESTS) */
764