test/misc.c

00001 #include <string.h>
00002 #include <stdlib.h>
00003 #include <stdio.h>
00004 #include <sys/stat.h>
00005 #include <sys/time.h>
00006 #include <sys/types.h>
00007 #include <fcntl.h>
00008 #include <signal.h>
00009 #include <u/libu.h>
00010 
00011 int test_suite_misc_register (u_test_t *t);
00012 
00013 static int test_u_path_snprintf (u_test_case_t *tc);
00014 static int test_u_strtok (u_test_case_t *tc);
00015 static int test_u_atoi (u_test_case_t *tc);
00016 
00017 #ifdef HAVE_SETITIMER
00018 static int test_u_rdwr (u_test_case_t *tc);
00019 
00020 struct itimerval itv;
00021 size_t file_size, buf_size;
00022 
00023 static void setitv(struct itimerval *pitv)
00024 {
00025     memset(pitv, 0, sizeof(struct itimerval));
00026 
00027     pitv->it_value.tv_sec = 0;
00028     pitv->it_value.tv_usec = 1; /* use maximum granularity */
00029 }
00030 
00031 static void onsigalrm(int s)
00032 {
00033     u_unused_args(s);
00034     setitv(&itv);
00035     con_if(setitimer(ITIMER_REAL, &itv, NULL) < 0);
00036 }
00037 
00038 static int cat_file(const char *fn, unsigned int *phash)
00039 {
00040     ssize_t tot = 0, c = 0;
00041     unsigned int hash = 0;
00042     int fd, i;
00043     struct stat st;
00044     char *buf = NULL;
00045 
00046     con_err_sif(stat(fn, &st) < 0);
00047 
00048     buf = u_malloc(buf_size);
00049     con_err_if(buf == NULL);
00050 
00051     memset(buf, 0, buf_size);
00052 
00053     fd = open(fn, O_NONBLOCK | O_RDONLY);
00054     con_err_if(fd < 0);
00055 
00056     for(tot = 0; ; tot += c)
00057     {
00058         c = u_read(fd, buf, buf_size);
00059 
00060         con_err_sif(c < 0);
00061 
00062         for(i = 0; i < c; ++i)
00063             hash += buf[i]; /* idiot hash */
00064 
00065         dbg_ifb(c == 0)
00066             break; /* eof */
00067     }
00068 
00069     close(fd);
00070 
00071     *phash = hash;
00072 
00073     con_err_ifm(st.st_size != tot, "file size differs (%d != %d)", 
00074             st.st_size, tot);
00075 
00076     u_free(buf);
00077 
00078     return 0;
00079 err:
00080     if(buf)
00081         u_free(buf);
00082     return 1;
00083 }
00084 
00085 static int gen_file(const char *fn, unsigned int *phash)
00086 {
00087     int fd = -1;
00088     char *buf = NULL;
00089     unsigned int hash = 0;
00090     size_t i, c, size = file_size;
00091 
00092     buf = u_malloc(buf_size);
00093     con_err_if(buf == NULL);
00094 
00095     memset(buf, 0, buf_size);
00096 
00097     fd = open(fn, O_CREAT | O_WRONLY | O_NONBLOCK, 0600);
00098     con_err_sif(fd < 0);
00099 
00100     while(size)
00101     {
00102         c = (size < buf_size ? size : buf_size);
00103 
00104         for(i = 0; i < c; ++i)
00105             buf[i] = (char) i; /* just fill buf somehow */
00106 
00107         con_err_if(u_write(fd, buf, c) < 0);
00108 
00109         for(i = 0; i < c; ++i)
00110             hash += buf[i]; /* idiot hash */
00111 
00112         size -= c;
00113     }
00114 
00115     close(fd);
00116     u_free(buf);
00117 
00118     *phash = hash;
00119 
00120     return 0;
00121 err:
00122     if(fd >= 0)
00123         close(fd);
00124     if(buf)
00125         u_free(buf);
00126     return ~0;
00127 }
00128 
00129 static int tmp_u_rdwr(int rd, const char *fn, unsigned int *phash)
00130 {
00131     int read_rc, write_rc;
00132 
00133     /* set a fast timer to generate EINTRs */
00134     signal(SIGALRM, onsigalrm);
00135     setitv(&itv);
00136     con_err_if(setitimer(ITIMER_REAL, &itv, NULL) < 0);
00137 
00138     if(rd)
00139         read_rc = cat_file(fn, phash);
00140     else
00141         write_rc = gen_file(fn, phash);
00142 
00143     /* disable timers */
00144     signal(SIGALRM, SIG_IGN);
00145     memset(&itv, 0, sizeof(itv));
00146     setitimer(ITIMER_REAL, &itv, &itv);
00147     signal(SIGALRM, SIG_DFL);
00148 
00149     if(rd)
00150         con_err_if(read_rc);
00151     else
00152         con_err_if(write_rc);
00153  
00154     return 0;
00155 err:
00156     return ~0;
00157 }
00158 
00159 static int test_u_rdwr (u_test_case_t *tc)
00160 {
00161     char fn[U_FILENAME_MAX + 1] = { 0 };
00162     unsigned int hash_read, hash_write;
00163     int i;
00164 
00165     buf_size = 1;
00166     file_size = 1013;
00167 
00168     /* try with diferent buffer size and file size */
00169     for(i = 0; i < 10; ++i)
00170     {
00171         /* add 1 to avoid multiples of 2 */
00172         buf_size = (buf_size << 1) + 1;
00173         file_size = (file_size << 1) + 1;
00174 
00175         u_test_err_if(tmpnam(fn) == NULL);
00176 
00177         u_test_err_if(tmp_u_rdwr(0 /* write */, fn, &hash_write));
00178 
00179         u_test_err_if(tmp_u_rdwr(1 /* read */, fn, &hash_read));
00180 
00181         u_test_err_if(hash_read != hash_write);
00182 
00183         unlink(fn);
00184     }
00185 
00186     return U_TEST_SUCCESS;
00187 err:
00188     u_test_case_printf(tc, "failed. file: %s file_size: %d, buf_size: %d", 
00189             fn, file_size, buf_size);
00190     return U_TEST_FAILURE;
00191 }
00192 #endif  /* HAVE_SETITIMER */
00193 
00194 static int test_u_strtok (u_test_case_t *tc)
00195 {
00196     char **tv = NULL;
00197     size_t nelems, i, j;
00198     enum { MAX_TOKENS = 100 };
00199 
00200     struct vt_s
00201     {
00202         const char *in; 
00203         const char *delim; 
00204         const char *ex[MAX_TOKENS];
00205     } vt[] = {
00206         { 
00207             /* tv idx 0 */
00208             "this . is , a : test ; string |", 
00209             " \t", 
00210             { 
00211                 "this", 
00212                 ".", 
00213                 "is", 
00214                 ",", 
00215                 "a", 
00216                 ":", 
00217                 "test", 
00218                 ";", 
00219                 "string", 
00220                 "|", 
00221                 NULL 
00222             }
00223         },
00224         {
00225             /* tv idx 1 */
00226             "this . is , a : test ; string |", 
00227             ".",
00228             {
00229                 "this ",
00230                 " is , a : test ; string |",
00231                 NULL 
00232             }
00233         },
00234         {
00235             /* tv idx 2 */
00236             "this . is , a : test ; string |", 
00237             ",",
00238             {
00239                 "this . is ",
00240                 " a : test ; string |",
00241                 NULL 
00242             }
00243         },
00244         {
00245             /* tv idx 3 */
00246             "this .. is ,, a : test ; string |", 
00247             ",.:",
00248             {
00249                 "this ",
00250                 " is ",
00251                 " a ",
00252                 " test ; string |",
00253                 NULL 
00254             }
00255         },
00256         {
00257             /* tv idx 4 */
00258             "is .. this ,, a : test ; string ||? |", 
00259             ",.:;|",
00260             {
00261                 "is ",
00262                 " this ",
00263                 " a ",
00264                 " test ",
00265                 " string ",
00266                 "? ",
00267                 NULL 
00268             }
00269         },
00270         {
00271             /* tv idx 5 */
00272             "       is .. this ,, a : test ; string ||? |", 
00273             " ,.:;|",
00274             {
00275                 "is",
00276                 "this",
00277                 "a",
00278                 "test",
00279                 "string",
00280                 "?",
00281                 NULL 
00282             }
00283         },
00284         {
00285             /* tv idx 6 */
00286             "       is .. this ,, a : test ; string ||? |", 
00287             "-",
00288             {
00289                 "       is .. this ,, a : test ; string ||? |",
00290                 NULL 
00291             }
00292         },
00293         {
00294             /* tv idx 7 (string containing separator chars only) */
00295             "|,,,  | ,",
00296             "|, ",
00297             { NULL }
00298         },
00299         {
00300             /* tv idx 8 (empty string) */
00301             "",
00302             "|, ",
00303             { NULL }
00304         },
00305         { 
00306              NULL, 
00307              NULL, 
00308              { NULL }
00309         }
00310     };
00311 
00312     for (i = 0; vt[i].in; i++)
00313     {
00314         u_test_err_ifm (u_strtok(vt[i].in, vt[i].delim, &tv, &nelems),
00315                 "u_strtok failed on input: %s", vt[i].in);
00316 
00317         for (j = 0; j < nelems; j++)
00318         {
00319             u_test_err_ifm (strcmp(tv[j], vt[i].ex[j]), 
00320                     "%s != %s (tv idx=%zu)", tv[j], vt[i].ex[j], i);
00321         }
00322 
00323         u_test_err_ifm (vt[i].ex[j] != NULL, 
00324                 "got %zu tokens from u_strtok, need some more (tv idx=%zu)", 
00325                 nelems, i);
00326 
00327         u_strtok_cleanup(tv, nelems);
00328         tv = NULL;
00329     }
00330 
00331     return U_TEST_SUCCESS;
00332 err:
00333     u_strtok_cleanup(tv, nelems);
00334     return U_TEST_FAILURE;
00335 }
00336 
00337 static int test_u_path_snprintf (u_test_case_t *tc)
00338 {
00339     struct vt_s
00340     {
00341         const char *src, *ex;
00342     } vt[] = {
00343         { "",           "" },
00344         { "/",          "/" },
00345         { "//",         "/" },
00346         { "///",        "/" },
00347         { "a",          "a" },
00348         { "ab",         "ab" },
00349         { "abc",        "abc" },
00350         { "a/b",        "a/b" },
00351         { "/a",         "/a" },
00352         { "//a",        "/a" },
00353         { "///a",       "/a" },
00354         { "////a",      "/a" },
00355         { "/a//",       "/a/" },
00356         { "/a///",      "/a/" },
00357         { "/a////",     "/a/" },
00358         { "a//b",       "a/b" },
00359         { "a///b",      "a/b" },
00360         { "a////b",     "a/b" },
00361         { "a/b//c",     "a/b/c" },
00362         { "a/b//c/",    "a/b/c/" },
00363         { "a//b//c//",  "a/b/c/" },
00364         { NULL,         NULL }
00365     };
00366     int i;
00367     char buf[4096];
00368 
00369     for(i = 0; vt[i].src; ++i)
00370     {
00371         u_path_snprintf(buf, sizeof(buf), '/', "%s", vt[i].src);
00372         u_test_err_ifm(strcmp(buf, vt[i].ex), "src: %s  exp: %s  got: %s",
00373                 vt[i].src, vt[i].ex, buf);
00374     }
00375 
00376     return U_TEST_SUCCESS;
00377 err:
00378     return U_TEST_FAILURE;
00379 }
00380 
00381 static int test_u_atoi (u_test_case_t *tc)
00382 {
00383     int i, j, rc, dummy = 0;
00384 
00385     struct
00386     {
00387         const char *in;
00388         int ex, rc;
00389     } vt[] = {
00390         /* minimum value for INT_MIN (16-bit) */
00391         {   "-32767",   -32767, 0   },  
00392         /* minimum value for INT_MAX (16-bit) */
00393         {   "32767",    32767,  0   },  
00394 
00395         /* check mixed numeric/non-numeric strings
00396          * man strtol(3): the string may begin with an arbitrary amount of 
00397          * white space (as determined by isspace(3)) followed by a single 
00398          * optional `+' or `-' sign. conversion stop at the first character 
00399          * which is not a valid base-10 digit */
00400         {   "123abc",   123,    0   },  /* stop at 'a' */
00401         {   "  +1+1",   1,      0   },  /* stop at the second '+' */
00402         {   "abc123",   dummy,  ~0  },  /* stop at 'a' */
00403         {   "1b2c3",    1,      0   },  /* stop at 'b' */
00404         {   "bongo",    dummy,  ~0  },  /* stop at 'b' */
00405 
00406         /* check underflows */
00407 #if (INT_MIN < (-2147483647 - 1))       /* less than 32-bit */
00408         {   "-2147483648",  dummy,      ~0  },
00409 #elif (INT_MIN == (-2147483647 - 1))    /* 32-bit */
00410         {   "-2147483648", -2147483648, 0   },
00411         {   "-2147483649",  dummy,      ~0  },
00412 #else                                   /* more than 32-bit */
00413         {   "-2147483649", -2147483649, 0   },
00414 #endif
00415 
00416         /* check overflows */
00417 #if (INT_MAX < 2147483647)              /* less than 32-bit */
00418         {   "2147483647",   dummy,      ~0  },
00419 #elif (INT_MAX == 2147483647)           /* 32-bit */
00420         {   "2147483647",   2147483647, 0   },
00421         {   "2147483648",   dummy,      ~0  },
00422 #else                                   /* more than 32-bit */
00423         {   "2147483648",   2147483648, 0   },
00424 #endif
00425 
00426         {   NULL,   0,  0   }
00427     };
00428 
00429     for (i = 0; vt[i].in; ++i)
00430     {
00431         rc = u_atoi(vt[i].in, &j);
00432 
00433         u_test_err_ifm (rc != vt[i].rc, 
00434                 "unexpected return code %d != %d (tested conversion was: %s)",
00435                 rc, vt[i].rc, vt[i].in);
00436 
00437         if (rc == 0)
00438         {
00439             u_test_err_ifm (j != vt[i].ex, 
00440                     "unexpected conversion value %d != %d on  %s",
00441                     j, vt[i].ex, vt[i].in);
00442         }
00443     }
00444 
00445     return U_TEST_SUCCESS;
00446 err:
00447     return U_TEST_FAILURE;
00448 }
00449 
00450 int test_suite_misc_register (u_test_t *t)
00451 {
00452     u_test_suite_t *ts = NULL;
00453 
00454     con_err_if (u_test_suite_new("Miscellaneous Utilities", &ts));
00455 
00456 #ifdef HAVE_SETITIMER
00457     con_err_if (u_test_case_register("Various I/O routines", test_u_rdwr, ts));
00458 #endif  /* HAVE_SETITIMER */
00459 
00460     con_err_if (u_test_case_register("u_path_snprintf function", 
00461                 test_u_path_snprintf, ts));
00462     con_err_if (u_test_case_register("u_strtok function", test_u_strtok, ts));
00463     con_err_if (u_test_case_register("u_atoi function", test_u_atoi, ts));
00464 
00465     return u_test_suite_add(ts, t);
00466 err:
00467     u_test_suite_free(ts);
00468     return ~0;
00469 }

←Products
© 2005-2012 - KoanLogic S.r.l. - All rights reserved