s3:utils: Fix 'Usage:' for 'net ads enctypes'
[samba4-gss.git] / lib / util / tests / rfc1738.c
blob4f7eced9499db3125c3c0d462191c8ffa9593a32
1 #include <stdarg.h>
2 #include <stddef.h>
3 #include <setjmp.h>
4 #include <stdint.h>
5 #include <cmocka.h>
6 #include "lib/replace/replace.h"
8 #include <errno.h>
9 #include <unistd.h>
10 #include <talloc.h>
11 #include <ctype.h>
12 #include <string.h>
13 #include "lib/util/samba_util.h"
15 /* These flags say what can be asserted about a relationship between a string
16 and its supposedly escaped equivalent.
18 The first part of the flag name indicates the direction of transformation;
19 the second part is the expected result. For example, ESCAPE_EQ means the
20 escape is expected to succeed and result is expected to be equal to the
21 given answer. ESCAPE_EQ_CASECMP is only equal when compared
22 case-insensitively. UNESCAPE_ERR means unescaping the escaped string should
23 result in an error.
25 #define UNESCAPE_ERR 1
26 #define ESCAPE_ERR 2
27 #define ESCAPE_EQ 4
28 #define UNESCAPE_EQ 8
29 #define ESCAPE_NE 16
30 #define UNESCAPE_NE 32
31 #define ESCAPE_EQ_CASECMP 64
33 struct rfc1738_test {
34 const char *escaped; /* original for unescape; result for escape */
35 const char *unescaped; /* result in unescape; original for escape */
36 uint32_t flags; /* see above */
37 int unesc_len; /* end - start will be this */
38 int unesc_strlen; /* strlen() will say this */
39 int esc_len; /* escaped string length */
42 /* unreserved = ALPHA DIGIT - . _ ~ */
44 char spectrum[255 + 1];
45 char spectrum_escaped[255 * 3 + 1];
47 struct rfc1738_test examples[] = {
49 #define SIMPLE1 "this_is_a_simple-string._With_no_escapes~" /* maps to self */
51 SIMPLE1,
52 SIMPLE1,
53 ESCAPE_EQ | UNESCAPE_EQ, /* round trip should work */
54 sizeof(SIMPLE1) - 1,
55 sizeof(SIMPLE1) - 1,
56 sizeof(SIMPLE1) - 1,
58 #define SIMPLE2 "no escapes, but\n non-printables \xc5\x8d\x99"
59 #define SIMPLE2_ESC "no%20escapes%2C%20but%0A%20non-printables%20%C5%8D%99"
61 SIMPLE2_ESC,
62 SIMPLE2,
63 ESCAPE_EQ | UNESCAPE_EQ,
64 sizeof(SIMPLE2) - 1,
65 sizeof(SIMPLE2) - 1,
66 sizeof(SIMPLE2_ESC) - 1,
68 #define SIMPLE3 "this @#$^&*()_+{}:;"
69 #define SIMPLE3_ESC "this%20%40%23%24%5E%26%2A%28%29_%2B%7B%7D%3A%3B"
71 SIMPLE3_ESC,
72 SIMPLE3,
73 ESCAPE_EQ | UNESCAPE_EQ,
74 sizeof(SIMPLE3) - 1,
75 sizeof(SIMPLE3) - 1,
76 sizeof(SIMPLE3_ESC) - 1,
79 #define ESCAPE1 "%/\x06this string has expected escapes"
80 #define ESCAPE1_ESC "%25%2F%06this%20string%20has%20expected%20escapes"
81 #define ESCAPE1_ESC_ESC "%2525%252F%2506this%2520string%2520has%2520expected"\
82 "%2520escapes"
84 ESCAPE1_ESC,
85 ESCAPE1,
86 ESCAPE_EQ | UNESCAPE_EQ,
87 sizeof(ESCAPE1) - 1,
88 sizeof(ESCAPE1) - 1,
89 sizeof(ESCAPE1_ESC) - 1,
92 ESCAPE1_ESC_ESC, /*re-escaping */
93 ESCAPE1_ESC,
94 ESCAPE_EQ | UNESCAPE_EQ,
95 sizeof(ESCAPE1_ESC) - 1,
96 sizeof(ESCAPE1_ESC) - 1,
97 sizeof(ESCAPE1_ESC_ESC) - 1,
99 #define ESCAPE2 "%25%2f%06-this-string-has-expected-lowercase-escapes-%ab"
100 #define ESCAPE2_UNESC "%/\x06-this-string-has-expected-lowercase-escapes-\xab"
102 ESCAPE2,
103 ESCAPE2_UNESC,
104 ESCAPE_EQ_CASECMP | UNESCAPE_EQ, /* escape won't match case */
105 sizeof(ESCAPE2_UNESC) - 1,
106 sizeof(ESCAPE2_UNESC) - 1,
107 sizeof(ESCAPE2) - 1,
109 #define ESCAPE3 "%25%2f%06 %32 %44 %6a%AA THIS string h%61s random escapes %ab"
110 #define ESCAPE3_UNESC "%/\x06 2 D j\xAA THIS string has random escapes \xab"
112 ESCAPE3,
113 ESCAPE3_UNESC,
114 ESCAPE_NE | UNESCAPE_EQ, /* escape will have escaped spaces */
115 sizeof(ESCAPE3_UNESC) - 1,
116 sizeof(ESCAPE3_UNESC) - 1,
117 sizeof(ESCAPE3) - 1,
119 #define ESCAPE4 "%25%25%25" /* */
120 #define ESCAPE4_UNESC "%%%" /* */
121 #define ESCAPE4_ESC "%2525%2525%2525"
123 ESCAPE4,
124 ESCAPE4_UNESC,
125 ESCAPE_EQ | UNESCAPE_EQ,
126 sizeof(ESCAPE4_UNESC) - 1,
127 sizeof(ESCAPE4_UNESC) - 1,
128 sizeof(ESCAPE4) - 1,
131 ESCAPE4_ESC,
132 ESCAPE4,
133 ESCAPE_EQ | UNESCAPE_EQ,
134 sizeof(ESCAPE4) - 1,
135 sizeof(ESCAPE4) - 1,
136 sizeof(ESCAPE4_ESC) - 1,
138 #define BAD1 "trailing percent is bad %"
139 #define BAD1_ESC "trailing%20percent%20is%20bad%20%25"
141 BAD1_ESC,
142 BAD1,
143 UNESCAPE_EQ |ESCAPE_EQ,
144 sizeof(BAD1) - 1,
145 sizeof(BAD1) - 1,
146 sizeof(BAD1_ESC) - 1,
149 BAD1,
150 NULL,
151 UNESCAPE_ERR,
154 sizeof(BAD1) - 1,
156 #define BAD2 "trailing percent is bad %1"
157 #define BAD3 "bad characters %1 "
159 BAD2,
160 NULL,
161 UNESCAPE_ERR,
164 sizeof(BAD2) - 1,
167 BAD3,
168 NULL,
169 UNESCAPE_ERR,
172 sizeof(BAD3) - 1,
174 #define BAD4 "bad characters %1 "
176 BAD4,
177 NULL,
178 UNESCAPE_ERR,
181 sizeof(BAD4) - 1,
183 #define BAD5 "bad characters %1- "
185 BAD5,
186 NULL,
187 UNESCAPE_ERR,
190 sizeof(BAD5) - 1,
192 #define BAD6 "bad characters %1G "
194 BAD6,
195 NULL,
196 UNESCAPE_ERR,
199 sizeof(BAD6) - 1,
201 #define BAD7 "bad characters %%1 "
203 BAD7,
204 NULL,
205 UNESCAPE_ERR,
208 sizeof(BAD7) - 1,
210 #define BAD8 "bad characters %sb "
212 BAD8,
213 NULL,
214 UNESCAPE_ERR,
217 sizeof(BAD8) - 1,
219 #define BAD_SSCANF "sscanf would be happy with this\n"
220 #define BAD_SSCANF_ESC "sscanf would be happy with this% a"
222 BAD_SSCANF_ESC,
223 BAD_SSCANF,
224 ESCAPE_NE | UNESCAPE_ERR,
225 sizeof(BAD_SSCANF) - 1,
226 sizeof(BAD_SSCANF) - 1,
227 sizeof(BAD_SSCANF_ESC) - 1,
229 /* now try some with zeros in. escaping can't see past zeros, and the result is truncated */
230 #define ZERO "%00"
231 #define ZERO_UNESC "\0"
233 ESCAPE4 ZERO ESCAPE4,
234 ESCAPE4_UNESC ZERO_UNESC ESCAPE4_UNESC,
235 ESCAPE_NE | UNESCAPE_EQ,
236 sizeof(ESCAPE4_UNESC ZERO_UNESC ESCAPE4_UNESC) - 1,
237 sizeof(ESCAPE4_UNESC) - 1,
238 sizeof(ESCAPE4 ZERO ESCAPE4) - 1,
241 ZERO ESCAPE4,
242 ZERO_UNESC ESCAPE4_UNESC,
243 ESCAPE_NE | UNESCAPE_EQ,
244 sizeof(ZERO_UNESC ESCAPE4_UNESC) - 1,
246 sizeof(ZERO ESCAPE4) - 1,
249 ZERO,
250 ZERO_UNESC,
251 ESCAPE_NE | UNESCAPE_EQ,
252 sizeof(ZERO_UNESC) - 1,
254 sizeof(ZERO) - 1,
257 spectrum_escaped,
258 spectrum,
259 ESCAPE_EQ | UNESCAPE_EQ,
260 255,
261 255,
262 255 * 3,
266 static struct rfc1738_test * dup_test(struct rfc1738_test *src)
268 struct rfc1738_test *dest = malloc(sizeof(*dest));
269 char *esc = NULL, *unesc = NULL;
270 if (dest == NULL) {
271 return NULL;
273 *dest = *src;
274 if (src->esc_len) {
275 esc = malloc(src->esc_len + 1);
276 if (esc == NULL) {
277 free(dest);
278 return NULL;
280 memcpy(esc, src->escaped, src->esc_len + 1);
281 dest->escaped = esc;
284 if (src->unesc_len) {
285 unesc = malloc(src->unesc_len + 1);
286 if (unesc == NULL) {
287 free(esc);
288 free(dest);
289 return NULL;
291 memcpy(unesc, src->unescaped, src->unesc_len + 1);
292 dest->unescaped = unesc;
295 return dest;
298 static void free_test(struct rfc1738_test *t)
300 free(discard_const_p(char, t->escaped));
301 free(discard_const_p(char, t->unescaped));
302 free(t);
306 static void test_unescape(void **state)
308 uint i;
309 char *s, *e;
310 struct rfc1738_test *test, *orig;
311 for (i = 0; i < ARRAY_SIZE(examples); i++) {
312 orig = &examples[i];
313 if ((orig->flags & (UNESCAPE_ERR |
314 UNESCAPE_EQ |
315 UNESCAPE_NE)) == 0) {
316 continue;
318 test = dup_test(&examples[i]);
319 s = discard_const_p(char, test->escaped);
320 e = rfc1738_unescape(s);
321 if (test->flags & UNESCAPE_ERR) {
322 assert_null(e);
323 free_test(test);
324 continue;
326 assert_non_null(e);
327 assert_int_equal(e - s, test->unesc_len);
329 if (test->flags & UNESCAPE_EQ) {
330 assert_memory_equal(s,
331 orig->unescaped,
332 orig->unesc_len);
333 assert_int_equal(strlen(s),
334 orig->unesc_strlen);
335 } else {
336 assert_memory_not_equal(s,
337 orig->unescaped,
338 orig->unesc_len);
339 assert_int_equal(strlen(s),
340 orig->unesc_strlen);
342 free_test(test);
346 static void test_escape(void **state)
348 uint i;
349 char *s, *e;
350 struct rfc1738_test *test, *orig;
351 for (i = 0; i < ARRAY_SIZE(examples); i++) {
352 orig = &examples[i];
353 if ((orig->flags & (ESCAPE_EQ |
354 ESCAPE_EQ_CASECMP |
355 ESCAPE_NE)) == 0) {
356 continue;
358 test = dup_test(&examples[i]);
359 s = discard_const_p(char, test->unescaped);
360 e = rfc1738_escape_part(NULL, s);
361 if (test->flags & ESCAPE_EQ) {
362 assert_memory_equal(e, test->escaped,
363 test->esc_len + 1);
364 } else if (test->flags & ESCAPE_EQ_CASECMP) {
365 int cmp = strcasecmp(e, test->escaped);
366 assert_int_equal(cmp, 0);
367 assert_string_not_equal(e, test->escaped);
368 } else {
369 assert_string_not_equal(e, test->escaped);
371 free_test(test);
376 static void gen_spectrum(void)
378 int i, j = 0;
379 const char *lut = "0123456789ABCDEF";
380 for (i = 1; i < 256; i++) {
381 spectrum[i - 1] = i;
382 if (isalnum(i) ||
383 i == '-' ||
384 i == '.' ||
385 i == '_' ||
386 i == '-' ||
387 i == '~') {
388 spectrum_escaped[j] = i;
389 j++;
390 } else {
391 spectrum_escaped[j] = '%';
392 spectrum_escaped[j + 1] = lut[i >> 4];
393 spectrum_escaped[j + 2] = lut[i & 15];
394 j += 3;
397 spectrum[i - 1] = '\0';
398 spectrum_escaped[j] = '\0';
401 int main(int argc, const char **argv)
403 const struct CMUnitTest tests[] = {
404 cmocka_unit_test(test_escape),
405 cmocka_unit_test(test_unescape),
408 gen_spectrum();
409 cmocka_set_message_output(CM_OUTPUT_SUBUNIT);
410 return cmocka_run_group_tests(tests, NULL, NULL);