#include "safestr.h" #include #include #include #define FAIL(why) \ do { \ fprintf(stderr, "%s\n", (why)); \ exit(1); \ } while (0) static void test_alloc(void) { int passed; safestr_t str; XXL_ASSET_BLOCK_BEGIN { str = safestr_alloc(512, SAFESTR_ASSET_TEMPORARY); if (safestr_length(str) != 0) FAIL("Allocated string has a length!"); } XXL_ASSET_BLOCK_END; XXL_TRY_BEGIN { passed = 0; safestr_free(str); } XXL_CATCH(SAFESTR_ERROR_BAD_ADDRESS) { passed = 1; } XXL_TRY_END; if (!passed) FAIL("SafeStr asset management didn't clean up properly!"); str = safestr_alloc(1, 0); safestr_reference(str); XXL_TRY_BEGIN { passed = 1; safestr_free(str); } XXL_CATCH(SAFESTR_ERROR_BAD_ADDRESS) { passed = 0; } XXL_TRY_END; if (!passed) FAIL("safestr_free(1) failed"); XXL_TRY_BEGIN { passed = 1; safestr_free(str); } XXL_CATCH(SAFESTR_ERROR_BAD_ADDRESS) { passed = 0; } XXL_TRY_END; if (!passed) FAIL("safestr_free(2) failed"); XXL_TRY_BEGIN { passed = 0; safestr_free(str); } XXL_CATCH(SAFESTR_ERROR_BAD_ADDRESS) { passed = 1; } XXL_TRY_END; if (!passed) FAIL("safestr_free(3) failed"); } static void test_create(void) { int passed; char *c_str; safestr_t clone, str; u_int32_t i; /* safestr_create() */ c_str = "A quick brown fox jumps over the lazy dog."; str = safestr_create(c_str, SAFESTR_IMMUTABLE); if (safestr_length(str) != strlen(c_str)) FAIL("String length after safestr_create() is wrong!"); /* safestr_charat() */ for (i = safestr_length(str); i > 0; i--) { if (safestr_charat(str, i - 1) != c_str[i - 1]) FAIL("safestr_charat() fails!"); } XXL_TRY_BEGIN { passed = 0; safestr_charat(str, safestr_length(str)); } XXL_CATCH(SAFESTR_ERROR_INDEX_OUT_OF_RANGE) { passed = 1; } XXL_TRY_END; if (!passed) FAIL("safestr_charat with index out of range failed to throw!"); /* safestr_setcharat(), immutability, etc. */ XXL_TRY_BEGIN { passed = 0; safestr_setcharat(str, 0, 'a', 1); } XXL_CATCH(SAFESTR_ERROR_IMMUTABLE_STRING) { passed = 1; } XXL_TRY_END; if (!passed) FAIL("safestr_setcharat on immutable string failed to throw!"); safestr_makewritable(str); safestr_setcharat(str, 0, 'a', 1); if (safestr_charat(str, 0) != 'a') FAIL("safestr_setcharat failed to modify the string!"); XXL_TRY_BEGIN { passed = 0; safestr_setcharat(str, safestr_length(str), 'X', 1); } XXL_CATCH(SAFESTR_ERROR_INDEX_OUT_OF_RANGE) { passed = 1; } XXL_TRY_END; if (!passed) FAIL("safestr_setcharat with index out of range failed to throw!"); safestr_setcharat(str, 0, 'A', 1); if (safestr_charat(str, 0) != 'A') FAIL("safestr_setcharat failed to modify the string (2)!"); safestr_makereadonly(str); XXL_TRY_BEGIN { passed = 0; safestr_setcharat(str, 0, 'X', 1); } XXL_CATCH(SAFESTR_ERROR_IMMUTABLE_STRING) { passed = 1; } XXL_TRY_END; if (!passed) FAIL("safestr_makereadonly failed to make the string immutable!"); /* safestr_clone() */ clone = safestr_clone(str, 0); if (safestr_length(clone) != safestr_length(str)) FAIL("Cloned string's length does not match source length!"); if (!safestr_equal(clone, str, 0)) { if (strcmp((char *)clone, (char *)str)) { printf("str: [%s]\nclone: [%s]\n", (char *)str, (char *)clone); FAIL("Cloned string's content is incorrect."); } FAIL("safestr_equal() failed to match two equal strings!"); } /* safestr_makereadonly(), safestr_makewritable(), safestr_isreadonly() */ if (!safestr_isreadonly(str)) FAIL("String isn't read-only as expected!"); safestr_makewritable(str); if (safestr_isreadonly(str)) FAIL("String is read-only and shouldn't be!"); safestr_makereadonly(str); if (!safestr_isreadonly(str)) FAIL("String isn't read-only and should be!"); safestr_makewritable(str); /* safestr_convert() */ c_str = "A QUICK BROWN FOX JUMPS OVER THE LAZY DOG."; safestr_convert(str, SAFESTR_CONVERT_UPPERCASE); if (!safestr_equal(str, SAFESTR_TEMP(c_str), 0)) { if (strcmp((char *)str, c_str)) { printf("str: [%s]\nc_str: [%s]\n", (char *)str, c_str); FAIL("Uppercase converted string's content is incorrect."); } FAIL("safestr_equal() failed to match two equal strings!"); } c_str = "a quick brown fox jumps over the lazy dog."; safestr_convert(str, SAFESTR_CONVERT_LOWERCASE); if (!safestr_equal(str, SAFESTR_TEMP(c_str), 0)) { if (strcmp((char *)str, c_str)) { printf("str: [%s]\nc_str: [%s]\n", (char *)str, c_str); FAIL("Lowercase convert string's content is incorrect."); } FAIL("safestr_equal() failed to match two equal strings!"); } c_str = "A Quick Brown Fox Jumps Over The Lazy Dog."; safestr_convert(str, SAFESTR_CONVERT_TITLECASE); if (!safestr_equal(str, SAFESTR_TEMP(c_str), 0)) { if (strcmp((char *)str, c_str)) { printf("str: [%s]\nc_str: [%s]\n", (char *)str, c_str); FAIL("Titlecase convert string's content is incorrect."); } FAIL("safestr_equal() failed to match two equal strings!"); } /* safestr_free() */ safestr_free(clone); safestr_free(str); XXL_TRY_BEGIN { passed = 0; safestr_free(str); } XXL_CATCH(SAFESTR_ERROR_BAD_ADDRESS) { passed = 1; } XXL_TRY_END; if (!passed) FAIL("safestr_free failed to free 'str'"); XXL_TRY_BEGIN { passed = 0; safestr_free(clone); } XXL_CATCH(SAFESTR_ERROR_BAD_ADDRESS) { passed = 1; } XXL_TRY_END; if (!passed) FAIL("safestr_free failed to free 'clone'"); } static void test_comparison(void) { char *c_str; safestr_t str1, str2; str1 = safestr_create("/Volumes/Music/iTunes/iTunes Music/Fischerspooner/Exclusive/Emerge.aac", 0); str2 = safestr_clone(str1, 0); if (!safestr_equal(str1, str2, 0)) FAIL("safestr_equal(1) failed!"); if (safestr_compare(str1, str2, 0)) FAIL("safestr_compare(1) failed!"); safestr_convert(str2, SAFESTR_CONVERT_LOWERCASE); if (!safestr_equal(str1, str2, SAFESTR_COMPARE_NOCASE)) FAIL("safestr_equal(2) failed!"); if (safestr_compare(str1, str2, SAFESTR_COMPARE_NOCASE)) FAIL("safestr_compare(2) failed!"); c_str = "/Volumes/Music/iTunes"; safestr_duplicate(&str2, SAFESTR_TEMP(c_str), 0); if (safestr_length(str2) != strlen(c_str)) FAIL("String length after safestr_duplicate() doesn't match!"); if (!safestr_equal(str2, SAFESTR_TEMP(c_str), 0)) { printf("str1: [%s]\nc_str: [%s]\n", (char *)str2, c_str); FAIL("Duplicated string contents don't match!"); } if (!safestr_equal(str1, str2, SAFESTR_COMPARE_LIMIT, safestr_length(str2))) FAIL("Limited safestr_equal doesn't match!"); if (safestr_compare(str1, str2, SAFESTR_COMPARE_LIMIT, safestr_length(str2))) FAIL("Limited safestr_compare doesn't match!"); safestr_free(str2); safestr_free(str1); } static void test_modify(void) { char *c_str; safestr_t str1; u_int32_t length; c_str = "A brown fox jumped over the stupid dog."; str1 = safestr_create(c_str, SAFESTR_TRUSTED); if (!safestr_istrusted(str1)) FAIL("String is not trusted as expected!"); if (safestr_length(str1) != strlen(c_str)) FAIL("String lengths don't match after safestr_create()!"); safestr_replace(&str1, SAFESTR_TEMP("jumped"), SAFESTR_TEMP("jumps")); c_str = "A brown fox jumps over the stupid dog."; if (!safestr_equal(str1, SAFESTR_TEMP(c_str), 0)) { printf("str1: [%s] length = %u\nc_str: [%s] length = %zu\n", (char *)str1, safestr_length(str1), c_str, strlen(c_str)); FAIL("Strings don't match after safestr_replace()!"); } if (safestr_istrusted(str1)) FAIL("String is trusted after safestr_replace() and shouldn't be!"); safestr_trust(str1); if (!safestr_istrusted(str1)) FAIL("String is not trusted after safestr_trust() and should be!"); safestr_replace(&str1, SAFESTR_TEMP("stupid"), SAFESTR_TEMP_TRUSTED("lazy")); if (!safestr_istrusted(str1)) FAIL("String isn't trusted after safestr_replace() and should be!"); safestr_untrust(str1); if (safestr_istrusted(str1)) FAIL("String is trusted after safestr_untrust() and shouldn't be!"); safestr_trust(str1); safestr_insert(&str1, 2, SAFESTR_TEMP_TRUSTED("quick and dirty ")); c_str = "A quick and dirty brown fox jumps over the lazy dog."; if (!safestr_equal(str1, SAFESTR_TEMP(c_str), 0)) { printf("str1: [%s]\nc_str: [%s]\n", (char *)str1, c_str); FAIL("Strings don't match after safestr_insert()!"); } if (!safestr_istrusted(str1)) FAIL("String isn't trusted after safestr_insert() and should be!"); safestr_delete(&str1, 8, 10); c_str = "A quick brown fox jumps over the lazy dog."; if (!safestr_equal(str1, SAFESTR_TEMP(c_str), 0)) { printf("str1: [%s]\nc_str: [%s]\n", (char *)str1, c_str); FAIL("Strings don't match after safestr_delete()!"); } length = safestr_length(str1); safestr_append(&str1, SAFESTR_TEMP(" Word.")); c_str = "A quick brown fox jumps over the lazy dog. Word."; if (!safestr_equal(str1, SAFESTR_TEMP(c_str), 0)) { printf("str1: [%s]\nc_str: [%s]\n", (char *)str1, c_str); FAIL("Strings don't match after safestr_concatenate()!"); } if (safestr_istrusted(str1)) FAIL("String is trusted after safestr_concatenate() and shouldn't be!"); safestr_delete(&str1, length, length); c_str = "A quick brown fox jumps over the lazy dog."; if (!safestr_equal(str1, SAFESTR_TEMP(c_str), 0)) { printf("str1: [%s]\nc_str: [%s]\n", (char *)str1, c_str); FAIL("Strings don't match after safestr_delete()! (2)"); } safestr_free(str1); } static char *c_array[] = { "A", "quick", "brown", "fox", "jumps", "over", "the", "lazy", "dog.", NULL }; static void test_arrays(void) { char *c_str; u_int32_t c_length, i, safe_length; safestr_t *safe_array, str; for (c_length = 0; c_array[c_length]; c_length++); safe_array = safestr_convertarray(c_array, SAFESTR_TRUSTED | SAFESTR_IMMUTABLE); for (safe_length = 0; safe_array[safe_length]; safe_length++); if (c_length != safe_length) FAIL("safestr_convertarray() array size doesn't match original!"); for (i = 0; safe_array[i]; i++) { if (!safestr_equal(safe_array[i], SAFESTR_TEMP(c_array[i]), 0)) FAIL("safestr_convertarray() array contents don't match original!"); } str = safestr_join(safe_array, SAFESTR_TEMP_TRUSTED(" ")); c_str = "A quick brown fox jumps over the lazy dog."; if (!safestr_equal(str, SAFESTR_TEMP(c_str), 0)) { printf("str: [%s]\nc_str: [%s]\n", (char *)str, c_str); FAIL("Strings don't match after safestr_join()!"); } if (!safestr_istrusted(str)) FAIL("String isn't trusted after safestr_join() and should be!"); for (i = 0; safe_array[i]; safestr_free(safe_array[i++])); free(safe_array); safe_array = safestr_split(str, SAFESTR_TEMP(" ")); for (safe_length = 0; safe_array[safe_length]; safe_length++); if (c_length != safe_length) FAIL("safestr_split() array size doesn't match original!"); for (i = 0; safe_array[i]; i++) { if (!safestr_equal(safe_array[i], SAFESTR_TEMP(c_array[i]), 0)) FAIL("safestr_split() array contents don't match original!"); } for (i = 0; safe_array[i]; safestr_free(safe_array[i++])); free(safe_array); safe_array = safestr_split(str, SAFESTR_TEMP("")); for (safe_length = 0; safe_array[safe_length]; safe_length++); if (strlen(c_str) != safe_length) FAIL("safestr_split() character array size doesn't match original!"); for (i = 0; safe_array[i]; i++) { if (safestr_length(safe_array[i]) != 1) FAIL("safestr_length() on character array element != 1!"); if (safestr_charat(safe_array[i], 0) != c_str[i]) FAIL("safestr_charat() on character array element != original!"); } safestr_free(str); for (i = 0; safe_array[i]; safestr_free(safe_array[i++])); free(safe_array); } static void test_misc(void) { char *c_str; safestr_t slice, str; u_int32_t idx; c_str = "A quick brown fox jumps over the lazy dog."; str = safestr_create(c_str, 0); idx = safestr_search(str, SAFESTR_TEMP("fox"), 0); if (idx != (u_int32_t)(strstr(c_str, "fox") - c_str)) FAIL("safestr_search() result not as expected!"); if (safestr_search(str, SAFESTR_TEMP("FOX"), SAFESTR_FIND_NOMATCHCASE) != idx) FAIL("safestr_search() case insensitive search result erroneous!"); if (safestr_search(str, SAFESTR_TEMP("fox"), SAFESTR_FIND_REVERSE) != idx) FAIL("safestr_search() reverse search result erroneous!"); if (safestr_search(str, SAFESTR_TEMP("foo"), 0) != SAFESTR_ERROR_NOTFOUND) FAIL("safestr_search() found non-existant substring!"); if (safestr_search(str, SAFESTR_TEMP("fox"), SAFESTR_FIND_FROMCHAR, 10) != idx) FAIL("safestr_search() w/FROMCHAR search result erroneous!"); c_str = "The house with the white fence is also painted white."; safestr_copy(&str, SAFESTR_TEMP(c_str)); idx = safestr_search(str, SAFESTR_TEMP("white"), 0); if (idx != (u_int32_t)(strstr(c_str, "white") - c_str)) FAIL("safestr_search() result not as expected! (2)"); idx = safestr_search(str, SAFESTR_TEMP("white"), SAFESTR_FIND_NTH, 2); if (idx != (u_int32_t)(strstr(strstr(c_str, "white") + 5, "white") - c_str)) FAIL("safestr_search() result not as expected! (3)"); idx = safestr_search(str, SAFESTR_TEMP("white"), SAFESTR_FIND_FROMNTH, 1); if (idx != (u_int32_t)(strstr(strstr(c_str, "white") + 5, "white") - c_str)) FAIL("safestr_search() result not as expected! (4)"); idx = safestr_search(str, SAFESTR_TEMP("white"), SAFESTR_FIND_REVERSE | SAFESTR_FIND_NTH, 2); if (idx != (u_int32_t)(strstr(c_str, "white") - c_str)) FAIL("safestr_search() reverse not as expected!"); c_str = "white."; idx = safestr_search(str, SAFESTR_TEMP("white"), SAFESTR_FIND_REVERSE); slice = safestr_slice(str, idx, safestr_length(str)); if (!safestr_equal(slice, SAFESTR_TEMP(c_str), 0)) { printf("slice: [%s]\nc_str: [%s]\n", (char *)slice, c_str); FAIL("Sliced string is not correct!"); } safestr_free(slice); c_str = "house"; slice = safestr_slice(str, 4, 4 + strlen(c_str)); if (!safestr_equal(slice, SAFESTR_TEMP(c_str), 0)) { printf("slice: [%s]\nc_str: [%s]\n", (char *)slice, c_str); FAIL("Sliced string is not correct! (2)"); } safestr_free(slice); safestr_truncate(&str, 0); if (safestr_length(str) != 0) FAIL("String length is wrong after first safestr_truncate()!"); safestr_truncate(&str, 10); if (safestr_length(str) != 10) FAIL("String length is wrong after second safestr_truncate()!"); c_str = " "; if (!safestr_equal(str, SAFESTR_TEMP(c_str), 0)) { printf("str: [%s]\nc_str: [%s]\n", (char *)str, c_str); FAIL("String contents are wrong after second safestr_truncate()!"); } c_str = " \t foo\t\t\t \t\t\t"; safestr_copy(&str, SAFESTR_TEMP(c_str)); safestr_trim(str, SAFESTR_TRIM_LEADING); if (!safestr_equal(str, SAFESTR_TEMP(c_str + 3), 0)) { printf("str: [%s]\nc_str: [%s]\n", (char *)str, c_str + 3); FAIL("String contents are wrong after leading space trim!"); } safestr_copy(&str, SAFESTR_TEMP(c_str)); safestr_trim(str, SAFESTR_TRIM_TRAILING); if (!safestr_equal(str, SAFESTR_TEMP(" \t foo"), 0)) { printf("str: [%s]\nc_str: [ \t foo]\n", (char *)str); FAIL("String contents are wrong after trailing space trim!"); } safestr_copy(&str, SAFESTR_TEMP(c_str)); safestr_trim(str, SAFESTR_TRIM_BOTH); if (!safestr_equal(str, SAFESTR_TEMP("foo"), 0)) { printf("str: [%s]\nc_str: [foo]\n", (char *)str); FAIL("String contents are wrong after leading AND trailing space trim!"); } safestr_copy(&str, SAFESTR_TEMP("0xdeadbeef")); if (safestr_toint32(str, 0) != (int32_t)0xdeadbeef) { printf("safestr_toint32(\"0xdeadbeef\", 0) == %#08x\n", safestr_toint32(str, 0)); FAIL("safestr_toint32(\"0xdeadbeef\", 0) FAILED"); } if (safestr_toint64(str, 0) != (int64_t)0xdeadbeef) { printf("safestr_toint64(\"0xdeadbeef\", 0) == %#08llx\n", safestr_toint64(str, 0)); FAIL("safestr_toint64(\"0xdeadbeef\", 0) FAILED"); } if (safestr_touint32(str, 0) != (u_int32_t)0xdeadbeef) { printf("safestr_touint32(\"0xdeadbeef\", 0) == %#08x\n", safestr_touint32(str, 0)); FAIL("safestr_touint32(\"0xdeadbeef\", 0) FAILED"); } if (safestr_touint64(str, 0) != (u_int64_t)0xdeadbeef) { printf("safestr_touint64(\"0xdeadbeef\", 0) == %#08llx\n", safestr_touint64(str, 0)); FAIL("safestr_touint64(\"0xdeadbeef\", 0) FAILED"); } safestr_copy(&str, SAFESTR_TEMP("0xDEADBEEF")); if (safestr_toint32(str, 16) != (int32_t)0xDEADBEEF) { printf("safestr_toint32(\"0xDEADBEEF\", 16) == %#08x\n", safestr_toint32(str, 16)); FAIL("safestr_toint32(\"0xDEADBEEF\", 16) FAILED"); } if (safestr_toint64(str, 16) != (int64_t)0xDEADBEEF) { printf("safestr_toint64(\"0xDEADBEEF\", 16) == %#08llx\n", safestr_toint64(str, 16)); FAIL("safestr_toint64(\"0xDEADBEEF\", 16) FAILED"); } if (safestr_touint32(str, 16) != (u_int32_t)0xDEADBEEF) { printf("safestr_touint32(\"0xDEADBEEF\", 16) == %#08x\n", safestr_touint32(str, 16)); FAIL("safestr_touint32(\"0xDEADBEEF\", 16) FAILED"); } if (safestr_touint64(str, 16) != (u_int64_t)0xDEADBEEF) { printf("safestr_touint64(\"0xDEADBEEF\", 16) == %#08llx\n", safestr_touint64(str, 16)); FAIL("safestr_touint64(\"0xDEADBEEF\", 16) FAILED"); } safestr_copy(&str, SAFESTR_TEMP("0177")); if (safestr_toint32(str, 8) != (int32_t)0177) { printf("safestr_toint32(\"0177\", 8) == %#08x\n", safestr_toint32(str, 8)); FAIL("safestr_toint32(\"0177\", 8) FAILED"); } if (safestr_toint64(str, 8) != (int64_t)0177) { printf("safestr_toint64(\"0177\", 8) == %#08llx\n", safestr_toint64(str, 8)); FAIL("safestr_toint64(\"0177\", 8) FAILED"); } if (safestr_touint32(str, 8) != (u_int32_t)0177) { printf("safestr_touint32(\"0177\", 8) == %#08x\n", safestr_touint32(str, 8)); FAIL("safestr_touint32(\"0177\", 8) FAILED"); } if (safestr_touint64(str, 8) != (u_int64_t)0177) { printf("safestr_touint64(\"0177\", 8) == %#08llx\n", safestr_touint64(str, 8)); FAIL("safestr_touint64(\"0177\", 8) FAILED"); } safestr_free(str); } typedef struct sprintf_int_t { char *fmt; char *expect; int value; } sprintf_int_t; static sprintf_int_t int_tests[] = { { "%6d", " 42", 42 }, /* 7 */ { "%6d", " -42", -42 }, /* 8 */ { "%+6d", " +42", 42 }, /* 9 */ { "%+6d", " -42", -42 }, /* 10 */ { "%-6d", "42 ", 42 }, /* 11 */ { "%-6d", "-42 ", -42 }, /* 12 */ { "%-+6d", "+42 ", 42 }, /* 13 */ { "%-+6d", "-42 ", -42 }, /* 14 */ { "%12.6d", " 004217", 4217 }, /* 15 */ { "%12.6d", " -004217", -4217 }, /* 16 */ { "%+12.6d", " +004217", 4217 }, /* 17 */ { "%+12.6d", " -004217", -4217 }, /* 18 */ { "%-12.6d", "004217 ", 4217 }, /* 19 */ { "%-12.6d", "-004217 ", -4217 }, /* 20 */ { "%-+12.6d", "+004217 ", 4217 }, /* 21 */ { "%-+12.6d", "-004217 ", -4217 }, /* 22 */ { "%06d", "000042", 42 }, /* 23 */ { "%06d", "-00042", -42 }, /* 24 */ { "%0+6d", "+00042", 42 }, /* 25 */ { "%0+6d", "-00042", -42 }, /* 26 */ { "%012.6d", " 000042", 42 }, /* 27 */ { "%012.6d", " -000042", -42 }, /* 28 */ { "%0+12.6d", " +000042", 42 }, /* 29 */ { "%0+12.6d", " -000042", -42 }, /* 30 */ { "%o", "52", 42 }, /* 31 */ { "%.o", "52", 42 }, /* 32 */ { "%#.o", "052", 42 }, /* 33 */ { "%x", "2a", 42 }, /* 34 */ { "%X", "2A", 42 }, /* 35 */ { "%.x", "2a", 42 }, /* 36 */ { "%08x", "0000002a", 42 }, /* 37 */ { "%#08x", "0x00002a", 42 }, /* 38 */ { "%#8x", " 0x2a", 42 }, /* 39 */ { "%#x", "0x2a", 42 }, /* 40 */ { "%#.x", "0x2a", 42 }, /* 41 */ { "%#.8x", "0x0000002a", 42 }, /* 42 */ { "%c", "*", 42 }, /* 43 */ { "%p", "0x00007a69", 31337 }, /* 44 */ { NULL, NULL, 0 }, }; typedef struct sprintf_float_t { char *fmt; char *expect; double value; } sprintf_float_t; /* Good enough for now since we're just basically testing to make sure that * the whole format string gets passed through to the underlying sprintf() * function, which is really shitty since not all platforms have %a/%A */ static sprintf_float_t float_tests[] = { { "%#e", "4.217000e+01", 42.17 }, /* 45 */ { "%#f", "42.170000", 42.17 }, /* 46 */ { "%#g", "42.1700", 42.17 }, /* 47 */ { NULL, NULL, 0 }, }; #define SPRINTF_TEST(num) \ do { \ if (!safestr_equal(str, SAFESTR_TEMP(c_str), 0)) { \ printf("str: [%s] length = %u\nc_str: [%s] length = %zu\n", \ (char *)str, safestr_length(str), \ c_str, strlen(c_str)); \ FAIL("safestr_sprintf() test #" #num " FAILED"); \ } \ } while (0) static void test_sprintf(void) { int i; char *c_str, msg[256]; safestr_t str; sprintf_int_t *int_test; sprintf_float_t *float_test; str = safestr_alloc(0, 0); /* String Tests */ c_str = "This is a simple test."; safestr_sprintf(&str, SAFESTR_TEMP(c_str)); SPRINTF_TEST(1); c_str = "Is the SafeStr library working?"; safestr_sprintf(&str, SAFESTR_TEMP("%s"), SAFESTR_TEMP(c_str)); SPRINTF_TEST(2); c_str = "safestr "; safestr_sprintf(&str, SAFESTR_TEMP("%-10s"), SAFESTR_TEMP("safestr")); SPRINTF_TEST(3); c_str = " safestr"; safestr_sprintf(&str, SAFESTR_TEMP("%10s"), SAFESTR_TEMP("safestr")); SPRINTF_TEST(4); c_str = "safe"; safestr_sprintf(&str, SAFESTR_TEMP("%.4s"), SAFESTR_TEMP("safestr")); SPRINTF_TEST(5); c_str = ""; safestr_sprintf(&str, SAFESTR_TEMP("%.s"), SAFESTR_TEMP("safestr")); SPRINTF_TEST(6); /* Integer Tests */ i = 7; for (int_test = int_tests; int_test->fmt; int_test++, i++) { safestr_sprintf(&str, SAFESTR_TEMP(int_test->fmt), int_test->value); if (!safestr_equal(str, SAFESTR_TEMP(int_test->expect), 0)) { printf("got: [%s] length = %u\nexpect: [%s] length = %zu\n", (char *)str, safestr_length(str), int_test->expect, strlen(int_test->expect)); sprintf(msg, "safestr_sprintf() test #%d FAILED", i); FAIL(msg); } } /* Floating Point Tests */ for (float_test = float_tests; float_test->fmt; float_test++, i++) { safestr_sprintf(&str, SAFESTR_TEMP(float_test->fmt), float_test->value); if (!safestr_equal(str, SAFESTR_TEMP(float_test->expect), 0)) { printf("got: [%s] length = %u\nexpect: [%s] length = %zu\n", (char *)str, safestr_length(str), float_test->expect, strlen(float_test->expect)); sprintf(msg, "safestr_sprintf() test #%d FAILED", i); FAIL(msg); } } safestr_free(str); } static void test_readline(void) { char c_str[256]; FILE *f; safestr_t str; /* First create a temporary file to read from with safestr_readline() */ f = fopen("safetest.txt", "w"); memset(c_str, 'x', 42); c_str[42] = '\0'; fprintf(f, "%s\n", c_str); memset(c_str, 'x', 110); c_str[110] = '\0'; fprintf(f, "%s\n", c_str); memset(c_str, 'x', 250); c_str[250] = '\0'; fprintf(f, "%s\n", c_str); fclose(f); /* Open the file we just created and read from it with safestr_readline() */ f = fopen("safetest.txt", "r"); memset(c_str, 'x', 42); c_str[42] = '\0'; str = safestr_readline(f); if (!safestr_equal(str, SAFESTR_TEMP(c_str), 0)) { fclose(f); remove("safetest.txt"); printf("str: [%s]\nc_str: [%s]\n", (char *)str, c_str); FAIL("safestr_readline() length of 42 failed!"); } safestr_free(str); memset(c_str, 'x', 110); c_str[110] = '\0'; str = safestr_readline(f); if (!safestr_equal(str, SAFESTR_TEMP(c_str), 0)) { fclose(f); remove("safetest.txt"); printf("str: [%s]\nc_str: [%s]\n", (char *)str, c_str); FAIL("safestr_readline() length of 110 failed!"); } safestr_free(str); memset(c_str, 'x', 250); c_str[250] = '\0'; str = safestr_readline(f); if (!safestr_equal(str, SAFESTR_TEMP(c_str), 0)) { fclose(f); remove("safetest.txt"); printf("str: [%s]\nc_str: [%s]\n", (char *)str, c_str); FAIL("safestr_readline() length of 250 failed!"); } safestr_free(str); /* cleanup */ fclose(f); remove("safetest.txt"); } int main(int argc, char *argv[]) { char *tmp; tmp = safestr_strdup(argv[0]); if (strcmp(tmp, argv[0])) FAIL("safestr_strdup failed"); free(tmp); test_alloc(); test_create(); test_comparison(); test_modify(); test_arrays(); test_misc(); test_sprintf(); test_readline(); #if 0 if (isatty(fileno(stdin))) { safestr_t password; password = safestr_getpassword(NULL, SAFESTR_TEMP("Enter a password: ")); printf("Got: [%s]\n", (char *)password); safestr_free(password); } #endif exit(0); return 0; }