xref: /aosp_15_r20/external/skia/tests/SkUTFTest.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1 // Copyright 2018 Google LLC.
2 // Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
3 
4 #include "include/core/SkTypes.h"
5 #include "src/base/SkUTF.h"
6 #include "tests/Test.h"
7 
8 #include <array>
9 #include <cstdint>
10 #include <cstddef>
11 #include <cstring>
12 
DEF_TEST(SkUTF_UTF16,reporter)13 DEF_TEST(SkUTF_UTF16, reporter) {
14     // Test non-basic-multilingual-plane unicode.
15     static const SkUnichar gUni[] = {
16         0x10000, 0x18080, 0x20202, 0xFFFFF, 0x101234
17     };
18     for (SkUnichar uni : gUni) {
19         uint16_t buf[2];
20         size_t count = SkUTF::ToUTF16(uni, buf);
21         REPORTER_ASSERT(reporter, count == 2);
22         size_t count2 = SkUTF::CountUTF16(buf, sizeof(buf));
23         REPORTER_ASSERT(reporter, count2 == 1);
24         const uint16_t* ptr = buf;
25         SkUnichar c = SkUTF::NextUTF16(&ptr, buf + std::size(buf));
26         REPORTER_ASSERT(reporter, c == uni);
27         REPORTER_ASSERT(reporter, ptr - buf == 2);
28     }
29 }
30 
DEF_TEST(SkUTF_UTF8,reporter)31 DEF_TEST(SkUTF_UTF8, reporter) {
32     static const struct {
33         const char* fUtf8;
34         SkUnichar   fUni;
35     } gTest[] = {
36         { "a",                  'a' },
37         { "\x7f",               0x7f },
38         { "\xC2\x80",           0x80 },
39         { "\xC3\x83",           (3 << 6) | 3    },
40         { "\xDF\xBF",           0x7ff },
41         { "\xE0\xA0\x80",       0x800 },
42         { "\xE0\xB0\xB8",       0xC38 },
43         { "\xE3\x83\x83",       (3 << 12) | (3 << 6) | 3    },
44         { "\xEF\xBF\xBF",       0xFFFF },
45         { "\xF0\x90\x80\x80",   0x10000 },
46         { "\xF3\x83\x83\x83",   (3 << 18) | (3 << 12) | (3 << 6) | 3    }
47     };
48     for (auto test : gTest) {
49         const char* p = test.fUtf8;
50         const char* stop = p + strlen(p);
51         int         n = SkUTF::CountUTF8(p, strlen(p));
52         SkUnichar   u1 = SkUTF::NextUTF8(&p, stop);
53 
54         REPORTER_ASSERT(reporter, n == 1);
55         REPORTER_ASSERT(reporter, u1 == test.fUni);
56         REPORTER_ASSERT(reporter, p - test.fUtf8 == (int)strlen(test.fUtf8));
57     }
58 }
59 
60 #define ASCII_BYTE         "X"
61 #define CONTINUATION_BYTE  "\xA1"
62 #define LEADING_TWO_BYTE   "\xC2"
63 #define LEADING_THREE_BYTE "\xE1"
64 #define LEADING_FOUR_BYTE  "\xF0"
65 #define INVALID_BYTE       "\xFC"
DEF_TEST(SkUTF_CountUTF8,r)66 DEF_TEST(SkUTF_CountUTF8, r) {
67     static const struct {
68         int expectedCount;
69         const char* utf8String;
70     } testCases[] = {
71         { 0, "" },
72         { 1, ASCII_BYTE },
73         { 2, ASCII_BYTE ASCII_BYTE },
74         { 1, LEADING_TWO_BYTE CONTINUATION_BYTE },
75         { 2, ASCII_BYTE LEADING_TWO_BYTE CONTINUATION_BYTE },
76         { 3, ASCII_BYTE ASCII_BYTE LEADING_TWO_BYTE CONTINUATION_BYTE },
77         { 1, LEADING_THREE_BYTE CONTINUATION_BYTE CONTINUATION_BYTE },
78         { 2, ASCII_BYTE LEADING_THREE_BYTE CONTINUATION_BYTE CONTINUATION_BYTE },
79         { 3, ASCII_BYTE ASCII_BYTE LEADING_THREE_BYTE CONTINUATION_BYTE CONTINUATION_BYTE },
80         { 1, LEADING_FOUR_BYTE CONTINUATION_BYTE CONTINUATION_BYTE CONTINUATION_BYTE },
81         { 2, ASCII_BYTE LEADING_FOUR_BYTE CONTINUATION_BYTE CONTINUATION_BYTE CONTINUATION_BYTE },
82         { 3, ASCII_BYTE ASCII_BYTE LEADING_FOUR_BYTE CONTINUATION_BYTE CONTINUATION_BYTE
83              CONTINUATION_BYTE },
84         { -1, INVALID_BYTE },
85         { -1, INVALID_BYTE CONTINUATION_BYTE },
86         { -1, INVALID_BYTE CONTINUATION_BYTE CONTINUATION_BYTE },
87         { -1, INVALID_BYTE CONTINUATION_BYTE CONTINUATION_BYTE CONTINUATION_BYTE },
88         { -1, LEADING_TWO_BYTE },
89         { -1, CONTINUATION_BYTE },
90         { -1, CONTINUATION_BYTE CONTINUATION_BYTE },
91         { -1, LEADING_THREE_BYTE CONTINUATION_BYTE },
92         { -1, CONTINUATION_BYTE CONTINUATION_BYTE CONTINUATION_BYTE },
93         { -1, LEADING_FOUR_BYTE CONTINUATION_BYTE },
94         { -1, CONTINUATION_BYTE CONTINUATION_BYTE CONTINUATION_BYTE CONTINUATION_BYTE },
95     };
96     for (auto testCase : testCases) {
97         const char* str = testCase.utf8String;
98         REPORTER_ASSERT(r, testCase.expectedCount == SkUTF::CountUTF8(str, strlen(str)));
99     }
100 }
101 
DEF_TEST(SkUTF_NextUTF8_ToUTF8,r)102 DEF_TEST(SkUTF_NextUTF8_ToUTF8, r) {
103     struct {
104         SkUnichar expected;
105         const char* utf8String;
106     } testCases[] = {
107         { -1, INVALID_BYTE },
108         { -1, "" },
109         { 0x0058, ASCII_BYTE },
110         { 0x00A1, LEADING_TWO_BYTE CONTINUATION_BYTE },
111         { 0x1861, LEADING_THREE_BYTE CONTINUATION_BYTE CONTINUATION_BYTE },
112         { 0x010330, LEADING_FOUR_BYTE "\x90\x8C\xB0" },
113     };
114     for (auto testCase : testCases) {
115         const char* str = testCase.utf8String;
116         SkUnichar uni = SkUTF::NextUTF8(&str, str + strlen(str));
117         REPORTER_ASSERT(r, str == testCase.utf8String + strlen(testCase.utf8String));
118         REPORTER_ASSERT(r, uni == testCase.expected);
119         char buff[5] = {0, 0, 0, 0, 0};
120         size_t len = SkUTF::ToUTF8(uni, buff);
121         if (buff[len] != 0) {
122             ERRORF(r, "unexpected write");
123             continue;
124         }
125         if (uni == -1) {
126             REPORTER_ASSERT(r, len == 0);
127             continue;
128         }
129         if (len == 0) {
130            ERRORF(r, "unexpected failure.");
131            continue;
132         }
133         if (len > 4) {
134            ERRORF(r, "wrote too much");
135            continue;
136         }
137         str = testCase.utf8String;
138         REPORTER_ASSERT(r, len == strlen(buff));
139         REPORTER_ASSERT(r, len == strlen(str));
140         REPORTER_ASSERT(r, 0 == strcmp(str, buff));
141     }
142 }
143 #undef ASCII_BYTE
144 #undef CONTINUATION_BYTE
145 #undef LEADING_TWO_BYTE
146 #undef LEADING_THREE_BYTE
147 #undef LEADING_FOUR_BYTE
148 #undef INVALID_BYTE
149