• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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