1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4 -*- */
2 /* vi: set expandtab shiftwidth=4 tabstop=4: */
3 
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <string.h>
7 #include "modp_burl.h"
8 #include "minunit.h"
9 
10 /**
11  * Test empty input to encode and decode
12  */
testUrlEmpty()13 static char* testUrlEmpty()
14 {
15     int d;
16     char buf[1000];
17     buf[0] = 1;
18     d = modp_burl_encode(buf, "", 0);
19     mu_assert_int_equals(d, 0);
20     mu_assert(buf[0] == 0);
21 
22     buf[0] = 1;
23     d = modp_burl_decode(buf, "", 0);
24     mu_assert_int_equals(d, 0);
25     mu_assert(buf[0] == 0);
26 
27     return 0;
28 }
29 
30 /**
31  * test space <--> plus conversion
32  */
testUrlSpaces()33 static char* testUrlSpaces()
34 {
35     size_t d = 0;
36     char buf[1000];
37     const char* input = "   ";
38     const char* output = "+++";
39 
40     d = modp_burl_encode(buf, input, strlen(input));
41     mu_assert_int_equals(d, strlen(output));
42     mu_assert_str_equals(buf, output);
43 
44     d = modp_burl_decode(buf, output, strlen(output));
45     mu_assert_int_equals(d, strlen(input));
46     mu_assert_str_equals(buf, input);
47 
48     return 0;
49 }
50 
51 /**
52  * Test charactes that should be unchanged
53  */
testUrlUntouched()54 static char* testUrlUntouched()
55 {
56     const char* lower = "abcdefghijklmnopqrstuvwxyz";
57     const char* upper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
58     const char* digits = "0123456789";
59     const char* special = ".-_";
60     char buf[1000];
61     size_t d = 0;
62 
63     memset(buf, 0, sizeof(buf));
64     d = modp_burl_encode(buf, lower, strlen(lower));
65     mu_assert_int_equals(d, strlen(lower));
66     mu_assert_str_equals(buf, lower);
67     memset(buf, 0, sizeof(buf));
68     d = modp_burl_decode(buf, lower, strlen(lower));
69     mu_assert_int_equals(d, strlen(lower));
70     mu_assert_str_equals(buf, lower);
71 
72     memset(buf, 0, sizeof(buf));
73     d = modp_burl_encode(buf, upper, strlen(upper));
74     mu_assert_int_equals(d, strlen(upper));
75     mu_assert_str_equals(buf, upper);
76     memset(buf, 0, sizeof(buf));
77     d = modp_burl_decode(buf, upper, strlen(upper));
78     mu_assert_int_equals(d, strlen(upper));
79     mu_assert_str_equals(buf, upper);
80 
81     memset(buf, 0, sizeof(buf));
82     d = modp_burl_encode(buf, digits, strlen(digits));
83     mu_assert_int_equals(d, strlen(digits));
84     mu_assert_str_equals(buf, digits);
85     memset(buf, 0, sizeof(buf));
86     d = modp_burl_decode(buf, digits, strlen(digits));
87     mu_assert_int_equals(d, strlen(digits));
88     mu_assert_str_equals(buf, digits);
89 
90     memset(buf, 0, sizeof(buf));
91     d = modp_burl_encode(buf, special, strlen(special));
92     mu_assert_int_equals(d, strlen(special));
93     mu_assert_str_equals(buf, special);
94     memset(buf, 0, sizeof(buf));
95     d = modp_burl_decode(buf, special, strlen(special));
96     mu_assert_int_equals(d, strlen(special));
97     mu_assert_str_equals(buf, special);
98 
99     return 0;
100 }
101 
102 
103 /**
104  * Test charactes that should be unchanged
105  */
testUrlMinUntouched()106 static char* testUrlMinUntouched()
107 {
108     const char* lower   = "abcdefghijklmnopqrstuvwxyz";
109     const char* upper   = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
110     const char* digits  = "0123456789";
111     const char* special = ".-_";
112     const char* extra = "~!$()*,;:@/?";
113     char buf[1000];
114     size_t d = 0;
115 
116     memset(buf, 0, sizeof(buf));
117     d = modp_burl_min_encode(buf, lower, strlen(lower));
118     mu_assert_int_equals(d, strlen(lower));
119     mu_assert_str_equals(buf, lower);
120     memset(buf, 0, sizeof(buf));
121     d = modp_burl_decode(buf, lower, strlen(lower));
122     mu_assert_int_equals(d, strlen(lower));
123     mu_assert_str_equals(buf, lower);
124 
125     memset(buf, 0, sizeof(buf));
126     d = modp_burl_min_encode(buf, upper, strlen(upper));
127     mu_assert_int_equals(d, strlen(upper));
128     mu_assert_str_equals(buf, upper);
129     memset(buf, 0, sizeof(buf));
130     d = modp_burl_decode(buf, upper, strlen(upper));
131     mu_assert_int_equals(d, strlen(upper));
132     mu_assert_str_equals(buf, upper);
133 
134     memset(buf, 0, sizeof(buf));
135     d = modp_burl_min_encode(buf, digits, strlen(digits));
136     mu_assert_int_equals(d, strlen(digits));
137     mu_assert_str_equals(buf, digits);
138     memset(buf, 0, sizeof(buf));
139     d = modp_burl_decode(buf, digits, strlen(digits));
140     mu_assert_int_equals(d, strlen(digits));
141     mu_assert_str_equals(buf, digits);
142 
143     memset(buf, 0, sizeof(buf));
144     d = modp_burl_min_encode(buf, special, strlen(special));
145     mu_assert_int_equals(d, strlen(special));
146     mu_assert_str_equals(buf, special);
147     memset(buf, 0, sizeof(buf));
148     d = modp_burl_decode(buf, special, strlen(special));
149     mu_assert_int_equals(d, strlen(special));
150     mu_assert_str_equals(buf, special);
151 
152     memset(buf, 0, sizeof(buf));
153     d = modp_burl_min_encode(buf, extra, strlen(extra));
154     mu_assert_int_equals(d, strlen(extra));
155     mu_assert_str_equals(buf, extra);
156     memset(buf, 0, sizeof(buf));
157     d = modp_burl_decode(buf, extra, strlen(extra));
158     mu_assert_int_equals(d, strlen(extra));
159     mu_assert_str_equals(buf, extra);
160 
161     return 0;
162 }
163 
164 /** \brief make sure min encoding actually does hex encoding
165  *
166  */
testUrlMinEncodeHex()167 static char* testUrlMinEncodeHex()
168 {
169     char buf[1000];
170     size_t d = 0;
171 
172     memset(buf, 0, sizeof(buf));
173     const char* str1 = "a b";
174     d = modp_burl_min_encode(buf, str1, strlen(str1));
175     mu_assert_int_equals(3, d);
176     mu_assert_str_equals("a+b", buf);
177 
178     memset(buf, 0, sizeof(buf));
179     const char* str2 = "ab\n";
180     d = modp_burl_min_encode(buf, str2, strlen(str2));
181     mu_assert_int_equals(5, d);
182     mu_assert_str_equals("ab%0A", buf);
183 
184     return 0;
185 }
186 
testUrlDecodeHexBad()187 static char* testUrlDecodeHexBad()
188 {
189 
190     const char* bad1 = "%0X"; // bad trailing char
191     const char* bad2 = "%X0"; // bad leading char
192     const char* bad3 = "%XX"; // bad chars
193     const char* bad4 = "%2"; // not enough room, good char
194     const char* bad5 = "%X"; // not enought room, bad char
195     const char* bad6 = "%";  // test oddball
196     const char* bad7 = "AA%"; // test end of line
197     char bad8[4]; // %XX where X is high bit (test sign char vs. uint8_t*)
198     bad8[0] = '%';
199     bad8[1] = 0x81;
200     bad8[2] = 0x82;
201     bad8[3] = 0;
202 
203     size_t d = 0;
204     char buf[1000];
205 
206     memset(buf, 0, sizeof(buf));
207     d = modp_burl_decode(buf, bad1, strlen(bad1));
208     mu_assert_int_equals(d, strlen(bad1));
209     mu_assert_str_equals(buf, bad1);
210 
211     memset(buf, 0, sizeof(buf));
212     d = modp_burl_decode(buf, bad2, strlen(bad2));
213     mu_assert_int_equals(d, strlen(bad2));
214     mu_assert_str_equals(bad2, buf);
215 
216     memset(buf, 0, sizeof(buf));
217     d = modp_burl_decode(buf, bad3, strlen(bad3));
218     mu_assert_int_equals(d, strlen(bad3));
219     mu_assert_str_equals(buf, bad3);
220 
221     memset(buf, 0, sizeof(buf));
222     d = modp_burl_decode(buf, bad4, strlen(bad4));
223     mu_assert_int_equals(d, strlen(bad4));
224     mu_assert_str_equals(buf, bad4);
225 
226     memset(buf, 0, sizeof(buf));
227     d = modp_burl_decode(buf, bad5, strlen(bad5));
228     mu_assert_int_equals(d, strlen(bad5));
229     mu_assert_str_equals(buf, bad5);
230 
231     memset(buf, 0, sizeof(buf));
232     d= modp_burl_decode(buf, bad6, strlen(bad6));
233     mu_assert_int_equals(d, strlen(bad6));
234     mu_assert_str_equals(buf, bad6);
235 
236     memset(buf, 0, sizeof(buf));
237     d= modp_burl_decode(buf, bad7, strlen(bad7));
238     mu_assert_int_equals(d, strlen(bad7));
239     mu_assert_str_equals(buf, bad7);
240 
241     memset(buf, 0, sizeof(buf));
242     d = modp_burl_decode(buf, bad8, strlen(bad8));
243     mu_assert_int_equals(d, strlen(bad8));
244     mu_assert_str_equals(buf, bad8);
245     return 0;
246 
247     return 0;
248 }
249 
testUrlDecodeHex()250 static char* testUrlDecodeHex()
251 {
252     int d; // size of output
253     int i, j; // loops
254     int k = 0; // position in inputbuf;
255     char inputbuf[3*256+1];
256     char output[257];
257     char msg[1000];
258 
259     // make input string contain every possible "%XX"
260     static const char* hexdigits1 = "0123456789ABCDEF";
261     memset(inputbuf, 0, sizeof(inputbuf));
262     memset(output, 1, sizeof(output));
263     k = 0;
264     for (i = 0; i < 16; ++i) {
265         for (j = 0; j < 16; ++j) {
266             inputbuf[k++] = '%';
267             inputbuf[k++] = hexdigits1[i];
268             inputbuf[k++] = hexdigits1[j];
269         }
270     }
271 
272     d = modp_burl_decode(output, inputbuf, sizeof(inputbuf)-1);
273     mu_assert_int_equals(d, 256);
274     for (i = 0; i < 256; ++i) {
275         sprintf(msg, "Loop at %d", i);
276         mu_assert_int_equals_msg(msg, i, (unsigned char) output[i]);
277     }
278 
279     // make input string contain every possible "%XX"
280     static const char* hexdigits2 = "0123456789abcdef";
281     memset(inputbuf, 0, sizeof(inputbuf));
282     memset(output, 1, sizeof(output));
283 
284     k = 0;
285     for (i = 0; i < 16; ++i) {
286         for (j = 0; j < 16; ++j) {
287             inputbuf[k++] = '%';
288             inputbuf[k++] = hexdigits2[i];
289             inputbuf[k++] = hexdigits2[j];
290         }
291     }
292 
293     d = modp_burl_decode(output, inputbuf, sizeof(inputbuf)-1);
294     mu_assert_int_equals(256, d);
295     for (i = 0; i < 256; ++i) {
296         sprintf(msg, "Loop at %d", i);
297         mu_assert_int_equals_msg(msg, i, (unsigned char)output[i]);
298     }
299     return 0;
300 }
301 
302 /**
303  * test hex encoding.. to be done after hex decoding
304  * is tested.
305  */
testHexEncoding()306 static char* testHexEncoding()
307 {
308     int i = 0;
309     int d = 0;
310     char msg[1000];
311     char input[257];
312     memset(input, 0, sizeof(input));
313     char output[257*3];
314     memset(output, 0, sizeof(output));
315     char buf[1000];
316     memset(buf, 0, sizeof(buf));
317     d = modp_burl_encode(output, input, 256);
318     d = modp_burl_decode(buf, output, d);
319     mu_assert_int_equals(256, d);
320     for (i= 0; i < 256; ++i) {
321         sprintf(msg, "Loop at %d failed", i);
322         mu_assert_int_equals_msg(msg, input[i], buf[i]);
323     }
324     return 0;
325 }
326 
testEncodeStrlen()327 static char* testEncodeStrlen()
328 {
329     char ibuf[100];
330     char obuf[100];
331     memset(ibuf, 0, sizeof(ibuf));
332     memset(obuf, 0, sizeof(obuf));
333 
334     // Empty.  should be 0
335     ibuf[0] = 0;
336     mu_assert_int_equals(strlen(ibuf), (size_t) modp_burl_encode_strlen(ibuf, strlen(ibuf)));
337 
338     // Plain, should be same size
339     strcpy(ibuf, "abcdefg");
340     mu_assert_int_equals(strlen(ibuf), (size_t) modp_burl_encode_strlen(ibuf, strlen(ibuf)));
341 
342     // Plain and spaces, should be same size
343     strcpy(ibuf, "a b c d e f g");
344     mu_assert_int_equals(strlen(ibuf), (size_t) modp_burl_encode_strlen(ibuf, strlen(ibuf)));
345 
346     // one bad char, adds two bytes
347     strcpy(ibuf, "abcdefg\n");
348     mu_assert_int_equals(strlen(ibuf)+2, (size_t) modp_burl_encode_strlen(ibuf, strlen(ibuf)));
349 
350     // 2 bad chars, adds 4 bytes
351     strcpy(ibuf, "\nabcdefg\n");
352     mu_assert_int_equals(strlen(ibuf)+4, (size_t) modp_burl_encode_strlen(ibuf, strlen(ibuf)));
353     return 0;
354 }
355 
356 
357 /** \brief test "modp_burl_min_encode_strlen"
358  *
359  */
testEncodeMinStrlen()360 static char* testEncodeMinStrlen()
361 {
362     char ibuf[100];
363     char obuf[100];
364     memset(ibuf, 0, sizeof(ibuf));
365     memset(obuf, 0, sizeof(obuf));
366 
367     // Empty.  should be 0
368     ibuf[0] = 0;
369     mu_assert_int_equals(strlen(ibuf), (size_t) modp_burl_min_encode_strlen(ibuf, strlen(ibuf)));
370 
371     // Plain, should be same size
372     strcpy(ibuf, "abcdefg");
373     mu_assert_int_equals(strlen(ibuf), (size_t) modp_burl_min_encode_strlen(ibuf, strlen(ibuf)));
374 
375     // Plain and spaces, should be same size
376     strcpy(ibuf, "a b c d e f g");
377     mu_assert_int_equals(strlen(ibuf), (size_t) modp_burl_min_encode_strlen(ibuf, strlen(ibuf)));
378 
379     // one bad char, adds two bytes
380     strcpy(ibuf, "abcdefg\n");
381     mu_assert_int_equals(strlen(ibuf)+2, (size_t) modp_burl_min_encode_strlen(ibuf, strlen(ibuf)));
382 
383     // 2 bad chars, adds 4 bytes
384     strcpy(ibuf, "\nabcdefg\n");
385     mu_assert_int_equals(strlen(ibuf)+4, (size_t) modp_burl_min_encode_strlen(ibuf, strlen(ibuf)));
386     return 0;
387 }
388 
all_tests()389 static char* all_tests()
390 {
391     mu_run_test(testUrlUntouched);
392     mu_run_test(testUrlEmpty);
393     mu_run_test(testUrlSpaces);
394     mu_run_test(testUrlDecodeHex);
395     mu_run_test(testUrlDecodeHexBad);
396     mu_run_test(testHexEncoding);
397     mu_run_test(testEncodeStrlen);
398     mu_run_test(testUrlMinUntouched);
399     mu_run_test(testUrlMinEncodeHex);
400     mu_run_test(testEncodeMinStrlen);
401     return 0;
402 }
403 
404 UNITTESTS
405 
406