• 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 #include <gtest/gtest.h>
16 #include <algorithm>
17 #include "asm_test.h"
18 #include "assembly-field.h"
19 
20 namespace test::utils {
21 
AsmTest()22 AsmTest::AsmTest()
23 {
24     ark::mem::MemConfig::Initialize(0, 0, ark::es2panda::COMPILER_SIZE, 0, 0, 0);
25     ark::PoolManager::Initialize(ark::PoolType::MMAP);
26 }
~AsmTest()27 AsmTest::~AsmTest()
28 {
29     ark::PoolManager::Finalize();
30     ark::mem::MemConfig::Finalize();
31 }
32 
GetFunction(std::string_view functionName,const std::map<std::string,ark::pandasm::Function> & table)33 ark::pandasm::Function *AsmTest::GetFunction(std::string_view functionName,
34                                              const std::map<std::string, ark::pandasm::Function> &table)
35 {
36     auto it = table.find(functionName.data());
37     if (it == table.end()) {
38         return nullptr;
39     }
40     return const_cast<ark::pandasm::Function *>(&it->second);
41 }
42 
GetRecord(std::string_view recordName,const std::unique_ptr<ark::pandasm::Program> & program)43 ark::pandasm::Record *AsmTest::GetRecord(std::string_view recordName,
44                                          const std::unique_ptr<ark::pandasm::Program> &program)
45 {
46     auto it = program->recordTable.find(recordName.data());
47     if (it == program->recordTable.end()) {
48         return nullptr;
49     }
50     return &it->second;
51 }
52 
CompareActualWithExpected(const std::string & expectedValue,ark::pandasm::ScalarValue * scalarValue,const std::string & field)53 void AsmTest::CompareActualWithExpected(const std::string &expectedValue, ark::pandasm::ScalarValue *scalarValue,
54                                         const std::string &field)
55 {
56     std::string actualValue = std::visit(
57         [](const auto &value) -> std::string {
58             using ValueType = std::decay_t<decltype(value)>;
59             if constexpr (std::is_same_v<ValueType, std::string>) {
60                 return value;
61             } else if constexpr (std::is_arithmetic_v<ValueType>) {
62                 return std::to_string(value);
63             } else {
64                 return "Unsupported type";
65             }
66         },
67         scalarValue->GetValue());
68 
69     ASSERT_EQ(actualValue, expectedValue) << "Value mismatch for " + field;
70 }
71 
CheckAnnoDecl(ark::pandasm::Program * program,const std::string & annoName,const std::vector<std::pair<std::string,std::string>> & expectedAnnotations)72 void AsmTest::CheckAnnoDecl(ark::pandasm::Program *program, const std::string &annoName,
73                             const std::vector<std::pair<std::string, std::string>> &expectedAnnotations)
74 {
75     const auto &recordTable = program->recordTable;
76     ASSERT_FALSE(recordTable.empty()) << "No records found in the program.";
77     auto found = recordTable.find(annoName);
78     ASSERT_NE(found, recordTable.end());
79 
80     for (size_t i = 0; i < expectedAnnotations.size(); i++) {
81         auto scalarValue = found->second.fieldList[i].metadata->GetValue();
82         if (scalarValue) {
83             CompareActualWithExpected(expectedAnnotations[i].second, &*scalarValue, found->second.fieldList[i].name);
84         }
85     }
86 }
87 
CheckLiteralArrayTable(ark::pandasm::Program * program,const std::vector<std::pair<std::string,std::vector<AnnotationValueType>>> & expectedLiteralArrayTable)88 void AsmTest::CheckLiteralArrayTable(
89     ark::pandasm::Program *program,
90     const std::vector<std::pair<std::string, std::vector<AnnotationValueType>>> &expectedLiteralArrayTable)
91 {
92     const auto &literalarrayTable = program->literalarrayTable;
93     ASSERT_FALSE(literalarrayTable.empty()) << "literalarrayTable is empty!";
94     for (const auto &literalArray : expectedLiteralArrayTable) {
95         auto found = literalarrayTable.find(literalArray.first);
96         ASSERT_NE(found, literalarrayTable.end());
97         size_t i = 1;
98         for (const auto &value : literalArray.second) {
99             constexpr int STRIDE = 2;
100             ASSERT_EQ(value, found->second.literals[i].value) << "Value mismatch for " + literalArray.first;
101             i += STRIDE;
102         }
103     }
104 }
105 
CheckAnnotation(const std::vector<std::pair<std::string,std::string>> & expectedValues,const ark::pandasm::AnnotationData & annotation)106 void AsmTest::CheckAnnotation(const std::vector<std::pair<std::string, std::string>> &expectedValues,
107                               const ark::pandasm::AnnotationData &annotation)
108 {
109     for (const auto &element : annotation.GetElements()) {
110         auto it = std::find_if(expectedValues.begin(), expectedValues.end(),
111                                [&element](const auto &pair) { return pair.first == element.GetName(); });
112         if (it != expectedValues.end()) {
113             CompareActualWithExpected(it->second, element.GetValue()->GetAsScalar(), element.GetName());
114         }
115     }
116 }
117 
CheckRecordAnnotations(ark::pandasm::Program * program,const std::string & recordName,const AnnotationMap & expectedAnnotations)118 void AsmTest::CheckRecordAnnotations(ark::pandasm::Program *program, const std::string &recordName,
119                                      const AnnotationMap &expectedAnnotations)
120 {
121     const auto &recordTable = program->recordTable;
122     ASSERT_FALSE(recordTable.empty()) << "No records found in the program.";
123     auto found = recordTable.find(recordName);
124     ASSERT_NE(found, recordTable.end());
125 
126     for (const auto &expected : expectedAnnotations) {
127         auto annotations = found->second.metadata->GetAnnotations();
128         auto it = std::find_if(annotations.begin(), annotations.end(),
129                                [&expected](const ark::pandasm::AnnotationData &annotation) {
130                                    return annotation.GetName() == expected.first;
131                                });
132 
133         ASSERT_NE(it, annotations.end()) << recordName << " missing expected annotation: " << expected.first;
134 
135         // Check the fields for the matched annotation name
136         CheckAnnotation(expected.second, *it);
137     }
138 }
139 
CheckModuleAnnotation(ark::pandasm::Program * program,const std::string & recordName,bool isModule,const std::vector<std::string> & expectedAnnotations)140 void AsmTest::CheckModuleAnnotation(ark::pandasm::Program *program, const std::string &recordName, bool isModule,
141                                     const std::vector<std::string> &expectedAnnotations)
142 {
143     const auto &recordTable = program->recordTable;
144     ASSERT_FALSE(recordTable.empty()) << "No records found in the program.";
145     auto found = recordTable.find(recordName);
146     ASSERT_NE(found, recordTable.end());
147 
148     auto annotations = found->second.metadata->GetAnnotations();
149     auto it = std::find_if(annotations.begin(), annotations.end(), [](const ark::pandasm::AnnotationData &annotation) {
150         return annotation.GetName() == std::string {ark::es2panda::compiler::Signatures::ETS_ANNOTATION_MODULE};
151     });
152     if (isModule) {
153         ASSERT_NE(it, annotations.end()) << recordName << " missing expected annotation: "
154                                          << ark::es2panda::compiler::Signatures::ETS_ANNOTATION_MODULE;
155     } else {
156         ASSERT_EQ(it, annotations.end()) << recordName << " has annotation: "
157                                          << ark::es2panda::compiler::Signatures::ETS_ANNOTATION_MODULE
158                                          << ", but shouldn't";
159         return;
160     }
161     ASSERT_EQ(it->GetElements().size(), 1);
162     const auto &element = it->GetElements()[0];
163     ASSERT_EQ(element.GetName(), std::string {ark::es2panda::compiler::Signatures::ANNOTATION_KEY_EXPORTED})
164         << recordName << "module annotation missing element "
165         << ark::es2panda::compiler::Signatures::ANNOTATION_KEY_EXPORTED;
166 
167     for (const auto &val : element.GetValue()->GetAsArray()->GetValues()) {
168         auto name = val.GetValue<ark::pandasm::Type>().GetName();
169         auto foundExpected = std::find(expectedAnnotations.begin(), expectedAnnotations.end(), name);
170         ASSERT_NE(foundExpected, expectedAnnotations.end()) << "Value mismatch for " + name;
171     }
172 }
173 
CheckRecordWithoutAnnotations(ark::pandasm::Program * program,const std::string & recordName,bool isModule)174 void AsmTest::CheckRecordWithoutAnnotations(ark::pandasm::Program *program, const std::string &recordName,
175                                             bool isModule)
176 {
177     const auto &recordTable = program->recordTable;
178     ASSERT_FALSE(recordTable.empty()) << "No records found in the program.";
179     auto found = recordTable.find(recordName);
180     ASSERT_NE(found, recordTable.end());
181     if (isModule) {
182         ASSERT_EQ(found->second.metadata->GetAnnotations().size(), 1);
183     } else {
184         ASSERT(found->second.metadata->GetAnnotations().empty());
185     }
186 }
187 
CheckFunctionAnnotations(ark::pandasm::Program * program,const std::string & functionName,bool isStatic,const AnnotationMap & expectedAnnotations)188 void AsmTest::CheckFunctionAnnotations(ark::pandasm::Program *program, const std::string &functionName, bool isStatic,
189                                        const AnnotationMap &expectedAnnotations)
190 {
191     const auto &functionTable = isStatic ? program->functionStaticTable : program->functionInstanceTable;
192     auto found = functionTable.find(functionName);
193     ASSERT_NE(found, functionTable.end()) << "Unexpected function Name: " << functionName;
194 
195     for (const auto &expected : expectedAnnotations) {
196         auto annotations = found->second.metadata->GetAnnotations();
197         auto it = std::find_if(annotations.begin(), annotations.end(),
198                                [&expected](const ark::pandasm::AnnotationData &annotation) {
199                                    return annotation.GetName() == expected.first;
200                                });
201 
202         ASSERT_NE(it, annotations.end()) << functionName << " missing expected annotation: " << expected.first;
203 
204         // Check the fields for the matched annotation name
205         CheckAnnotation(expected.second, *it);
206     }
207 }
208 
CheckFunctionWithoutAnnotations(ark::pandasm::Program * program,const std::string & functionName,bool isStatic)209 void AsmTest::CheckFunctionWithoutAnnotations(ark::pandasm::Program *program, const std::string &functionName,
210                                               bool isStatic)
211 {
212     const auto &functionTable = isStatic ? program->functionStaticTable : program->functionInstanceTable;
213     auto found = functionTable.find(functionName);
214     ASSERT_NE(found, functionTable.end()) << "Unexpected function Name: " << functionName;
215     ASSERT(found->second.metadata->GetAnnotations().empty());
216 }
217 
CheckFunctionParameterAnnotations(ark::pandasm::Program * program,const std::string & functionName,bool isStatic,const uint32_t & paramIndex,const AnnotationMap & expectedAnnotations)218 void AsmTest::CheckFunctionParameterAnnotations(ark::pandasm::Program *program, const std::string &functionName,
219                                                 bool isStatic, const uint32_t &paramIndex,
220                                                 const AnnotationMap &expectedAnnotations)
221 {
222     const auto &functionTable = isStatic ? program->functionStaticTable : program->functionInstanceTable;
223     auto found = functionTable.find(functionName);
224     ASSERT_NE(found, functionTable.end());
225     ASSERT_LT(paramIndex, found->second.params.size());
226 
227     for (const auto &expected : expectedAnnotations) {
228         auto annotations = found->second.params.at(paramIndex).GetOrCreateMetadata().GetAnnotations();
229         auto it = std::find_if(annotations.begin(), annotations.end(),
230                                [&expected](const ark::pandasm::AnnotationData &annotation) {
231                                    return annotation.GetName() == expected.first;
232                                });
233 
234         ASSERT_NE(it, annotations.end()) << functionName << "param at " << paramIndex
235                                          << " missing expected annotation: " << expected.first;
236 
237         // Check the fields for the matched annotation name
238         CheckAnnotation(expected.second, *it);
239     }
240 }
241 
CheckFunctionParameterWithoutAnnotations(ark::pandasm::Program * program,const std::string & functionName,bool isStatic,const uint32_t & paramIndex)242 void AsmTest::CheckFunctionParameterWithoutAnnotations(ark::pandasm::Program *program, const std::string &functionName,
243                                                        bool isStatic, const uint32_t &paramIndex)
244 {
245     const auto &functionTable = isStatic ? program->functionStaticTable : program->functionInstanceTable;
246     auto found = functionTable.find(functionName);
247     ASSERT_NE(found, functionTable.end());
248     ASSERT_LT(paramIndex, found->second.params.size());
249     ASSERT(found->second.params.at(paramIndex).GetOrCreateMetadata().GetAnnotations().empty());
250 }
251 
CheckClassFieldAnnotations(ark::pandasm::Program * program,const std::string & recordName,const std::string & fieldName,const AnnotationMap & expectedAnnotations)252 void AsmTest::CheckClassFieldAnnotations(ark::pandasm::Program *program, const std::string &recordName,
253                                          const std::string &fieldName, const AnnotationMap &expectedAnnotations)
254 {
255     const auto &recordTable = program->recordTable;
256     auto found = recordTable.find(recordName);
257     ASSERT_NE(found, recordTable.end());
258     auto &filedList = found->second.fieldList;
259     auto result = std::find_if(filedList.begin(), filedList.end(),
260                                [&fieldName](const ark::pandasm::Field &field) { return field.name == fieldName; });
261     ASSERT_NE(result, filedList.end()) << "Cannot find classProperty '" << fieldName << "'.";
262     for (const auto &expected : expectedAnnotations) {
263         auto annotations = result->metadata->GetAnnotations();
264         auto it = std::find_if(annotations.begin(), annotations.end(),
265                                [&expected](const ark::pandasm::AnnotationData &annotation) {
266                                    return annotation.GetName() == expected.first;
267                                });
268 
269         ASSERT_NE(it, annotations.end()) << fieldName << " missing expected annotation: " << expected.first;
270 
271         // Check the fields for the matched annotation name
272         CheckAnnotation(expected.second, *it);
273     }
274 }
275 
CheckClassFieldWithoutAnnotations(ark::pandasm::Program * program,const std::string & recordName,const std::string & fieldName)276 void AsmTest::CheckClassFieldWithoutAnnotations(ark::pandasm::Program *program, const std::string &recordName,
277                                                 const std::string &fieldName)
278 {
279     const auto &recordTable = program->recordTable;
280     auto found = recordTable.find(recordName);
281     ASSERT_NE(found, recordTable.end());
282     auto &filedList = found->second.fieldList;
283     auto result = std::find_if(filedList.begin(), filedList.end(),
284                                [&fieldName](const ark::pandasm::Field &field) { return field.name == fieldName; });
285     ASSERT_NE(result, filedList.end()) << "Cannot find classProperty '" << fieldName << "'.";
286     ASSERT(result->metadata->GetAnnotations().empty());
287 }
288 
SetCurrentProgram(std::string_view src)289 void AsmTest::SetCurrentProgram(std::string_view src)
290 {
291     int argc = 1;
292     const char *argv = "../../../../bin/es2panda";  // NOLINT(modernize-avoid-c-arrays)
293     static constexpr std::string_view FILE_NAME = "dummy.ets";
294 
295     program_ = GetProgram(argc, &argv, FILE_NAME, src);
296     ASSERT_NE(program_.get(), nullptr);
297 }
298 
GetCurrentProgram(std::string_view src)299 std::unique_ptr<ark::pandasm::Program> AsmTest::GetCurrentProgram(std::string_view src)
300 {
301     static constexpr std::string_view FILE_NAME = "annotation.ets";
302     std::array<char const *, 2> args = {"../../../../../bin/es2panda",
303                                         "--ets-unnamed"};  // NOLINT(modernize-avoid-c-arrays)
304 
305     auto program = GetProgram(args.size(), args.data(), FILE_NAME, src);
306     return program;
307 }
308 
309 }  // namespace test::utils
310