-struct {
- const char *in;
- const char *expect[10];
-} wtest[] = {
- /* Empty string */
- { "", { 0 } },
- /* Only whitespace and punctuation */
- { " ", { 0 } },
- { " ' ", { 0 } },
- { " ! ", { 0 } },
- { " \"\" ", { 0 } },
- { " @ ", { 0 } },
- /* Basics */
- { "wibble", { "wibble", 0 } },
- { " wibble", { "wibble", 0 } },
- { " wibble ", { "wibble", 0 } },
- { "wibble ", { "wibble", 0 } },
- { "wibble spong", { "wibble", "spong", 0 } },
- { " wibble spong", { "wibble", "spong", 0 } },
- { " wibble spong ", { "wibble", "spong", 0 } },
- { "wibble spong ", { "wibble", "spong", 0 } },
- { "wibble spong splat foo zot ", { "wibble", "spong", "splat", "foo", "zot", 0 } },
- /* Apostrophes */
- { "wibble 'spong", { "wibble", "spong", 0 } },
- { " wibble's", { "wibble's", 0 } },
- { " wibblespong' ", { "wibblespong", 0 } },
- { "wibble sp''ong ", { "wibble", "sp", "ong", 0 } },
-};
-#define NWTEST (sizeof wtest / sizeof *wtest)
-
-static void test_words(void) {
- size_t t, nexpect, ngot, i;
- int right;
-
- fprintf(stderr, "test_words\n");
- for(t = 0; t < NWTEST; ++t) {
- char **got = utf8_word_split(wtest[t].in, strlen(wtest[t].in), &ngot, 0);
-
- 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);
-}
-
-int main(void) {
- fail_first = !!getenv("FAIL_FIRST");
- insist('\n' == 0x0A);
- insist('\r' == 0x0D);
- insist(' ' == 0x20);
- insist('0' == 0x30);
- insist('9' == 0x39);
- insist('A' == 0x41);
- insist('Z' == 0x5A);
- insist('a' == 0x61);
- insist('z' == 0x7A);
- /* addr.c */
- /* asprintf.c */
- /* authhash.c */
- /* basen.c */
- /* charset.c */
- /* client.c */
- /* configuration.c */
- /* event.c */
- /* filepart.c */
- test_filepart();
- /* fprintf.c */
- /* heap.c */
- test_heap();
- /* hex.c */
- test_hex();
- /* inputline.c */
- /* kvp.c */
- /* log.c */
- /* mem.c */
- /* mime.c */
- test_mime();
- /* mixer.c */
- /* plugin.c */
- /* printf.c */
- /* queue.c */
- /* sink.c */
- /* snprintf.c */
- /* split.c */
- /* syscalls.c */
- /* table.c */
- /* unicode.c */
- test_unicode();
- /* utf8.c */
- test_utf8();
- /* vector.c */
- /* words.c */
- test_casefold();
- test_words();
- /* wstat.c */
- /* signame.c */
- test_signame();
- /* cache.c */
- test_cache();
- /* selection.c */
- test_selection();
- fprintf(stderr, "%d errors out of %d tests\n", errors, tests);
- return !!errors;
-}
-