1#include "tests/test_internal.h"
2
3TEST_GROUP_DEFINE(string);
4
5TEST_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
23TEST_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
39TEST_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
67TEST_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
99TEST_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
114TEST_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
128TEST_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