diff options
Diffstat (limited to 'tests')
| -rw-r--r-- | tests/runner.c | 1 | ||||
| -rw-r--r-- | tests/t_hex.c | 128 | ||||
| -rw-r--r-- | tests/test.h | 1 |
3 files changed, 130 insertions, 0 deletions
diff --git a/tests/runner.c b/tests/runner.c index 1b6deb1..c9385f0 100644 --- a/tests/runner.c +++ b/tests/runner.c | |||
| @@ -18,6 +18,7 @@ static const struct module modules[] = {{"scan_urlencoded_query", test_scan_urle | |||
| 18 | {"ot_iovec", test_iovec}, | 18 | {"ot_iovec", test_iovec}, |
| 19 | {"ot_vector", test_vector}, | 19 | {"ot_vector", test_vector}, |
| 20 | {"ot_random", test_random}, | 20 | {"ot_random", test_random}, |
| 21 | {"ot_hex", test_hex}, | ||
| 21 | {NULL, NULL}}; | 22 | {NULL, NULL}}; |
| 22 | 23 | ||
| 23 | /* Run every module, or only those whose name contains argv[1] */ | 24 | /* Run every module, or only those whose name contains argv[1] */ |
diff --git a/tests/t_hex.c b/tests/t_hex.c new file mode 100644 index 0000000..7cce8ac --- /dev/null +++ b/tests/t_hex.c | |||
| @@ -0,0 +1,128 @@ | |||
| 1 | /* This software was written by Dirk Engling <erdgeist@erdgeist.org> | ||
| 2 | It is considered beerware. Prost. Skol. Cheers or whatever. | ||
| 3 | |||
| 4 | $id$ */ | ||
| 5 | |||
| 6 | /* System */ | ||
| 7 | #include <stdint.h> | ||
| 8 | #include <string.h> | ||
| 9 | |||
| 10 | /* Opentracker */ | ||
| 11 | #include "ot_hex.h" | ||
| 12 | #include "test.h" | ||
| 13 | |||
| 14 | static const uint8_t sample[20] = {0x00, 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xff, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, 0x90, 0xa0}; | ||
| 15 | |||
| 16 | static void case_encode(void) { | ||
| 17 | char dest[64]; | ||
| 18 | |||
| 19 | test_case("a hash encodes to forty upper case digits and a terminator"); | ||
| 20 | memset(dest, 0x7f, sizeof(dest)); | ||
| 21 | CHECK_PTR(hex_fromhash(dest, sample), dest); | ||
| 22 | CHECK_STR(dest, "000123456789ABCDEFFF10203040506070809" "0A0"); | ||
| 23 | CHECK_INT(strlen(dest), 40); | ||
| 24 | CHECK_INT((unsigned char)dest[41], 0x7f); | ||
| 25 | } | ||
| 26 | |||
| 27 | static void case_decode(void) { | ||
| 28 | ot_hash hash; | ||
| 29 | |||
| 30 | test_case("forty digits decode back to the hash"); | ||
| 31 | CHECK(hex_tohash(hash, "000123456789ABCDEFFF10203040506070809" "0A0")); | ||
| 32 | CHECK_MEM(hash, sample, sizeof(sample)); | ||
| 33 | } | ||
| 34 | |||
| 35 | static void case_round_trip(void) { | ||
| 36 | ot_hash hash; | ||
| 37 | char text[64]; | ||
| 38 | size_t i; | ||
| 39 | |||
| 40 | test_case("encode and decode are inverses over every byte value"); | ||
| 41 | for (i = 0; i < 256; ++i) { | ||
| 42 | uint8_t probe[20]; | ||
| 43 | memset(probe, (uint8_t)i, sizeof(probe)); | ||
| 44 | hex_fromhash(text, probe); | ||
| 45 | if (!hex_tohash(hash, text) || memcmp(hash, probe, sizeof(probe))) { | ||
| 46 | test_failf(__FILE__, __LINE__, "round trip failed for byte value %zu", i); | ||
| 47 | return; | ||
| 48 | } | ||
| 49 | } | ||
| 50 | ++test_checks; | ||
| 51 | } | ||
| 52 | |||
| 53 | static void case_decode_is_case_insensitive(void) { | ||
| 54 | ot_hash upper, lower; | ||
| 55 | |||
| 56 | test_case("lower case digits decode the same as upper case"); | ||
| 57 | CHECK(hex_tohash(upper, "ABCDEF0123456789ABCDEF0123456789ABCDEF01")); | ||
| 58 | CHECK(hex_tohash(lower, "abcdef0123456789abcdef0123456789abcdef01")); | ||
| 59 | CHECK_MEM(lower, upper, sizeof(ot_hash)); | ||
| 60 | } | ||
| 61 | |||
| 62 | static void case_rejects_non_digits(void) { | ||
| 63 | ot_hash hash; | ||
| 64 | |||
| 65 | test_case("a non hex character anywhere rejects the whole string"); | ||
| 66 | CHECK_INT(hex_tohash(hash, "g00123456789ABCDEFFF102030405060708090A0"), 0); | ||
| 67 | CHECK_INT(hex_tohash(hash, "000123456789ABCDEFFF102030405060708090Ag"), 0); | ||
| 68 | CHECK_INT(hex_tohash(hash, "000123456789ABCDEF:F102030405060708090A"), 0); | ||
| 69 | } | ||
| 70 | |||
| 71 | static void case_rejects_short_input(void) { | ||
| 72 | ot_hash hash; | ||
| 73 | |||
| 74 | test_case("a string shorter than forty digits is rejected"); | ||
| 75 | CHECK_INT(hex_tohash(hash, ""), 0); | ||
| 76 | CHECK_INT(hex_tohash(hash, "00"), 0); | ||
| 77 | CHECK_INT(hex_tohash(hash, "000123456789ABCDEFFF102030405060708090A"), 0); | ||
| 78 | } | ||
| 79 | |||
| 80 | static void case_leaves_hash_untouched_on_failure(void) { | ||
| 81 | ot_hash hash; | ||
| 82 | |||
| 83 | test_case("a rejected string leaves the destination untouched"); | ||
| 84 | memset(hash, 0x5a, sizeof(hash)); | ||
| 85 | CHECK_INT(hex_tohash(hash, "000123456789ABCDEFFF10203040506070809XX0"), 0); | ||
| 86 | CHECK_MEM(hash, "\x5a\x5a\x5a\x5a\x5a\x5a\x5a\x5a\x5a\x5a\x5a\x5a\x5a\x5a\x5a\x5a\x5a\x5a\x5a\x5a", sizeof(hash)); | ||
| 87 | } | ||
| 88 | |||
| 89 | static void case_stops_at_the_terminator(void) { | ||
| 90 | /* The saved state parser hands this whole buffers that may end early. The | ||
| 91 | decoder must not read past the zero that stopped it. */ | ||
| 92 | char guarded[8]; | ||
| 93 | ot_hash hash; | ||
| 94 | |||
| 95 | test_case("decoding stops at a terminator rather than running past it"); | ||
| 96 | memcpy(guarded, "0012", 4); | ||
| 97 | guarded[4] = 0; | ||
| 98 | memset(guarded + 5, 'f', 3); | ||
| 99 | CHECK_INT(hex_tohash(hash, guarded), 0); | ||
| 100 | } | ||
| 101 | |||
| 102 | static void case_isdigit(void) { | ||
| 103 | test_case("hex_isdigit accepts exactly the hex digits"); | ||
| 104 | CHECK(hex_isdigit('0')); | ||
| 105 | CHECK(hex_isdigit('9')); | ||
| 106 | CHECK(hex_isdigit('a')); | ||
| 107 | CHECK(hex_isdigit('f')); | ||
| 108 | CHECK(hex_isdigit('A')); | ||
| 109 | CHECK(hex_isdigit('F')); | ||
| 110 | CHECK_INT(hex_isdigit('g'), 0); | ||
| 111 | CHECK_INT(hex_isdigit('G'), 0); | ||
| 112 | CHECK_INT(hex_isdigit(':'), 0); | ||
| 113 | CHECK_INT(hex_isdigit('\n'), 0); | ||
| 114 | CHECK_INT(hex_isdigit(0), 0); | ||
| 115 | CHECK_INT(hex_isdigit(0x80), 0); | ||
| 116 | } | ||
| 117 | |||
| 118 | void test_hex(void) { | ||
| 119 | case_encode(); | ||
| 120 | case_decode(); | ||
| 121 | case_round_trip(); | ||
| 122 | case_decode_is_case_insensitive(); | ||
| 123 | case_rejects_non_digits(); | ||
| 124 | case_rejects_short_input(); | ||
| 125 | case_leaves_hash_untouched_on_failure(); | ||
| 126 | case_stops_at_the_terminator(); | ||
| 127 | case_isdigit(); | ||
| 128 | } | ||
diff --git a/tests/test.h b/tests/test.h index 19acb2f..6af0083 100644 --- a/tests/test.h +++ b/tests/test.h | |||
| @@ -80,5 +80,6 @@ void test_scan_urlencoded_query(void); | |||
| 80 | void test_iovec(void); | 80 | void test_iovec(void); |
| 81 | void test_vector(void); | 81 | void test_vector(void); |
| 82 | void test_random(void); | 82 | void test_random(void); |
| 83 | void test_hex(void); | ||
| 83 | 84 | ||
| 84 | #endif | 85 | #endif |
