| 1 | #include "tests/test_internal.h" |
| 2 | |
| 3 | TEST_GROUP_DEFINE(string); |
| 4 | |
| 5 | TEST_DEFINE_UNIT(string, strncmp_edge) { |
| 6 | TEST_ASSERT_EQ(strncmp("a" , "a" , 2), 0); |
| 7 | TEST_ASSERT_EQ(strncmp("" , "" , 1), 0); |
| 8 | TEST_ASSERT_EQ(strncmp("a" , "b" , 0), 0); |
| 9 | TEST_ASSERT_EQ(strncmp("abcd" , "abce" , 3), 0); |
| 10 | TEST_ASSERT(strncmp("abcd" , "abce" , 4) < 0); |
| 11 | TEST_ASSERT(strncmp("abce" , "abcd" , 4) > 0); |
| 12 | TEST_ASSERT(strncmp("a" , "ab" , 2) < 0); |
| 13 | TEST_ASSERT(strncmp("ab" , "a" , 2) > 0); |
| 14 | const char high[] = {(char) 0x80, 0}; |
| 15 | TEST_ASSERT(strncmp(high, "\x7f" , 1) > 0); |
| 16 | TEST_ASSERT(strncmp("\x7f" , high, 1) < 0); |
| 17 | const char a[] = {'a', 'b'}; |
| 18 | const char b[] = {'a', 'b'}; |
| 19 | TEST_ASSERT_EQ(strncmp(a, b, sizeof(a)), 0); |
| 20 | return TEST_SUCCESS; |
| 21 | } |
| 22 | |
| 23 | TEST_DEFINE_UNIT(string, memmem_binary) { |
| 24 | const unsigned char h[] = {0x80, 0, 0xff, 0x80, 0, 0xff}; |
| 25 | const unsigned char n[] = {0, 0xff}; |
| 26 | TEST_ASSERT_PTR_EQ(memmem(h, sizeof(h), n, sizeof(n)), h + 1); |
| 27 | TEST_ASSERT_PTR_EQ(memmem(h, sizeof(h), h, sizeof(h)), h); |
| 28 | TEST_ASSERT_PTR_EQ(memmem(h, sizeof(h), n, 0), h); |
| 29 | TEST_ASSERT_PTR_EQ(memmem(h, 0, n, 0), h); |
| 30 | TEST_ASSERT_NULL(memmem(h, 0, n, sizeof(n))); |
| 31 | TEST_ASSERT_NULL(memmem(h, 1, n, sizeof(n))); |
| 32 | TEST_ASSERT_NULL(memmem(h, 2, n, sizeof(n))); |
| 33 | TEST_ASSERT_NULL(memmem(h, sizeof(h), "x" , 1)); |
| 34 | const char repeated[] = "aaaaab" ; |
| 35 | TEST_ASSERT_PTR_EQ(memmem(repeated, 6, "aaab" , 4), repeated + 2); |
| 36 | return TEST_SUCCESS; |
| 37 | } |
| 38 | |
| 39 | TEST_DEFINE_UNIT(string, bounded_substring_search) { |
| 40 | const char h[] = {'a', 'B', 'c', 'D', 'e'}; |
| 41 | TEST_ASSERT_PTR_EQ(strnstr(h, "BcD" , sizeof(h)), h + 1); |
| 42 | TEST_ASSERT_PTR_EQ(strnstr(h, "De" , sizeof(h)), h + 3); |
| 43 | TEST_ASSERT_NULL(strnstr(h, "BcD" , 3)); |
| 44 | TEST_ASSERT_NULL(strnstr(h, "bcd" , sizeof(h))); |
| 45 | TEST_ASSERT_PTR_EQ(strncasestr(h, "bCd" , 4), h + 1); |
| 46 | TEST_ASSERT_NULL(strncasestr(h, "bCd" , 3)); |
| 47 | TEST_ASSERT_PTR_EQ(strncasestr(h, "dE" , sizeof(h)), h + 3); |
| 48 | TEST_ASSERT_PTR_EQ(strnstr(h, "" , 0), h); |
| 49 | TEST_ASSERT_PTR_EQ(strncasestr(h, "" , 0), h); |
| 50 | TEST_ASSERT_NULL(strnstr(h, "a" , 0)); |
| 51 | TEST_ASSERT_NULL(strncasestr(h, "a" , 0)); |
| 52 | TEST_ASSERT_NULL(strnstr(h, "abcdef" , sizeof(h))); |
| 53 | TEST_ASSERT_NULL(strncasestr(h, "abcdef" , sizeof(h))); |
| 54 | const char terminated[] = {'a', 0, 'B', 0}; |
| 55 | TEST_ASSERT_NULL(strnstr(terminated, "B" , sizeof(terminated))); |
| 56 | TEST_ASSERT_NULL(strncasestr(terminated, "b" , sizeof(terminated))); |
| 57 | TEST_ASSERT_NULL(strnstr("" , "a" , 1)); |
| 58 | TEST_ASSERT_NULL(strncasestr("" , "a" , 1)); |
| 59 | const char high[] = {(char) 0xff, 'A', 0}; |
| 60 | const char needle[] = {(char) 0xff, 'a', 0}; |
| 61 | TEST_ASSERT_PTR_EQ(strncasestr(high, needle, 2), high); |
| 62 | const char repeated[] = "aAaAab" ; |
| 63 | TEST_ASSERT_PTR_EQ(strncasestr(repeated, "AAab" , 6), repeated + 2); |
| 64 | return TEST_SUCCESS; |
| 65 | } |
| 66 | |
| 67 | TEST_DEFINE_UNIT(string, end_pointer_copies) { |
| 68 | char dst[8]; |
| 69 | memset(dst, '!', sizeof(dst)); |
| 70 | TEST_ASSERT_PTR_EQ(stpcpy(dst, "abc" ), dst + 3); |
| 71 | TEST_ASSERT_EQ(memcmp(dst, "abc\0!" , 5), 0); |
| 72 | TEST_ASSERT_PTR_EQ(stpcpy(dst, "" ), dst); |
| 73 | TEST_ASSERT_EQ(dst[0], 0); |
| 74 | |
| 75 | memset(dst, '!', sizeof(dst)); |
| 76 | TEST_ASSERT_PTR_EQ(stpncpy(dst, "ab" , 5), dst + 2); |
| 77 | TEST_ASSERT_EQ(memcmp(dst, "ab\0\0\0!" , 6), 0); |
| 78 | TEST_ASSERT_PTR_EQ(stpncpy(dst, "" , 3), dst); |
| 79 | TEST_ASSERT_EQ(memcmp(dst, "\0\0\0" , 3), 0); |
| 80 | |
| 81 | memset(dst, '!', sizeof(dst)); |
| 82 | const char src[] = {'a', 'b', 'c'}; |
| 83 | TEST_ASSERT_PTR_EQ(stpncpy(dst, src, sizeof(src)), dst + 3); |
| 84 | TEST_ASSERT_EQ(memcmp(dst, "abc!" , 4), 0); |
| 85 | TEST_ASSERT_PTR_EQ(stpncpy(dst, "abcdef" , 2), dst + 2); |
| 86 | TEST_ASSERT_EQ(dst[2], 'c'); |
| 87 | TEST_ASSERT_PTR_EQ(stpncpy(dst, "ignored" , 0), dst); |
| 88 | TEST_ASSERT_EQ(memcmp(dst, "abc!" , 4), 0); |
| 89 | |
| 90 | const unsigned char binary[] = {0x80, 0, 0xff}; |
| 91 | TEST_ASSERT_PTR_EQ(mempcpy(dst, binary, sizeof(binary)), dst + 3); |
| 92 | TEST_ASSERT_EQ(memcmp(dst, binary, sizeof(binary)), 0); |
| 93 | TEST_ASSERT_EQ(dst[3], '!'); |
| 94 | TEST_ASSERT_PTR_EQ(mempcpy(dst, binary, 0), dst); |
| 95 | TEST_ASSERT_EQ(memcmp(dst, binary, sizeof(binary)), 0); |
| 96 | return TEST_SUCCESS; |
| 97 | } |
| 98 | |
| 99 | TEST_DEFINE_UNIT(string, ascii_classification) { |
| 100 | for (int c = -1; c <= 256; c++) { |
| 101 | TEST_ASSERT_EQ(!!isblank(c), c == ' ' || c == '\t'); |
| 102 | TEST_ASSERT_EQ(!!iscntrl(c), (c >= 0 && c <= 31) || c == 127); |
| 103 | TEST_ASSERT_EQ(!!isgraph(c), c >= 33 && c <= 126); |
| 104 | TEST_ASSERT_EQ(!!ispunct(c), |
| 105 | (c >= 33 && c <= 47) || (c >= 58 && c <= 64) || |
| 106 | (c >= 91 && c <= 96) || (c >= 123 && c <= 126)); |
| 107 | TEST_ASSERT_EQ(!!isxdigit(c), (c >= '0' && c <= '9') || |
| 108 | (c >= 'A' && c <= 'F') || |
| 109 | (c >= 'a' && c <= 'f')); |
| 110 | } |
| 111 | return TEST_SUCCESS; |
| 112 | } |
| 113 | |
| 114 | TEST_DEFINE_UNIT(string, strcasestr_patterns) { |
| 115 | const char h[] = "aAbAaBaAbAaX" ; |
| 116 | TEST_ASSERT_PTR_EQ(strcasestr(h, "" ), h); |
| 117 | TEST_ASSERT_PTR_EQ(strcasestr(h, "AABAAX" ), h + 6); |
| 118 | TEST_ASSERT_PTR_EQ(strcasestr(h, "aab" ), h); |
| 119 | TEST_ASSERT_NULL(strcasestr(h, "aabac" )); |
| 120 | TEST_ASSERT_NULL(strcasestr("short" , "longer_needle" )); |
| 121 | TEST_ASSERT_NULL(strcasestr("" , "a" )); |
| 122 | const char high[] = {(char) 0xff, 'A', 0}; |
| 123 | const char needle[] = {(char) 0xff, 'a', 0}; |
| 124 | TEST_ASSERT_PTR_EQ(strcasestr(high, needle), high); |
| 125 | return TEST_SUCCESS; |
| 126 | } |
| 127 | |
| 128 | TEST_DEFINE_UNIT(string, strstr_patterns) { |
| 129 | /* Giving an empty needle returns start of haystack */ |
| 130 | const char *h1 = "abcdef" ; |
| 131 | TEST_ASSERT_PTR_EQ(strstr(h1, "" ), h1); |
| 132 | |
| 133 | TEST_ASSERT_NULL(strstr("short" , "longer_needle" )); |
| 134 | |
| 135 | TEST_ASSERT_NONNULL(strstr("hello" , "hello" )); |
| 136 | |
| 137 | /* KMP prefix backtracking */ |
| 138 | const char *h2 = "aabaabaabaax" ; |
| 139 | const char *n2 = "aabaax" ; |
| 140 | char *match2 = strstr(haystack: h2, needle: n2); |
| 141 | TEST_ASSERT_NONNULL(match2); |
| 142 | TEST_ASSERT_PTR_EQ(match2, h2 + 6); |
| 143 | |
| 144 | /* trailing */ |
| 145 | const char *h3 = "aaaaab" ; |
| 146 | const char *n3 = "aaab" ; |
| 147 | char *match3 = strstr(haystack: h3, needle: n3); |
| 148 | TEST_ASSERT_NONNULL(match3); |
| 149 | TEST_ASSERT_PTR_EQ(match3, h3 + 2); |
| 150 | |
| 151 | TEST_ASSERT_NULL(strstr("ababababa" , "ababc" )); |
| 152 | |
| 153 | return TEST_SUCCESS; |
| 154 | } |
| 155 | |