• 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/module/module_manager_map.h"
17 #include "ecmascript/tests/test_helper.h"
18 
19 using namespace panda::ecmascript;
20 
21 namespace panda::test {
22 
23 class ModuleManagerMapTest : public BaseTestWithScope<false> {
24 public:
SetUp()25     void SetUp() override
26     {
27         JSRuntimeOptions options;
28         instance = JSNApi::CreateEcmaVM(options);
29         ASSERT_TRUE(instance != nullptr) << "Cannot create EcmaVM";
30         thread = instance->GetJSThread();
31         thread->ManagedCodeBegin();
32         scope = new EcmaHandleScope(thread);
33         instance->SetEnableForceGC(false);
34     }
35 
36 protected:
37     ModuleManagerMap<int> map;
38 };
39 
40 // --- GCRoot Tests ---
41 
HWTEST_F_L0(ModuleManagerMapTest,GCRoot)42 HWTEST_F_L0(ModuleManagerMapTest, GCRoot)
43 {
44     // Test default constructor
45     GCRoot root;
46     ASSERT_EQ(root.Read().GetRawData(), JSTaggedValue::Hole().GetRawData());
47 
48     // Test regular and move constructor
49     {
50         JSTaggedValue value(static_cast<JSTaggedType>(42));
51         GCRoot root1(value);
52 
53         GCRoot root2(std::move(root1));
54         ASSERT_EQ(root2.Read().GetRawData(), value.GetRawData());
55     }
56 
57     // Test move assignment
58     {
59         JSTaggedValue value1(static_cast<JSTaggedType>(42));
60 
61         JSTaggedValue value2(static_cast<JSTaggedType>(84));
62 
63         GCRoot root1(value1);
64         GCRoot root2(value2);
65 
66         root2 = std::move(root1);
67         ASSERT_EQ(root2.Read().GetRawData(), value1.GetRawData());
68     }
69 
70     // Test read barrier
71     {
72         JSTaggedValue value(static_cast<JSTaggedType>(42));
73         GCRoot root(value);
74 
75         JSTaggedValue read_value = root.Read();
76         ASSERT_EQ(read_value.GetRawData(), value.GetRawData());
77     }
78 
79     // Test Hash er
80     {
81         JSTaggedValue value1(static_cast<JSTaggedType>(42));
82         JSTaggedValue value2(static_cast<JSTaggedType>(42));
83         JSTaggedValue value3(static_cast<JSTaggedType>(84));
84 
85         GCRoot root1(value1);
86         GCRoot root2(value2);
87         GCRoot root3(value3);
88 
89         GCRoot::GCRootHash hasher;
90 
91         // Same values should have same hash
92         ASSERT_EQ(hasher(root1), hasher(root2));
93 
94         // Different values should have different hashes
95         ASSERT_NE(hasher(root1), hasher(root3));
96 
97         // Template version should work with raw types
98         ASSERT_EQ(hasher(root1), hasher(value1.GetRawData()));
99     }
100 }
101 
HWTEST_F_L0(ModuleManagerMapTest,InsertAndFind)102 HWTEST_F_L0(ModuleManagerMapTest, InsertAndFind)
103 {
104     JSTaggedValue value(static_cast<JSTaggedType>(42));
105 
106     map.Insert(1, value);
107 
108     auto result = map.Find(1);
109     ASSERT_TRUE(result.has_value());
110     ASSERT_EQ(result->GetRawData(), value.GetRawData());
111 }
112 
HWTEST_F_L0(ModuleManagerMapTest,EmplaceAndFind)113 HWTEST_F_L0(ModuleManagerMapTest, EmplaceAndFind)
114 {
115     JSTaggedValue value(static_cast<JSTaggedType>(42));
116 
117     map.Emplace(1, value);
118 
119     auto result = map.Find(1);
120     ASSERT_TRUE(result.has_value());
121     ASSERT_EQ(result->GetRawData(), value.GetRawData());
122 }
123 
HWTEST_F_L0(ModuleManagerMapTest,EmplaceDoesNotOverwrite)124 HWTEST_F_L0(ModuleManagerMapTest, EmplaceDoesNotOverwrite)
125 {
126     JSTaggedValue value1(static_cast<JSTaggedType>(42));
127     JSTaggedValue value2(static_cast<JSTaggedType>(84));
128 
129     map.Insert(1, value1);
130     map.Emplace(1, value2);  // Should not overwrite
131 
132     auto result = map.Find(1);
133     ASSERT_TRUE(result.has_value());
134     ASSERT_EQ(result->GetRawData(), value1.GetRawData());  // Should still be original value
135 }
136 
HWTEST_F_L0(ModuleManagerMapTest,InsertOverwrites)137 HWTEST_F_L0(ModuleManagerMapTest, InsertOverwrites)
138 {
139     JSTaggedValue value1(static_cast<JSTaggedType>(42));
140     JSTaggedValue value2(static_cast<JSTaggedType>(84));
141 
142     map.Insert(1, value1);
143     map.Insert(1, value2);  // Should overwrite
144 
145     auto result = map.Find(1);
146     ASSERT_TRUE(result.has_value());
147     ASSERT_EQ(result->GetRawData(), value2.GetRawData());  // Should be new value
148 }
149 
HWTEST_F_L0(ModuleManagerMapTest,FindNonExistent)150 HWTEST_F_L0(ModuleManagerMapTest, FindNonExistent)
151 {
152     auto result = map.Find(999);
153     ASSERT_FALSE(result.has_value());
154 }
155 
HWTEST_F_L0(ModuleManagerMapTest,ForEach)156 HWTEST_F_L0(ModuleManagerMapTest, ForEach)
157 {
158     JSTaggedValue value1(static_cast<JSTaggedType>(42));
159     JSTaggedValue value2(static_cast<JSTaggedType>(84));
160 
161     map.Insert(1, value1);
162     map.Insert(2, value2);
163 
164     std::vector<std::pair<int, JSTaggedValue>> collected;
165     map.ForEach([&](auto it) { collected.emplace_back(it->first, it->second.Read()); });
166 
167     ASSERT_EQ(collected.size(), 2U);
168 
169     // Sort for deterministic comparison
170     std::sort(collected.begin(), collected.end(), [](const auto &a, const auto &b) { return a.first < b.first; });
171 
172     ASSERT_EQ(collected[0].first, 1);
173     ASSERT_EQ(collected[0].second.GetRawData(), value1.GetRawData());
174     ASSERT_EQ(collected[1].first, 2);
175     ASSERT_EQ(collected[1].second.GetRawData(), value2.GetRawData());
176 }
177 
HWTEST_F_L0(ModuleManagerMapTest,Erase)178 HWTEST_F_L0(ModuleManagerMapTest, Erase)
179 {
180     JSTaggedValue value(static_cast<JSTaggedType>(42));
181 
182     map.Insert(1, value);
183     ASSERT_TRUE(map.Find(1).has_value());
184 
185     map.Erase(1);
186     ASSERT_FALSE(map.Find(1).has_value());
187     ASSERT_EQ(map.Size(), 0U);
188 }
189 
HWTEST_F_L0(ModuleManagerMapTest,Size)190 HWTEST_F_L0(ModuleManagerMapTest, Size)
191 {
192     ASSERT_EQ(map.Size(), 0U);
193 
194     map.Insert(1, JSTaggedValue(static_cast<JSTaggedType>(42)));
195     ASSERT_EQ(map.Size(), 1U);
196 
197     map.Insert(2, JSTaggedValue(static_cast<JSTaggedType>(84)));
198     ASSERT_EQ(map.Size(), 2U);
199 
200     map.Erase(1);
201     ASSERT_EQ(map.Size(), 1U);
202 }
203 
HWTEST_F_L0(ModuleManagerMapTest,Clear)204 HWTEST_F_L0(ModuleManagerMapTest, Clear)
205 {
206     map.Insert(1, JSTaggedValue(static_cast<JSTaggedType>(42)));
207     map.Insert(2, JSTaggedValue(static_cast<JSTaggedType>(84)));
208 
209     ASSERT_EQ(map.Size(), 2U);
210 
211     map.Clear();
212 
213     ASSERT_EQ(map.Size(), 0U);
214     ASSERT_FALSE(map.Find(1).has_value());
215     ASSERT_FALSE(map.Find(2).has_value());
216 }
217 
HWTEST_F_L0(ModuleManagerMapTest,TemplateKeyType)218 HWTEST_F_L0(ModuleManagerMapTest, TemplateKeyType)
219 {
220     ModuleManagerMap<std::string> string_map;
221     JSTaggedValue value(static_cast<JSTaggedType>(42));
222 
223     string_map.Insert("test_key", value);
224 
225     auto result = string_map.Find("test_key");
226     ASSERT_TRUE(result.has_value());
227     ASSERT_EQ(result->GetRawData(), value.GetRawData());
228 
229     ASSERT_FALSE(string_map.Find("non_existent").has_value());
230 }
231 }  // namespace panda::test
232