- for(nexpect = 0; wtest[t].expect[nexpect]; ++nexpect)
- ;
- if(nexpect == ngot) {
- for(i = 0; i < ngot; ++i)
- if(strcmp(wtest[t].expect[i], got[i]))
- break;
- right = i == ngot;
- } else
- right = 0;
- if(!right) {
- fprintf(stderr, "word split %zu failed\n", t);
- fprintf(stderr, "input: %s\n", wtest[t].in);
- fprintf(stderr, " | %-30s | %-30s\n",
- "expected", "got");
- for(i = 0; i < nexpect || i < ngot; ++i) {
- const char *e = i < nexpect ? wtest[t].expect[i] : "<none>";
- const char *g = i < ngot ? got[i] : "<none>";
- fprintf(stderr, " %2zu | %-30s | %-30s\n", i, e, g);
- }
- count_error();
- }
- ++tests;
- }
-}
-
-/** @brief Less-than comparison function for integer heap */
-static inline int int_lt(int a, int b) { return a < b; }
-
-/** @struct iheap
- * @brief A heap with @c int elements */
-HEAP_TYPE(iheap, int, int_lt);
-HEAP_DEFINE(iheap, int, int_lt);
-
-/** @brief Tests for @ref heap.h */
-static void test_heap(void) {
- struct iheap h[1];
- int n;
- int last = -1;
-
- fprintf(stderr, "test_heap\n");
-
- iheap_init(h);
- for(n = 0; n < 1000; ++n)
- iheap_insert(h, random() % 100);
- for(n = 0; n < 1000; ++n) {
- const int latest = iheap_remove(h);
- if(last > latest)
- fprintf(stderr, "should have %d <= %d\n", last, latest);
- insist(last <= latest);
- last = latest;
- }
- putchar('\n');
-}
-
-/** @brief Open a Unicode test file */
-static FILE *open_unicode_test(const char *path) {
- const char *base;
- FILE *fp;
- char buffer[1024];
- int w;
-
- if((base = strrchr(path, '/')))
- ++base;
- else
- base = path;
- if(!(fp = fopen(base, "r"))) {
- snprintf(buffer, sizeof buffer,
- "wget http://www.unicode.org/Public/5.0.0/ucd/%s", path);
- if((w = system(buffer)))
- fatal(0, "%s: %s", buffer, wstat(w));
- if(chmod(base, 0444) < 0)
- fatal(errno, "chmod %s", base);
- if(!(fp = fopen(base, "r")))
- fatal(errno, "%s", base);
- }
- return fp;
-}
-
-/** @brief Run breaking tests for utf32_grapheme_boundary() etc */
-static void breaktest(const char *path,
- int (*breakfn)(const uint32_t *, size_t, size_t)) {
- FILE *fp = open_unicode_test(path);
- int lineno = 0;
- char *l, *lp;
- size_t bn, n;
- char break_allowed[1024];
- uint32_t buffer[1024];
-
- while(!inputline(path, fp, &l, '\n')) {
- ++lineno;
- if(l[0] == '#') continue;
- bn = 0;
- lp = l;
- while(*lp) {
- if(*lp == ' ' || *lp == '\t') {
- ++lp;
- continue;
- }
- if(*lp == '#')
- break;
- if((unsigned char)*lp == 0xC3 && (unsigned char)lp[1] == 0xB7) {
- /* 00F7 DIVISION SIGN */
- break_allowed[bn] = 1;
- lp += 2;
- continue;
- }
- if((unsigned char)*lp == 0xC3 && (unsigned char)lp[1] == 0x97) {
- /* 00D7 MULTIPLICATION SIGN */
- break_allowed[bn] = 0;
- lp += 2;
- continue;
- }
- if(isxdigit((unsigned char)*lp)) {
- buffer[bn++] = strtoul(lp, &lp, 16);
- continue;
- }
- fatal(0, "%s:%d: evil line: %s", path, lineno, l);
- }
- for(n = 0; n <= bn; ++n) {
- if(breakfn(buffer, bn, n) != break_allowed[n]) {
- fprintf(stderr,
- "%s:%d: offset %zu: mismatch\n"
- "%s\n"
- "\n",
- path, lineno, n, l);
- count_error();
- }
- ++tests;
- }
- xfree(l);
- }
- fclose(fp);
-}
-
-/** @brief Tests for @ref lib/unicode.h */
-static void test_unicode(void) {
- FILE *fp;
- int lineno = 0;
- char *l, *lp;
- uint32_t buffer[1024];
- uint32_t *c[6], *NFD_c[6], *NFKD_c[6], *NFC_c[6], *NFKC_c[6]; /* 1-indexed */
- int cn, bn;
-
- fprintf(stderr, "test_unicode\n");
- fp = open_unicode_test("NormalizationTest.txt");
- while(!inputline("NormalizationTest.txt", fp, &l, '\n')) {
- ++lineno;
- if(*l == '#' || *l == '@')
- continue;
- bn = 0;
- cn = 1;
- lp = l;
- c[cn++] = &buffer[bn];
- while(*lp && *lp != '#') {
- if(*lp == ' ') {
- ++lp;
- continue;
- }
- if(*lp == ';') {
- buffer[bn++] = 0;
- if(cn == 6)
- break;
- c[cn++] = &buffer[bn];
- ++lp;
- continue;
- }
- buffer[bn++] = strtoul(lp, &lp, 16);
- }
- buffer[bn] = 0;
- assert(cn == 6);
- for(cn = 1; cn <= 5; ++cn) {
- NFD_c[cn] = utf32_decompose_canon(c[cn], utf32_len(c[cn]), 0);
- NFKD_c[cn] = utf32_decompose_compat(c[cn], utf32_len(c[cn]), 0);
- NFC_c[cn] = utf32_compose_canon(c[cn], utf32_len(c[cn]), 0);
- NFKC_c[cn] = utf32_compose_compat(c[cn], utf32_len(c[cn]), 0);
- }
-#define unt_check(T, A, B) do { \
- ++tests; \
- if(utf32_cmp(c[A], T##_c[B])) { \
- fprintf(stderr, \
- "NormalizationTest.txt:%d: c%d != "#T"(c%d)\n", \
- lineno, A, B); \
- fprintf(stderr, " c%d:%s\n", \
- A, format_utf32(c[A])); \
- fprintf(stderr, " c%d:%s\n", \
- B, format_utf32(c[B])); \
- fprintf(stderr, "%4s(c%d):%s\n", \
- #T, B, format_utf32(T##_c[B])); \
- count_error(); \
- } \
- } while(0)
- unt_check(NFD, 3, 1);
- unt_check(NFD, 3, 2);
- unt_check(NFD, 3, 3);
- unt_check(NFD, 5, 4);
- unt_check(NFD, 5, 5);
- unt_check(NFKD, 5, 1);
- unt_check(NFKD, 5, 2);
- unt_check(NFKD, 5, 3);
- unt_check(NFKD, 5, 4);
- unt_check(NFKD, 5, 5);
- unt_check(NFC, 2, 1);
- unt_check(NFC, 2, 2);
- unt_check(NFC, 2, 3);
- unt_check(NFC, 4, 4);
- unt_check(NFC, 4, 5);
- unt_check(NFKC, 4, 1);
- unt_check(NFKC, 4, 2);
- unt_check(NFKC, 4, 3);
- unt_check(NFKC, 4, 4);
- unt_check(NFKC, 4, 5);
- for(cn = 1; cn <= 5; ++cn) {
- xfree(NFD_c[cn]);
- xfree(NFKD_c[cn]);
- }
- xfree(l);
- }
- fclose(fp);
- breaktest("auxiliary/GraphemeBreakTest.txt", utf32_is_grapheme_boundary);
- breaktest("auxiliary/WordBreakTest.txt", utf32_is_word_boundary);
- insist(utf32_combining_class(0x40000) == 0);
- insist(utf32_combining_class(0xE0000) == 0);
-}
-
-static void test_signame(void) {
- fprintf(stderr, "test_signame\n");
- insist(find_signal("SIGTERM") == SIGTERM);
- insist(find_signal("SIGHUP") == SIGHUP);
- insist(find_signal("SIGINT") == SIGINT);
- insist(find_signal("SIGQUIT") == SIGQUIT);
- insist(find_signal("SIGKILL") == SIGKILL);
- insist(find_signal("SIGYOURMUM") == -1);
-}
-
-static void test_cache(void) {
- const struct cache_type t1 = { 1 }, t2 = { 10 };
- const char v11[] = "spong", v12[] = "wibble", v2[] = "blat";
- fprintf(stderr, "test_cache\n");
- cache_put(&t1, "1_1", v11);
- cache_put(&t1, "1_2", v12);
- cache_put(&t2, "2", v2);
- insist(cache_count() == 3);
- insist(cache_get(&t2, "2") == v2);
- insist(cache_get(&t1, "1_1") == v11);
- insist(cache_get(&t1, "1_2") == v12);
- insist(cache_get(&t1, "2") == 0);
- insist(cache_get(&t2, "1_1") == 0);
- insist(cache_get(&t2, "1_2") == 0);
- insist(cache_get(&t1, "2") == 0);
- insist(cache_get(&t2, "1_1") == 0);
- insist(cache_get(&t2, "1_2") == 0);
- sleep(2);
- cache_expire();
- insist(cache_count() == 1);
- insist(cache_get(&t1, "1_1") == 0);
- insist(cache_get(&t1, "1_2") == 0);
- insist(cache_get(&t2, "2") == v2);
- cache_clean(0);
- insist(cache_count() == 0);
- insist(cache_get(&t2, "2") == 0);
-}
-
-static void test_filepart(void) {
- fprintf(stderr, "test_filepart\n");
- check_string(d_dirname("/"), "/");
- check_string(d_dirname("/spong"), "/");
- check_string(d_dirname("/foo/bar"), "/foo");
- check_string(d_dirname("./bar"), ".");
- check_string(d_dirname("."), ".");
- check_string(d_dirname(".."), ".");
- check_string(d_dirname("../blat"), "..");
- check_string(d_dirname("wibble"), ".");
- check_string(extension("foo.c"), ".c");
- check_string(extension(".c"), ".c");
- check_string(extension("."), ".");
- check_string(extension("foo"), "");
- check_string(extension("./foo"), "");
- check_string(extension("./foo.c"), ".c");
-}
-
-static void test_selection(void) {
- hash *h;
- fprintf(stderr, "test_selection\n");
- insist((h = selection_new()) != 0);
- selection_set(h, "one", 1);
- selection_set(h, "two", 1);
- selection_set(h, "three", 0);
- selection_set(h, "four", 1);
- insist(selection_selected(h, "one") == 1);
- insist(selection_selected(h, "two") == 1);
- insist(selection_selected(h, "three") == 0);
- insist(selection_selected(h, "four") == 1);
- insist(selection_selected(h, "five") == 0);
- insist(hash_count(h) == 3);
- selection_flip(h, "one");
- selection_flip(h, "three");
- insist(selection_selected(h, "one") == 0);
- insist(selection_selected(h, "three") == 1);
- insist(hash_count(h) == 3);
- selection_live(h, "one");
- selection_live(h, "two");
- selection_live(h, "three");
- selection_cleanup(h);
- insist(selection_selected(h, "one") == 0);
- insist(selection_selected(h, "two") == 1);
- insist(selection_selected(h, "three") == 1);
- insist(selection_selected(h, "four") == 0);
- insist(selection_selected(h, "five") == 0);
- insist(hash_count(h) == 2);
- selection_empty(h);
- insist(selection_selected(h, "one") == 0);
- insist(selection_selected(h, "two") == 0);
- insist(selection_selected(h, "three") == 0);
- insist(selection_selected(h, "four") == 0);
- insist(selection_selected(h, "five") == 0);
- insist(hash_count(h) == 0);
-}
-
-static void test_wstat(void) {
- pid_t pid;
- int w;
-
- fprintf(stderr, "test_wstat\n");
- if(!(pid = xfork())) {
- _exit(1);
- }
- while(waitpid(pid, &w, 0) < 0 && errno == EINTR)
- ;
- check_string(wstat(w), "exited with status 1");
- if(!(pid = xfork())) {
- kill(getpid(), SIGTERM);
- _exit(-1);
- }
- while(waitpid(pid, &w, 0) < 0 && errno == EINTR)
- ;
- check_string_prefix(wstat(w), "terminated by signal 15");
-}
-
-static void test_kvp(void) {
- struct kvp *k;
- size_t n;
-
- fprintf(stderr, "test_kvp\n");
- /* decoding */
-#define KVP_URLDECODE(S) kvp_urldecode((S), strlen(S))
- insist(KVP_URLDECODE("=%zz") == 0);
- insist(KVP_URLDECODE("=%0") == 0);
- insist(KVP_URLDECODE("=%0z") == 0);
- insist(KVP_URLDECODE("=%%") == 0);
- insist(KVP_URLDECODE("==%") == 0);
- insist(KVP_URLDECODE("wibble") == 0);
- insist(KVP_URLDECODE("") == 0);
- insist(KVP_URLDECODE("wibble&") == 0);
- insist((k = KVP_URLDECODE("one=bl%61t+foo")) != 0);
- check_string(kvp_get(k, "one"), "blat foo");
- insist(kvp_get(k, "ONE") == 0);
- insist(k->next == 0);
- insist((k = KVP_URLDECODE("wibble=splat&bar=spong")) != 0);
- check_string(kvp_get(k, "wibble"), "splat");
- check_string(kvp_get(k, "bar"), "spong");
- insist(kvp_get(k, "ONE") == 0);
- insist(k->next->next == 0);
- /* encoding */
- insist(kvp_set(&k, "bar", "spong") == 0);
- insist(kvp_set(&k, "bar", "foo") == 1);
- insist(kvp_set(&k, "zog", "%") == 1);
- insist(kvp_set(&k, "wibble", 0) == 1);
- insist(kvp_set(&k, "wibble", 0) == 0);
- check_string(kvp_urlencode(k, 0),
- "bar=foo&zog=%25");
- check_string(kvp_urlencode(k, &n),
- "bar=foo&zog=%25");
- insist(n == strlen("bar=foo&zog=%25"));
- check_string(urlencodestring("abc% +\n"),
- "abc%25%20%2b%0a");
-}
-
-static void test_sink(void) {
- struct sink *s;
- struct dynstr d[1];
- FILE *fp;
- char *l;
-
- fprintf(stderr, "test_sink\n");
-
- fp = tmpfile();
- assert(fp != 0);
- s = sink_stdio("tmpfile", fp);
- insist(sink_printf(s, "test: %d\n", 999) == 10);
- insist(sink_printf(s, "wibble: %s\n", "foobar") == 15);
- rewind(fp);
- insist(inputline("tmpfile", fp, &l, '\n') == 0);
- check_string(l, "test: 999");
- insist(inputline("tmpfile", fp, &l, '\n') == 0);
- check_string(l, "wibble: foobar");
- insist(inputline("tmpfile", fp, &l, '\n') == -1);
-
- dynstr_init(d);
- s = sink_dynstr(d);
- insist(sink_printf(s, "test: %d\n", 999) == 10);
- insist(sink_printf(s, "wibble: %s\n", "foobar") == 15);
- dynstr_terminate(d);
- check_string(d->vec, "test: 999\nwibble: foobar\n");