• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include <gtest/gtest.h>
17 
18 #include "drawing_font_collection.h"
19 #include "drawing_text_typography.h"
20 
21 using namespace testing;
22 using namespace testing::ext;
23 
24 namespace OHOS {
25 namespace Rosen {
26 class NdkAddTextTest : public testing::Test {};
27 
GetUnresolvedGlyphCount(const void * text,size_t length,OH_Drawing_TextEncoding encode)28 static int32_t GetUnresolvedGlyphCount(const void* text, size_t length, OH_Drawing_TextEncoding encode)
29 {
30     auto typoStyle = OH_Drawing_CreateTypographyStyle();
31     EXPECT_NE(typoStyle, nullptr);
32     auto handler = OH_Drawing_CreateTypographyHandler(typoStyle, OH_Drawing_GetFontCollectionGlobalInstance());
33     EXPECT_NE(handler, nullptr);
34     OH_Drawing_TypographyHandlerAddEncodedText(handler, text, length, encode);
35     auto typography = OH_Drawing_CreateTypography(handler);
36     EXPECT_NE(typography, nullptr);
37     OH_Drawing_TypographyLayout(typography, 100.0f);
38     int32_t unresolved = OH_Drawing_TypographyGetUnresolvedGlyphsCount(typography);
39     OH_Drawing_DestroyTypography(typography);
40     OH_Drawing_DestroyTypographyHandler(handler);
41     OH_Drawing_DestroyTypographyStyle(typoStyle);
42     return unresolved;
43 }
44 /**
45  * @tc.name: AddValidUTF8TextTest
46  * @tc.desc: Test valid UTF-8 text input scenarios
47  * @tc.type: FUNC
48  */
49 HWTEST_F(NdkAddTextTest, AddValidUTF8TextTest, TestSize.Level0)
50 {
51     // Basic ASCII characters
52     const char ascii[] = u8"Hello World";
53     EXPECT_EQ(GetUnresolvedGlyphCount(ascii, sizeof(ascii), TEXT_ENCODING_UTF8), 0);
54 
55     // Non-ASCII characters (Chinese)
56     const char chinese[] = u8"你好世界";
57     EXPECT_EQ(GetUnresolvedGlyphCount(chinese, sizeof(chinese), TEXT_ENCODING_UTF8), 0);
58 
59     // Special characters
60     const char tabsNewline[] = u8"Tabs\tNewline\n";
61     EXPECT_EQ(GetUnresolvedGlyphCount(tabsNewline, sizeof(tabsNewline), TEXT_ENCODING_UTF8), 0);
62 
63     // 4-byte emoji characters
64     const char emoji[] = u8"������";
65     EXPECT_EQ(GetUnresolvedGlyphCount(emoji, sizeof(emoji), TEXT_ENCODING_UTF8), 0);
66 
67     // Mixed case and symbols
68     const char mixedCaseSymbols[] = u8"Aa1!Ωπ";
69     EXPECT_EQ(GetUnresolvedGlyphCount(mixedCaseSymbols, sizeof(mixedCaseSymbols), TEXT_ENCODING_UTF8), 0);
70 }
71 
72 /**
73  * @tc.name: AddInvalidUTF8TextTest
74  * @tc.desc: Test invalid UTF-8 text input scenarios
75  * @tc.type: FUNC
76  */
77 HWTEST_F(NdkAddTextTest, AddInvalidUTF8TextTest, TestSize.Level0)
78 {
79     // Invalid continuation bytes
80     const char invalid1[] = "abc\x80\xff";
81     EXPECT_EQ(GetUnresolvedGlyphCount(invalid1, sizeof(invalid1), TEXT_ENCODING_UTF8), 0);
82 
83     // Truncated multi-byte sequence
84     const char invalid2[] = u8"正常\xE6\x97继续";
85     EXPECT_EQ(GetUnresolvedGlyphCount(invalid2, sizeof(invalid2), TEXT_ENCODING_UTF8), 0);
86 
87     // Overlong encoding
88     const char invalid3[] = "\xF0\x82\x82\xAC"; // Overlong € symbol
89     EXPECT_EQ(GetUnresolvedGlyphCount(invalid3, sizeof(invalid3), TEXT_ENCODING_UTF8), 0);
90 }
91 
92 /**
93  * @tc.name: AddValidUTF16TextTest
94  * @tc.desc: Test valid UTF-16 text input scenarios
95  * @tc.type: FUNC
96  */
97 HWTEST_F(NdkAddTextTest, AddValidUTF16TextTest, TestSize.Level0)
98 {
99     // Basic BMP characters
100     const char16_t ascii16[] = u"Hello World";
101     EXPECT_EQ(GetUnresolvedGlyphCount(ascii16, sizeof(ascii16), TEXT_ENCODING_UTF16), 0);
102 
103     // Non-BMP characters (emoji)
104     const char16_t emoji16[] = u"����";
105     EXPECT_EQ(GetUnresolvedGlyphCount(emoji16, sizeof(emoji16), TEXT_ENCODING_UTF16), 0); // ����
106 
107     // RTL text with control characters
108     const char16_t rtlText16[] = u"\x202E右到左文本";
109     EXPECT_EQ(GetUnresolvedGlyphCount(rtlText16, sizeof(rtlText16), TEXT_ENCODING_UTF16), 0);
110 
111     // Combining characters
112     const char16_t combiningChars16[] = u"A\u0300\u0301";
113     EXPECT_EQ(GetUnresolvedGlyphCount(combiningChars16, sizeof(combiningChars16), TEXT_ENCODING_UTF16), 0); // À́
114 }
115 
116 /**
117  * @tc.name: AddInvalidUTF16TextTest
118  * @tc.desc: Test invalid UTF-16 text input scenarios
119  * @tc.type: FUNC
120  */
121 HWTEST_F(NdkAddTextTest, AddInvalidUTF16TextTest, TestSize.Level0)
122 {
123     // Unpaired high surrogate
124     const char16_t invalid1[] = u"\xD800\x0041";
125     EXPECT_EQ(GetUnresolvedGlyphCount(invalid1, sizeof(invalid1), TEXT_ENCODING_UTF16), 0);
126 
127     // Unpaired low surrogate
128     const char16_t invalid2[] = u"\xDC00";
129     EXPECT_EQ(GetUnresolvedGlyphCount(invalid2, sizeof(invalid2), TEXT_ENCODING_UTF16), 0);
130 
131     // Swapped surrogate pair
132     const char16_t invalid3[] = u"\xDC00\xD800";
133     EXPECT_EQ(GetUnresolvedGlyphCount(invalid3, sizeof(invalid3), TEXT_ENCODING_UTF16), 0);
134 }
135 
136 /**
137  * @tc.name: AddValidUTF32TextTest
138  * @tc.desc: Test valid UTF-32 text input scenarios
139  * @tc.type: FUNC
140  */
141 HWTEST_F(NdkAddTextTest, AddValidUTF32TextTest, TestSize.Level0)
142 {
143     // Basic ASCII range
144     const char32_t ascii32[] = U"ASCII Text!";
145     EXPECT_EQ(GetUnresolvedGlyphCount(ascii32, sizeof(ascii32), TEXT_ENCODING_UTF32), 0);
146 
147     // Non-BMP characters
148     const char32_t emoji32[] = { 0x1F600, 0x1F308, 0 }; // ����
149     EXPECT_EQ(GetUnresolvedGlyphCount(emoji32, sizeof(emoji32), TEXT_ENCODING_UTF32), 0);
150 
151     // Maximum valid code point
152     const char32_t maxUnicode32[] = { 0x10FFFF };
153     EXPECT_EQ(GetUnresolvedGlyphCount(maxUnicode32, sizeof(maxUnicode32), TEXT_ENCODING_UTF32), 1);
154 }
155 /**
156  * @tc.name: AddInvalidUTF32TextTest
157  * @tc.desc: Test invalid UTF-32 text input scenarios
158  * @tc.type: FUNC
159  */
160 HWTEST_F(NdkAddTextTest, AddInvalidUTF32TextTest, TestSize.Level0)
161 {
162     // Code point beyond U+10FFFF
163     const char32_t invalid1[] = { 0x110000 };
164     EXPECT_EQ(GetUnresolvedGlyphCount(invalid1, sizeof(invalid1), TEXT_ENCODING_UTF32), 0);
165 
166     // Surrogate code points
167     const char32_t invalid2[] = { 0xD800, 0xDFFF };
168     EXPECT_EQ(GetUnresolvedGlyphCount(invalid2, sizeof(invalid2), TEXT_ENCODING_UTF32), 0);
169 
170     // Negative value
171     const char32_t invalid3[] = { -100 };
172     EXPECT_EQ(GetUnresolvedGlyphCount(invalid3, sizeof(invalid3), TEXT_ENCODING_UTF32), 0);
173 }
174 
175 /**
176  * @tc.name: AddTextBoundaryTest
177  * @tc.desc: Test boundary cases and edge conditions
178  * @tc.type: FUNC
179  */
180 HWTEST_F(NdkAddTextTest, AddTextBoundaryTest, TestSize.Level0)
181 {
182     // Empty input with different encodings
183     EXPECT_EQ(GetUnresolvedGlyphCount("", 0, TEXT_ENCODING_UTF8), -1);
184     EXPECT_EQ(GetUnresolvedGlyphCount(u"", 0, TEXT_ENCODING_UTF16), -1);
185     EXPECT_EQ(GetUnresolvedGlyphCount(U"", 0, TEXT_ENCODING_UTF32), -1);
186 
187     // Null pointer with zero length
188     EXPECT_EQ(GetUnresolvedGlyphCount(nullptr, 0, TEXT_ENCODING_UTF8), -1);
189 
190     // Maximum code point boundary
191     const char32_t boundary1[] = { 0x10FFFF, 0x0000 };
192     EXPECT_EQ(GetUnresolvedGlyphCount(boundary1, sizeof(boundary1), TEXT_ENCODING_UTF32), 1);
193 
194     // Minimum code point boundary
195     const char32_t boundary2[] = { 0x0000 };
196     EXPECT_EQ(GetUnresolvedGlyphCount(boundary2, sizeof(boundary2), TEXT_ENCODING_UTF32), 0);
197 }
198 
199 /**
200  * @tc.name: AddTextStressTest
201  * @tc.desc: Test stress and performance scenarios
202  * @tc.type: PERF
203  */
204 HWTEST_F(NdkAddTextTest, AddTextStressTest, TestSize.Level0)
205 {
206     // Large UTF-8 text
207     std::vector<char> bigUtf8(10000, 'A');
208     EXPECT_EQ(GetUnresolvedGlyphCount(bigUtf8.data(), bigUtf8.size(), TEXT_ENCODING_UTF8), 0);
209 
210     // Large UTF-16 text with surrogate pairs
211     std::vector<char16_t> bigUtf16;
212     for (int i = 0; i < 10000; ++i) {
213         bigUtf16.push_back(0xD83D);
214         bigUtf16.push_back(0xDE00);
215     }
216     EXPECT_EQ(GetUnresolvedGlyphCount(bigUtf16.data(), bigUtf16.size(), TEXT_ENCODING_UTF16), 0);
217 
218     // Mixed valid/invalid UTF-32 data
219     std::vector<char32_t> mixed_utf32(10000, 0x1F600);
220     mixed_utf32[5000] = 0x110000; // Insert invalid code point
221     EXPECT_EQ(GetUnresolvedGlyphCount(mixed_utf32.data(), mixed_utf32.size(), TEXT_ENCODING_UTF32), 0);
222 }
223 
224 /**
225  * @tc.name: AddTextInvalidEncodingTest
226  * @tc.desc: Test invalid encoding type scenarios
227  * @tc.type: FUNC
228  */
229 HWTEST_F(NdkAddTextTest, AddTextInvalidEncodingTest, TestSize.Level0)
230 {
231     // Invalid encoding type
232     const char testStr[] = "test";
233     EXPECT_EQ(GetUnresolvedGlyphCount(testStr, sizeof(testStr), TEXT_ENCODING_GLYPH_ID), -1);
234 
235     // Mismatched encoding and data
236     const char16_t utf16Data[] = u"test";
237     EXPECT_EQ(GetUnresolvedGlyphCount(utf16Data, sizeof(utf16Data), TEXT_ENCODING_UTF8), 0);
238 
239     // Null pointer with non-zero length
240     EXPECT_EQ(GetUnresolvedGlyphCount(nullptr, 5, TEXT_ENCODING_UTF16), -1);
241 }
242 } // namespace Rosen
243 } // namespace OHOS