#include #include #include #include #include int do_test(int func, const char *name, const char *fmt, const wchar_t *wfmt, const char *input, int xret, int xlen, const void *expect, size_t size, void *obuf) { int consumed = 0; int err = 0; FILE *f; int ret; int same; if (func&1) { f = tmpfile(); if (!f) { printf("%s: cannot create temp file: %s\n", name, strerror(errno)); return 1; } if (fwrite(input, strlen(input), 1, f)!=1) { fclose(f); printf("%s: cannot create temp file: %s\n", name, strerror(errno)); return 1; } rewind(f); if (func&2) ret = fwscanf(f, wfmt, obuf, &consumed); else ret = fscanf(f, fmt, obuf, &consumed); } else { wchar_t winput[1024]; swprintf(winput, 1024, L"%s", input); if (func&2) ret = swscanf(winput, wfmt, obuf, &consumed); else ret = sscanf(input, fmt, obuf, &consumed); } if (func&1) { int final = ftell(f); if (final != xlen) { printf("%s: wrong final position %d, should be %d\n", name, final, xlen); err = 1; } fclose(f); } if (ret != xret) { printf("%s: returned %d, expected %d\n", name, ret, xret); return 1; } if (ret <= 0) return err; if (consumed != xlen) { printf("%s: consumed %d, should have consumed %d\n", name, consumed, xlen); err = 1; } /* We assume no padding bits except possibly long double. */ if (size == sizeof(long double) && strchr(fmt, 'L')) same = *(long double *)obuf == *(long double *)expect; else same = !memcmp(expect, obuf, size); if (!same) { printf("%s: wrong value: ", name); return 2; } return err; } #define TEST_1(func,name,fmt,in,xr,xl,type,ex,ofmt,obuf) do { \ memset(obuf, 0, sizeof(type)); \ switch (do_test(func,name,fmt "%n",fmt L"%n",in,xr,xl,(type[]){ex},sizeof ex,obuf)) { \ case 2: if (#ex[0]=='"' || #ex[0]=='L') \ printf(ofmt ", expected " ofmt "\n", (type *)obuf, ex); \ else printf(ofmt ", expected " ofmt "\n", *(type *)obuf, ex); \ case 1: err++; } } while (0) #define TEST(fmt,in,xr,xl,type,ex,ofmt) do { \ TEST_1(0,"sscanf(" #in "," #fmt ")",fmt,in,xr,xl,type,ex,ofmt,obuf); \ TEST_1(1,"fscanf(" #in "," #fmt ")",fmt,in,xr,xl,type,ex,ofmt,obuf); \ TEST_1(2,"swscanf(" #in "," #fmt ")",fmt,in,xr,xl,type,ex,ofmt,obuf); \ TEST_1(3,"fwscanf(" #in "," #fmt ")",fmt,in,xr,xl,type,ex,ofmt,obuf); \ } while (0) /* TEST macro takes 7 arguments: * - format string ("%n" is automatically appended to test termination) * - input text to scan * - expected return value (-1, 0, or 1) * - expected number of characters consumed * - data type (char or wchar_t for strings) of result * - expected result * - format for printing result mismatches * All arguments should be literals of the correct type, not * programmatically generated. The macro does some crazy stuff. */ int main() { void *obuf = malloc(256); int err=0; TEST("%9d", "9999999999", 1, 9, int, 999999999, "%d"); TEST("%5s", "abcdefg", 1, 5, char, "abcde", "%s"); TEST("%5[abc]", "ababab", 1, 5, char, "ababa", "%s"); TEST("%x", "0xq", 0, 2, int, 0, "%d"); TEST("%Lf", "1.0", 1, 3, long double, 1.0, "%La"); }