aboutsummaryrefslogtreecommitdiff
path: root/tests/SkUTFTest.cpp
blob: 5481ef94199b47d4ef1fc20278bfc4809894cce7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
// Copyright 2018 Google LLC.
// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.

#include "SkUTF.h"
#include "Test.h"

DEF_TEST(SkUTF_UTF16, reporter) {
    // Test non-basic-multilingual-plane unicode.
    static const SkUnichar gUni[] = {
        0x10000, 0x18080, 0x20202, 0xFFFFF, 0x101234
    };
    for (SkUnichar uni : gUni) {
        uint16_t buf[2];
        size_t count = SkUTF::ToUTF16(uni, buf);
        REPORTER_ASSERT(reporter, count == 2);
        size_t count2 = SkUTF::CountUTF16(buf, sizeof(buf));
        REPORTER_ASSERT(reporter, count2 == 1);
        const uint16_t* ptr = buf;
        SkUnichar c = SkUTF::NextUTF16(&ptr, buf + SK_ARRAY_COUNT(buf));
        REPORTER_ASSERT(reporter, c == uni);
        REPORTER_ASSERT(reporter, ptr - buf == 2);
    }
}

DEF_TEST(SkUTF_UTF8, reporter) {
    static const struct {
        const char* fUtf8;
        SkUnichar   fUni;
    } gTest[] = {
        { "a",                  'a' },
        { "\x7f",               0x7f },
        { "\xC2\x80",           0x80 },
        { "\xC3\x83",           (3 << 6) | 3    },
        { "\xDF\xBF",           0x7ff },
        { "\xE0\xA0\x80",       0x800 },
        { "\xE0\xB0\xB8",       0xC38 },
        { "\xE3\x83\x83",       (3 << 12) | (3 << 6) | 3    },
        { "\xEF\xBF\xBF",       0xFFFF },
        { "\xF0\x90\x80\x80",   0x10000 },
        { "\xF3\x83\x83\x83",   (3 << 18) | (3 << 12) | (3 << 6) | 3    }
    };
    for (auto test : gTest) {
        const char* p = test.fUtf8;
        const char* stop = p + strlen(p);
        int         n = SkUTF::CountUTF8(p, strlen(p));
        SkUnichar   u1 = SkUTF::NextUTF8(&p, stop);

        REPORTER_ASSERT(reporter, n == 1);
        REPORTER_ASSERT(reporter, u1 == test.fUni);
        REPORTER_ASSERT(reporter, p - test.fUtf8 == (int)strlen(test.fUtf8));
    }
}

#define ASCII_BYTE         "X"
#define CONTINUATION_BYTE  "\xA1"
#define LEADING_TWO_BYTE   "\xC2"
#define LEADING_THREE_BYTE "\xE1"
#define LEADING_FOUR_BYTE  "\xF0"
#define INVALID_BYTE       "\xFC"
DEF_TEST(SkUTF_CountUTF8, r) {
    static const struct {
        int expectedCount;
        const char* utf8String;
    } testCases[] = {
        { 0, "" },
        { 1, ASCII_BYTE },
        { 2, ASCII_BYTE ASCII_BYTE },
        { 1, LEADING_TWO_BYTE CONTINUATION_BYTE },
        { 2, ASCII_BYTE LEADING_TWO_BYTE CONTINUATION_BYTE },
        { 3, ASCII_BYTE ASCII_BYTE LEADING_TWO_BYTE CONTINUATION_BYTE },
        { 1, LEADING_THREE_BYTE CONTINUATION_BYTE CONTINUATION_BYTE },
        { 2, ASCII_BYTE LEADING_THREE_BYTE CONTINUATION_BYTE CONTINUATION_BYTE },
        { 3, ASCII_BYTE ASCII_BYTE LEADING_THREE_BYTE CONTINUATION_BYTE CONTINUATION_BYTE },
        { 1, LEADING_FOUR_BYTE CONTINUATION_BYTE CONTINUATION_BYTE CONTINUATION_BYTE },
        { 2, ASCII_BYTE LEADING_FOUR_BYTE CONTINUATION_BYTE CONTINUATION_BYTE CONTINUATION_BYTE },
        { 3, ASCII_BYTE ASCII_BYTE LEADING_FOUR_BYTE CONTINUATION_BYTE CONTINUATION_BYTE
             CONTINUATION_BYTE },
        { -1, INVALID_BYTE },
        { -1, INVALID_BYTE CONTINUATION_BYTE },
        { -1, INVALID_BYTE CONTINUATION_BYTE CONTINUATION_BYTE },
        { -1, INVALID_BYTE CONTINUATION_BYTE CONTINUATION_BYTE CONTINUATION_BYTE },
        { -1, LEADING_TWO_BYTE },
        { -1, CONTINUATION_BYTE },
        { -1, CONTINUATION_BYTE CONTINUATION_BYTE },
        { -1, LEADING_THREE_BYTE CONTINUATION_BYTE },
        { -1, CONTINUATION_BYTE CONTINUATION_BYTE CONTINUATION_BYTE },
        { -1, LEADING_FOUR_BYTE CONTINUATION_BYTE },
        { -1, CONTINUATION_BYTE CONTINUATION_BYTE CONTINUATION_BYTE CONTINUATION_BYTE },
    };
    for (auto testCase : testCases) {
        const char* str = testCase.utf8String;
        REPORTER_ASSERT(r, testCase.expectedCount == SkUTF::CountUTF8(str, strlen(str)));
    }
}

DEF_TEST(SkUTF_NextUTF8_ToUTF8, r) {
    struct {
        SkUnichar expected;
        const char* utf8String;
    } testCases[] = {
        { -1, INVALID_BYTE },
        { -1, "" },
        { 0x0058, ASCII_BYTE },
        { 0x00A1, LEADING_TWO_BYTE CONTINUATION_BYTE },
        { 0x1861, LEADING_THREE_BYTE CONTINUATION_BYTE CONTINUATION_BYTE },
        { 0x010330, LEADING_FOUR_BYTE "\x90\x8C\xB0" },
    };
    for (auto testCase : testCases) {
        const char* str = testCase.utf8String;
        SkUnichar uni = SkUTF::NextUTF8(&str, str + strlen(str));
        REPORTER_ASSERT(r, str == testCase.utf8String + strlen(testCase.utf8String));
        REPORTER_ASSERT(r, uni == testCase.expected);
        char buff[5] = {0, 0, 0, 0, 0};
        size_t len = SkUTF::ToUTF8(uni, buff);
        if (buff[len] != 0) {
            ERRORF(r, "unexpected write");
            continue;
        }
        if (uni == -1) {
            REPORTER_ASSERT(r, len == 0);
            continue;
        }
        if (len == 0) {
           ERRORF(r, "unexpected failure.");
           continue;
        }
        if (len > 4) {
           ERRORF(r, "wrote too much");
           continue;
        }
        str = testCase.utf8String;
        REPORTER_ASSERT(r, len == strlen(buff));
        REPORTER_ASSERT(r, len == strlen(str));
        REPORTER_ASSERT(r, 0 == strcmp(str, buff));
    }
}
#undef ASCII_BYTE
#undef CONTINUATION_BYTE
#undef LEADING_TWO_BYTE
#undef LEADING_THREE_BYTE
#undef LEADING_FOUR_BYTE
#undef INVALID_BYTE