Extend info in tests
[yaffs2.git] / direct / tests / nor_stress.c
1 #include "nor_stress.h"
2
3
4 #include "yaffsfs.h"
5 #include "yaffs_fsx.h"
6
7 #include <stdio.h>
8
9
10
11 #if 1
12 #define FSX_INIT(mount_pt) do{ if(interleave_fsx) yaffs_fsx_init(mount_pt); } while(0)
13 #define FSX_COMPLETE() do { if(interleave_fsx) yaffs_fsx_complete(); } while (0)
14
15 #define FSX() \
16 do { \
17   if((myrand() & 0x1) == 0){\
18      if(interleave_fsx) \
19         yaffs_fsx_do_op(); \
20   } \
21 } while(0)
22
23 #else
24 #define FSX_INIT(mount_point) do { } while(0)
25 #define FSX_COMPLETE() do { } while(0)
26 #define FSX() do { } while(0)
27 #endif
28
29
30 static unsigned powerUps;
31 static unsigned cycleStarts;
32 static unsigned cycleEnds;
33
34 static int interleave_fsx;
35
36 char fullPathName[100];
37 char fullPowerUpName[100];
38 char fullStartName[100];
39 char fullEndName[100];
40 char fullMainName[100];
41 char fullTempMainName[100];
42 char fullTempCounterName[100];
43
44
45 extern int random_seed;
46
47 int myrand(void) {
48   random_seed = random_seed * 1103515245 + 12345;
49   return((unsigned)(random_seed/65536) % 32768);
50 }
51
52 void MakeName(char *fullName,const char *prefix, const char *name)
53 {
54   strcpy(fullName,prefix);
55   strcat(fullName,"/");
56   strcat(fullName,name);
57 }
58
59
60 void MakeFullNames(const char *prefix)
61 {
62   MakeName(fullPathName,prefix,"");
63   MakeName(fullPowerUpName,prefix,"powerUps");
64   MakeName(fullStartName,prefix,"starts");
65   MakeName(fullEndName,prefix,"ends");
66   MakeName(fullMainName,prefix,"main");
67   MakeName(fullTempCounterName,prefix,"tmp-counter");
68   MakeName(fullTempMainName,prefix,"tmp-main");
69 }
70
71 static void FatalError(int lineNo)
72 {
73   printf("Integrity error %d\n",lineNo);
74   while(1){
75    sleep(1);
76   }
77 }
78 void print_stat(const char *str, struct yaffs_stat *st)
79 {
80         printf("%s inode %d\n",str,st->st_ino);
81 }
82
83 static void UpdateCounter(const char *name, unsigned *val,  int initialise)
84 {
85   int inh=-1;
86   int outh=-1;
87   unsigned x[2];
88   int nread = 0;
89   int nwritten = 0;
90   
91   x[0] = x[1] = 0;
92   
93   if(initialise){
94     x[0] = 0; 
95     x[1] = 1;
96   } else {
97     inh = yaffs_open(name,O_RDONLY, S_IREAD | S_IWRITE);
98     if(inh >= 0){
99       nread = yaffs_read(inh,x,sizeof(x));
100       yaffs_close(inh);
101     }
102
103     if(nread != sizeof(x) ||
104        x[0] + 1 != x[1]){
105       printf("Error reading counter %s handle %d, x[0] %u x[1] %u last error %d\n",
106               name, inh, x[0], x[1],yaffsfs_GetLastError());
107       FatalError(__LINE__);
108               
109     }
110     x[0]++;
111     x[1]++;
112   }
113   
114   FSX();
115   outh = yaffs_open(fullTempCounterName, O_RDWR | O_TRUNC | O_CREAT, S_IREAD | S_IWRITE);
116   if(outh >= 0){
117    struct yaffs_stat tmpstat, oldstat, tmpfstat;
118    FSX(); 
119     nwritten = yaffs_write(outh,x,sizeof(x));
120     FSX();
121     yaffs_fstat(outh,&tmpfstat);
122     yaffs_close(outh);
123     FSX();
124
125     printf("About to rename %s to %s\n",fullTempCounterName,name);
126     yaffs_stat(fullTempCounterName,&tmpstat);
127     yaffs_stat(name,&oldstat);
128     print_stat("old stat",&oldstat);
129     print_stat("new stat",&tmpstat);
130     print_stat("new fstat",&tmpfstat);
131     yaffs_rename(fullTempCounterName,name);
132     FSX();
133   }
134   
135   if(nwritten != sizeof(x)){
136       printf("Error writing counter %s handle %d, x[0] %u x[1] %u\n",
137               name, inh, x[0], x[1]);
138       FatalError(__LINE__);
139   }
140   
141   *val = x[0];
142   
143   printf("##\n"
144          "## Set counter %s to %u\n"
145          "##\n", name,x[0]);
146 }
147
148
149 static void dump_directory_tree_worker(const char *dname,int recursive)
150 {
151         yaffs_DIR *d;
152         yaffs_dirent *de;
153         struct yaffs_stat s;
154         char str[1000];
155                         
156         d = yaffs_opendir(dname);
157         
158         if(!d)
159         {
160                 printf("opendir failed\n");
161         }
162         else
163         {
164                 while((de = yaffs_readdir(d)) != NULL)
165                 {
166                         strcpy(str,dname);
167                         strcat(str,"/");
168                         strcat(str,de->d_name);
169                         
170                         yaffs_lstat(str,&s);
171                         
172                         printf("%s inode %ld %d obj %x length %d mode %X ",str, de->d_ino, s.st_ino,de->d_dont_use,(int)s.st_size,s.st_mode);\
173                         if(de->d_ino != s.st_ino){
174                                 printf(" \n\n!!!! HEY inode mismatch\n\n");
175                                 FatalError(__LINE__);
176                         }
177
178                         switch(s.st_mode & S_IFMT)
179                         {
180                                 case S_IFREG: printf("data file"); break;
181                                 case S_IFDIR: printf("directory"); break;
182                                 case S_IFLNK: printf("symlink -->");
183                                                           if(yaffs_readlink(str,str,100) < 0)
184                                                                 printf("no alias");
185                                                           else
186                                                                 printf("\"%s\"",str);    
187                                                           break;
188                                 default: printf("unknown"); break;
189                         }
190                         
191                         printf("\n");
192
193                         if((s.st_mode & S_IFMT) == S_IFDIR && recursive)
194                                 dump_directory_tree_worker(str,1);
195                                 
196                         if(s.st_ino > 10000)
197                           FatalError(__LINE__);
198                                                         
199                 }
200                 
201                 yaffs_closedir(d);
202         }
203
204 }
205
206 static void dump_directory_tree(const char *dname)
207 {
208         dump_directory_tree_worker(dname,1);
209         printf("\n");
210         printf("Free space in %s is %d\n\n",dname,(int)yaffs_freespace(dname));
211 }
212
213
214
215
216 #define XX_SIZE 500
217
218 static unsigned xx[XX_SIZE];
219
220 static int yWriteFile(const char *fname, unsigned sz32)
221 {
222         int h;
223         int r;
224         int i;
225         struct yaffs_stat st;
226         unsigned checksum = 0;
227         
228
229         FSX();
230         h = yaffs_open(fname,O_RDWR | O_CREAT | O_TRUNC, S_IREAD | S_IWRITE);
231         yaffs_fstat(h,&st);
232         printf("Writing file %s inode %d\n",fname, st.st_ino);
233         
234         FSX();
235
236         if(h < 0){
237                 printf("could not open file %s\n",fname);
238                 return h;
239         }
240
241         xx[0] = sz32;
242         checksum ^= xx[0];
243
244         if((r = yaffs_write(h,xx,sizeof(unsigned))) != sizeof(unsigned)){
245                 goto WRITE_ERROR;
246         }
247         FSX();
248         while(sz32> 0){
249                 for(i = 0; i < XX_SIZE; i++){
250                   xx[i] = sz32 + i;
251                   checksum ^= xx[i];
252                 }
253                 
254                 FSX();
255                 if((r = yaffs_write(h,xx,sizeof(xx))) != sizeof(xx)){
256                         goto WRITE_ERROR;
257                 }
258                 sz32--;
259         }
260
261         xx[0] = checksum;
262         FSX();
263         if((r = yaffs_write(h,xx,sizeof(unsigned))) != sizeof(unsigned)){
264                 goto WRITE_ERROR;
265         }
266         
267         FSX();
268         yaffs_close(h);
269         return 0;
270
271 WRITE_ERROR:
272         printf("ywrite error at position %d\n",(int)yaffs_lseek(h,0,SEEK_END));
273         yaffs_close(h);
274         return -1;
275         
276 }
277
278 static int yVerifyFile(const char *fName)
279 {
280         unsigned checksum = 0;
281         unsigned totalSize;
282         unsigned sz32;
283         unsigned recordedSize = 0;
284         int r;
285         int h;
286         int i;
287         int retval = 0;
288
289
290         printf("Verifying file %s\n",fName);
291                 
292         h = yaffs_open(fName, O_RDONLY,S_IREAD | S_IWRITE);
293
294         if(h < 0){
295                 printf("could not open file %s\n",fName);
296                 return -1;
297         }
298
299         totalSize = yaffs_lseek(h,0,SEEK_END);
300         yaffs_lseek(h,0,SEEK_SET);
301
302         r = yaffs_read(h,&sz32,sizeof(sz32));
303
304         if(r != sizeof(sz32)){
305                 printf("reading size failed ... returned %d\n",r);
306                 yaffs_close(h);
307                 return -1;
308         }
309         
310         recordedSize = sz32 * sizeof(xx) + 8;
311
312         printf("verify %s: file size is %d, recorded size is %d\n", fName, totalSize, recordedSize);
313         if(totalSize != recordedSize){
314                 printf("!!!!!!!!!!!!!!!!!!!!!!!!file size is wrong, should be %d, is %d\n", recordedSize,totalSize);
315                 yaffs_close(h);
316                 return -1;
317         }
318
319         checksum ^= sz32;
320
321
322         while(sz32 > 0){
323                 r = yaffs_read(h,xx,sizeof(xx));
324                 if(r != sizeof(xx)){
325                         printf("!!!!!!!!!!!!!!!!!!!!!!!!!!reading data failed ... returned %d\n",r);
326                         yaffs_close(h);
327                         return -1;
328                 }
329                 for(i = 0; i < XX_SIZE; i++)
330                   checksum ^= xx[i];
331                 sz32--;
332         }
333         r = yaffs_read(h,xx,sizeof(xx[0]));
334         if(r != sizeof(xx[0])){
335                 printf("!!!!!!!!!!!!!!!!!!!!!!!!!!reading data failed ... returned %d\n",r);
336                 yaffs_close(h);
337                 return -1;
338         }
339         
340         checksum ^= xx[0];
341
342         if(checksum != 0){
343                 printf("!!!!!!!!!!!!!!!!!!!!! checksum failed\n");
344                 retval = -1;
345         } else
346                 printf("verified ok\n");
347         yaffs_close(h);
348
349         return retval;
350 }
351
352
353 static void DoUpdateMainFile(void)
354 {
355         int result;
356         int sz32;
357         sz32 = (myrand() % 1000)   + 20;
358         
359         result = yWriteFile(fullTempMainName,sz32);
360         FSX();
361         if(result)
362             FatalError(__LINE__);
363         yaffs_rename(fullTempMainName,fullMainName);
364         FSX();
365 }
366
367 static void DoVerifyMainFile(void)
368 {
369         int result;
370         result = yVerifyFile(fullMainName);
371         if(result)
372             FatalError(__LINE__);
373
374 }
375
376
377 void NorStressTestInitialise(const char *prefix)
378 {
379   MakeFullNames(prefix);
380   
381   UpdateCounter(fullPowerUpName,&powerUps,1);
382   UpdateCounter(fullStartName,&cycleStarts,1);
383   UpdateCounter(fullEndName,&cycleEnds,1);
384   UpdateCounter(fullPowerUpName,&powerUps,1);
385   DoUpdateMainFile();
386   DoVerifyMainFile();
387 }
388
389
390 void NorStressTestRun(const char *prefix, int n_cycles, int do_fsx)
391 {
392   interleave_fsx = do_fsx;
393   MakeFullNames(prefix);
394   FSX_INIT(prefix);
395     
396   dump_directory_tree(fullPathName);
397   
398   UpdateCounter(fullPowerUpName,&powerUps,0);
399   dump_directory_tree(fullPathName);
400   
401   while(n_cycles < 0 || n_cycles > 0){
402     if(n_cycles > 0)
403       n_cycles--;
404     UpdateCounter(fullStartName, &cycleStarts,0);
405     dump_directory_tree(fullPathName);
406     DoVerifyMainFile();
407     DoUpdateMainFile();
408     dump_directory_tree(fullPathName);
409   
410     UpdateCounter(fullEndName,&cycleEnds,0);
411     dump_directory_tree(fullPathName);
412   }
413   FSX_COMPLETE();
414 }