Pick three bugfixes from next branch to trunk for inclusion in 4.5.0 RC2, as discusse...
[sdcc.git] / sdcc / support / regression / tests / string.c
blobe8ce4cdef9a1e231eca12086c5fca4ac885a07a2
1 /** tests for strXXX
2 */
3 #include <testfwk.h>
4 #include <string.h>
5 #include <stdlib.h>
6 #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199409L
7 #include <wchar.h>
8 #endif
9 #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
10 #if defined(__APPLE__) || defined(__OpenBSD__) // As of 2023, macOS and OpenBSD are still not fully C11-compliant: they lack uchar.h.
11 // Work around Apple's missing uchar.h
12 #include <stdint.h>
13 typedef int_least16_t char16_t;
14 typedef int_least32_t char32_t;
15 #else
16 #include <uchar.h> // For char16_t, char32_t
17 #endif
18 #endif
20 /** tests for strcmp
22 static void
23 do_teststrcmp (void)
25 #ifndef __SDCC_pdk14 // Lack of memory
26 #if !(defined (__SDCC_pdk15) && defined(__SDCC_STACK_AUTO)) // Lack of code memory
27 int result = strcmp ("", "");
28 ASSERT (result == 0);
30 result = strcmp ("", "a");
31 ASSERT (result < 0);
33 result = strcmp ("a", "");
34 ASSERT (result > 0);
36 result = strcmp ("ab", "ab");
37 ASSERT (result == 0);
39 result = strcmp ("aa", "ab");
40 ASSERT (result < 0);
41 #endif
42 #endif
45 /** tests for strcpy
47 static void
48 do_teststrcpy (void)
50 #ifndef __SDCC_pdk14 // Lack of memory
51 #if !(defined (__SDCC_pdk15) && defined(__SDCC_STACK_AUTO)) // Lack of code memory
52 static char empty[] = "";
53 static char string[] = "\1\2\0\3";
54 char buf[40] = "abcdefghijklmnopqrstuvwxyz";
56 char * result = strcpy (buf, empty);
57 ASSERT (strlen (buf) == 0);
58 ASSERT (result == buf);
60 result = strcpy (buf, string);
61 ASSERT (result == buf);
62 ASSERT (strlen (buf) == 2);
63 ASSERT (buf[0] == '\1');
64 ASSERT (buf[1] == '\2');
65 ASSERT (buf[3] == 'd');
66 #endif
67 #endif
70 /** tests for strncmp
72 static void
73 do_teststrncmp (void)
75 #ifndef __SDCC_pdk14 // Lack of memory
76 #if !(defined (__SDCC_pdk15) && defined(__SDCC_STACK_AUTO)) // Lack of code memory
77 ASSERT (strncmp ("", "", 0) == 0);
78 ASSERT (strncmp ("ab", "ab", 0) == 0);
79 ASSERT (strncmp ("a", "a", 2) == 0);
80 ASSERT (strncmp ("aa", "ab", 1) == 0);
81 ASSERT (strncmp ("aa", "ab", 2) < 0);
82 ASSERT (strncmp ("abc", "abd", 2) == 0);
83 ASSERT (strncmp ("abc", "abc", 3) == 0);
84 #endif
85 #endif
88 /** tests for strpbrk
89 * related to bug #2908537
91 static void
92 do_teststrpbrk (void)
94 #if !defined(__SDCC_pdk14) && !defined(__SDCC_pdk15) // Lack of memory
95 const char *a = "test";
97 ASSERT (strpbrk (a, "e") == &a[1] );
98 ASSERT (strpbrk (a, "z") == NULL );
99 ASSERT (strpbrk (a, "et") == &a[0] );
100 ASSERT (strpbrk (a, "ze") == &a[1] );
101 ASSERT (strpbrk (a, "") == NULL );
102 ASSERT (strpbrk ("", "e") == NULL );
103 ASSERT (*strpbrk ("test2", "s") == 's' );
104 #endif
107 /** tests for strrchr
109 static void
110 do_teststrrchr (void)
112 #if !defined(__SDCC_pdk14) && !defined(__SDCC_pdk15) // Lack of memory
113 const char *test = "test";
115 ASSERT (strrchr (test, 0) == test + 4);
116 ASSERT (strrchr (test, 't') == test + 3);
117 ASSERT (strrchr (test, 'e') == test + 1);
118 #endif
121 /** tests for strstr
123 static void
124 do_teststrstr (void)
126 #if !defined(__SDCC_pdk14) && !defined(__SDCC_pdk15) // Lack of memory
127 const char *a = "aabbcd";
128 ASSERT (strstr (a, "\0\1") == a);
129 ASSERT (strstr (a, "") == a);
130 ASSERT (strstr (a, "ab") == &a[1]);
131 ASSERT (strstr (a, "abc") == NULL);
132 ASSERT (strstr (a, "abbc") == &a[1]);
133 ASSERT (strstr ("", "abbc") == NULL);
134 /* ASSERT (strstr ("", "") == a); should work, but it doesn't */
135 ASSERT (strstr (a, "cd") == &a[4]);
136 #endif
139 /** tests for strspn
141 static void
142 do_teststrspn (void)
144 #if !defined(__SDCC_pdk14) && !defined(__SDCC_pdk15) // Lack of memory
145 ASSERT (strspn("aabbcd", "ab") == 4);
146 ASSERT (strspn("abbacd", "") == 0);
147 ASSERT (strspn("abbacd", "ac") == 1);
148 ASSERT (strspn("abbacd", "x") == 0);
149 ASSERT (strspn("abbacd", "c") == 0);
150 ASSERT (strspn("abbacd", "cba") == 5);
151 ASSERT (strspn("abbacd", "cdba") == 6);
152 #endif
155 /** tests for strtok
157 static void
158 do_teststrtok (void)
160 #if !defined(__SDCC_pdk14) && !defined(__SDCC_pdk15) // Lack of memory
161 static char str[] = "?a???b,,,#c";
162 char str2[] = "axaaba";
163 char *token = strtok (str, "?"); // 'token' points to the token "a"
164 ASSERT (token == &str[1] && 0 == strcmp (token,"a"));
165 token = strtok (NULL, ","); // 'token' points to the token "??b"
166 ASSERT (token == &str[3] && 0 == strcmp (token,"??b"));
167 token = strtok (NULL, "#,"); // 'token' points to the token "c"
168 ASSERT (token == &str[10] && 0 == strcmp (token,"c"));
169 token = strtok (NULL, "?"); // 'token' is a null pointer
170 ASSERT (token == NULL);
172 token = strtok (str2, "ab");
173 ASSERT (token && 0 == strcmp (token, "x"));
174 token = strtok (NULL, "ab");
175 ASSERT (token == NULL);
176 #if !defined (__SUNPRO_C) && !defined (__sun__)
177 /* SunPro C compiler and GCC on Solaris have problem with strtok-ing after NULL */
178 token = strtok (NULL, "a");
179 ASSERT (token == NULL);
180 #endif
181 #endif
184 #if !defined (__APPLE__) // uchar.h/char16_t/char32_t are not supported on MacOS/Clang
186 // Test C11 UTF-8 behaviour.
187 static void
188 do_utf_8 (void)
190 #ifndef __SDCC_pdk14 // Lack of memory
191 #if defined(__STDC_VERSION) && __STDC_VERSION >= 201112L
192 const char *str1 = u8"Ä ä";
193 const char *str2 = u8"\u00c4 ä";
194 const char *str3 = u8"Ä " "ä";
195 const char *str4 = u8"Ä " u8"ä";
196 const char *str5 = "Ä " u8"ä";
198 ASSERT (str1[0] == 0xc3);
199 ASSERT (str2[1] == 0x84);
200 ASSERT (!strcmp (str1, str2));
201 ASSERT (!strcmp (str1, str3));
202 ASSERT (!strcmp (str1, str4));
203 ASSERT (!strcmp (str1, str5));
204 #endif
205 #endif
208 // Test SDCC implementation-defined UTF-8 behaviour
209 // string literals are UTF-8 (as nearly all implementations out there)
210 static void
211 do_utf_8_sdcc (void)
213 #ifndef __SDCC_pdk14 // Lack of memory
214 #if !(defined (__SDCC_pdk15) && defined(__SDCC_STACK_AUTO)) // Lack of code memory
215 #ifdef __SDCC
216 const char *str1 = "Ä ä";
217 const char *str2 = "\u00c4 ä";
218 const char *str3 = u8"Ä " "ä";
219 const char *str4 = "Ä " "ä";
220 const char *str5 = u8"Ä " u8"ä";
222 ASSERT (str1[0] == 0xc3);
223 ASSERT (str2[1] == 0x84);
224 ASSERT (!strcmp (str1, str2));
225 ASSERT (!strcmp (str1, str3));
226 ASSERT (!strcmp (str1, str4));
227 ASSERT (!strcmp (str1, str5));
229 ASSERT (!mblen(0, 0));
230 ASSERT (mblen(str1, 3) == 2);
231 ASSERT (mblen("test", 3) == 1);
232 ASSERT (mblen("", 3) == 0);
233 #endif
234 #endif
235 #endif
238 // Test C11 UTF-16 behaviour
239 static void
240 do_utf_16 (void)
242 #if defined(__STDC_UTF_16__) && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
243 const char16_t *str1 = u"Ä ä";
244 const char16_t *str2 = u"\u00c4 ä";
245 const char16_t *str3 = u"Ä " "ä";
246 const char16_t *str4 = "Ä " u"ä";
247 const char16_t *str5 = u"Ä " u"ä";
249 ASSERT (str1[0] == 0xc4);
250 ASSERT (str2[2] == 0xe4);
251 ASSERT (!memcmp (str1, str2, 4 * sizeof(char16_t)));
252 ASSERT (!memcmp (str1, str3, 4 * sizeof(char16_t)));
253 ASSERT (!memcmp (str1, str4, 4 * sizeof(char16_t)));
254 ASSERT (!memcmp (str1, str5, 4 * sizeof(char16_t)));
255 #endif
258 // Test C95 UTF-32 behaviour
259 static void
260 do_utf_32_c95 (void)
262 #ifndef __SDCC_pdk14 // Lack of memory
263 #if !(defined (__SDCC_pdk15) && defined(__SDCC_STACK_AUTO)) // Lack of code memory
264 #ifdef __STDC_ISO_10646__
265 const wchar_t *str1 = L"Ä ä";
266 const wchar_t *str2 = L"\u00c4 ä";
267 const wchar_t *str3 = L"Ä " "ä";
268 const wchar_t *str4 = "Ä " L"ä";
269 const wchar_t *str5 = L"Ä " L"ä";
271 ASSERT (str1[0] == 0xc4);
272 ASSERT (str2[2] == 0xe4);
273 ASSERT (wcslen (str1) == 3);
274 ASSERT (!memcmp (str1, str2, 4 * sizeof(wchar_t)));
275 ASSERT (!memcmp (str1, str3, 4 * sizeof(wchar_t)));
276 ASSERT (!memcmp (str1, str4, 4 * sizeof(wchar_t)));
277 ASSERT (!memcmp (str1, str5, 4 * sizeof(wchar_t)));
278 #endif
279 #endif
280 #endif
283 // Test C11 UTF-32 behaviour
284 static void
285 do_utf_32_c11 (void)
287 #if defined(__STDC_UTF_32__) && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
288 const char32_t *str1 = U"Ä ä";
289 const char32_t *str2 = U"\u00c4 ä";
290 const char32_t *str3 = U"Ä " "ä";
291 const char32_t *str4 = "Ä " U"ä";
292 const char32_t *str5 = U"Ä " U"ä";
294 ASSERT (str1[0] == 0xc4);
295 ASSERT (str2[2] == 0xe4);
296 ASSERT (!memcmp (str1, str2, 4 * sizeof(char32_t)));
297 ASSERT (!memcmp (str1, str3, 4 * sizeof(char32_t)));
298 ASSERT (!memcmp (str1, str4, 4 * sizeof(char32_t)));
299 ASSERT (!memcmp (str1, str5, 4 * sizeof(char32_t)));
300 #endif
303 static void
304 do_chinese (void)
306 #if defined(__STDC_UTF_32__) && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
307 const char32_t *p0 = U"史斌";
308 #endif
309 #ifdef __STDC_ISO_10646__
310 const wchar_t *p1 = L"史庭芳";
311 #endif
312 #if defined(__STDC_UTF_16__) && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
313 const char16_t *p2 = u"天津";
314 #endif
315 #if defined(__STDC_UTF_32__) && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
316 ASSERT (p0[0] == 0x53f2);
317 #endif
318 #ifdef __STDC_ISO_10646__
319 ASSERT (p1[2] == 0x82b3);
320 #endif
321 #if defined(__STDC_UTF_16__) && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
322 ASSERT (p2[1] == 0x6d25);
323 #endif
326 #endif // __APPLE__
328 static void
329 teststr (void)
331 do_teststrcmp ();
332 do_teststrcpy ();
333 do_teststrncmp ();
334 do_teststrpbrk ();
335 do_teststrrchr ();
336 do_teststrstr ();
337 do_teststrspn ();
338 do_teststrtok ();
339 #if !defined (__APPLE__)
340 do_utf_8 ();
341 do_utf_8_sdcc ();
342 do_utf_16 ();
343 do_utf_32_c95 ();
344 do_utf_32_c11 ();
345 do_chinese ();
346 #endif // __APPLE__