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