/* * EBS - RTFS (Real Time File Manager) * * Copyright EBS Inc. 1987-2012 * All rights reserved. * This code may not be redistributed in source or linkable object form * without the consent of its author. */ #include "rtfslite.h" #include "rtfslitetests.h" #include "stdlib.h" /* Callback instructions */ #define ROOT_SCAN_TEST_PRINT_FILE_NAMES 1 #define ROOT_SCAN_TEST_BOOTFILETEST 2 #define BOOTFILENAME "BOOTFILEBIN" #define RENAMEDFILENAME "RENAMEDFILE" extern int writing; static unsigned char *path[4] = {(unsigned char*)"RTFSL ",0,0,0}; /* Failsafe test scenarios // Create a directory in the journal but not on the medium rtfs reports no directory exists #define DOFAILSAFEOPENTEST 1 #define DOFAILSAFERESTORETEST 0 #define DOMKDIRTEST 1 #define DORMDIRTEST 0 #define DOFAILSAFEFLUSHTEST 0 // Restore from the journal. Rtfs reports the directory exists #define DOFAILSAFEOPENTEST 1 #define DOFAILSAFERESTORETEST 1 #define DOMKDIRTEST 0 #define DORMDIRTEST 0 #define DOFAILSAFEFLUSHTEST 0 // Remove the director and flush the journal. Rtfs still reports the directory exists #define DOFAILSAFEOPENTEST 1 #define DOFAILSAFERESTORETEST 1 #define DOMKDIRTEST 0 #define DORMDIRTEST 0 #define DOFAILSAFEFLUSHTEST 1 // Restore from the journal. Rtfs reports the directory does not #define DOFAILSAFEOPENTEST 1 #define DOFAILSAFERESTORETEST 1 #define DOMKDIRTEST 0 #define DORMDIRTEST 0 #define DOFAILSAFEFLUSHTEST 0 // Write to the journal file and perform the file read and write tests. There is no record of the fiole in RTFS #define DOFAILSAFEOPENTEST 1 #define DOFAILSAFERESTORETEST 0 #define DOMKDIRTEST 0 #define DORMDIRTEST 0 #define DOFILEWRITETEST 1 #define DOBOOTFILEEST 1 #define DOFILIOREADAPITEST 1 #define DOFAILSAFEFLUSHTEST 1 // Restore from the journal file RTFS sees the file #define DOFAILSAFEOPENTEST 1 #define DOFAILSAFERESTORETEST 1 // Delete the to the journal file. The file is still seen in Rtfs #define DOFAILSAFEOPENTEST 1 #define DOFAILSAFERESTORETEST 0 #define DOMKDIRTEST 0 #define DORMDIRTEST 0 #define DOFILEWRITETEST 0 #define DOFILEDELETETEST 1 #define DOBOOTFILEEST 0 #define DOFILIOREADAPITEST 0 #define DOFAILSAFEFLUSHTEST 1 // Restore from the journal file RTFS no longer sees the file #define DOFAILSAFEOPENTEST 1 #define DOFAILSAFERESTORETEST 1 */ /* Compile tiome options for test selection */ #define DOFATSCANTEST 0 #define DOROOTSCANTEST 1 #define DOROOTGFIRSTSCANTEST 1 #define DOFAILSAFEFLUSHTEST 0 #define DOFAILSAFEOPENTEST 1 #define DOFAILSAFESYNCTEST 1 #define DOFAILSAFERESTORETEST 1 #define DOMKDIRTEST 1 #define DORMDIRTEST 0 #define DIRECTORY_FRAGMENT_LENGTH 1 /* One for every other cluster fragmentation but may be larger */ #define DIRECTORY_GAP_FRAGMENT_LENGTH 0 /* Zero for no fragments, or the gap between file fragments */ #define WRITETESTNLONGS 10240 #define DOFILEWRITETEST 1 #define DOSEQUENTIALREADTEST 1 #define DOFILERANDOMWRITETEST 0 #define FILE_FRAGMENT_LENGTH 1 /* One for every other cluster fragmentation but may be larger */ #define FILE_GAP_FRAGMENT_LENGTH 0 /* Zero for no fragments, or the gap between file fragments */ #define DOAPPENDTEST 1 /* If 1 the sequential write test closes and seeks to the end every 1000th write */ #define DORENAMETEST 1 #define DOFILEDELETETEST 0 #if (DORMDIRTEST&&DOFILEDELETETEST) #error Tests are mutually exclusive #endif #define DOBOOTFILEEST 0 #define DOFILIOREADAPITEST 0 #define DOFILERANDOMREADTEST 0 #define DOSETPATHTEST 1 #define DOMULTICHAINSUBDIRECTORYTEST 0 /* Requires DOSETPATH */ #if (RTFSL_INCLUDE_LOAD_ONLY) #undef DOFATSCANTEST #undef DOROOTSCANTEST #undef DOROOTGFIRSTSCANTEST #undef DOFAILSAFEFLUSHTEST #undef DOFAILSAFEOPENTEST #undef DOFAILSAFESYNCTEST #undef DOFAILSAFERESTORETEST #define DOFATSCANTEST 0 #define DOROOTSCANTEST 0 #define DOROOTGFIRSTSCANTEST 0 #define DOFAILSAFEFLUSHTEST 0 #define DOFAILSAFEOPENTEST 0 #define DOFAILSAFESYNCTEST 0 #define DOFAILSAFERESTORETEST 0 #undef DOMKDIRTEST #undef DORMDIRTEST #define DOMKDIRTEST 0 #define DORMDIRTEST 0 #undef DOFILEWRITETEST #undef DOFILERANDOMWRITETEST #undef DOAPPENDTEST #undef DORENAMETEST #undef DOFILEDELETETEST #undef DOSEQUENTIALREADTEST #define DOSEQUENTIALREADTEST 0 #define DOFILEWRITETEST 0 #define DOFILERANDOMWRITETEST 0 #define DOAPPENDTEST 0 #define DORENAMETEST 0 #define DOFILEDELETETEST 0 #undef DOBOOTFILEEST #undef DOFILIOREADAPITEST #undef DOFILERANDOMREADTEST #define DOBOOTFILEEST 1 #define DOFILIOREADAPITEST 0 #define DOFILERANDOMREADTEST 0 #undef DOSETPATHTEST #define DOSETPATHTEST 0 #undef DOMULTICHAINSUBDIRECTORYTEST #define DOMULTICHAINSUBDIRECTORYTEST 0 #endif //HEREHERE //.. Test putting next index and bytes free into failsafe buffer so it re-loads //.. Create failsafe load and failsafe sync functions //.. Failsafe representation of info sector update //.. Put checksum of all journalled entities into failsafe file for catching changes outside. //.. Update of multiple fat copies //.. Update of FAT32 info sector fields. //.. done test directory extend //.. test directory extend with fragments //.. done test file append (seek to end and write) //.. unsigned char test_buffer[RTFSL_CFG_MAXBLOCKSIZE]; #if (DOFAILSAFETEST&&RTFSL_INCLUDE_FAILSAFE_SUPPORT) int rtfslfs_test(void); #endif int rootscan_test_callback(struct rtfsl_file const *pcurrent_entry_file, void *puser_data) { if (puser_data==(void *)ROOT_SCAN_TEST_PRINT_FILE_NAMES) { if (pcurrent_entry_file->rtfsl_direntry_type==RTFSL_ENTRY_TYPE_FILE) { PRINTF("Found file %8.8s.%3.3s\n",pcurrent_entry_file->dos_inode.fname,pcurrent_entry_file->dos_inode.fext); return 2; } else if (pcurrent_entry_file->rtfsl_direntry_type==RTFSL_ENTRY_TYPE_EOF) return 1; else if (pcurrent_entry_file->rtfsl_direntry_type==RTFSL_ENTRY_TYPE_LFN) ; else if (pcurrent_entry_file->rtfsl_direntry_type==RTFSL_ENTRY_TYPE_VOLUME) ; else if (pcurrent_entry_file->rtfsl_direntry_type==RTFSL_ENTRY_TYPE_DIRECTORY) { PRINTF("Found dir %8.8s.%3.3s\n",pcurrent_entry_file->dos_inode.fname,pcurrent_entry_file->dos_inode.fext); return 2; } } return 0; /* Continue */ } void test_rtfsl_lite(void) { unsigned long fragrecord[32]; struct rtfsl_statstructure statstruct; int rval; struct rtfsl_file root_file; rtfsl_diskopen(); #if (DOFAILSAFEOPENTEST&&RTFSL_INCLUDE_FAILSAFE_SUPPORT) rtfsl.rtfsl_current_failsafe_context=&rtfsl.rtfsl_failsafe_context; ANSImemset(rtfsl.rtfsl_current_failsafe_context,0,sizeof(*rtfsl.rtfsl_current_failsafe_context)); rtfsl.rtfsl_current_failsafe_context->journal_buffer=rtfsl.rtfslfs_sector_buffer; rtfsl.rtfsl_current_failsafe_context->journal_buffer_size=RTFSL_CFG_FSBUFFERSIZEBYTES; rtfslfs_start(); #endif #if (DOFAILSAFERESTORETEST&&RTFSL_INCLUDE_FAILSAFE_SUPPORT) rtfslfs_restore(); rtfsl_setpath(0); rtfsl_mkdir((unsigned char*)"AFTERRESTORE"); return; #endif #if (DOFATSCANTEST) { unsigned long maxfindex; unsigned long cluster, next_cluster; long rval; #ifdef RTFSL_MAJOR_VERSION maxfindex=pdr->drive_info.maxfindex; #else maxfindex=pdr->maxfindex; #endif for (cluster=2;cluster< maxfindex;cluster++) { next_cluster=cluster+1; rval=fatop_buff_get_frag(&tdrive, cluster|RTFSL_WRITE_CLUSTER, &next_cluster, 1); next_cluster=0; rval=fatop_buff_get_frag(&tdrive, cluster, &next_cluster, 1); if (next_cluster != cluster+1) { PRINTF("error: Cluster %ld: should be %X but returned %X\n", cluster, cluster+1,next_cluster); } } { unsigned long cluster_segment_array[32][2]; unsigned long chain_length_clusters,start_next_segment; int i,num_segments; num_segments = rtfsl_load_cluster_chain(&tdrive, 2, &chain_length_clusters, &start_next_segment, cluster_segment_array, 32); PRINTF(" = %d\n", num_segments); for (i = 0; i < num_segments; i++) { PRINTF("%d: (%ld) - (%ld) \n", i, cluster_segment_array[i][0],cluster_segment_array[i][1]); } } } #endif #if (RTFSL_INCLUDE_WRITE_SUPPORT&&RTFSL_INCLUDE_SUBDIRECTORIES&&DOSETPATHTEST) { if (rtfsl_mkdir(path[0])<0) { PRINTF("First mkdir failed-assuming path exists\n"); } path[1]=0; /* Set default path one layer deep */ rtfsl_setpath(path); /* Set up a scenario so the directory entries we create are fragmented - make 4 fragments but test only uses 2 */ #if (DIRECTORY_GAP_FRAGMENT_LENGTH&&DOMKDIRTEST) ut_create_fragments(DIRECTORY_FRAGMENT_LENGTH, DIRECTORY_GAP_FRAGMENT_LENGTH, 4, fragrecord/*[numfrags]*/); #endif if (rtfsl_mkdir(path[0])<0) { PRINTF("Second mkdir failed-assuming path exists\n"); } path[1]=path[0]; /* Path should be two deep now */ } #endif #if (RTFSL_INCLUDE_WRITE_SUPPORT&&DOMKDIRTEST&&RTFSL_INCLUDE_SUBDIRECTORIES&&DOSETPATHTEST&&DOMULTICHAINSUBDIRECTORYTEST) ut_fill_directory(0); #endif #if (RTFSL_INCLUDE_WRITE_SUPPORT&&RTFSL_INCLUDE_SUBDIRECTORIES&&DOMKDIRTEST) if (rtfsl_mkdir((unsigned char*)"MKDIR MDX")<0) { PRINTF("mkdir test failed\n"); return; } #endif #if (RTFSL_INCLUDE_WRITE_SUPPORT&&DOMKDIRTEST&&DIRECTORY_GAP_FRAGMENT_LENGTH&&RTFSL_INCLUDE_SUBDIRECTORIES&&DOSETPATHTEST&&DOMULTICHAINSUBDIRECTORYTEST) /* Release the clusters we allocate so the directory entries we create were fragmented */ ut_release_fragments(DIRECTORY_FRAGMENT_LENGTH, DIRECTORY_GAP_FRAGMENT_LENGTH, 4, fragrecord/*[numfrags]*/); #endif #if (DOROOTSCANTEST) { struct rtfsl_file current_entry_file; if (rtfsl_root_finode_open(&root_file) == 0) { int r; do { PRINTF("Calling enum dir \n"); r=rtfsl_enumerate_directory(&root_file,¤t_entry_file,rootscan_test_callback,(void *) ROOT_SCAN_TEST_PRINT_FILE_NAMES); } while (r==2); } } #endif #if (DOROOTGFIRSTSCANTEST) if (rtfsl_root_finode_open(&root_file) == 0) { struct rtfsl_dstat dstat; if (rtfsl_gfirst(&dstat, 0)==1) { do { if ((dstat.fattribute&(AVOLUME|ADIRENT))==0) { PRINTF("Got file : %s size: %ld \n",dstat.fnameandext,dstat.fsize); } else { PRINTF("Got entry: %s \n",dstat.fnameandext); } } while (rtfsl_gnext(&dstat)==1); } } #endif #if (RTFSL_INCLUDE_WRITE_SUPPORT&&DOFILEWRITETEST) rval=rtfsltest_file_sequential_write((unsigned char *)BOOTFILENAME, FILE_FRAGMENT_LENGTH, FILE_GAP_FRAGMENT_LENGTH, WRITETESTNLONGS, DOAPPENDTEST); if (rval<0) return; #endif #if (DOSEQUENTIALREADTEST) rval=rtfsltest_file_sequential_read((unsigned char *)BOOTFILENAME); if (rval<0) return; #endif #if (RTFSL_INCLUDE_WRITE_SUPPORT&&DOFILEWRITETEST&&DOFILERANDOMWRITETEST) rval=rtfsltest_file_random_write((unsigned char *)BOOTFILENAME); if (rval<0) return; #endif PRINTF("File sequential write-seek-write-seek-read test completed\n"); #if (RTFSL_INCLUDE_WRITE_SUPPORT&&DOFILEWRITETEST&&DORENAMETEST) if (rtfsl_rename((unsigned char *)BOOTFILENAME, (unsigned char *)BOOTFILENAME)!=RTFSL_ERROR_EXIST) { PRINTF("Rename should have failed but did not\n"); } rtfsl_rename((unsigned char *)BOOTFILENAME, (unsigned char *)RENAMEDFILENAME); #endif #if (DOBOOTFILEEST) { int fd; void * load_address = malloc(1000000); rtfsl_load_file((unsigned char *)BOOTFILENAME, (unsigned long) load_address); #if (DOFILIOREADAPITEST) fd=rtfsl_open((unsigned char*)BOOTFILENAME); if (fd>=0) { int nread; unsigned long total=0; unsigned char *loadimage=(unsigned char *)load_address; rtfsl_fstat(fd,&statstruct); do { nread=rtfsl_read(fd,test_buffer,rtfsl.current_dr.bytespsector); if (nread>0) { total+=nread; if (ANSImemcmp(test_buffer, loadimage, nread)!=0) { PRINTF("Compare failed\n"); } loadimage += nread; } } while (nread > 0); if (statstruct.st_size!=total) { PRINTF("filesize == %d total read == %ld\n",statstruct.st_size,total); } #if (DOFILERANDOMREADTEST) { unsigned long seekoffset,seekpointer; for (seekoffset=1;seekoffset<7;seekoffset++) { for (seekpointer=0; seekpointer