• 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 "ecmascript/checkpoint/thread_state_transition.h"
17 #include "ecmascript/ecma_string_table_optimization-inl.h"
18 #include "ecmascript/ecma_string_table.h"
19 #include "ecmascript/tests/test_helper.h"
20 
21 using EcmaString = panda::ecmascript::EcmaString;
22 using EcmaStringAccessor = panda::ecmascript::EcmaStringAccessor;
23 
24 namespace panda::test {
25 class BaseStringTableTest : public BaseTestWithScope<false> {
26 public:
27     common::BaseStringTableInterface<common::BaseStringTableImpl>::HandleCreator handleCreator_ = [
__anon879005f50102(common::ThreadHolder* holder, common::BaseString* string) 28         ](common::ThreadHolder* holder, common::BaseString* string) -> common::ReadOnlyHandle<common::BaseString> {
29         return JSHandle<EcmaString>(holder->GetJSThread(), EcmaString::FromBaseString(string));
30     };
31 };
32 
33 /**
34  * @tc.name: GetOrInternFlattenString_EmptyString
35  * @tc.desc: Write empty string emptyStr to the Intern pool and takes the hash code as its index.
36  * @tc.type: FUNC
37  * @tc.require:
38  */
HWTEST_F_L0(BaseStringTableTest,GetOrInternFlattenString_EmptyString)39 HWTEST_F_L0(BaseStringTableTest, GetOrInternFlattenString_EmptyString)
40 {
41     if (!ecmascript::g_isEnableCMCGC) {
42         return;
43     }
44     auto& table = common::BaseRuntime::GetInstance()->GetStringTable();
45 
46     JSHandle<EcmaString> emptyEcmaStrHandle(thread, EcmaStringAccessor::CreateEmptyString(thread->GetEcmaVM()));
47     EXPECT_TRUE(!EcmaStringAccessor(emptyEcmaStrHandle).IsInternString());
48 
49     table.GetOrInternFlattenString(thread->GetThreadHolder(), handleCreator_, emptyEcmaStrHandle->ToBaseString());
50     EXPECT_TRUE(!EcmaStringAccessor(emptyEcmaStrHandle).IsInternString());
51     common::BaseString* emptyEcmaStr = table.TryGetInternString(emptyEcmaStrHandle);
52     EXPECT_STREQ(EcmaStringAccessor(EcmaString::FromBaseString(emptyEcmaStr)).ToCString(thread).c_str(), "");
53     EXPECT_TRUE(EcmaStringAccessor(EcmaString::FromBaseString(emptyEcmaStr)).IsInternString());
54 }
55 
56 /**
57  * @tc.name: GetOrInternString
58  * @tc.desc: Obtain EcmaString string from utf8 encoded data. If the string already exists in the detention pool,
59              it will be returned directly. If not, it will be added to the detention pool and then returned.
60  * @tc.type: FUNC
61  * @tc.require:
62  */
HWTEST_F_L0(BaseStringTableTest,GetOrInternString_utf8Data)63 HWTEST_F_L0(BaseStringTableTest, GetOrInternString_utf8Data)
64 {
65     if (!ecmascript::g_isEnableCMCGC) {
66         return;
67     }
68     EcmaVM* vm = thread->GetEcmaVM();
69     auto& table = common::BaseRuntime::GetInstance()->GetStringTable();
70 
71     uint8_t utf8Data[] = {0x68, 0x65, 0x6c, 0x6c, 0x6f}; // " hello "
72     EcmaString* ecmaStrCreatePtr = EcmaStringAccessor::CreateFromUtf8(vm, utf8Data, sizeof(utf8Data), true);
73     EXPECT_TRUE(!EcmaStringAccessor(ecmaStrCreatePtr).IsInternString());
74 
75     common::BaseString* ecmaStrGetPtr = table.GetOrInternString(thread->GetThreadHolder(), handleCreator_, utf8Data,
76                                                                 sizeof(utf8Data), true);
77     EXPECT_STREQ(EcmaStringAccessor(EcmaString::FromBaseString(ecmaStrGetPtr)).ToCString(thread).c_str(), "hello");
78     EXPECT_TRUE(EcmaStringAccessor(EcmaString::FromBaseString(ecmaStrGetPtr)).IsInternString());
79 }
80 
81 /**
82  * @tc.name: GetOrInternString
83  * @tc.desc: Obtain EcmaString string from utf16 encoded data. If the string already exists in the detention pool,
84              it will be returned directly. If not, it will be added to the detention pool and then returned.
85  * @tc.type: FUNC
86  * @tc.require:
87  */
HWTEST_F_L0(BaseStringTableTest,GetOrInternString_utf16Data)88 HWTEST_F_L0(BaseStringTableTest, GetOrInternString_utf16Data)
89 {
90     if (!ecmascript::g_isEnableCMCGC) {
91         return;
92     }
93     EcmaVM* vm = thread->GetEcmaVM();
94     auto& table = common::BaseRuntime::GetInstance()->GetStringTable();
95 
96     uint16_t utf16Data[] = {0x7F16, 0x7801, 0x89E3, 0x7801}; // “ 编码解码 ”
97     EcmaString* ecmaStrCreatePtr =
98         EcmaStringAccessor::CreateFromUtf16(vm, utf16Data, sizeof(utf16Data) / sizeof(uint16_t), false);
99     EXPECT_TRUE(!EcmaStringAccessor(ecmaStrCreatePtr).IsInternString());
100 
101     common::BaseString* ecmaStrGetPtr = table.GetOrInternString(thread->GetThreadHolder(), handleCreator_, utf16Data,
102                                                                 sizeof(utf16Data) / sizeof(uint16_t), false);
103     EXPECT_STREQ(EcmaStringAccessor(EcmaString::FromBaseString(ecmaStrGetPtr)).ToCString(thread).c_str(), "编码解码");
104     EXPECT_TRUE(EcmaStringAccessor(EcmaString::FromBaseString(ecmaStrGetPtr)).IsInternString());
105 }
106 
107 /**
108  * @tc.name: GetOrInternStringFromCompressedSubString_SubString
109  * @tc.desc: Test creating interned string from a compressed substring of another string
110  * @tc.type: FUNC
111  * @tc.require: AR001
112  */
HWTEST_F_L0(BaseStringTableTest,GetOrInternStringFromCompressedSubString_SubString)113 HWTEST_F_L0(BaseStringTableTest, GetOrInternStringFromCompressedSubString_SubString)
114 {
115     if (!ecmascript::g_isEnableCMCGC) {
116         return;
117     }
118     EcmaVM* vm = thread->GetEcmaVM();
119     ecmascript::ObjectFactory* factory = vm->GetFactory();
120     auto& table = common::BaseRuntime::GetInstance()->GetStringTable();
121 
122     JSHandle<EcmaString> originalStr =
123         factory->NewFromASCII("00000x680x650x6c0x6c0x6f0x200x770x6f0x720x6c0x64"); // "hello world"
124     uint32_t offset = 4;
125     uint32_t utf8Len = EcmaStringAccessor(*originalStr).GetLength() - offset;
126 
127     common::BaseString* internStr = table.GetOrInternStringFromCompressedSubString(
128         thread->GetThreadHolder(), handleCreator_, originalStr, offset, utf8Len);
129     EXPECT_STREQ(EcmaStringAccessor(EcmaString::FromBaseString(internStr)).ToCString(thread).c_str(),
130                  "0x680x650x6c0x6c0x6f0x200x770x6f0x720x6c0x64");
131     EXPECT_TRUE(EcmaStringAccessor(EcmaString::FromBaseString(internStr)).IsInternString());
132 }
133 } // namespace panda::test
134