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 "ets_coroutine.h"
19 #include "ets_platform_types.h"
20 #include "types/ets_box_primitive.h"
21 #include "types/ets_box_primitive-inl.h"
22 #include "types/ets_array.h"
23 #include "types/ets_string.h"
24
25 // NOLINTBEGIN(readability-magic-numbers)
26
27 namespace ark::ets::test {
28 class EtsStringFromCharCodeTest : public testing::Test {
29 public:
EtsStringFromCharCodeTest()30 EtsStringFromCharCodeTest()
31 {
32 options_.SetShouldLoadBootPandaFiles(true);
33 options_.SetShouldInitializeIntrinsics(false);
34 options_.SetCompilerEnableJit(false);
35 options_.SetGcType("epsilon");
36 options_.SetLoadRuntimes({"ets"});
37
38 auto stdlib = std::getenv("PANDA_STD_LIB");
39 if (stdlib == nullptr) {
40 std::cerr << "PANDA_STD_LIB env variable should be set and point to etsstdlib.abc" << std::endl;
41 std::abort();
42 }
43 options_.SetBootPandaFiles({stdlib});
44
45 Runtime::Create(options_);
46 }
47
~EtsStringFromCharCodeTest()48 ~EtsStringFromCharCodeTest() override
49 {
50 Runtime::Destroy();
51 }
52
53 NO_COPY_SEMANTIC(EtsStringFromCharCodeTest);
54 NO_MOVE_SEMANTIC(EtsStringFromCharCodeTest);
55
SetUp()56 void SetUp() override
57 {
58 coroutine_ = EtsCoroutine::GetCurrent();
59 coroutine_->ManagedCodeBegin();
60 }
61
TearDown()62 void TearDown() override
63 {
64 coroutine_->ManagedCodeEnd();
65 }
66
67 template <typename DoubleIter>
CreateNewStringFromCharCodes(DoubleIter first,DoubleIter last)68 EtsString *CreateNewStringFromCharCodes(DoubleIter first, DoubleIter last)
69 {
70 using CharCodeArray = EtsString::CharCodeArray;
71 using CharCode = std::remove_pointer_t<CharCodeArray::ValueType>;
72 EtsClass *klass = CharCode::GetEtsBoxClass(coroutine_);
73 ASSERT(klass != nullptr);
74 CharCodeArray *charCodeArray = CharCodeArray::Create(klass, std::distance(first, last));
75 std::for_each(first, last, [&charCodeArray, this, idx = 0U](double d) mutable {
76 auto *boxedValue = CharCode::Create(coroutine_, d);
77 charCodeArray->Set(idx++, boxedValue);
78 });
79
80 return EtsString::CreateNewStringFromCharCode(charCodeArray);
81 }
82
CreateNewStringFromCharCodes(const std::vector<double> & codes)83 EtsString *CreateNewStringFromCharCodes(const std::vector<double> &codes)
84 {
85 return CreateNewStringFromCharCodes(codes.begin(), codes.end());
86 }
87
CreateNewStringFromCharCode(double code)88 static EtsString *CreateNewStringFromCharCode(double code)
89 {
90 return EtsString::CreateNewStringFromCharCode(code);
91 }
92
93 private:
94 RuntimeOptions options_;
95 EtsCoroutine *coroutine_ = nullptr;
96 };
97
TEST_F(EtsStringFromCharCodeTest,CreateNewCompressedStringFromCharCodes)98 TEST_F(EtsStringFromCharCodeTest, CreateNewCompressedStringFromCharCodes)
99 {
100 EtsString *expectedCompressedString = EtsString::CreateFromMUtf8("Helloff\n");
101 EtsString *stringFromCompressedCharCodes =
102 CreateNewStringFromCharCodes({0x48, 0x65, 0x6C, 0x6C, 0x6F, 4294901862, 0xffff0066, 10.316});
103 ASSERT_TRUE(stringFromCompressedCharCodes->GetCoreType()->IsMUtf8());
104 ASSERT_TRUE(coretypes::String::StringsAreEqual(expectedCompressedString->GetCoreType(),
105 stringFromCompressedCharCodes->GetCoreType()));
106 }
107
TEST_F(EtsStringFromCharCodeTest,CreateNewCompressedStringFromCharCode)108 TEST_F(EtsStringFromCharCodeTest, CreateNewCompressedStringFromCharCode)
109 {
110 EtsString *expectedCompressedString = EtsString::CreateFromMUtf8("A");
111 EtsString *stringFromCompressedCharCodes = CreateNewStringFromCharCodes({0x41});
112 ASSERT_TRUE(stringFromCompressedCharCodes->GetCoreType()->IsMUtf8());
113 ASSERT_TRUE(coretypes::String::StringsAreEqual(expectedCompressedString->GetCoreType(),
114 stringFromCompressedCharCodes->GetCoreType()));
115
116 EtsString *stringFromCompressedCharCode = CreateNewStringFromCharCode(0x41);
117 ASSERT_TRUE(stringFromCompressedCharCode->GetCoreType()->IsMUtf8());
118 ASSERT_TRUE(coretypes::String::StringsAreEqual(expectedCompressedString->GetCoreType(),
119 stringFromCompressedCharCode->GetCoreType()));
120 }
121
TEST_F(EtsStringFromCharCodeTest,CreateNewUncompressedStringFromCharCode)122 TEST_F(EtsStringFromCharCodeTest, CreateNewUncompressedStringFromCharCode)
123 {
124 std::vector<uint16_t> data = {0x3B2};
125 EtsString *expectedUncompressedString = EtsString::CreateFromUtf16(data.data(), static_cast<ets_int>(data.size()));
126 EtsString *stringFromUncompressedCharCodes = CreateNewStringFromCharCodes({0x3B2});
127 ASSERT_TRUE(stringFromUncompressedCharCodes->GetCoreType()->IsUtf16());
128 ASSERT_TRUE(coretypes::String::StringsAreEqual(expectedUncompressedString->GetCoreType(),
129 stringFromUncompressedCharCodes->GetCoreType()));
130
131 EtsString *stringFromUncompressedCharCode = CreateNewStringFromCharCode(0x3B2);
132 ASSERT_TRUE(stringFromUncompressedCharCode->GetCoreType()->IsUtf16());
133 ASSERT_TRUE(coretypes::String::StringsAreEqual(expectedUncompressedString->GetCoreType(),
134 stringFromUncompressedCharCode->GetCoreType()));
135 }
136
TEST_F(EtsStringFromCharCodeTest,CreateNewUncompressedStringFromCharCodes)137 TEST_F(EtsStringFromCharCodeTest, CreateNewUncompressedStringFromCharCodes)
138 {
139 std::vector<uint16_t> data = {0x3B2, 'A', 'B', 'C', 'D', 0xac, 0xff9c, 0, 0xffff, 1, 0xffff, 0, 0, 0};
140 EtsString *expectedUncompressedString = EtsString::CreateFromUtf16(data.data(), static_cast<ets_int>(data.size()));
141 std::vector<double> charCodes {0x3B2,
142 0x41,
143 66.3,
144 67.00009,
145 68.99998,
146 172.9999,
147 -100,
148 static_cast<double>(0x7fffffffffffffff),
149 static_cast<double>(0x1fffffffffffff),
150 static_cast<double>(-0x1fffffffffffff),
151 static_cast<double>(0xffff),
152 static_cast<double>(0x10000),
153 static_cast<double>(0x8000000000000000),
154 0};
155 EtsString *stringFromUncompressedCharCodes = CreateNewStringFromCharCodes(charCodes);
156 ASSERT_TRUE(stringFromUncompressedCharCodes->GetCoreType()->IsUtf16());
157 ASSERT_TRUE(coretypes::String::StringsAreEqual(expectedUncompressedString->GetCoreType(),
158 stringFromUncompressedCharCodes->GetCoreType()));
159 }
160
TEST_F(EtsStringFromCharCodeTest,CreateNewEmptyStringFromCharCode)161 TEST_F(EtsStringFromCharCodeTest, CreateNewEmptyStringFromCharCode)
162 {
163 EtsString *emptyString = EtsString::CreateNewEmptyString();
164 EtsString *stringFromCharCodes = CreateNewStringFromCharCodes({});
165 ASSERT_TRUE(stringFromCharCodes->GetCoreType()->IsMUtf8());
166 ASSERT_TRUE(coretypes::String::StringsAreEqual(emptyString->GetCoreType(), stringFromCharCodes->GetCoreType()));
167 }
168
TEST_F(EtsStringFromCharCodeTest,CreateNewStringFromNaNCharCode)169 TEST_F(EtsStringFromCharCodeTest, CreateNewStringFromNaNCharCode)
170 {
171 std::vector<uint16_t> data = {0};
172 EtsString *expectedUncompressedString = EtsString::CreateFromUtf16(data.data(), static_cast<ets_int>(data.size()));
173 EtsString *stringFromUncompressedCharCodes =
174 CreateNewStringFromCharCodes({std::numeric_limits<double>::quiet_NaN()});
175 ASSERT_TRUE(stringFromUncompressedCharCodes->GetCoreType()->IsUtf16());
176 ASSERT_TRUE(coretypes::String::StringsAreEqual(expectedUncompressedString->GetCoreType(),
177 stringFromUncompressedCharCodes->GetCoreType()));
178
179 EtsString *stringFromUncompressedCharCode = CreateNewStringFromCharCode(std::numeric_limits<double>::quiet_NaN());
180 ASSERT_TRUE(stringFromUncompressedCharCode->GetCoreType()->IsUtf16());
181 ASSERT_TRUE(coretypes::String::StringsAreEqual(expectedUncompressedString->GetCoreType(),
182 stringFromUncompressedCharCode->GetCoreType()));
183 }
184
TEST_F(EtsStringFromCharCodeTest,CreateNewStringFromInfinityCharCode)185 TEST_F(EtsStringFromCharCodeTest, CreateNewStringFromInfinityCharCode)
186 {
187 std::vector<uint16_t> data = {0};
188 EtsString *expectedUncompressedString = EtsString::CreateFromUtf16(data.data(), static_cast<ets_int>(data.size()));
189 EtsString *stringFromUncompressedCharCodes =
190 CreateNewStringFromCharCodes({std::numeric_limits<double>::infinity()});
191 ASSERT_TRUE(stringFromUncompressedCharCodes->GetCoreType()->IsUtf16());
192 ASSERT_TRUE(coretypes::String::StringsAreEqual(expectedUncompressedString->GetCoreType(),
193 stringFromUncompressedCharCodes->GetCoreType()));
194
195 EtsString *stringFromUncompressedCharCode = CreateNewStringFromCharCode(std::numeric_limits<double>::infinity());
196 ASSERT_TRUE(stringFromUncompressedCharCode->GetCoreType()->IsUtf16());
197 ASSERT_TRUE(coretypes::String::StringsAreEqual(expectedUncompressedString->GetCoreType(),
198 stringFromUncompressedCharCode->GetCoreType()));
199 }
200
TEST_F(EtsStringFromCharCodeTest,CreateNewStringFromNaNAndInfinityCharCodes)201 TEST_F(EtsStringFromCharCodeTest, CreateNewStringFromNaNAndInfinityCharCodes)
202 {
203 std::vector<uint16_t> data = {0, 0, 0};
204 EtsString *expectedUncompressedString = EtsString::CreateFromUtf16(data.data(), static_cast<ets_int>(data.size()));
205 EtsString *stringFromUncompressedCharCodes =
206 CreateNewStringFromCharCodes({std::numeric_limits<double>::quiet_NaN(), std::numeric_limits<double>::infinity(),
207 -std::numeric_limits<double>::infinity()});
208 ASSERT_TRUE(stringFromUncompressedCharCodes->GetCoreType()->IsUtf16());
209 ASSERT_TRUE(coretypes::String::StringsAreEqual(expectedUncompressedString->GetCoreType(),
210 stringFromUncompressedCharCodes->GetCoreType()));
211 }
212
TEST_F(EtsStringFromCharCodeTest,CreateNewStringFromMaxAvailableCharCode)213 TEST_F(EtsStringFromCharCodeTest, CreateNewStringFromMaxAvailableCharCode)
214 {
215 std::vector<uint16_t> data = {0xffff};
216 EtsString *expectedUncompressedString = EtsString::CreateFromUtf16(data.data(), static_cast<ets_int>(data.size()));
217 EtsString *stringFromMaxCharCodes1 = CreateNewStringFromCharCodes({9007199254740991.0});
218 ASSERT_TRUE(stringFromMaxCharCodes1->GetCoreType()->IsUtf16());
219 ASSERT_TRUE(coretypes::String::StringsAreEqual(expectedUncompressedString->GetCoreType(),
220 stringFromMaxCharCodes1->GetCoreType()));
221
222 EtsString *stringFromMaxCharCode1 = CreateNewStringFromCharCode(9007199254740991.0);
223 ASSERT_TRUE(stringFromMaxCharCode1->GetCoreType()->IsUtf16());
224 ASSERT_TRUE(coretypes::String::StringsAreEqual(expectedUncompressedString->GetCoreType(),
225 stringFromMaxCharCode1->GetCoreType()));
226 }
227
TEST_F(EtsStringFromCharCodeTest,CreateNewStringFromMinAvailableCharCode)228 TEST_F(EtsStringFromCharCodeTest, CreateNewStringFromMinAvailableCharCode)
229 {
230 EtsString *expectedCompressedString = EtsString::CreateFromMUtf8("\x01");
231 EtsString *stringFromMaxCharCodes1 = CreateNewStringFromCharCodes({-9007199254740991.0});
232 ASSERT_TRUE(stringFromMaxCharCodes1->GetCoreType()->IsMUtf8());
233 ASSERT_TRUE(coretypes::String::StringsAreEqual(expectedCompressedString->GetCoreType(),
234 stringFromMaxCharCodes1->GetCoreType()));
235
236 EtsString *stringFromMaxCharCode1 = CreateNewStringFromCharCode(-9007199254740991.0);
237 ASSERT_TRUE(stringFromMaxCharCode1->GetCoreType()->IsMUtf8());
238 ASSERT_TRUE(coretypes::String::StringsAreEqual(expectedCompressedString->GetCoreType(),
239 stringFromMaxCharCode1->GetCoreType()));
240 }
241
TEST_F(EtsStringFromCharCodeTest,CreateNewStringFromHugeCharCode)242 TEST_F(EtsStringFromCharCodeTest, CreateNewStringFromHugeCharCode)
243 {
244 std::vector<uint16_t> data = {0};
245 EtsString *expectedUncompressedString = EtsString::CreateFromUtf16(data.data(), static_cast<ets_int>(data.size()));
246 EtsString *stringFromHugeCharCodes1 = CreateNewStringFromCharCodes({18446744073709551616.0});
247 ASSERT_TRUE(stringFromHugeCharCodes1->GetCoreType()->IsUtf16());
248 ASSERT_TRUE(coretypes::String::StringsAreEqual(expectedUncompressedString->GetCoreType(),
249 stringFromHugeCharCodes1->GetCoreType()));
250
251 EtsString *stringFromHugeCharCode1 = CreateNewStringFromCharCode(18446744073709551616.0);
252 ASSERT_TRUE(stringFromHugeCharCode1->GetCoreType()->IsUtf16());
253 ASSERT_TRUE(coretypes::String::StringsAreEqual(expectedUncompressedString->GetCoreType(),
254 stringFromHugeCharCode1->GetCoreType()));
255
256 EtsString *stringFromHugeCharCodes2 = CreateNewStringFromCharCodes({18446744073709551617.0});
257 ASSERT_TRUE(stringFromHugeCharCodes2->GetCoreType()->IsUtf16());
258 ASSERT_TRUE(coretypes::String::StringsAreEqual(expectedUncompressedString->GetCoreType(),
259 stringFromHugeCharCodes2->GetCoreType()));
260
261 EtsString *stringFromHugeCharCode2 = CreateNewStringFromCharCode(18446744073709551617.0);
262 ASSERT_TRUE(stringFromHugeCharCode2->GetCoreType()->IsUtf16());
263 ASSERT_TRUE(coretypes::String::StringsAreEqual(expectedUncompressedString->GetCoreType(),
264 stringFromHugeCharCode2->GetCoreType()));
265
266 EtsString *stringFromHugeCharCodes3 = CreateNewStringFromCharCodes({9007199254740992.0});
267 ASSERT_TRUE(stringFromHugeCharCodes3->GetCoreType()->IsUtf16());
268 ASSERT_TRUE(coretypes::String::StringsAreEqual(expectedUncompressedString->GetCoreType(),
269 stringFromHugeCharCodes3->GetCoreType()));
270
271 EtsString *stringFromHugeCharCode3 = CreateNewStringFromCharCode(9007199254740992.0);
272 ASSERT_TRUE(stringFromHugeCharCode3->GetCoreType()->IsUtf16());
273 ASSERT_TRUE(coretypes::String::StringsAreEqual(expectedUncompressedString->GetCoreType(),
274 stringFromHugeCharCode3->GetCoreType()));
275 }
276
TEST_F(EtsStringFromCharCodeTest,CreateNewStringFromHugeNegativeCharCode)277 TEST_F(EtsStringFromCharCodeTest, CreateNewStringFromHugeNegativeCharCode)
278 {
279 std::vector<uint16_t> data = {0};
280 EtsString *expectedUncompressedString = EtsString::CreateFromUtf16(data.data(), static_cast<ets_int>(data.size()));
281 EtsString *stringFromHugeCharCodes1 = CreateNewStringFromCharCodes({-18446744073709551616.0});
282 ASSERT_TRUE(stringFromHugeCharCodes1->GetCoreType()->IsUtf16());
283 ASSERT_TRUE(coretypes::String::StringsAreEqual(expectedUncompressedString->GetCoreType(),
284 stringFromHugeCharCodes1->GetCoreType()));
285
286 EtsString *stringFromHugeCharCode1 = CreateNewStringFromCharCode(-18446744073709551616.0);
287 ASSERT_TRUE(stringFromHugeCharCode1->GetCoreType()->IsUtf16());
288 ASSERT_TRUE(coretypes::String::StringsAreEqual(expectedUncompressedString->GetCoreType(),
289 stringFromHugeCharCode1->GetCoreType()));
290
291 EtsString *stringFromHugeCharCodes2 = CreateNewStringFromCharCodes({-18446744073709551617.0});
292 ASSERT_TRUE(stringFromHugeCharCodes2->GetCoreType()->IsUtf16());
293 ASSERT_TRUE(coretypes::String::StringsAreEqual(expectedUncompressedString->GetCoreType(),
294 stringFromHugeCharCodes2->GetCoreType()));
295
296 EtsString *stringFromHugeCharCode2 = CreateNewStringFromCharCode(-18446744073709551617.0);
297 ASSERT_TRUE(stringFromHugeCharCode2->GetCoreType()->IsUtf16());
298 ASSERT_TRUE(coretypes::String::StringsAreEqual(expectedUncompressedString->GetCoreType(),
299 stringFromHugeCharCode2->GetCoreType()));
300
301 EtsString *stringFromHugeCharCodes3 = CreateNewStringFromCharCodes({-9007199254740992.0});
302 ASSERT_TRUE(stringFromHugeCharCodes3->GetCoreType()->IsUtf16());
303 ASSERT_TRUE(coretypes::String::StringsAreEqual(expectedUncompressedString->GetCoreType(),
304 stringFromHugeCharCodes3->GetCoreType()));
305
306 EtsString *stringFromHugeCharCode3 = CreateNewStringFromCharCode(-9007199254740992.0);
307 ASSERT_TRUE(stringFromHugeCharCode3->GetCoreType()->IsUtf16());
308 ASSERT_TRUE(coretypes::String::StringsAreEqual(expectedUncompressedString->GetCoreType(),
309 stringFromHugeCharCode3->GetCoreType()));
310 }
311
TEST_F(EtsStringFromCharCodeTest,CreateNewStringFromHugeCharCodes)312 TEST_F(EtsStringFromCharCodeTest, CreateNewStringFromHugeCharCodes)
313 {
314 std::vector<uint16_t> data = {0, 0, 0, 0, 0, 0, 0xffff, 0x1};
315 EtsString *expectedUncompressedString = EtsString::CreateFromUtf16(data.data(), static_cast<ets_int>(data.size()));
316 std::vector<double> charCodes {18446744073709551616.0, 18446744073709551617.0, 9007199254740992.0,
317 -18446744073709551616.0, -18446744073709551617.0, -9007199254740992.0,
318 9007199254740991.0, -9007199254740991.0};
319 EtsString *stringFromHugeCharCodes = CreateNewStringFromCharCodes(charCodes);
320 ASSERT_TRUE(stringFromHugeCharCodes->GetCoreType()->IsUtf16());
321 ASSERT_TRUE(coretypes::String::StringsAreEqual(expectedUncompressedString->GetCoreType(),
322 stringFromHugeCharCodes->GetCoreType()));
323 }
324 } // namespace ark::ets::test
325
326 // NOLINTEND(readability-magic-numbers)
327