home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / PROGRAMS / UTILS / BENCHMAR / OPTDRV.ZIP / TESTS.C < prev    next >
Encoding:
C/C++ Source or Header  |  1989-05-12  |  13.0 KB  |  676 lines

  1. /*
  2.  * File system test suite.
  3.  *
  4.  * Simson L. Garfinkel
  5.  *
  6.  */
  7.  
  8. /* There are five basic tests:
  9.  *
  10.  * Test #1:      Image store.
  11.  *        This test examines the raw read/write performance of the
  12.  *              filesystem.
  13.  *               1 Write, 10 Reads of a 256K file (512x512), delete file
  14.  *              Repeat 100 times.
  15.  *
  16.  * Test #2:    Same as test #1, but with smaller files.
  17.  *
  18.  * Test #3:    Database application.  Write a 2MB file, and a 100K file.
  19.  *        Randomly read/write 600 byte entries in the first and 20 byte
  20.  *        entries in the second
  21.  *
  22.  * Test #4:    Directory write/read, testing directory caching.  Create
  23.  *        1000 subdirectories, and 10 files in each.  Try to open
  24.  *        and then close each one, directory-wise.
  25.  *
  26.  * Test #5:    Same as test #4, except do all of the file#1s in each
  27.  *        directory, all of the file#2s in each directory, ...
  28.  *
  29.  * Test #6:    Do all tests randomly, until they are all done.
  30.  */
  31.  
  32.  
  33. int    debug=0;
  34.  
  35. #define    KBYTE        1024
  36. #define KBUFSIZE    60
  37. #define    BUFSIZE        KBUFSIZE * KBYTE
  38.  
  39. char    buf[BUFSIZE];
  40.  
  41.  
  42. #define    MAXTESTS 6
  43.  
  44. #define    TEST1_WRITES        5
  45. #define    TEST1_FILESIZE        256L * KBYTE
  46. #define TEST1_READS_PER_WRITE    10
  47. #define    TEST1_FILENAME        "TEST1"
  48.  
  49. #define    TEST2_WRITES        20
  50. #define    TEST2_FILESIZE        30L * KBYTE
  51. #define TEST2_READS_PER_WRITE    10
  52. #define    TEST2_FILENAME        "TEST2"
  53.  
  54. #define    TEST3_REPEATS        500
  55. #define    TEST3_FILE1NAME        "TEST3.1"
  56. #define TEST3_FILE2NAME        "TEST3.2"
  57. #define    TEST3_FILE1SIZE        2048L * KBYTE
  58. #define TEST3_FILE2SIZE        256L  * KBYTE
  59.  
  60. int    test3_xfer[2]    =    {600,20};
  61. long    test3_lens[2]    =    {TEST3_FILE1SIZE,TEST3_FILE2SIZE};
  62.  
  63. #define    TEST4_DIRS        25
  64. #define    TEST4_DIRNAME        "T4-%d"
  65. #define    TEST4_FILENAME        "FILE%d"
  66. #define    TEST4_FILES        10
  67.  
  68. int    TEST5_DIRS        = 25;
  69. #define    TEST5_DIRNAME        "T5-%d"
  70. #define    TEST5_FILENAME        "FILE%d"
  71. #define    TEST5_FILES        10
  72.  
  73.  
  74. #include <sys/types.h>
  75. #include <sys/stat.h>
  76. #include <stdio.h>
  77. #include <stdlib.h>
  78. #include <fcntl.h>
  79. #include <io.h>
  80.  
  81.  
  82. #ifndef O_BINARY        /* if not on MSDOS */
  83. #define O_BINARY 0
  84. #endif
  85.  
  86. int    test1_action(), test2_action(), test3_action();
  87. int    test4_action(), test5_action(), test6_action();
  88.  
  89. int    (*action[MAXTESTS])()    = {test1_action, test2_action, 
  90.             test3_action, test4_action, test5_action,
  91.             test6_action };
  92.  
  93.  
  94.  
  95. /* Define our own random number generator, so it is the same across all
  96.  * systems.
  97.  */
  98.  
  99. unsigned long    rndnum    = 0;
  100.  
  101. long    rnd_()
  102. {
  103.     rndnum    = (rndnum + 1234567L) % 65536;
  104.     return(rndnum >> 5);
  105. }
  106.  
  107. long    rnd(x)
  108. int    x;
  109. {
  110.     return(rnd_() % x);
  111. }
  112.  
  113.  
  114. /* debuggable system calls */
  115. int    smkdir(dir)
  116. char    *dir;
  117. {
  118.     int    q;
  119.  
  120.     if(debug){
  121.         printf("mkdir(%s)\n",dir);
  122.         if(debug==1) return(0);
  123.     }
  124.     q = mkdir(dir,0666);    /* 0666 for unix systems */
  125.     if(q>=0) return(q);
  126.     perror(dir);
  127.     exit(1);
  128. }
  129.  
  130.  
  131. int    srmdir(dir)
  132. char    *dir;
  133. {
  134.     int    q;
  135.  
  136.     if(debug){
  137.         printf("rmdir(%s)\n",dir);
  138.         if(debug==1) return(0);
  139.     }
  140.     q = rmdir(dir);
  141.     if(q>=0) return(q);
  142.     perror(dir);
  143.     exit(1);
  144. }
  145.  
  146.  
  147. int    screat(file,mode)
  148. char    *file;
  149. int    mode;
  150. {
  151.     int    q;
  152.  
  153.     if(debug){
  154.         printf("creat(%s,%o)\n",file,mode);
  155.         if(debug==1) return(0);
  156.     }
  157.     q = creat(file,mode);
  158.     if(q>=0) return(q);
  159.     perror(file);
  160.     exit(1);
  161. }
  162.  
  163.  
  164. int    sopen(file,flags,mode)
  165. char    *file;
  166. int    flags,mode;
  167. {
  168.     static    sopenfd=0;
  169.     int    fd;
  170.     
  171.     if(debug){
  172.         printf("open(%s,%x,%o)\n",file,flags,mode);
  173.         if(debug==1) return(++sopenfd);
  174.     }
  175.     fd    = open(file,flags,mode);
  176.     if(fd>0) return(fd);
  177.     perror(file);
  178.     exit(1);
  179. }
  180.  
  181. long    slseek(fd,offset,whence)
  182. int    fd,whence;
  183. long    offset;
  184. {
  185.     long    q;
  186.     
  187.     if(debug){
  188.         printf("lseek(%d,%ld,%d)\n",fd,offset,whence);
  189.         if(debug==1) return(offset);
  190.     }
  191.     q    = lseek(fd,offset,whence);
  192.     if(q>=0) return(q);
  193.     printf("q=%ld\n",q);
  194.     perror("lseek");
  195.     exit(1);
  196. }
  197.  
  198. int    swrite(fd,buf,len)
  199. int    fd;
  200. char    *buf;
  201. unsigned len;
  202. {
  203.     if(debug){
  204.         printf("write(%d,buf,%u)\n",fd,len);
  205.         if(debug==1) return;
  206.     }
  207.     if(write(fd,buf,len)!=len){
  208.         perror("write");
  209.         exit(1);
  210.     }
  211. }
  212.     
  213.  
  214. int    sread(fd,buf,len)
  215. int    fd;
  216. char    *buf;
  217. unsigned len;
  218. {
  219.     int q;
  220.     if(debug){
  221.         printf("read(%d,buf,%u)\n",fd,len);
  222.         if(debug==1) return;
  223.     }
  224.     if((q=read(fd,buf,len))!=len){
  225.         printf("q=%d len=%d\n",q,len);
  226.         perror("read");
  227.         exit(1);
  228.     }
  229. }
  230.     
  231. int    sclose(fd)
  232. int    fd;
  233. {
  234.     if(debug){
  235.         printf("close(%d)\n",fd);
  236.         if(debug==1) return;
  237.     }
  238.     if(close(fd)<0){
  239.         perror("close");
  240.         exit(1);
  241.     }
  242. }
  243.  
  244.  
  245. int    sunlink(filename)
  246. char    *filename;
  247. {
  248.     if(debug){
  249.         printf("cunlink(%s)\n",filename);
  250.         if(debug==1) return;
  251.     }
  252.     if(unlink(filename)<0){
  253.         perror(filename);
  254.         exit(1);
  255.     }
  256. }
  257.  
  258.  
  259. /* This is the action procedure for the first test.  It performs the next
  260.  * part of the test, increments the state variables, and returns.  If all
  261.  * of the tests have been finished, it returns 0, otherwise it returns 1.
  262.  *
  263.  * Action performed depends on the variable state, which can be:
  264.  *    0 - open file for writing, truncating, &c.
  265.  *    1 - write data till filled.
  266.  *    2    - close file for writing.
  267.  *    3 - open file for reading.
  268.  *    4 - read data till finished.
  269.  *    5 - close file, repeat to state 3 until number of reads is done.     
  270.  */     
  271.  
  272. int    test1_action()
  273. {
  274.     static    long repeat    = 0;    /* times test has been repeated */
  275.     static    long bytesleft    = 0;    /* bytes to transfer */
  276.     static    state        = 0;    /* next action to do */
  277.     static    readrepeat;
  278.     static    fd;
  279.  
  280.     unsigned    xfer;
  281.     
  282.     if(repeat >= TEST1_WRITES)    return(0);
  283.     
  284.     switch(state){
  285.         case 0:    fd = sopen(TEST1_FILENAME,
  286.                 O_WRONLY | O_CREAT | O_BINARY | O_TRUNC,0666);
  287.             state++;
  288.             bytesleft    = TEST1_FILESIZE;
  289.             readrepeat    = TEST1_READS_PER_WRITE;
  290.             return(1);
  291.         
  292.         case 1:    xfer    = min(BUFSIZE,bytesleft);
  293.             swrite(fd,buf,xfer);
  294.             bytesleft -=    xfer;
  295.             if(bytesleft==0){
  296.                 state++;
  297.             }
  298.             return(1);
  299.             
  300.         case 2:    sclose(fd);
  301.             state++;
  302.             return(1);
  303.             
  304.         case 3:    fd = sopen(TEST1_FILENAME, O_RDONLY | O_BINARY ,0666);
  305.             state++;
  306.             bytesleft    = TEST1_FILESIZE;
  307.             return(1);
  308.  
  309.         case 4:    xfer    = min(BUFSIZE,bytesleft);
  310.             sread(fd,buf,xfer);
  311.             bytesleft -=    xfer;
  312.             if(bytesleft==0){
  313.                 state = 5;
  314.             }
  315.             return(1);
  316.             
  317.         case 5: sclose(fd);
  318.             if(--readrepeat > 0){
  319.                 state = 3;
  320.                 return(1);
  321.             }
  322.             sunlink(TEST1_FILENAME);
  323.             repeat    ++;
  324.             state    = 0;
  325.             return(1);
  326.  
  327.         default:
  328.             fprintf(stderr,"test1 - unknown state %d\n",state);
  329.             return(-1);
  330.     }
  331. }
  332.  
  333.  
  334. /* This is the second test.  It is identical to the first test, except
  335.  * that it uses TEST2 variables, which are different values.
  336.  *
  337.  * This could be rewritten so that test1 & test2 called a common driver,
  338.  * but I think that would introduce more complexity than is warranted     
  339.  */     
  340.  
  341.  
  342.  
  343. int    test2_action()
  344. {
  345.     static    long repeat    = 0;    /* times test has been repeated */
  346.     static    long bytesleft    = 0;    /* bytes to transfer */
  347.     static    state        = 0;    /* next action to do */
  348.     static    readrepeat;
  349.     static    fd;
  350.  
  351.     unsigned    xfer;
  352.     
  353.     if(repeat >= TEST2_WRITES)    return(0);
  354.     
  355.     switch(state){
  356.         case 0:    fd = sopen(TEST2_FILENAME,
  357.                 O_WRONLY | O_CREAT | O_BINARY | O_TRUNC,0666);
  358.             state++;
  359.             bytesleft    = TEST2_FILESIZE;
  360.             readrepeat    = TEST2_READS_PER_WRITE;
  361.             return(1);
  362.         
  363.         case 1:    xfer    = min(BUFSIZE,bytesleft);
  364.             swrite(fd,buf,xfer);
  365.             bytesleft -=    xfer;
  366.             if(bytesleft==0){
  367.                 state++;
  368.             }
  369.             return(1);
  370.             
  371.         case 2:    sclose(fd);
  372.             state++;
  373.             return(1);
  374.             
  375.         case 3:    fd = sopen(TEST2_FILENAME, O_RDONLY | O_BINARY ,0666);
  376.             state++;
  377.             bytesleft    = TEST2_FILESIZE;
  378.             return(1);
  379.  
  380.         case 4:    xfer    = min(BUFSIZE,bytesleft);
  381.             sread(fd,buf,xfer);
  382.             bytesleft -=    xfer;
  383.             if(bytesleft==0){
  384.                 state = 5;
  385.             }
  386.             return(1);
  387.             
  388.         case 5: sclose(fd);
  389.             if(--readrepeat > 0){
  390.                 state = 3;
  391.                 return(1);
  392.             }
  393.             sunlink(TEST2_FILENAME);
  394.             repeat    ++;
  395.             state    = 0;
  396.             return(1);
  397.  
  398.         default:
  399.             fprintf(stderr,"test2 - unknown state %d\n",state);
  400.             return(-1);
  401.     }
  402. }
  403.  
  404.  
  405. /* This is the action procedure for the third test.  It performs the next
  406.  * part of the test, increments the state variables, and returns.  If all
  407.  * of the tests have been finished, it returns 0, otherwise it returns 1.
  408.  *
  409.  * Action performed depends on the variable state, which can be:
  410.  *    0 - Create initial files.
  411.  *    1 - Randomly choose file and action and perform it.
  412.  */     
  413.  
  414. int    test3_action()
  415. {
  416.     static    long repeat    = 0;    /* times test has been repeated */
  417.     static    state        = 0;    /* next action to do */
  418.     static    fd[2];
  419.  
  420.     repeat++;
  421.     if(repeat > TEST3_REPEATS)    return(0);
  422.     if(repeat == TEST3_REPEATS){
  423.         sclose(fd[0]);
  424.         sclose(fd[1]);
  425.         sunlink(TEST3_FILE1NAME);
  426.         sunlink(TEST3_FILE2NAME);
  427.         return(1);
  428.     }
  429.     if(state==0){        /* setup */
  430.         long bytesleft        = 0;    /* bytes to transfer */
  431.         unsigned xfer;
  432.     
  433.         /* create the first file */
  434.         fd[0] = sopen(TEST3_FILE1NAME,
  435.             O_RDWR | O_CREAT | O_BINARY | O_TRUNC,0666);
  436.         for(bytesleft = TEST3_FILE1SIZE; bytesleft>0;){
  437.             xfer    = min(BUFSIZE,bytesleft);
  438.             swrite(fd[0],buf,xfer);
  439.             bytesleft -=    xfer;
  440.         }
  441.  
  442.         fd[1] = sopen(TEST3_FILE2NAME,
  443.             O_RDWR | O_CREAT | O_BINARY | O_TRUNC,0666);
  444.         for(bytesleft = TEST3_FILE2SIZE; bytesleft>0;){
  445.             xfer    = min(BUFSIZE,bytesleft);
  446.             swrite(fd[1],buf,xfer);
  447.             bytesleft -=    xfer;
  448.         }
  449.         state++;
  450.     }
  451.     else{
  452.         int    file    = rnd(2);
  453.         int    action    = rnd(2);
  454.         long    pos;
  455.         
  456.         /* Choose a random record, then the record's offset */
  457.  
  458.         pos     = rnd(test3_lens[file] / test3_xfer[file]);
  459.         pos    *= test3_xfer[file];
  460.         
  461.         
  462.         slseek(fd[file],pos,0);
  463.         if(action==0){
  464.             swrite(fd[file],buf,test3_xfer[file]);
  465.         }
  466.         else{
  467.             sread(fd[file],buf,test3_xfer[file]);
  468.         }
  469.     }
  470.     return(1);
  471. }
  472.  
  473.  
  474. /* test4:
  475.  * Make 1000 dirs, and create 10 files in each.  (Using creat(2)).
  476.  * Open and close each one, directory-wise.
  477.  *
  478.  * State 0 - create directories and files
  479.  * State 1 - open/close file
  480.  * state 2 - delete files and directories
  481.  */
  482.  
  483. char    *test4_dirname(dir)
  484. int    dir;
  485. {
  486.     static    char buf[100];
  487.     
  488.     sprintf(buf,TEST4_DIRNAME, dir);
  489.     return(buf);
  490. }
  491.  
  492. char    *test4_filename(dir,file)
  493. int    dir,file;
  494. {
  495.     static    char buf[100];
  496.     
  497.     sprintf(buf,TEST4_DIRNAME "/" TEST4_FILENAME,dir,file);
  498.     return(buf);
  499. }
  500.  
  501. test4_action()
  502. {
  503.     static        state = 0;    /* major state variable */
  504.     static    long    fstate = 0;    /* dir/file counter */
  505.     int    dir,file;
  506.  
  507.     dir    = fstate / TEST4_FILES;
  508.     file    = fstate % TEST4_FILES;
  509.  
  510.     switch(state){
  511.         case 0:
  512.             if(file==0){
  513.                 smkdir(test4_dirname(dir));
  514.             }
  515.             else{
  516.                 sclose(screat(test4_filename(dir,file),
  517.                     S_IREAD | S_IWRITE));
  518.             }
  519.             break;
  520.             
  521.         case 1:
  522.             if(file>0){
  523.                 sclose(sopen(test4_filename(dir,file),
  524.                     O_RDONLY | O_BINARY,0666));
  525.             }
  526.             break;
  527.             
  528.         case 2:
  529.             if(++file==TEST4_FILES){
  530.                 srmdir(test4_dirname(dir));
  531.             }
  532.             else{
  533.                 sunlink(test4_filename(dir,file));
  534.             }
  535.             break;
  536.         case 3:    return(0);
  537.     }
  538.     if(++fstate >= TEST4_DIRS * TEST4_FILES){
  539.         fstate = 0;
  540.         state++;
  541.     }
  542.     return(1);
  543. }
  544.     
  545.  
  546.  
  547.  
  548. char    *test5_dirname(dir)
  549. int    dir;
  550. {
  551.     static    char buf[100];
  552.     
  553.     sprintf(buf,TEST5_DIRNAME, dir);
  554.     return(buf);
  555. }
  556.  
  557. char    *test5_filename(dir,file)
  558. int    dir,file;
  559. {
  560.     static    char buf[100];
  561.     
  562.     sprintf(buf,TEST5_DIRNAME "/" TEST5_FILENAME,dir,file);
  563.     return(buf);
  564. }
  565.  
  566. test5_action()
  567. {
  568.     static        state = 0;    /* major state variable */
  569.     static    long    fstate = 0;    /* dir/file counter */
  570.     int    dir,file;
  571.  
  572.     file    = fstate / TEST5_DIRS;
  573.     dir    = fstate % TEST5_DIRS;
  574.  
  575.     switch(state){
  576.         case 0:
  577.             if(file==0){
  578.                 smkdir(test5_dirname(dir));
  579.             }
  580.             else{
  581.                 sclose(screat(test5_filename(dir,file),
  582.                     S_IREAD | S_IWRITE));
  583.             }
  584.             break;
  585.             
  586.         case 1:
  587.             if(file>0){
  588.                 sclose(sopen(test5_filename(dir,file),
  589.                     O_RDONLY | O_BINARY,0666));
  590.             }
  591.             break;
  592.             
  593.         case 2:
  594.             if(++file==TEST5_FILES){
  595.                 srmdir(test5_dirname(dir));
  596.             }
  597.             else{
  598.                 sunlink(test5_filename(dir,file));
  599.             }
  600.             break;
  601.         case 3:    return(0);
  602.     }
  603.     if(++fstate >= TEST5_DIRS * TEST5_FILES){
  604.         fstate = 0;
  605.         state++;
  606.     }
  607.     return(1);
  608. }
  609.     
  610.  
  611. test6_action()
  612. {
  613.     int    test    = rnd(MAXTESTS-1);
  614.     int    test0;
  615.     
  616.     test0 = test;    /* remember which test we started at */
  617.  
  618.     do{
  619.         if((*action[test])()) return(1);/* if we did something, ret */
  620.         test = (test+1) % (MAXTESTS-1);    /* choose next test */
  621.         if(test==test0)      return(0);    /* if we wrapped, none left */
  622.     } while(1);
  623. }
  624.  
  625. main(argc,argv)
  626. char **argv;
  627. {
  628.     long    starttime,stoptime;
  629.     long    testclick = 0;
  630.     int    test;
  631.     unsigned i;
  632.     
  633.     for(i=0;i<BUFSIZE;i++){
  634.         buf[i] = i;
  635.     }
  636.  
  637.     while(argv[1][0]=='-'){
  638.         if(!strcmp(argv[1],"-d")){
  639.             debug++;
  640.             argv++;
  641.             argc--;
  642.         }
  643.     }
  644.  
  645.     if(argc<2){
  646.         fprintf(stderr,"usage: %s [-d] <test> where tests are:\n",
  647.             argv[0]);
  648.         fprintf(stderr,"\t1 - Image store test.\n");
  649.         exit(1);
  650.     }
  651.  
  652.     test = atoi(argv[1]);
  653.     if(argc>2){
  654.         TEST5_DIRS = atoi(argv[2]);
  655.     }
  656.     if(test<1 || test>MAXTESTS){
  657.         fprintf(stderr,"%d is out of range\n",test);
  658.         exit(1);
  659.     }
  660.     
  661.     time(&starttime);
  662.     
  663.     while((*action[test-1])()){
  664.         if((++testclick % 20)==0){
  665.             printf("%ld...",testclick);
  666.         }
  667.     }
  668.  
  669.     time(&stoptime);
  670.     
  671.     printf("\n\nTest %d total time = %ld\n",test,stoptime-starttime);
  672.     if(test==5) printf("TEST5_DIRS = %d\n",TEST5_DIRS);
  673.     puts("");
  674.     exit(0);
  675. }
  676.