/* we compile as C90 but use snprintf */ #define _ISOC99_SOURCE #include #include #include #include "minunit.h" #include "modp_burl.h" /** * Test empty input to encode and decode */ static char* testUrlEmpty(void) { size_t d; char buf[1000]; buf[0] = 1; d = modp_burl_encode(buf, "", (size_t)0); mu_assert_int_equals(d, 0); mu_assert(buf[0] == 0); buf[0] = 1; d = modp_burl_decode(buf, "", (size_t)0); mu_assert_int_equals(d, 0); mu_assert(buf[0] == 0); return 0; } /** * Handle gracefully null inputs, with 0 length. */ static char* testUrlEmptyNull(void) { size_t d; char buf[1000]; buf[0] = 1; d = modp_burl_encode(buf, NULL, (size_t)0); mu_assert_int_equals(d, 0); mu_assert(buf[0] == 0); buf[0] = 1; d = modp_burl_decode(buf, NULL, (size_t)0); mu_assert_int_equals(d, 0); mu_assert(buf[0] == 0); return 0; } /** * test space <--> plus conversion */ static char* testUrlSpaces(void) { size_t d = 0; char buf[1000]; const char* input = " "; const char* output = "+++"; d = modp_burl_encode(buf, input, strlen(input)); mu_assert_int_equals(d, strlen(output)); mu_assert_str_equals(buf, output); d = modp_burl_decode(buf, output, strlen(output)); mu_assert_int_equals(d, strlen(input)); mu_assert_str_equals(buf, input); return 0; } /** * Test charactes that should be unchanged */ static char* testUrlUntouched(void) { const char* lower = "abcdefghijklmnopqrstuvwxyz"; const char* upper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; const char* digits = "0123456789"; const char* special = ".-_"; char buf[1000]; size_t d = 0; memset(buf, 0, sizeof(buf)); d = modp_burl_encode(buf, lower, strlen(lower)); mu_assert_int_equals(d, strlen(lower)); mu_assert_str_equals(buf, lower); memset(buf, 0, sizeof(buf)); d = modp_burl_decode(buf, lower, strlen(lower)); mu_assert_int_equals(d, strlen(lower)); mu_assert_str_equals(buf, lower); memset(buf, 0, sizeof(buf)); d = modp_burl_encode(buf, upper, strlen(upper)); mu_assert_int_equals(d, strlen(upper)); mu_assert_str_equals(buf, upper); memset(buf, 0, sizeof(buf)); d = modp_burl_decode(buf, upper, strlen(upper)); mu_assert_int_equals(d, strlen(upper)); mu_assert_str_equals(buf, upper); memset(buf, 0, sizeof(buf)); d = modp_burl_encode(buf, digits, strlen(digits)); mu_assert_int_equals(d, strlen(digits)); mu_assert_str_equals(buf, digits); memset(buf, 0, sizeof(buf)); d = modp_burl_decode(buf, digits, strlen(digits)); mu_assert_int_equals(d, strlen(digits)); mu_assert_str_equals(buf, digits); memset(buf, 0, sizeof(buf)); d = modp_burl_encode(buf, special, strlen(special)); mu_assert_int_equals(d, strlen(special)); mu_assert_str_equals(buf, special); memset(buf, 0, sizeof(buf)); d = modp_burl_decode(buf, special, strlen(special)); mu_assert_int_equals(d, strlen(special)); mu_assert_str_equals(buf, special); return 0; } /** * Test charactes that should be unchanged */ static char* testUrlMinUntouched(void) { const char* lower = "abcdefghijklmnopqrstuvwxyz"; const char* upper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; const char* digits = "0123456789"; const char* special = ".-_"; const char* extra = "~!$()*,;:@/?"; char buf[1000]; size_t d = 0; memset(buf, 0, sizeof(buf)); d = modp_burl_min_encode(buf, lower, strlen(lower)); mu_assert_int_equals(d, strlen(lower)); mu_assert_str_equals(buf, lower); memset(buf, 0, sizeof(buf)); d = modp_burl_decode(buf, lower, strlen(lower)); mu_assert_int_equals(d, strlen(lower)); mu_assert_str_equals(buf, lower); memset(buf, 0, sizeof(buf)); d = modp_burl_min_encode(buf, upper, strlen(upper)); mu_assert_int_equals(d, strlen(upper)); mu_assert_str_equals(buf, upper); memset(buf, 0, sizeof(buf)); d = modp_burl_decode(buf, upper, strlen(upper)); mu_assert_int_equals(d, strlen(upper)); mu_assert_str_equals(buf, upper); memset(buf, 0, sizeof(buf)); d = modp_burl_min_encode(buf, digits, strlen(digits)); mu_assert_int_equals(d, strlen(digits)); mu_assert_str_equals(buf, digits); memset(buf, 0, sizeof(buf)); d = modp_burl_decode(buf, digits, strlen(digits)); mu_assert_int_equals(d, strlen(digits)); mu_assert_str_equals(buf, digits); memset(buf, 0, sizeof(buf)); d = modp_burl_min_encode(buf, special, strlen(special)); mu_assert_int_equals(d, strlen(special)); mu_assert_str_equals(buf, special); memset(buf, 0, sizeof(buf)); d = modp_burl_decode(buf, special, strlen(special)); mu_assert_int_equals(d, strlen(special)); mu_assert_str_equals(buf, special); memset(buf, 0, sizeof(buf)); d = modp_burl_min_encode(buf, extra, strlen(extra)); mu_assert_int_equals(d, strlen(extra)); mu_assert_str_equals(buf, extra); memset(buf, 0, sizeof(buf)); d = modp_burl_decode(buf, extra, strlen(extra)); mu_assert_int_equals(d, strlen(extra)); mu_assert_str_equals(buf, extra); return 0; } /** \brief make sure min encoding actually does hex encoding * */ static char* testUrlMinEncodeHex(void) { char buf[1000]; size_t d = 0; memset(buf, 0, sizeof(buf)); const char* str1 = "a b"; d = modp_burl_min_encode(buf, str1, strlen(str1)); mu_assert_int_equals(3, d); mu_assert_str_equals("a+b", buf); memset(buf, 0, sizeof(buf)); const char* str2 = "ab\n"; d = modp_burl_min_encode(buf, str2, strlen(str2)); mu_assert_int_equals(5, d); mu_assert_str_equals("ab%0A", buf); return 0; } static char* testUrlDecodeHexBad(void) { const char* bad1 = "%0X"; /* bad trailing char */ const char* bad2 = "%X0"; /* bad leading char */ const char* bad3 = "%XX"; /* bad chars */ const char* bad4 = "%2"; /* not enough room, good char */ const char* bad5 = "%X"; /* not enought room, bad char */ const char* bad6 = "%"; /* test oddball */ const char* bad7 = "AA%"; /* test end of line */ char bad8[4]; /* %XX where X is high bit (test sign char vs. uint8_t*) */ bad8[0] = '%'; bad8[1] = (char)0x81; bad8[2] = (char)0x82; bad8[3] = (char)0; size_t d = 0; char buf[1000]; memset(buf, 0, sizeof(buf)); d = modp_burl_decode(buf, bad1, strlen(bad1)); mu_assert_int_equals(d, strlen(bad1)); mu_assert_str_equals(buf, bad1); memset(buf, 0, sizeof(buf)); d = modp_burl_decode(buf, bad2, strlen(bad2)); mu_assert_int_equals(d, strlen(bad2)); mu_assert_str_equals(bad2, buf); memset(buf, 0, sizeof(buf)); d = modp_burl_decode(buf, bad3, strlen(bad3)); mu_assert_int_equals(d, strlen(bad3)); mu_assert_str_equals(buf, bad3); memset(buf, 0, sizeof(buf)); d = modp_burl_decode(buf, bad4, strlen(bad4)); mu_assert_int_equals(d, strlen(bad4)); mu_assert_str_equals(buf, bad4); memset(buf, 0, sizeof(buf)); d = modp_burl_decode(buf, bad5, strlen(bad5)); mu_assert_int_equals(d, strlen(bad5)); mu_assert_str_equals(buf, bad5); memset(buf, 0, sizeof(buf)); d = modp_burl_decode(buf, bad6, strlen(bad6)); mu_assert_int_equals(d, strlen(bad6)); mu_assert_str_equals(buf, bad6); memset(buf, 0, sizeof(buf)); d = modp_burl_decode(buf, bad7, strlen(bad7)); mu_assert_int_equals(d, strlen(bad7)); mu_assert_str_equals(buf, bad7); memset(buf, 0, sizeof(buf)); d = modp_burl_decode(buf, bad8, strlen(bad8)); mu_assert_int_equals(d, strlen(bad8)); mu_assert_str_equals(buf, bad8); return 0; } static char* testUrlDecodeHex(void) { size_t d; /* size of output */ int i, j; /* loops */ int k = 0; /* position in inputbuf; */ char inputbuf[3 * 256 + 1]; char output[257]; char msg[1000]; /* make input string contain every possible "%XX" */ static const char* hexdigits1 = "0123456789ABCDEF"; memset(inputbuf, 0, sizeof(inputbuf)); memset(output, 1, sizeof(output)); k = 0; for (i = 0; i < 16; ++i) { for (j = 0; j < 16; ++j) { inputbuf[k++] = '%'; inputbuf[k++] = hexdigits1[i]; inputbuf[k++] = hexdigits1[j]; } } d = modp_burl_decode(output, inputbuf, sizeof(inputbuf) - 1); mu_assert_int_equals(d, 256); for (i = 0; i < 256; ++i) { sprintf(msg, "Loop at %d", i); mu_assert_int_equals_msg(msg, i, (unsigned char)output[i]); } /* make input string contain every possible "%XX" */ static const char* hexdigits2 = "0123456789abcdef"; memset(inputbuf, 0, sizeof(inputbuf)); memset(output, 1, sizeof(output)); k = 0; for (i = 0; i < 16; ++i) { for (j = 0; j < 16; ++j) { inputbuf[k++] = '%'; inputbuf[k++] = hexdigits2[i]; inputbuf[k++] = hexdigits2[j]; } } d = modp_burl_decode(output, inputbuf, sizeof(inputbuf) - 1); mu_assert_int_equals(256, d); for (i = 0; i < 256; ++i) { sprintf(msg, "Loop at %d", i); mu_assert_int_equals_msg(msg, i, (unsigned char)output[i]); } return 0; } /** * test hex encoding.. to be done after hex decoding * is tested. */ static char* testHexEncoding(void) { int i = 0; size_t d = 0; char msg[1000]; char input[257]; memset(input, 0, sizeof(input)); char output[257 * 3]; memset(output, 0, sizeof(output)); char buf[1000]; memset(buf, 0, sizeof(buf)); d = modp_burl_encode(output, input, (size_t)256); d = modp_burl_decode(buf, output, d); mu_assert_int_equals(256, d); for (i = 0; i < 256; ++i) { sprintf(msg, "Loop at %d failed", i); mu_assert_int_equals_msg(msg, input[i], buf[i]); } return 0; } static char* testEncodeStrlen(void) { char ibuf[100]; char obuf[100]; memset(ibuf, 0, sizeof(ibuf)); memset(obuf, 0, sizeof(obuf)); /* Empty. should be 0 */ ibuf[0] = 0; mu_assert_int_equals(strlen(ibuf), (size_t)modp_burl_encode_strlen(ibuf, strlen(ibuf))); /* Plain, should be same size */ strcpy(ibuf, "abcdefg"); mu_assert_int_equals(strlen(ibuf), (size_t)modp_burl_encode_strlen(ibuf, strlen(ibuf))); /* Plain and spaces, should be same size */ strcpy(ibuf, "a b c d e f g"); mu_assert_int_equals(strlen(ibuf), (size_t)modp_burl_encode_strlen(ibuf, strlen(ibuf))); /* one bad char, adds two bytes */ strcpy(ibuf, "abcdefg\n"); mu_assert_int_equals(strlen(ibuf) + 2, (size_t)modp_burl_encode_strlen(ibuf, strlen(ibuf))); /* 2 bad chars, adds 4 bytes */ strcpy(ibuf, "\nabcdefg\n"); mu_assert_int_equals(strlen(ibuf) + 4, (size_t)modp_burl_encode_strlen(ibuf, strlen(ibuf))); return 0; } /** \brief test "modp_burl_min_encode_strlen" * */ static char* testEncodeMinStrlen(void) { char ibuf[100]; char obuf[100]; memset(ibuf, 0, sizeof(ibuf)); memset(obuf, 0, sizeof(obuf)); /* Empty. should be 0 */ ibuf[0] = 0; mu_assert_int_equals(strlen(ibuf), (size_t)modp_burl_min_encode_strlen(ibuf, strlen(ibuf))); /* Plain, should be same size */ strcpy(ibuf, "abcdefg"); mu_assert_int_equals(strlen(ibuf), (size_t)modp_burl_min_encode_strlen(ibuf, strlen(ibuf))); /* Plain and spaces, should be same size */ strcpy(ibuf, "a b c d e f g"); mu_assert_int_equals(strlen(ibuf), (size_t)modp_burl_min_encode_strlen(ibuf, strlen(ibuf))); /* one bad char, adds two bytes */ strcpy(ibuf, "abcdefg\n"); mu_assert_int_equals(strlen(ibuf) + 2, (size_t)modp_burl_min_encode_strlen(ibuf, strlen(ibuf))); /* 2 bad chars, adds 4 bytes */ strcpy(ibuf, "\nabcdefg\n"); mu_assert_int_equals(strlen(ibuf) + 4, (size_t)modp_burl_min_encode_strlen(ibuf, strlen(ibuf))); return 0; } static char* all_tests(void) { mu_run_test(testUrlUntouched); mu_run_test(testUrlEmpty); mu_run_test(testUrlEmptyNull); mu_run_test(testUrlSpaces); mu_run_test(testUrlDecodeHex); mu_run_test(testUrlDecodeHexBad); mu_run_test(testHexEncoding); mu_run_test(testEncodeStrlen); mu_run_test(testUrlMinUntouched); mu_run_test(testUrlMinEncodeHex); mu_run_test(testEncodeMinStrlen); return 0; } UNITTESTS