acpi: Add a method to write tables for a device
[oweals/u-boot.git] / test / unicode_ut.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Unit tests for Unicode functions
4  *
5  * Copyright (c) 2018 Heinrich Schuchardt <xypron.glpk@gmx.de>
6  */
7
8 #include <common.h>
9 #include <charset.h>
10 #include <command.h>
11 #include <errno.h>
12 #include <malloc.h>
13 #include <test/test.h>
14 #include <test/suites.h>
15 #include <test/ut.h>
16
17 /* Linker list entry for a Unicode test */
18 #define UNICODE_TEST(_name) UNIT_TEST(_name, 0, unicode_test)
19
20 /* Constants c1-c4 and d1-d4 encode the same letters */
21
22 /* Six characters translating to one utf-8 byte each. */
23 static const u16 c1[] = {0x55, 0x2d, 0x42, 0x6f, 0x6f, 0x74, 0x00};
24 /* One character translating to two utf-8 bytes */
25 static const u16 c2[] = {0x6b, 0x61, 0x66, 0x62, 0xe1, 0x74, 0x75, 0x72, 0x00};
26 /* Three characters translating to three utf-8 bytes each */
27 static const u16 c3[] = {0x6f5c, 0x6c34, 0x8266, 0x00};
28 /* Three letters translating to four utf-8 bytes each */
29 static const u16 c4[] = {0xd801, 0xdc8d, 0xd801, 0xdc96, 0xd801, 0xdc87,
30                          0x0000};
31
32 /* Illegal utf-16 strings */
33 static const u16 i1[] = {0x69, 0x31, 0xdc87, 0x6c, 0x00};
34 static const u16 i2[] = {0x69, 0x32, 0xd801, 0xd801, 0x6c, 0x00};
35 static const u16 i3[] = {0x69, 0x33, 0xd801, 0x00};
36
37 /* Six characters translating to one utf-16 word each. */
38 static const char d1[] = {0x55, 0x2d, 0x42, 0x6f, 0x6f, 0x74, 0x00};
39 /* Eight characters translating to one utf-16 word each */
40 static const char d2[] = {0x6b, 0x61, 0x66, 0x62, 0xc3, 0xa1, 0x74, 0x75,
41                           0x72, 0x00};
42 /* Three characters translating to one utf-16 word each */
43 static const char d3[] = {0xe6, 0xbd, 0x9c, 0xe6, 0xb0, 0xb4, 0xe8, 0x89,
44                           0xa6, 0x00};
45 /* Three letters translating to two utf-16 word each */
46 static const char d4[] = {0xf0, 0x90, 0x92, 0x8d, 0xf0, 0x90, 0x92, 0x96,
47                           0xf0, 0x90, 0x92, 0x87, 0x00};
48
49 /* Illegal utf-8 strings */
50 static const char j1[] = {0x6a, 0x31, 0xa1, 0x6c, 0x00};
51 static const char j2[] = {0x6a, 0x32, 0xc3, 0xc3, 0x6c, 0x00};
52 static const char j3[] = {0x6a, 0x33, 0xf0, 0x90, 0xf0, 0x00};
53
54 static int unicode_test_u16_strlen(struct unit_test_state *uts)
55 {
56         ut_asserteq(6, u16_strlen(c1));
57         ut_asserteq(8, u16_strlen(c2));
58         ut_asserteq(3, u16_strlen(c3));
59         ut_asserteq(6, u16_strlen(c4));
60         return 0;
61 }
62 UNICODE_TEST(unicode_test_u16_strlen);
63
64 static int unicode_test_u16_strdup(struct unit_test_state *uts)
65 {
66         u16 *copy = u16_strdup(c4);
67
68         ut_assert(copy != c4);
69         ut_assert(!memcmp(copy, c4, sizeof(c4)));
70         free(copy);
71         return 0;
72 }
73 UNICODE_TEST(unicode_test_u16_strdup);
74
75 static int unicode_test_u16_strcpy(struct unit_test_state *uts)
76 {
77         u16 *r;
78         u16 copy[10];
79
80         r = u16_strcpy(copy, c1);
81         ut_assert(r == copy);
82         ut_assert(!memcmp(copy, c1, sizeof(c1)));
83         return 0;
84 }
85 UNICODE_TEST(unicode_test_u16_strcpy);
86
87 /* U-Boot uses UTF-16 strings in the EFI context only. */
88 #if CONFIG_IS_ENABLED(EFI_LOADER) && !defined(API_BUILD)
89 static int unicode_test_string16(struct unit_test_state *uts)
90 {
91         char buf[20];
92
93         /* Test length and precision */
94         memset(buf, 0xff, sizeof(buf));
95         sprintf(buf, "%8.6ls", c2);
96         ut_asserteq(' ', buf[1]);
97         ut_assert(!strncmp(&buf[2], d2, 7));
98         ut_assert(!buf[9]);
99
100         memset(buf, 0xff, sizeof(buf));
101         sprintf(buf, "%8.6ls", c4);
102         ut_asserteq(' ', buf[4]);
103         ut_assert(!strncmp(&buf[5], d4, 12));
104         ut_assert(!buf[17]);
105
106         memset(buf, 0xff, sizeof(buf));
107         sprintf(buf, "%-8.2ls", c4);
108         ut_asserteq(' ', buf[8]);
109         ut_assert(!strncmp(buf, d4, 8));
110         ut_assert(!buf[14]);
111
112         /* Test handling of illegal utf-16 sequences */
113         memset(buf, 0xff, sizeof(buf));
114         sprintf(buf, "%ls", i1);
115         ut_asserteq_str("i1?l", buf);
116
117         memset(buf, 0xff, sizeof(buf));
118         sprintf(buf, "%ls", i2);
119         ut_asserteq_str("i2?l", buf);
120
121         memset(buf, 0xff, sizeof(buf));
122         sprintf(buf, "%ls", i3);
123         ut_asserteq_str("i3?", buf);
124
125         return 0;
126 }
127 UNICODE_TEST(unicode_test_string16);
128 #endif
129
130 static int unicode_test_utf8_get(struct unit_test_state *uts)
131 {
132         const char *s;
133         s32 code;
134         int i;
135
136         /* Check characters less than 0x800 */
137         s = d2;
138         for (i = 0; i < 8; ++i) {
139                 code = utf8_get((const char **)&s);
140                 /* c2 is the utf-8 encoding of d2 */
141                 ut_asserteq(c2[i], code);
142                 if (!code)
143                         break;
144         }
145         ut_asserteq_ptr(s, d2 + 9)
146
147         /* Check characters less than 0x10000 */
148         s = d3;
149         for (i = 0; i < 4; ++i) {
150                 code = utf8_get((const char **)&s);
151                 /* c3 is the utf-8 encoding of d3 */
152                 ut_asserteq(c3[i], code);
153                 if (!code)
154                         break;
155         }
156         ut_asserteq_ptr(s, d3 + 9)
157
158         /* Check character greater 0xffff */
159         s = d4;
160         code = utf8_get((const char **)&s);
161         ut_asserteq(0x0001048d, code);
162         ut_asserteq_ptr(s, d4 + 4);
163
164         return 0;
165 }
166 UNICODE_TEST(unicode_test_utf8_get);
167
168 static int unicode_test_utf8_put(struct unit_test_state *uts)
169 {
170         char buffer[8] = { 0, };
171         char *pos;
172
173         /* Commercial at, translates to one character */
174         pos = buffer;
175         ut_assert(!utf8_put('@', &pos))
176         ut_asserteq(1, pos - buffer);
177         ut_asserteq('@', buffer[0]);
178         ut_assert(!buffer[1]);
179
180         /* Latin letter G with acute, translates to two charactes */
181         pos = buffer;
182         ut_assert(!utf8_put(0x1f4, &pos));
183         ut_asserteq(2, pos - buffer);
184         ut_asserteq_str("\xc7\xb4", buffer);
185
186         /* Tagalog letter i, translates to three characters */
187         pos = buffer;
188         ut_assert(!utf8_put(0x1701, &pos));
189         ut_asserteq(3, pos - buffer);
190         ut_asserteq_str("\xe1\x9c\x81", buffer);
191
192         /* Hamster face, translates to four characters */
193         pos = buffer;
194         ut_assert(!utf8_put(0x1f439, &pos));
195         ut_asserteq(4, pos - buffer);
196         ut_asserteq_str("\xf0\x9f\x90\xb9", buffer);
197
198         /* Illegal code */
199         pos = buffer;
200         ut_asserteq(-1, utf8_put(0xd888, &pos));
201
202         return 0;
203 }
204 UNICODE_TEST(unicode_test_utf8_put);
205
206 static int unicode_test_utf8_utf16_strlen(struct unit_test_state *uts)
207 {
208         ut_asserteq(6, utf8_utf16_strlen(d1));
209         ut_asserteq(8, utf8_utf16_strlen(d2));
210         ut_asserteq(3, utf8_utf16_strlen(d3));
211         ut_asserteq(6, utf8_utf16_strlen(d4));
212
213         /* illegal utf-8 sequences */
214         ut_asserteq(4, utf8_utf16_strlen(j1));
215         ut_asserteq(4, utf8_utf16_strlen(j2));
216         ut_asserteq(3, utf8_utf16_strlen(j3));
217
218         return 0;
219 }
220 UNICODE_TEST(unicode_test_utf8_utf16_strlen);
221
222 static int unicode_test_utf8_utf16_strnlen(struct unit_test_state *uts)
223 {
224         ut_asserteq(3, utf8_utf16_strnlen(d1, 3));
225         ut_asserteq(6, utf8_utf16_strnlen(d1, 13));
226         ut_asserteq(6, utf8_utf16_strnlen(d2, 6));
227         ut_asserteq(2, utf8_utf16_strnlen(d3, 2));
228         ut_asserteq(4, utf8_utf16_strnlen(d4, 2));
229         ut_asserteq(6, utf8_utf16_strnlen(d4, 3));
230
231         /* illegal utf-8 sequences */
232         ut_asserteq(4, utf8_utf16_strnlen(j1, 16));
233         ut_asserteq(4, utf8_utf16_strnlen(j2, 16));
234         ut_asserteq(3, utf8_utf16_strnlen(j3, 16));
235
236         return 0;
237 }
238 UNICODE_TEST(unicode_test_utf8_utf16_strnlen);
239
240 /**
241  * ut_u16_strcmp() - Compare to u16 strings.
242  *
243  * @a1:         first string
244  * @a2:         second string
245  * @count:      number of u16 to compare
246  * Return:      -1 if a1 < a2, 0 if a1 == a2, 1 if a1 > a2
247  */
248 static int unicode_test_u16_strcmp(const u16 *a1, const u16 *a2, size_t count)
249 {
250         for (; (*a1 || *a2) && count; ++a1, ++a2, --count) {
251                 if (*a1 < *a2)
252                         return -1;
253                 if (*a1 > *a2)
254                         return 1;
255         }
256         return 0;
257 }
258
259 static int unicode_test_utf8_utf16_strcpy(struct unit_test_state *uts)
260 {
261         u16 buf[16];
262         u16 *pos;
263
264         pos = buf;
265         utf8_utf16_strcpy(&pos, d1);
266         ut_asserteq(6, pos - buf);
267         ut_assert(!unicode_test_u16_strcmp(buf, c1, SIZE_MAX));
268
269         pos = buf;
270         utf8_utf16_strcpy(&pos, d2);
271         ut_asserteq(8, pos - buf);
272         ut_assert(!unicode_test_u16_strcmp(buf, c2, SIZE_MAX));
273
274         pos = buf;
275         utf8_utf16_strcpy(&pos, d3);
276         ut_asserteq(3, pos - buf);
277         ut_assert(!unicode_test_u16_strcmp(buf, c3, SIZE_MAX));
278
279         pos = buf;
280         utf8_utf16_strcpy(&pos, d4);
281         ut_asserteq(6, pos - buf);
282         ut_assert(!unicode_test_u16_strcmp(buf, c4, SIZE_MAX));
283
284         /* Illegal utf-8 strings */
285         pos = buf;
286         utf8_utf16_strcpy(&pos, j1);
287         ut_asserteq(4, pos - buf);
288         ut_assert(!unicode_test_u16_strcmp(buf, L"j1?l", SIZE_MAX));
289
290         pos = buf;
291         utf8_utf16_strcpy(&pos, j2);
292         ut_asserteq(4, pos - buf);
293         ut_assert(!unicode_test_u16_strcmp(buf, L"j2?l", SIZE_MAX));
294
295         pos = buf;
296         utf8_utf16_strcpy(&pos, j3);
297         ut_asserteq(3, pos - buf);
298         ut_assert(!unicode_test_u16_strcmp(buf, L"j3?", SIZE_MAX));
299
300         return 0;
301 }
302 UNICODE_TEST(unicode_test_utf8_utf16_strcpy);
303
304 static int unicode_test_utf8_utf16_strncpy(struct unit_test_state *uts)
305 {
306         u16 buf[16];
307         u16 *pos;
308
309         pos = buf;
310         memset(buf, 0, sizeof(buf));
311         utf8_utf16_strncpy(&pos, d1, 4);
312         ut_asserteq(4, pos - buf);
313         ut_assert(!buf[4]);
314         ut_assert(!unicode_test_u16_strcmp(buf, c1, 4));
315
316         pos = buf;
317         memset(buf, 0, sizeof(buf));
318         utf8_utf16_strncpy(&pos, d2, 10);
319         ut_asserteq(8, pos - buf);
320         ut_assert(buf[4]);
321         ut_assert(!unicode_test_u16_strcmp(buf, c2, SIZE_MAX));
322
323         pos = buf;
324         memset(buf, 0, sizeof(buf));
325         utf8_utf16_strncpy(&pos, d3, 2);
326         ut_asserteq(2, pos - buf);
327         ut_assert(!buf[2]);
328         ut_assert(!unicode_test_u16_strcmp(buf, c3, 2));
329
330         pos = buf;
331         memset(buf, 0, sizeof(buf));
332         utf8_utf16_strncpy(&pos, d4, 2);
333         ut_asserteq(4, pos - buf);
334         ut_assert(!buf[4]);
335         ut_assert(!unicode_test_u16_strcmp(buf, c4, 4));
336
337         pos = buf;
338         memset(buf, 0, sizeof(buf));
339         utf8_utf16_strncpy(&pos, d4, 10);
340         ut_asserteq(6, pos - buf);
341         ut_assert(buf[5]);
342         ut_assert(!unicode_test_u16_strcmp(buf, c4, SIZE_MAX));
343
344         return 0;
345 }
346 UNICODE_TEST(unicode_test_utf8_utf16_strncpy);
347
348 static int unicode_test_utf16_get(struct unit_test_state *uts)
349 {
350         const u16 *s;
351         s32 code;
352         int i;
353
354         /* Check characters less than 0x10000 */
355         s = c2;
356         for (i = 0; i < 9; ++i) {
357                 code = utf16_get((const u16 **)&s);
358                 ut_asserteq(c2[i], code);
359                 if (!code)
360                         break;
361         }
362         ut_asserteq_ptr(c2 + 8, s);
363
364         /* Check character greater 0xffff */
365         s = c4;
366         code = utf16_get((const u16 **)&s);
367         ut_asserteq(0x0001048d, code);
368         ut_asserteq_ptr(c4 + 2, s);
369
370         return 0;
371 }
372 UNICODE_TEST(unicode_test_utf16_get);
373
374 static int unicode_test_utf16_put(struct unit_test_state *uts)
375 {
376         u16 buffer[4] = { 0, };
377         u16 *pos;
378
379         /* Commercial at, translates to one word */
380         pos = buffer;
381         ut_assert(!utf16_put('@', &pos));
382         ut_asserteq(1, pos - buffer);
383         ut_asserteq((u16)'@', buffer[0]);
384         ut_assert(!buffer[1]);
385
386         /* Hamster face, translates to two words */
387         pos = buffer;
388         ut_assert(!utf16_put(0x1f439, &pos));
389         ut_asserteq(2, pos - buffer);
390         ut_asserteq((u16)0xd83d, buffer[0]);
391         ut_asserteq((u16)0xdc39, buffer[1]);
392         ut_assert(!buffer[2]);
393
394         /* Illegal code */
395         pos = buffer;
396         ut_asserteq(-1, utf16_put(0xd888, &pos));
397
398         return 0;
399 }
400 UNICODE_TEST(unicode_test_utf16_put);
401
402 static int unicode_test_utf16_strnlen(struct unit_test_state *uts)
403 {
404         ut_asserteq(3, utf16_strnlen(c1, 3));
405         ut_asserteq(6, utf16_strnlen(c1, 13));
406         ut_asserteq(6, utf16_strnlen(c2, 6));
407         ut_asserteq(2, utf16_strnlen(c3, 2));
408         ut_asserteq(2, utf16_strnlen(c4, 2));
409         ut_asserteq(3, utf16_strnlen(c4, 3));
410
411         /* illegal utf-16 word sequences */
412         ut_asserteq(4, utf16_strnlen(i1, 16));
413         ut_asserteq(4, utf16_strnlen(i2, 16));
414         ut_asserteq(3, utf16_strnlen(i3, 16));
415
416         return 0;
417 }
418 UNICODE_TEST(unicode_test_utf16_strnlen);
419
420 static int unicode_test_utf16_utf8_strlen(struct unit_test_state *uts)
421 {
422         ut_asserteq(6, utf16_utf8_strlen(c1));
423         ut_asserteq(9, utf16_utf8_strlen(c2));
424         ut_asserteq(9, utf16_utf8_strlen(c3));
425         ut_asserteq(12, utf16_utf8_strlen(c4));
426
427         /* illegal utf-16 word sequences */
428         ut_asserteq(4, utf16_utf8_strlen(i1));
429         ut_asserteq(4, utf16_utf8_strlen(i2));
430         ut_asserteq(3, utf16_utf8_strlen(i3));
431
432         return 0;
433 }
434 UNICODE_TEST(unicode_test_utf16_utf8_strlen);
435
436 static int unicode_test_utf16_utf8_strnlen(struct unit_test_state *uts)
437 {
438         ut_asserteq(3, utf16_utf8_strnlen(c1, 3));
439         ut_asserteq(6, utf16_utf8_strnlen(c1, 13));
440         ut_asserteq(7, utf16_utf8_strnlen(c2, 6));
441         ut_asserteq(6, utf16_utf8_strnlen(c3, 2));
442         ut_asserteq(8, utf16_utf8_strnlen(c4, 2));
443         ut_asserteq(12, utf16_utf8_strnlen(c4, 3));
444         return 0;
445 }
446 UNICODE_TEST(unicode_test_utf16_utf8_strnlen);
447
448 static int unicode_test_utf16_utf8_strcpy(struct unit_test_state *uts)
449 {
450         char buf[16];
451         char *pos;
452
453         pos = buf;
454         utf16_utf8_strcpy(&pos, c1);
455         ut_asserteq(6, pos - buf);
456         ut_asserteq_str(d1, buf);
457
458         pos = buf;
459         utf16_utf8_strcpy(&pos, c2);
460         ut_asserteq(9, pos - buf);
461         ut_asserteq_str(d2, buf);
462
463         pos = buf;
464         utf16_utf8_strcpy(&pos, c3);
465         ut_asserteq(9, pos - buf);
466         ut_asserteq_str(d3, buf);
467
468         pos = buf;
469         utf16_utf8_strcpy(&pos, c4);
470         ut_asserteq(12, pos - buf);
471         ut_asserteq_str(d4, buf);
472
473         /* Illegal utf-16 strings */
474         pos = buf;
475         utf16_utf8_strcpy(&pos, i1);
476         ut_asserteq(4, pos - buf);
477         ut_asserteq_str("i1?l", buf);
478
479         pos = buf;
480         utf16_utf8_strcpy(&pos, i2);
481         ut_asserteq(4, pos - buf);
482         ut_asserteq_str("i2?l", buf);
483
484         pos = buf;
485         utf16_utf8_strcpy(&pos, i3);
486         ut_asserteq(3, pos - buf);
487         ut_asserteq_str("i3?", buf);
488
489         return 0;
490 }
491 UNICODE_TEST(unicode_test_utf16_utf8_strcpy);
492
493 static int unicode_test_utf16_utf8_strncpy(struct unit_test_state *uts)
494 {
495         char buf[16];
496         char *pos;
497
498         pos = buf;
499         memset(buf, 0, sizeof(buf));
500         utf16_utf8_strncpy(&pos, c1, 4);
501         ut_asserteq(4, pos - buf);
502         ut_assert(!buf[4]);
503         ut_assert(!strncmp(buf, d1, 4));
504
505         pos = buf;
506         memset(buf, 0, sizeof(buf));
507         utf16_utf8_strncpy(&pos, c2, 10);
508         ut_asserteq(9, pos - buf);
509         ut_assert(buf[4]);
510         ut_assert(!strncmp(buf, d2, SIZE_MAX));
511
512         pos = buf;
513         memset(buf, 0, sizeof(buf));
514         utf16_utf8_strncpy(&pos, c3, 2);
515         ut_asserteq(6, pos - buf);
516         ut_assert(!buf[6]);
517         ut_assert(!strncmp(buf, d3, 6));
518
519         pos = buf;
520         memset(buf, 0, sizeof(buf));
521         utf16_utf8_strncpy(&pos, c4, 2);
522         ut_asserteq(8, pos - buf);
523         ut_assert(!buf[8]);
524         ut_assert(!strncmp(buf, d4, 8));
525
526         pos = buf;
527         memset(buf, 0, sizeof(buf));
528         utf16_utf8_strncpy(&pos, c4, 10);
529         ut_asserteq(12, pos - buf);
530         ut_assert(buf[5]);
531         ut_assert(!strncmp(buf, d4, SIZE_MAX));
532
533         return 0;
534 }
535 UNICODE_TEST(unicode_test_utf16_utf8_strncpy);
536
537 static int unicode_test_utf_to_lower(struct unit_test_state *uts)
538 {
539         ut_asserteq('@', utf_to_lower('@'));
540         ut_asserteq('a', utf_to_lower('A'));
541         ut_asserteq('z', utf_to_lower('Z'));
542         ut_asserteq('[', utf_to_lower('['));
543         ut_asserteq('m', utf_to_lower('m'));
544         /* Latin letter O with diaresis (umlaut) */
545         ut_asserteq(0x00f6, utf_to_lower(0x00d6));
546 #ifdef CONFIG_EFI_UNICODE_CAPITALIZATION
547         /* Cyrillic letter I*/
548         ut_asserteq(0x0438, utf_to_lower(0x0418));
549 #endif
550         return 0;
551 }
552 UNICODE_TEST(unicode_test_utf_to_lower);
553
554 static int unicode_test_utf_to_upper(struct unit_test_state *uts)
555 {
556         ut_asserteq('`', utf_to_upper('`'));
557         ut_asserteq('A', utf_to_upper('a'));
558         ut_asserteq('Z', utf_to_upper('z'));
559         ut_asserteq('{', utf_to_upper('{'));
560         ut_asserteq('M', utf_to_upper('M'));
561         /* Latin letter O with diaresis (umlaut) */
562         ut_asserteq(0x00d6, utf_to_upper(0x00f6));
563 #ifdef CONFIG_EFI_UNICODE_CAPITALIZATION
564         /* Cyrillic letter I */
565         ut_asserteq(0x0418, utf_to_upper(0x0438));
566 #endif
567         return 0;
568 }
569 UNICODE_TEST(unicode_test_utf_to_upper);
570
571 static int unicode_test_u16_strncmp(struct unit_test_state *uts)
572 {
573         ut_assert(u16_strncmp(L"abc", L"abc", 3) == 0);
574         ut_assert(u16_strncmp(L"abcdef", L"abcghi", 3) == 0);
575         ut_assert(u16_strncmp(L"abcdef", L"abcghi", 6) < 0);
576         ut_assert(u16_strncmp(L"abcghi", L"abcdef", 6) > 0);
577         ut_assert(u16_strcmp(L"abc", L"abc") == 0);
578         ut_assert(u16_strcmp(L"abcdef", L"deghi") < 0);
579         ut_assert(u16_strcmp(L"deghi", L"abcdef") > 0);
580         return 0;
581 }
582 UNICODE_TEST(unicode_test_u16_strncmp);
583
584 int do_ut_unicode(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
585 {
586         struct unit_test *tests = ll_entry_start(struct unit_test, unicode_test);
587         const int n_ents = ll_entry_count(struct unit_test, unicode_test);
588
589         return cmd_ut_category("Unicode", "unicode_test_",
590                                tests, n_ents, argc, argv);
591 }