1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <stdint.h>
4 #include <inttypes.h>
5 #include <ctype.h>
6
7 #include "test-common.h"
8
9 #include <libmy/ubuf.h>
10 #include <wdns.h>
11
12 #define NAME "test-name_to_str"
13
14 struct test {
15 const void *input;
16 size_t ilen;
17 const char *expected;
18 const char *expected_lcase;
19 const char *expected_rev;
20 size_t skip_len;
21 };
22
23 struct test tdata[] = {
24 {
25 .input = "\x03" "fsi" "\x02" "io",
26 .ilen = 1 + 3 + 1 + 2 + 1,
27 .expected = "fsi.io.",
28 .expected_lcase = "fsi.io.",
29 .expected_rev = "io.fsi.",
30 .skip_len = 1 + 3 + 1 + 2 + 1,
31 },
32 {
33 .input = "\x04" "abcd" "\x03" "fsi" "\x02" "IO",
34 .ilen = 1 + 4 + 1 + 3 + 1 + 2 + 1,
35 .expected = "abcd.fsi.IO.",
36 .expected_lcase = "abcd.fsi.io.",
37 .expected_rev = "IO.fsi.abcd.",
38 .skip_len = 1 + 4 + 1 + 3 + 1 + 2 + 1,
39 },
40 {
41 .input = "\x05" "Mixed" "\x03" "fsi" "\x02" "IO",
42 .ilen = 1 + 5 + 1 + 3 + 1 + 2 + 1,
43 .expected = "Mixed.fsi.IO.",
44 .expected_lcase = "mixed.fsi.io.",
45 .expected_rev = "IO.fsi.Mixed.",
46 .skip_len = 1 + 5 + 1 + 3 + 1 + 2 + 1,
47 },
48 {
49 .input = "\x07" "testing" "\x08" "trailing" "\x04" "data" "\x03" "fsi" "\x02" "io" "\x00" "\x04" "abcd",
50 .ilen = 1 + 7 + 1 + 8 + 1 + 4 + 1 + 3 + 1 + 2 + 1 + 1 + 4 + 1,
51 .expected = "testing.trailing.data.fsi.io.",
52 .expected_lcase = "testing.trailing.data.fsi.io.",
53 // It's really unclear how this function should behave when presented
54 // with trailing data. This topic demands further discussion.
55 // Ref: https://github.com/farsightsec/wdns/issues/25
56 // .expected_rev = "io.fsi.data.trailing.testing.",
57 .expected_rev = ".",
58 .skip_len = 1 + 7 + 1 + 8 + 1 + 4 + 1 + 3 + 1 + 2 + 1,
59 },
60 {
61 0
62 }
63 };
64
65
66 static size_t
test_name_to_str(void)67 test_name_to_str(void)
68 {
69 char dstr[1024];
70 ubuf *u;
71 struct test *cur;
72 size_t failures = 0;
73
74 u = ubuf_init(256);
75
76 for(cur = tdata; cur->input != NULL; cur++) {
77 wdns_name_t name;
78 wdns_res res;
79 int err = 0;
80
81 ubuf_reset(u);
82 memset(&name, 0, sizeof(name));
83 memset(dstr, 0, sizeof(dstr));
84
85 // Don't check result of wdns_domain_to_str() here or elsewhere,
86 // because if it's wrong, subsequent string comparisons necessarily fail.
87 wdns_domain_to_str(cur->input, cur->ilen, dstr);
88
89 if (strcmp(dstr, cur->expected)) {
90 ubuf_add_fmt(u, "FAIL %" PRIu64 ": input=", cur-tdata);
91 escape(u, (uint8_t*)cur->input, strlen(cur->input));
92 ubuf_add_fmt(u, " name %s != %s", dstr, cur->expected);
93 err = 1;
94 }
95
96 if (!err) {
97 name.data = malloc(cur->ilen);
98 memcpy(name.data, cur->input, cur->ilen);
99 name.len = cur->ilen;
100 wdns_downcase_name(&name);
101
102 memset(dstr, 0, sizeof(dstr));
103 wdns_domain_to_str(name.data, name.len, dstr);
104
105 if (strcmp(dstr, cur->expected_lcase)) {
106 ubuf_add_fmt(u, "FAIL %" PRIu64 ": input=", cur-tdata);
107 escape(u, (uint8_t*)cur->input, strlen(cur->input));
108 ubuf_add_fmt(u, " lowercase name %s != %s", dstr, cur->expected_lcase);
109 err = 1;
110 }
111
112 }
113
114 if (!err) {
115 memset(name.data, 0, name.len);
116
117 if (wdns_reverse_name(cur->input, cur->ilen, name.data) != wdns_res_success) {
118 ubuf_add_fmt(u, "FAIL %" PRIu64 ": input=", cur-tdata);
119 escape(u, (uint8_t*)cur->input, strlen(cur->input));
120 ubuf_add_fmt(u, " reverse name failure");
121 err = 1;
122 } else {
123 memset(dstr, 0, sizeof(dstr));
124 wdns_domain_to_str(name.data, name.len, dstr);
125
126 if (strcmp(dstr, cur->expected_rev)) {
127 ubuf_add_fmt(u, "FAIL %" PRIu64 ": input=", cur-tdata);
128 escape(u, (uint8_t*)cur->input, strlen(cur->input));
129 ubuf_add_fmt(u, " reverse name %s != %s", dstr, cur->expected_rev);
130 err = 1;
131 }
132
133 }
134
135 }
136
137 if (!err) {
138 const uint8_t *sptr = cur->input;
139
140 res = wdns_skip_name(&sptr, (((const uint8_t *)cur->input) + cur->ilen));
141
142 if (res != cur->skip_len) {
143 ubuf_add_fmt(u, "FAIL %" PRIu64 ": input=", cur-tdata);
144 escape(u, (uint8_t*)cur->input, strlen(cur->input));
145 ubuf_add_fmt(u, " skip len %zu != %zu", res, cur->skip_len);
146 err = 1;
147 }
148
149 }
150
151 if (!err) {
152 ubuf_add_fmt(u, "PASS %" PRIu64 ": input=", cur-tdata);
153 escape(u, (uint8_t*)cur->input, cur->ilen);
154 } else {
155 failures++;
156 }
157
158 fprintf (stderr, "%s\n", ubuf_cstr(u));
159 if (name.data != NULL) {
160 free(name.data);
161 name.data = NULL;
162 }
163 }
164
165 ubuf_destroy(&u);
166 return failures;
167 }
168
main(void)169 int main (void)
170 {
171 int ret = 0;
172
173 ret |= check(test_name_to_str(), "test-name_to_str", NAME);
174
175 if (ret)
176 return (EXIT_FAILURE);
177 return (EXIT_SUCCESS);
178 }
179