• 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 <gtest/gtest.h>
17 #include "compiler/lowering/phase.h"
18 #include "ir/astNodeHistory.h"
19 
20 namespace ark::es2panda {
21 
22 class NodeHistoryTest : public testing::Test {
23 public:
24     ~NodeHistoryTest() override = default;
25 
SetUpTestCase()26     static void SetUpTestCase()
27     {
28         ark::mem::MemConfig::Initialize(0, 0, ark::es2panda::COMPILER_SIZE, 0, 0, 0);
29         ark::PoolManager::Initialize();
30     }
31 
NodeHistoryTest()32     NodeHistoryTest()
33     {
34         allocator_ = std::make_unique<ArenaAllocator>(SpaceType::SPACE_TYPE_COMPILER);
35         phaseManager_ = std::make_unique<compiler::PhaseManager>(ScriptExtension::ETS, Allocator());
36         compiler::SetPhaseManager(phaseManager_.get());
37     }
38 
39     NO_COPY_SEMANTIC(NodeHistoryTest);
40     NO_MOVE_SEMANTIC(NodeHistoryTest);
41 
Allocator() const42     ArenaAllocator *Allocator() const
43     {
44         return allocator_.get();
45     }
46 
PhaseManager() const47     compiler::PhaseManager *PhaseManager() const
48     {
49         return phaseManager_.get();
50     }
51 
52 private:
53     std::unique_ptr<ArenaAllocator> allocator_;
54     std::unique_ptr<compiler::PhaseManager> phaseManager_;
55 };
56 
57 constexpr int32_t PHASE_ID_0 = 0;
58 constexpr int32_t PHASE_ID_1 = 1;
59 constexpr int32_t PHASE_ID_2 = 2;
60 constexpr int32_t PHASE_ID_3 = 3;
61 constexpr int32_t PHASE_ID_4 = 4;
62 constexpr int32_t PHASE_ID_5 = 5;
63 
64 constexpr int32_t INDEX_0 = 0;
65 constexpr int32_t INDEX_1 = 1;
66 constexpr int32_t INDEX_2 = 2;
67 constexpr int32_t INDEX_3 = 3;
68 constexpr int32_t INDEX_4 = 4;
69 
70 constexpr int32_t VALUE_0 = 0;
71 constexpr int32_t VALUE_1 = 1;
72 constexpr int32_t VALUE_2 = 2;
73 constexpr int32_t VALUE_3 = 3;
74 constexpr int32_t VALUE_4 = 4;
75 
76 constexpr int32_t SIZE_5 = 5;
77 
78 // CC-OFFNXT(huge_method, G.FUN.01-CPP, G.FUD.05) solid logic
TEST_F(NodeHistoryTest,DoubleLinkedList)79 TEST_F(NodeHistoryTest, DoubleLinkedList)
80 {
81     util::ArenaDoubleLinkedList<int> list {Allocator()};
82 
83     ASSERT_EQ(list.Head(), nullptr);
84     ASSERT_EQ(list.Tail(), nullptr);
85     ASSERT_TRUE(list.Empty());
86 
87     // Make list: (1,2,4,0,3)
88     std::array<int, SIZE_5> data = {VALUE_0, VALUE_1, VALUE_2, VALUE_3, VALUE_4};
89 
90     auto item4 = list.Append(data[INDEX_4]);
91     auto item0 = list.Append(data[INDEX_0]);
92     auto item3 = list.Insert(item0, data[INDEX_3]);
93     auto item1 = list.Prepend(data[INDEX_1]);
94     auto item2 = list.Insert(item1, data[INDEX_2]);
95 
96     ASSERT_FALSE(list.Empty());
97 
98     ASSERT_EQ(item0->data, data[INDEX_0]);
99     ASSERT_EQ(item1->data, data[INDEX_1]);
100     ASSERT_EQ(item2->data, data[INDEX_2]);
101     ASSERT_EQ(item3->data, data[INDEX_3]);
102     ASSERT_EQ(item4->data, data[INDEX_4]);
103 
104     ASSERT_EQ(list.Head(), item1);
105     ASSERT_EQ(item1->next, item2);
106     ASSERT_EQ(item2->next, item4);
107     ASSERT_EQ(item4->next, item0);
108     ASSERT_EQ(item0->next, item3);
109     ASSERT_EQ(item3, list.Tail());
110     ASSERT_EQ(list.Tail()->next, nullptr);
111 
112     ASSERT_EQ(item3->prev, item0);
113     ASSERT_EQ(item0->prev, item4);
114     ASSERT_EQ(item4->prev, item2);
115     ASSERT_EQ(item2->prev, item1);
116     ASSERT_EQ(item1->prev, nullptr);
117 
118     ASSERT_EQ(item2->prev->next, item2);
119     ASSERT_EQ(item4->prev->next, item4);
120     ASSERT_EQ(item0->prev->next, item0);
121 
122     ASSERT_EQ(item2->next->prev, item2);
123     ASSERT_EQ(item4->next->prev, item4);
124     ASSERT_EQ(item0->next->prev, item0);
125 
126     list.Erase(item4);
127     ASSERT_EQ(item2->next, item0);
128     ASSERT_EQ(item0->prev, item2);
129 
130     list.Erase(item0);
131     ASSERT_EQ(item2->next, item3);
132     ASSERT_EQ(item3->prev, item2);
133 
134     list.Erase(list.Tail());
135     ASSERT_EQ(list.Tail(), item2);
136     ASSERT_EQ(item2->next, nullptr);
137     ASSERT_EQ(item2->prev, item1);
138 
139     list.Erase(list.Head());
140     ASSERT_EQ(list.Head(), item2);
141     ASSERT_EQ(item2->next, nullptr);
142     ASSERT_EQ(item2->prev, nullptr);
143 
144     list.Erase(item2);
145     ASSERT_EQ(list.Head(), nullptr);
146     ASSERT_EQ(list.Tail(), nullptr);
147     ASSERT_TRUE(list.Empty());
148 }
149 
TEST_F(NodeHistoryTest,HistoryAt)150 TEST_F(NodeHistoryTest, HistoryAt)
151 {
152     ASSERT_EQ(PhaseManager()->CurrentPhaseId(), compiler::PARSER_PHASE_ID);
153 
154     PhaseManager()->SetCurrentPhaseId(PHASE_ID_0);
155     auto identifier = Allocator()->New<ir::Identifier>(Allocator())->AsIdentifier();
156     auto history = Allocator()->New<ir::AstNodeHistory>(identifier, PhaseManager()->CurrentPhaseId(), Allocator());
157 
158     ASSERT_EQ(history->At(compiler::PARSER_PHASE_ID), nullptr);
159     ASSERT_EQ(history->At(PHASE_ID_0), identifier);
160     ASSERT_EQ(history->At(PHASE_ID_1), nullptr);
161 }
162 
TEST_F(NodeHistoryTest,HistoryGet)163 TEST_F(NodeHistoryTest, HistoryGet)
164 {
165     ASSERT_EQ(PhaseManager()->CurrentPhaseId(), compiler::PARSER_PHASE_ID);
166 
167     PhaseManager()->SetCurrentPhaseId(PHASE_ID_0);
168     auto identifier = Allocator()->New<ir::Identifier>(Allocator())->AsIdentifier();
169     auto history = Allocator()->New<ir::AstNodeHistory>(identifier, PhaseManager()->CurrentPhaseId(), Allocator());
170 
171     ASSERT_EQ(history->Get(compiler::PARSER_PHASE_ID), nullptr);
172     ASSERT_EQ(history->Get(PHASE_ID_0), identifier);
173     ASSERT_EQ(history->Get(PHASE_ID_1), identifier);
174     ASSERT_EQ(history->Get(PHASE_ID_2), identifier);
175     ASSERT_EQ(history->Get(PHASE_ID_3), identifier);
176 }
177 
178 // CC-OFFNXT(huge_method, G.FUN.01-CPP, G.FUD.05) solid logic
TEST_F(NodeHistoryTest,HistorySet)179 TEST_F(NodeHistoryTest, HistorySet)
180 {
181     ASSERT_EQ(PhaseManager()->CurrentPhaseId(), compiler::PARSER_PHASE_ID);
182 
183     PhaseManager()->SetCurrentPhaseId(PHASE_ID_0);
184     auto identifier0 = Allocator()->New<ir::Identifier>(Allocator())->AsIdentifier();
185     auto history = Allocator()->New<ir::AstNodeHistory>(identifier0, PhaseManager()->CurrentPhaseId(), Allocator());
186 
187     PhaseManager()->SetCurrentPhaseId(PHASE_ID_1);
188     auto identifier1 = Allocator()->New<ir::Identifier>(Allocator())->AsIdentifier();
189     history->Set(identifier1, PhaseManager()->CurrentPhaseId());
190 
191     PhaseManager()->SetCurrentPhaseId(PHASE_ID_2);
192     auto identifier2 = Allocator()->New<ir::Identifier>(Allocator())->AsIdentifier();
193     history->Set(identifier2, PhaseManager()->CurrentPhaseId());
194 
195     PhaseManager()->SetCurrentPhaseId(PHASE_ID_3);
196     history->Set(nullptr, PhaseManager()->CurrentPhaseId());
197 
198     // Search forward
199     ASSERT_EQ(history->Get(compiler::PARSER_PHASE_ID), nullptr);
200     ASSERT_EQ(history->Get(PHASE_ID_0), identifier0);
201     ASSERT_EQ(history->Get(PHASE_ID_1), identifier1);
202     ASSERT_EQ(history->Get(PHASE_ID_2), identifier2);
203     ASSERT_EQ(history->Get(PHASE_ID_3), nullptr);
204     ASSERT_EQ(history->Get(PHASE_ID_4), nullptr);
205     ASSERT_EQ(history->Get(PHASE_ID_5), nullptr);
206 
207     // Search backward
208     ASSERT_EQ(history->Get(PHASE_ID_5), nullptr);
209     ASSERT_EQ(history->Get(PHASE_ID_4), nullptr);
210     ASSERT_EQ(history->Get(PHASE_ID_3), nullptr);
211     ASSERT_EQ(history->Get(PHASE_ID_2), identifier2);
212     ASSERT_EQ(history->Get(PHASE_ID_1), identifier1);
213     ASSERT_EQ(history->Get(PHASE_ID_0), identifier0);
214     ASSERT_EQ(history->Get(compiler::PARSER_PHASE_ID), nullptr);
215 
216     // Search random
217     ASSERT_EQ(history->Get(PHASE_ID_1), identifier1);
218     ASSERT_EQ(history->Get(PHASE_ID_5), nullptr);
219     ASSERT_EQ(history->Get(PHASE_ID_2), identifier2);
220     ASSERT_EQ(history->Get(PHASE_ID_4), nullptr);
221     ASSERT_EQ(history->Get(PHASE_ID_0), identifier0);
222     ASSERT_EQ(history->Get(compiler::PARSER_PHASE_ID), nullptr);
223     ASSERT_EQ(history->Get(PHASE_ID_3), nullptr);
224 
225     // Search precise
226     ASSERT_EQ(history->At(compiler::PARSER_PHASE_ID), nullptr);
227     ASSERT_EQ(history->At(PHASE_ID_0), identifier0);
228     ASSERT_EQ(history->At(PHASE_ID_1), identifier1);
229     ASSERT_EQ(history->At(PHASE_ID_2), identifier2);
230     ASSERT_EQ(history->At(PHASE_ID_3), nullptr);
231     ASSERT_EQ(history->At(PHASE_ID_4), nullptr);
232     ASSERT_EQ(history->At(PHASE_ID_5), nullptr);
233 }
234 
TEST_F(NodeHistoryTest,HistoryReplace)235 TEST_F(NodeHistoryTest, HistoryReplace)
236 {
237     ASSERT_EQ(PhaseManager()->CurrentPhaseId(), compiler::PARSER_PHASE_ID);
238 
239     PhaseManager()->SetCurrentPhaseId(PHASE_ID_0);
240     auto identifier0Orig = Allocator()->New<ir::Identifier>(Allocator())->AsIdentifier();
241     auto history = Allocator()->New<ir::AstNodeHistory>(identifier0Orig, PhaseManager()->CurrentPhaseId(), Allocator());
242 
243     PhaseManager()->SetCurrentPhaseId(PHASE_ID_1);
244     auto identifier1Orig = Allocator()->New<ir::Identifier>(Allocator())->AsIdentifier();
245     history->Set(identifier1Orig, PhaseManager()->CurrentPhaseId());
246 
247     ASSERT_EQ(history->Get(compiler::PARSER_PHASE_ID), nullptr);
248     ASSERT_EQ(history->Get(PHASE_ID_0), identifier0Orig);
249     ASSERT_EQ(history->Get(PHASE_ID_1), identifier1Orig);
250     ASSERT_EQ(history->Get(PHASE_ID_2), identifier1Orig);
251     ASSERT_EQ(history->Get(PHASE_ID_3), identifier1Orig);
252 
253     ASSERT_EQ(history->At(compiler::PARSER_PHASE_ID), nullptr);
254     ASSERT_EQ(history->At(PHASE_ID_0), identifier0Orig);
255     ASSERT_EQ(history->At(PHASE_ID_1), identifier1Orig);
256     ASSERT_EQ(history->At(PHASE_ID_2), nullptr);
257 
258     PhaseManager()->SetCurrentPhaseId(PHASE_ID_0);
259     auto identifier0New = Allocator()->New<ir::Identifier>(Allocator())->AsIdentifier();
260     history->Set(identifier0New, PhaseManager()->CurrentPhaseId());
261 
262     PhaseManager()->SetCurrentPhaseId(PHASE_ID_1);
263     auto identifier1New = Allocator()->New<ir::Identifier>(Allocator())->AsIdentifier();
264     history->Set(identifier1New, PhaseManager()->CurrentPhaseId());
265 
266     PhaseManager()->SetCurrentPhaseId(PHASE_ID_2);
267     history->Set(nullptr, PhaseManager()->CurrentPhaseId());
268 
269     ASSERT_EQ(history->Get(compiler::PARSER_PHASE_ID), nullptr);
270     ASSERT_EQ(history->Get(PHASE_ID_0), identifier0New);
271     ASSERT_EQ(history->Get(PHASE_ID_1), identifier1New);
272     ASSERT_EQ(history->Get(PHASE_ID_2), nullptr);
273     ASSERT_EQ(history->Get(PHASE_ID_3), nullptr);
274 
275     ASSERT_EQ(history->At(compiler::PARSER_PHASE_ID), nullptr);
276     ASSERT_EQ(history->At(PHASE_ID_0), identifier0New);
277     ASSERT_EQ(history->At(PHASE_ID_1), identifier1New);
278     ASSERT_EQ(history->At(PHASE_ID_2), nullptr);
279 }
280 
NewClassDefinition(ArenaAllocator * allocator)281 ir::ClassDefinition *NewClassDefinition(ArenaAllocator *allocator)
282 {
283     ArenaVector<ir::AstNode *> body {allocator->Adapter()};
284     return allocator
285         ->New<ir::ClassDefinition>(allocator, nullptr, std::move(body), ir::ClassDefinitionModifiers::NONE,
286                                    ir::ModifierFlags::NONE, Language::Id::ETS)
287         ->AsClassDefinition();
288 }
289 
290 /// NOTE(mivanov): To be enabled after #24153/#24424 implemented
TEST_F(NodeHistoryTest,DISABLED_UpdateField)291 TEST_F(NodeHistoryTest, DISABLED_UpdateField)
292 {
293     ASSERT_EQ(PhaseManager()->CurrentPhaseId(), compiler::PARSER_PHASE_ID);
294 
295     auto definition = NewClassDefinition(Allocator());
296     ASSERT_FALSE(definition->IsAbstract());
297     definition->ClearModifier(ir::ModifierFlags::ABSTRACT);
298     ASSERT_FALSE(definition->IsAbstract());
299     definition->AddModifier(ir::ModifierFlags::FINAL);
300     ASSERT_TRUE(definition->IsFinal());
301 
302     PhaseManager()->SetCurrentPhaseId(PHASE_ID_0);
303     definition->AddModifier(ir::ModifierFlags::ABSTRACT);
304     ASSERT_TRUE(definition->IsAbstract());
305     definition->ClearModifier(ir::ModifierFlags::FINAL);
306     ASSERT_FALSE(definition->IsFinal());
307 
308     PhaseManager()->SetCurrentPhaseId(PHASE_ID_1);
309     definition->ClearModifier(ir::ModifierFlags::ABSTRACT);
310     ASSERT_FALSE(definition->IsAbstract());
311     definition->AddModifier(ir::ModifierFlags::FINAL);
312     ASSERT_TRUE(definition->IsFinal());
313 
314     PhaseManager()->SetCurrentPhaseId(PHASE_ID_2);
315     definition->ClearModifier(ir::ModifierFlags::FINAL);
316     ASSERT_FALSE(definition->IsFinal());
317 
318     PhaseManager()->Restart();
319     ASSERT_FALSE(definition->IsAbstract());
320     ASSERT_TRUE(definition->IsFinal());
321 
322     PhaseManager()->SetCurrentPhaseId(PHASE_ID_0);
323     ASSERT_TRUE(definition->IsAbstract());
324     ASSERT_FALSE(definition->IsFinal());
325 
326     PhaseManager()->SetCurrentPhaseId(PHASE_ID_1);
327     ASSERT_FALSE(definition->IsAbstract());
328     ASSERT_TRUE(definition->IsFinal());
329 
330     PhaseManager()->SetCurrentPhaseId(PHASE_ID_2);
331     ASSERT_FALSE(definition->IsAbstract());
332     ASSERT_FALSE(definition->IsFinal());
333 }
334 
335 /// NOTE(mivanov): To be enabled after #24153/#24424 implemented
TEST_F(NodeHistoryTest,DISABLED_UpdateChild)336 TEST_F(NodeHistoryTest, DISABLED_UpdateChild)
337 {
338     ASSERT_EQ(PhaseManager()->CurrentPhaseId(), compiler::PARSER_PHASE_ID);
339 
340     auto declaration =
341         Allocator()->New<ir::ClassDeclaration>(NewClassDefinition(Allocator()), Allocator())->AsClassDeclaration();
342     ASSERT_EQ(declaration->Definition()->Ident(), nullptr);
343 
344     PhaseManager()->SetCurrentPhaseId(PHASE_ID_0);
345     auto identifier0 = Allocator()->New<ir::Identifier>(Allocator())->AsIdentifier();
346     declaration->Definition()->SetIdent(identifier0);
347     ASSERT_EQ(declaration->Definition()->Ident(), identifier0);
348 
349     PhaseManager()->SetCurrentPhaseId(PHASE_ID_1);
350     auto identifier1 = Allocator()->New<ir::Identifier>(Allocator())->AsIdentifier();
351     declaration->Definition()->SetIdent(identifier1);
352     ASSERT_EQ(declaration->Definition()->Ident(), identifier1);
353 
354     PhaseManager()->SetCurrentPhaseId(PHASE_ID_2);
355     declaration->Definition()->SetIdent(nullptr);
356     ASSERT_EQ(declaration->Definition()->Ident(), nullptr);
357 
358     PhaseManager()->Restart();
359     ASSERT_EQ(declaration->Definition()->Ident(), nullptr);
360 
361     PhaseManager()->SetCurrentPhaseId(PHASE_ID_0);
362     ASSERT_EQ(declaration->Definition()->Ident(), identifier0);
363 
364     PhaseManager()->SetCurrentPhaseId(PHASE_ID_1);
365     ASSERT_EQ(declaration->Definition()->Ident(), identifier1);
366 
367     PhaseManager()->SetCurrentPhaseId(PHASE_ID_2);
368     ASSERT_EQ(declaration->Definition()->Ident(), nullptr);
369 }
370 }  // namespace ark::es2panda
371