1 /**
2 * Copyright (c) 2021-2024 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 #include "ets_coroutine.h"
18 #include "types/ets_string.h"
19 #include "types/ets_array.h"
20 #include "libpandabase/utils/utf.h"
21
22 // NOLINTBEGIN(readability-magic-numbers)
23
24 namespace ark::ets::test {
25 class EtsStringTest : public testing::Test {
26 public:
EtsStringTest()27 EtsStringTest()
28 {
29 options_.SetShouldLoadBootPandaFiles(true);
30 options_.SetShouldInitializeIntrinsics(false);
31 options_.SetCompilerEnableJit(false);
32 options_.SetGcType("epsilon");
33 options_.SetLoadRuntimes({"ets"});
34
35 auto stdlib = std::getenv("PANDA_STD_LIB");
36 if (stdlib == nullptr) {
37 std::cerr << "PANDA_STD_LIB env variable should be set and point to mock_stdlib.abc" << std::endl;
38 std::abort();
39 }
40 options_.SetBootPandaFiles({stdlib});
41
42 Runtime::Create(options_);
43 }
44
~EtsStringTest()45 ~EtsStringTest() override
46 {
47 Runtime::Destroy();
48 }
49
50 NO_COPY_SEMANTIC(EtsStringTest);
51 NO_MOVE_SEMANTIC(EtsStringTest);
52
SetUp()53 void SetUp() override
54 {
55 coroutine_ = EtsCoroutine::GetCurrent();
56 coroutine_->ManagedCodeBegin();
57 }
58
TearDown()59 void TearDown() override
60 {
61 coroutine_->ManagedCodeEnd();
62 }
63
64 private:
65 RuntimeOptions options_;
66 EtsCoroutine *coroutine_ = nullptr;
67 };
68
TEST_F(EtsStringTest,CreateFromUtf16)69 TEST_F(EtsStringTest, CreateFromUtf16)
70 {
71 std::vector<ets_char> data {0xffc3, 0x33, 0x00};
72
73 EtsString *firstEtsString = EtsString::CreateFromUtf16(data.data(), data.size());
74
75 auto *firstString = reinterpret_cast<coretypes::String *>(firstEtsString);
76 auto *secondString = reinterpret_cast<const uint16_t *>(data.data());
77
78 ASSERT_TRUE(coretypes::String::StringsAreEqualUtf16(firstString, secondString, data.size()));
79 }
80
TEST_F(EtsStringTest,CreateFromMUtf8)81 TEST_F(EtsStringTest, CreateFromMUtf8)
82 {
83 std::vector<uint8_t> data {0x01, 0x41, 0x24, 0x00};
84 auto *mutf8Data = reinterpret_cast<const char *>(data.data());
85
86 EtsString *firstEtsString = EtsString::CreateFromMUtf8(mutf8Data);
87
88 auto *firstString = reinterpret_cast<coretypes::String *>(firstEtsString);
89 auto *secondString = reinterpret_cast<const uint8_t *>(data.data());
90
91 ASSERT_TRUE(coretypes::String::StringsAreEqualMUtf8(
92 firstString, secondString, data.size() - 1)); // need to subtract 1 'cause of 0 in the end of Mutf8 string
93 }
94
TEST_F(EtsStringTest,CreateFromMUtf8WithLenArg)95 TEST_F(EtsStringTest, CreateFromMUtf8WithLenArg)
96 {
97 std::vector<uint8_t> data {0x01, 0x41, 0x24, 0x00};
98 auto *mutf8Data = reinterpret_cast<const char *>(data.data());
99
100 EtsString *firstEtsString = EtsString::CreateFromMUtf8(
101 mutf8Data, data.size() - 1); // need to subtract 1 'cause of 0 in the end of Mutf8 string
102
103 auto *firstString = reinterpret_cast<coretypes::String *>(firstEtsString);
104 auto *secondString = reinterpret_cast<const uint8_t *>(data.data());
105
106 ASSERT_TRUE(coretypes::String::StringsAreEqualMUtf8(
107 firstString, secondString, data.size() - 1)); // need to subtract 1 'cause of 0 in the end of Mutf8 string
108 }
109
TEST_F(EtsStringTest,ToCharArray)110 TEST_F(EtsStringTest, ToCharArray)
111 {
112 std::vector<uint8_t> data {'a', 'b', 'c', 'd', 'e', 0};
113 auto *mutf8Data = reinterpret_cast<const char *>(data.data());
114 EtsString *utf8String = EtsString::CreateFromMUtf8(mutf8Data, data.size() - 1);
115 EtsArray *newArray = utf8String->ToCharArray();
116
117 for (uint32_t i = 0; i < newArray->GetLength(); ++i) {
118 ASSERT_EQ(data[i], newArray->GetCoreType()->Get<uint16_t>(i));
119 }
120
121 std::vector<ets_char> data1 {'f', 'g', 'h', 'a', 'b', 0x8ab, 0xdc, 'z', 0};
122 EtsString *utf16String = EtsString::CreateFromUtf16(data1.data(), data1.size());
123 EtsArray *newArray1 = utf16String->ToCharArray();
124
125 for (uint32_t i = 0; i < newArray1->GetLength(); ++i) {
126 ASSERT_EQ(data1[i], newArray1->GetCoreType()->Get<uint16_t>(i));
127 }
128 }
129
TEST_F(EtsStringTest,CreateFromUtf8)130 TEST_F(EtsStringTest, CreateFromUtf8)
131 {
132 std::vector<uint8_t> data {0x01, 0x41, 0x24, 0x32, 0x16, 0x08};
133 size_t firstStringLength = data.size();
134 auto *utf8Data = reinterpret_cast<const char *>(data.data());
135
136 EtsString *firstEtsString = EtsString::CreateFromUtf8(utf8Data, firstStringLength);
137 auto *firstString = reinterpret_cast<const uint8_t *>(data.data());
138
139 // Test full string
140 ASSERT_TRUE(utf::IsEqual({firstEtsString->GetDataMUtf8(), firstStringLength}, {firstString, firstStringLength}));
141 ASSERT_TRUE(
142 utf::IsEqual({firstEtsString->GetDataMUtf8(), firstStringLength - 2}, {firstString, firstStringLength - 2}));
143
144 size_t thirdStringLength = firstStringLength / 2;
145 EtsString *thirdEtsString = EtsString::CreateFromUtf8(utf8Data, thirdStringLength);
146 auto *thirdString = reinterpret_cast<coretypes::String *>(thirdEtsString);
147
148 // Utf8 format, no need to have \0 at the end, so check half string
149 ASSERT_TRUE(utf::IsEqual({firstEtsString->GetDataMUtf8(), thirdStringLength},
150 {thirdString->GetDataMUtf8(), thirdStringLength}));
151 ASSERT_TRUE(utf::IsEqual({firstEtsString->GetDataMUtf8(), thirdStringLength - 1},
152 {thirdString->GetDataMUtf8(), thirdStringLength - 1}));
153 }
154
TEST_F(EtsStringTest,CreateNewStringFromChars)155 TEST_F(EtsStringTest, CreateNewStringFromChars)
156 {
157 std::vector<ets_char> data {0x8ab, 0xdc, 'h', 'e', 'l', 'l', 'o', 0};
158
159 EtsString *utf16String = EtsString::CreateFromUtf16(data.data(), data.size());
160 EtsArray *charArray = utf16String->ToCharArray();
161
162 uint32_t beginOffset = 2;
163 uint32_t length = data.size() - beginOffset;
164
165 // make char array from subdata
166 std::vector<ets_char> subdata {'h', 'e', 'l', 'l', 'o', 0};
167
168 EtsString *expectedString = EtsString::CreateFromUtf16(subdata.data(), subdata.size());
169
170 EtsString *stringFromCharArray = EtsString::CreateNewStringFromChars(beginOffset, length, charArray);
171
172 ASSERT_TRUE(coretypes::String::StringsAreEqual(reinterpret_cast<coretypes::String *>(expectedString),
173 reinterpret_cast<coretypes::String *>(stringFromCharArray)));
174 }
175
TEST_F(EtsStringTest,CreateNewStringFromString)176 TEST_F(EtsStringTest, CreateNewStringFromString)
177 {
178 std::vector<ets_char> data {0xffc3, 0x33, 0x00};
179
180 EtsString *string1 = EtsString::CreateFromUtf16(data.data(), data.size());
181 EtsString *string2 = EtsString::CreateFromUtf16(data.data(), data.size() - 1);
182 EtsString *createdString = EtsString::CreateNewStringFromString(string1);
183
184 ASSERT_TRUE(coretypes::String::StringsAreEqual(reinterpret_cast<coretypes::String *>(string1),
185 reinterpret_cast<coretypes::String *>(createdString)));
186
187 ASSERT_FALSE(coretypes::String::StringsAreEqual(reinterpret_cast<coretypes::String *>(string2),
188 reinterpret_cast<coretypes::String *>(createdString)));
189 }
190
TEST_F(EtsStringTest,CreateNewEmptyString)191 TEST_F(EtsStringTest, CreateNewEmptyString)
192 {
193 ets_char data = 0;
194 EtsString *str1 = EtsString::CreateFromUtf16(&data, 0);
195 EtsString *str2 = EtsString::CreateFromUtf16(&data, 1);
196 EtsString *str3 = EtsString::CreateNewEmptyString();
197
198 ASSERT_TRUE(coretypes::String::StringsAreEqual(reinterpret_cast<coretypes::String *>(str1),
199 reinterpret_cast<coretypes::String *>(str3)));
200 ASSERT_FALSE(coretypes::String::StringsAreEqual(reinterpret_cast<coretypes::String *>(str2),
201 reinterpret_cast<coretypes::String *>(str3)));
202 }
203
TEST_F(EtsStringTest,Compare)204 TEST_F(EtsStringTest, Compare)
205 {
206 // utf8 vs utf8
207 std::vector<uint8_t> data1 {'a', 'b', 'c', 'd', 'z', 0};
208 std::vector<uint8_t> data2 {'a', 'b', 'c', 'd', 'z', 'x', 0};
209 std::vector<uint16_t> data3 {'a', 'b', 'c', 'd', 'z', 0};
210 std::vector<uint16_t> data4 {'a', 'b', 'd', 'c', 'z', 0};
211
212 auto *mutf8Data1 = reinterpret_cast<const char *>(data1.data());
213 auto *mutf8Data2 = reinterpret_cast<const char *>(data2.data());
214
215 EtsString *string1 = EtsString::CreateFromMUtf8(mutf8Data1);
216 EtsString *string2 = EtsString::CreateFromMUtf8(mutf8Data2);
217 EtsString *string3 = EtsString::CreateFromUtf16(data3.data(), data3.size() - 1);
218 EtsString *string4 = EtsString::CreateFromUtf16(data4.data(), data4.size() - 1);
219
220 ASSERT_EQ(false, string1->IsUtf16());
221 ASSERT_EQ(false, string2->IsUtf16());
222 ASSERT_EQ(false, string3->IsUtf16());
223 ASSERT_EQ(false, string4->IsUtf16());
224 ASSERT_LT(string1->Compare(string2), 0);
225 ASSERT_GT(string2->Compare(string1), 0);
226 ASSERT_EQ(string1->Compare(string3), 0);
227 ASSERT_EQ(string3->Compare(string1), 0);
228 ASSERT_LT(string2->Compare(string4), 0);
229 ASSERT_GT(string4->Compare(string2), 0);
230
231 // utf8 vs utf16
232 std::vector<uint16_t> data5 {'a', 'b', 0xab, 0xdc, 'z', 0};
233 EtsString *string5 = EtsString::CreateFromUtf16(data5.data(), data5.size() - 1);
234
235 ASSERT_EQ(true, string5->IsUtf16());
236 ASSERT_LT(string2->Compare(string5), 0);
237 ASSERT_GT(string5->Compare(string2), 0);
238 ASSERT_LT(string4->Compare(string5), 0);
239 ASSERT_GT(string5->Compare(string4), 0);
240
241 // utf16 vs utf16
242 std::vector<uint16_t> data6 {'a', 0xab, 0xab, 0};
243 EtsString *string6 = EtsString::CreateFromUtf16(data6.data(), data6.size() - 1);
244 EtsString *string7 = EtsString::CreateFromUtf16(data6.data(), data6.size() - 1);
245
246 ASSERT_EQ(true, string6->IsUtf16());
247 ASSERT_EQ(true, string7->IsUtf16());
248 ASSERT_LT(string5->Compare(string6), 0);
249 ASSERT_GT(string6->Compare(string5), 0);
250 ASSERT_EQ(string6->Compare(string7), 0);
251 ASSERT_EQ(string7->Compare(string6), 0);
252
253 // compare with self
254 ASSERT_EQ(string1->Compare(string1), 0);
255 ASSERT_EQ(string2->Compare(string2), 0);
256 ASSERT_EQ(string3->Compare(string3), 0);
257 ASSERT_EQ(string4->Compare(string4), 0);
258 ASSERT_EQ(string5->Compare(string5), 0);
259 ASSERT_EQ(string6->Compare(string6), 0);
260 ASSERT_EQ(string7->Compare(string7), 0);
261 }
262
TEST_F(EtsStringTest,Concat)263 TEST_F(EtsStringTest, Concat)
264 {
265 // utf8 + utf8
266 std::vector<uint8_t> data1 {'H', 'e', 'l', 'l', 'o', 0};
267 std::vector<uint8_t> data2 {'w', 'o', 'r', 'l', 'd', '!', 0};
268 std::vector<uint8_t> data3;
269
270 data3.insert(data3.end(), data1.begin(), data1.end() - 1);
271 data3.insert(data3.end(), data2.begin(), data2.end());
272
273 auto *mutf8Data1 = reinterpret_cast<const char *>(data1.data());
274 auto *mutf8Data2 = reinterpret_cast<const char *>(data2.data());
275 auto *mutf8Data3 = reinterpret_cast<const char *>(data3.data());
276
277 EtsString *str1 = EtsString::CreateFromMUtf8(mutf8Data1);
278 EtsString *str2 = EtsString::CreateFromMUtf8(mutf8Data2);
279 EtsString *str3 = EtsString::Concat(str1, str2);
280 EtsString *expectedStr1 = EtsString::CreateFromMUtf8(mutf8Data3);
281
282 ASSERT_EQ(str3->Compare(expectedStr1), 0);
283 ASSERT_EQ(expectedStr1->Compare(str3), 0);
284
285 // utf16 + utf16
286 std::vector<uint16_t> data4 {'a', 'b', 'c', 'd', 0};
287 std::vector<uint16_t> data5 {'e', 'f', 'g', 0};
288 std::vector<uint16_t> data6;
289
290 data6.insert(data6.end(), data4.begin(), data4.end() - 1);
291 data6.insert(data6.end(), data5.begin(), data5.end());
292
293 EtsString *str4 = EtsString::CreateFromUtf16(data4.data(), data4.size() - 1);
294 EtsString *str5 = EtsString::CreateFromUtf16(data5.data(), data5.size());
295 EtsString *str6 = EtsString::Concat(str4, str5);
296 EtsString *expectedStr2 = EtsString::CreateFromUtf16(data6.data(), data6.size());
297
298 ASSERT_EQ(str6->Compare(expectedStr2), 0);
299 ASSERT_EQ(expectedStr2->Compare(str6), 0);
300
301 // utf8 + utf16
302 std::vector<uint16_t> data7;
303 data7.insert(data7.end(), data1.begin(), data1.end() - 1);
304 data7.insert(data7.end(), data4.begin(), data4.end() - 1);
305
306 EtsString *str7 = EtsString::Concat(str1, str4);
307 EtsString *expectedStr3 = EtsString::CreateFromUtf16(data7.data(), data7.size());
308
309 ASSERT_EQ(str7->Compare(expectedStr3), 0);
310 ASSERT_EQ(expectedStr3->Compare(str7), 0);
311 }
312
TEST_F(EtsStringTest,At)313 TEST_F(EtsStringTest, At)
314 {
315 // utf8
316 std::vector<uint8_t> data1 {'a', 'b', 'c', 'd', 'z', 0};
317 auto *mutf8Data1 = reinterpret_cast<const char *>(data1.data());
318 EtsString *string = EtsString::CreateFromMUtf8(mutf8Data1, data1.size() - 1);
319 ASSERT_EQ(false, string->IsUtf16());
320 for (uint32_t i = 0; i < data1.size() - 1; i++) {
321 ASSERT_EQ(data1[i], string->At(i));
322 }
323
324 // utf16
325 std::vector<uint16_t> data2 {'a', 'b', 0xab, 0xdc, 'z', 0};
326 string = EtsString::CreateFromUtf16(data2.data(), data2.size() - 1);
327 ASSERT_EQ(true, string->IsUtf16());
328 for (uint32_t i = 0; i < data2.size() - 1; i++) {
329 ASSERT_EQ(data2[i], string->At(i));
330 }
331
332 // utf16 -> utf8
333 std::vector<uint16_t> data3 {'a', 'b', 121, 122, 'z', 0};
334 string = EtsString::CreateFromUtf16(data3.data(), data3.size() - 1);
335 ASSERT_EQ(false, string->IsUtf16());
336 for (uint32_t i = 0; i < data3.size() - 1; i++) {
337 ASSERT_EQ(data3[i], string->At(i));
338 }
339 }
340
TEST_F(EtsStringTest,DoReplace)341 TEST_F(EtsStringTest, DoReplace)
342 {
343 uint32_t len = 10;
344 std::vector<char> data1(len + 1);
345 std::vector<char> data2(len + 1);
346
347 for (uint32_t i = 0; i < len; i++) {
348 data1[i] = 'A' + i;
349 data2[i] = 'A' + i;
350 }
351
352 data1.front() = 'Z';
353 data1.back() = '\0';
354 data2.back() = '\0';
355
356 EtsString *str1 = EtsString::CreateFromMUtf8(data1.data());
357 EtsString *str2 = EtsString::CreateFromMUtf8(data2.data());
358 EtsString *str3 = EtsString::DoReplace(str1, 'Z', 'A');
359
360 ASSERT_NE(str1->Compare(str2), 0);
361 ASSERT_EQ(str2->Compare(str3), 0);
362 }
363
TEST_F(EtsStringTest,FastSubString)364 TEST_F(EtsStringTest, FastSubString)
365 {
366 uint32_t strLen = 10;
367 uint32_t subStrLen = 5;
368 uint32_t subStrStart = 1;
369
370 std::vector<char> data1(strLen + 1);
371 std::vector<char> data2(subStrLen + 1);
372
373 for (uint32_t i = 0; i < strLen; i++) {
374 data1[i] = 'A' + i;
375 }
376 data1.back() = '\0';
377
378 for (uint32_t i = 0; i < subStrLen; i++) {
379 data2[i] = data1[subStrStart + i];
380 }
381 data2.back() = '\0';
382
383 EtsString *str1 = EtsString::CreateFromMUtf8(data1.data());
384 EtsString *str2 = EtsString::CreateFromMUtf8(data2.data());
385 EtsString *str3 = EtsString::FastSubString(str1, subStrStart, subStrLen);
386
387 ASSERT_EQ(str3->Compare(str2), 0);
388 }
389
TEST_F(EtsStringTest,GetLength)390 TEST_F(EtsStringTest, GetLength)
391 {
392 // utf16
393 std::vector<uint16_t> data1 {0xffc3, 0x33, 0x00};
394 EtsString *str = EtsString::CreateFromUtf16(data1.data(), data1.size());
395 ASSERT_EQ(str->GetLength(), data1.size());
396
397 // utf8
398 std::vector<char> data2 {'H', 'e', 'l', 'l', 'o', 'w', 'o', 'r', 'l', 'd', '!', 0};
399 str = EtsString::CreateFromMUtf8(data2.data());
400
401 ASSERT_EQ(false, str->IsUtf16());
402 ASSERT_EQ(str->GetLength(), data2.size() - 1);
403 }
404
TEST_F(EtsStringTest,GetMUtf8Length)405 TEST_F(EtsStringTest, GetMUtf8Length)
406 {
407 std::vector<char> data2 {'H', 'e', 'l', 'l', 'o', 'w', 'o', 'r', 'l', 'd', '!', 0};
408 EtsString *str = EtsString::CreateFromMUtf8(data2.data());
409 ASSERT_EQ(false, str->IsUtf16());
410 ASSERT_EQ(str->GetMUtf8Length(), data2.size());
411 ASSERT_EQ(str->GetMUtf8Length(), str->GetLength() + 1);
412 }
413
TEST_F(EtsStringTest,GetUtf16Length)414 TEST_F(EtsStringTest, GetUtf16Length)
415 {
416 std::vector<uint16_t> data1 {0xffc3, 0x33, 'a', 'b', 'c', 0x00};
417 EtsString *str = EtsString::CreateFromUtf16(data1.data(), data1.size());
418 ASSERT_EQ(true, str->IsUtf16());
419 ASSERT_EQ(str->GetUtf16Length(), data1.size());
420 ASSERT_EQ(str->GetLength(), str->GetUtf16Length());
421 }
422
TEST_F(EtsStringTest,CopyDataMUtf8)423 TEST_F(EtsStringTest, CopyDataMUtf8)
424 {
425 std::vector<char> data {'a', 'b', 'c', 'd', 'z', 0};
426 std::vector<char> copiedDataMutf8(data.size());
427 EtsString *str = EtsString::CreateFromMUtf8(data.data());
428
429 ASSERT_EQ(str->CopyDataMUtf8(copiedDataMutf8.data(), copiedDataMutf8.size(), true), data.size());
430 ASSERT_EQ(copiedDataMutf8, data);
431 }
432
TEST_F(EtsStringTest,CopyDataUtf16)433 TEST_F(EtsStringTest, CopyDataUtf16)
434 {
435 std::vector<char> data {'a', 'b', 'c', 'd', 'z', 0};
436 EtsString *str = EtsString::CreateFromMUtf8(data.data());
437 std::vector<uint16_t> resUtf16 {'a', 'b', 'c', 'd', 'z'};
438 std::vector<uint16_t> copiedDataUtf16(resUtf16.size());
439
440 ASSERT_EQ(str->CopyDataUtf16(copiedDataUtf16.data(), copiedDataUtf16.size()), resUtf16.size());
441 ASSERT_EQ(copiedDataUtf16, resUtf16);
442 }
443
TEST_F(EtsStringTest,CopyDataRegionMUtf8)444 TEST_F(EtsStringTest, CopyDataRegionMUtf8)
445 {
446 std::vector<char> data {'a', 'b', 'h', 'e', 'l', 'l', 'o', 'c', 'd', 'z', 0};
447 std::vector<char> res {'h', 'e', 'l', 'l', 'o', 0};
448 std::vector<char> copiedDataMutf8(res.size());
449 size_t start = 2;
450 size_t len = 5;
451 EtsString *str = EtsString::CreateFromMUtf8(data.data());
452
453 ASSERT_EQ(str->CopyDataRegionMUtf8(copiedDataMutf8.data(), start, len, copiedDataMutf8.size()), res.size() - 1);
454 ASSERT_EQ(copiedDataMutf8, res);
455
456 std::vector<uint16_t> res16 {'h', 'e', 'l', 'l', 'o'};
457 std::vector<uint16_t> copiedDataUtf16(res16.size());
458
459 ASSERT_EQ(str->CopyDataRegionUtf16(copiedDataUtf16.data(), start, len, copiedDataUtf16.size()), res16.size());
460 ASSERT_EQ(copiedDataUtf16, res16);
461 }
462
TEST_F(EtsStringTest,CopyDataRegionUtf16)463 TEST_F(EtsStringTest, CopyDataRegionUtf16)
464 {
465 std::vector<uint16_t> data {0xb7, 0xc7, 0xa4, 'h', 'e', 'l', 'l', 'o', 0xa7, 0};
466 std::vector<uint8_t> res {'h', 'e', 'l', 'l', 'o', 0};
467 std::vector<uint8_t> copiedDataMutf8(res.size());
468 size_t start = 3;
469 size_t len = 5;
470 EtsString *str = EtsString::CreateFromUtf16(data.data(), data.size());
471
472 ASSERT_EQ(str->CopyDataRegionMUtf8(copiedDataMutf8.data(), start, len, copiedDataMutf8.size()), res.size() - 1);
473 ASSERT_EQ(copiedDataMutf8, res);
474
475 std::vector<uint16_t> res16 {'h', 'e', 'l', 'l', 'o'};
476 std::vector<uint16_t> copiedDataUtf16(res16.size());
477
478 ASSERT_EQ(str->CopyDataRegionUtf16(copiedDataUtf16.data(), start, len, copiedDataUtf16.size()), res16.size());
479 ASSERT_EQ(copiedDataUtf16, res16);
480 }
481
TEST_F(EtsStringTest,IsEqual)482 TEST_F(EtsStringTest, IsEqual)
483 {
484 std::vector<char> data1 {'a', 'b', 'c', 'd', 'e', 0};
485 std::vector<char> data2 {'a', 'b', 'c', 'd', 'f', 0};
486 char data3 = 0;
487
488 EtsString *str1 = EtsString::CreateFromMUtf8(data1.data());
489 EtsString *str2 = EtsString::CreateFromMUtf8(data2.data());
490 EtsString *str3 = EtsString::CreateNewEmptyString();
491
492 ASSERT_TRUE(str1->IsEqual(data1.data()));
493 ASSERT_TRUE(str2->IsEqual(data2.data()));
494 ASSERT_TRUE(str3->IsEqual(&data3));
495 ASSERT_FALSE(str1->IsEqual(data2.data()));
496 ASSERT_FALSE(str2->IsEqual(data1.data()));
497 ASSERT_FALSE(str1->IsEqual(&data3));
498 ASSERT_FALSE(str2->IsEqual(&data3));
499 ASSERT_FALSE(str3->IsEqual(data1.data()));
500 ASSERT_FALSE(str3->IsEqual(data2.data()));
501 }
502
TEST_F(EtsStringTest,IsEmpty)503 TEST_F(EtsStringTest, IsEmpty)
504 {
505 std::vector<char> data {'a', 'f', 'a', 0};
506 EtsString *str1 = EtsString::CreateFromMUtf8(data.data());
507 EtsString *str2 = EtsString::CreateNewEmptyString();
508
509 ASSERT_FALSE(str1->IsEmpty());
510 ASSERT_TRUE(str2->IsEmpty());
511 }
512
TEST_F(EtsStringTest,StringsAreEqual)513 TEST_F(EtsStringTest, StringsAreEqual)
514 {
515 std::vector<char> data1 {'a', 'b', 's', 'r', 'd', 'r', 0};
516 std::vector<char> data2 {'a', 'b', 's', 0};
517
518 EtsString *str1 = EtsString::CreateFromMUtf8(data1.data(), data1.size() - 1);
519 data1[data1.size() - 4U] = 0;
520 EtsString *str2 = EtsString::CreateFromMUtf8(data1.data(), data1.size() - 4U);
521 EtsString *str3 = EtsString::CreateFromMUtf8(data2.data());
522
523 ASSERT_TRUE(str1->StringsAreEqual(reinterpret_cast<EtsObject *>(str1)));
524 ASSERT_TRUE(str2->StringsAreEqual(reinterpret_cast<EtsObject *>(str2)));
525 ASSERT_TRUE(str3->StringsAreEqual(reinterpret_cast<EtsObject *>(str3)));
526 ASSERT_TRUE(str2->StringsAreEqual(reinterpret_cast<EtsObject *>(str3)));
527 ASSERT_TRUE(str3->StringsAreEqual(reinterpret_cast<EtsObject *>(str2)));
528
529 ASSERT_FALSE(str1->StringsAreEqual(reinterpret_cast<EtsObject *>(str2)));
530 ASSERT_FALSE(str2->StringsAreEqual(reinterpret_cast<EtsObject *>(str1)));
531 }
532
TEST_F(EtsStringTest,GetCoreType)533 TEST_F(EtsStringTest, GetCoreType)
534 {
535 std::vector<char> data {'a', 'b', 'c', 'd', 0};
536 EtsString *str = EtsString::CreateFromMUtf8(data.data());
537 EtsString *emptyStr = EtsString::CreateNewEmptyString();
538
539 ASSERT_EQ(reinterpret_cast<coretypes::String *>(str), str->GetCoreType());
540 ASSERT_EQ(reinterpret_cast<coretypes::String *>(emptyStr), emptyStr->GetCoreType());
541 }
542
TEST_F(EtsStringTest,FromEtsObject)543 TEST_F(EtsStringTest, FromEtsObject)
544 {
545 std::vector<char> data {'a', 'b', 'c', 'd', 'e', 0};
546
547 EtsString *str1 = EtsString::CreateFromMUtf8(data.data());
548 EtsString *str3 = EtsString::CreateNewEmptyString();
549
550 ASSERT_EQ(str1->Compare(EtsString::FromEtsObject(reinterpret_cast<EtsObject *>(str1))), 0);
551 ASSERT_EQ(str3->Compare(EtsString::FromEtsObject(reinterpret_cast<EtsObject *>(str3))), 0);
552 }
553
TEST_F(EtsStringTest,CreateNewStringFromBytes)554 TEST_F(EtsStringTest, CreateNewStringFromBytes)
555 {
556 std::vector<uint8_t> data {'f', 'g', 'h', 'a', 'b', 0xab, 0xdc, 'z', 0};
557 uint32_t byteArrayLength = 5;
558 uint32_t byteArrayOffset = 1;
559 uint32_t highByte = 1;
560
561 std::vector<uint16_t> data1(byteArrayLength);
562 for (uint32_t i = 0; i < byteArrayLength; ++i) {
563 data1[i] = (highByte << 8U) + (data[i + byteArrayOffset]);
564 }
565
566 EtsString *string1 = EtsString::CreateFromUtf16(data1.data(), byteArrayLength);
567 EtsByteArray *byteArray = EtsByteArray::Create(data.size() - 1);
568
569 Span<uint8_t> sp(data.data(), data.size() - 1);
570 for (uint32_t i = 0; i < data.size() - 1; i++) {
571 byteArray->Set(i, sp[i]);
572 }
573
574 EtsString *result = EtsString::CreateNewStringFromBytes(byteArray, highByte, byteArrayOffset, byteArrayLength);
575
576 ASSERT_TRUE(result->StringsAreEqual(reinterpret_cast<EtsObject *>(string1)));
577 }
578
TEST_F(EtsStringTest,GetDataUtf16)579 TEST_F(EtsStringTest, GetDataUtf16)
580 {
581 std::vector<uint16_t> data = {'a', 'b', 'c', 'd', 'e', 0xac, 0};
582
583 EtsString *string1 = EtsString::CreateFromUtf16(data.data(), data.size());
584 ASSERT_TRUE(string1->IsUtf16());
585 EtsString *string2 = EtsString::CreateFromUtf16(string1->GetDataUtf16(), data.size());
586 ASSERT_TRUE(string2->IsUtf16());
587
588 ASSERT_TRUE(string1->StringsAreEqual(reinterpret_cast<EtsObject *>(string2)));
589 }
590
TEST_F(EtsStringTest,GetDataMUtf8)591 TEST_F(EtsStringTest, GetDataMUtf8)
592 {
593 std::vector<char> data = {'a', 'b', 'c', 'd', 'e', 0};
594
595 EtsString *string1 = EtsString::CreateFromMUtf8(data.data());
596 ASSERT_FALSE(string1->IsUtf16());
597
598 std::vector<uint8_t> data2(string1->GetDataMUtf8(), string1->GetDataMUtf8() + data.size() - 1); // NOLINT
599 data2.push_back(0); // GetDataMUtf8 return array without 0
600
601 EtsString *string2 = EtsString::CreateFromMUtf8(reinterpret_cast<const char *>(data2.data()));
602 ASSERT_FALSE(string2->IsUtf16());
603
604 ASSERT_TRUE(string1->StringsAreEqual(reinterpret_cast<EtsObject *>(string2)));
605 }
606
TEST_F(EtsStringTest,GetMutf8)607 TEST_F(EtsStringTest, GetMutf8)
608 {
609 std::vector<char> data = {'h', 'e', 'l', 'l', 'o', 0};
610
611 EtsString *string = EtsString::CreateFromMUtf8(data.data());
612 PandaString pandaString = string->GetMutf8();
613
614 ASSERT_EQ(strcmp(pandaString.data(), "hello"), 0);
615 }
616
TEST_F(EtsStringTest,Resolve)617 TEST_F(EtsStringTest, Resolve)
618 {
619 std::vector<uint8_t> data {'H', 'e', 'l', 'l', 'o', 'w', 'o', 'r', 'l', 'd', '!', 0};
620
621 EtsString *string1 = EtsString::Resolve(data.data(), data.size() - 1);
622 EtsString *string2 = EtsString::Resolve(data.data(), data.size() - 1);
623 EtsString *string3 = EtsString::CreateFromMUtf8(reinterpret_cast<const char *>(data.data()));
624
625 ASSERT_EQ(string1, string2);
626 ASSERT_TRUE(string1->StringsAreEqual(reinterpret_cast<EtsObject *>(string3)));
627 ASSERT_TRUE(string2->StringsAreEqual(reinterpret_cast<EtsObject *>(string3)));
628 }
629
630 } // namespace ark::ets::test
631
632 // NOLINTEND(readability-magic-numbers)
633