• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2024 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 #ifndef PANDA_ANNOTATIONS_EMIT_TEST_H
17 #define PANDA_ANNOTATIONS_EMIT_TEST_H
18 
19 #include <gtest/gtest.h>
20 #include "annotation.h"
21 #include "macros.h"
22 #include "util/options.h"
23 #include <cstddef>
24 #include <iostream>
25 #include <ostream>
26 #include <string>
27 #include <utility>
28 #include <variant>
29 #include <vector>
30 #include "assembly-program.h"
31 namespace ark::es2panda::compiler::test {
32 
33 using AnnotationMap = std::map<std::string, std::vector<std::pair<std::string, std::string>>>;
34 using AnnotationValueType = std::variant<bool, uint8_t, uint16_t, uint32_t, uint64_t, float, double, std::string>;
35 class AnnotationEmitTest : public ::testing::Test {
36 public:
AnnotationEmitTest()37     AnnotationEmitTest()
38     {
39         const auto compilerSize = 268435456;
40 
41         mem::MemConfig::Initialize(0, 0, compilerSize, 0, 0, 0);
42         PoolManager::Initialize(PoolType::MMAP);
43     }
44 
~AnnotationEmitTest()45     ~AnnotationEmitTest() override
46     {
47         PoolManager::Finalize();
48         mem::MemConfig::Finalize();
49     }
50 
51 protected:
52     static constexpr uint32_t COLOR_OPTION_0 = 0;
53     static constexpr uint32_t COLOR_OPTION_1 = 1;
54     static constexpr double AGE_18 = 18.0;
55     static constexpr double AGE_21 = 21.0;
56     static constexpr double AGE_32 = 32.0;
57     static constexpr double VALUE_1 = 1.0;
58     static constexpr double VALUE_2 = 2.0;
59     static constexpr double VALUE_3 = 3.0;
60     static constexpr double VALUE_4 = 4.0;
61     static constexpr double VALUE_5 = 5.0;
62     static constexpr double VALUE_6 = 6.0;
63     static constexpr double VALUE_7 = 7.0;
64     static constexpr double VALUE_8 = 8.0;
65     static constexpr double VALUE_9 = 9.0;
66     static constexpr uint32_t COLOR_0 = 0;
67     static constexpr uint32_t COLOR_1 = 1;
68     static constexpr double REVIEWER_AGE_19 = 19.0;
69     static constexpr double REVIEWER_AGE_20 = 20.0;
70     static constexpr double REVIEWER_AGE_24 = 24.0;
71 
GetCurrentProgram(std::string_view src)72     std::unique_ptr<pandasm::Program> GetCurrentProgram(std::string_view src)
73     {
74         int argc = 1;
75         const char *argv = "../../../../../bin/es2panda";
76         static constexpr std::string_view FILE_NAME = "annotation.sts";
77         auto program = std::unique_ptr<pandasm::Program>(GetProgram(argc, &argv, FILE_NAME, src));
78         return program;
79     }
80 
CheckAnnoDecl(ark::pandasm::Program * program,const std::string & annoName,const std::vector<std::pair<std::string,std::string>> & expectedAnnotations)81     void CheckAnnoDecl(ark::pandasm::Program *program, const std::string &annoName,
82                        const std::vector<std::pair<std::string, std::string>> &expectedAnnotations)
83     {
84         const auto &recordTable = program->recordTable;
85         ASSERT_FALSE(recordTable.empty()) << "No records found in the program.";
86         auto found = recordTable.find(annoName);
87         ASSERT_NE(found, recordTable.end());
88 
89         for (size_t i = 0; i < expectedAnnotations.size(); i++) {
90             auto scalarValue = found->second.fieldList[i].metadata->GetValue();
91             if (scalarValue) {
92                 CompareActualWithExpected(expectedAnnotations[i].second, &*scalarValue,
93                                           found->second.fieldList[i].name);
94             }
95         }
96     }
97 
CheckLiteralArrayTable(ark::pandasm::Program * program,const std::vector<std::pair<std::string,std::vector<AnnotationValueType>>> & expectedLiteralArrayTable)98     void CheckLiteralArrayTable(
99         ark::pandasm::Program *program,
100         const std::vector<std::pair<std::string, std::vector<AnnotationValueType>>> &expectedLiteralArrayTable)
101     {
102         const auto &literalarrayTable = program->literalarrayTable;
103         ASSERT_FALSE(literalarrayTable.empty()) << "literalarrayTable is empty!";
104         for (const auto &literalArray : expectedLiteralArrayTable) {
105             auto found = literalarrayTable.find(literalArray.first);
106             ASSERT_NE(found, literalarrayTable.end());
107             size_t i = 1;
108             for (const auto &value : literalArray.second) {
109                 constexpr int STRIDE = 2;
110                 ASSERT_EQ(value, found->second.literals[i].value) << "Value mismatch for " + literalArray.first;
111                 i += STRIDE;
112             }
113         }
114     }
115 
CheckClassAnnotations(ark::pandasm::Program * program,const std::string & className,const AnnotationMap & expectedAnnotations)116     void CheckClassAnnotations(ark::pandasm::Program *program, const std::string &className,
117                                const AnnotationMap &expectedAnnotations)
118     {
119         const auto &recordTable = program->recordTable;
120         ASSERT_FALSE(recordTable.empty()) << "No records found in the program.";
121         auto found = recordTable.find(className);
122         ASSERT_NE(found, recordTable.end());
123 
124         for (const auto &anno : found->second.metadata->GetAnnotations()) {
125             auto it = expectedAnnotations.find(anno.GetName());
126             ASSERT_NE(it, expectedAnnotations.end()) << "Unexpected annotation: " << anno.GetName();
127 
128             // Check the fields for the matched annotation name
129             CheckAnnotation(it->second, anno);
130         }
131     }
132 
CheckFunctionAnnotations(ark::pandasm::Program * program,const std::string & functionName,const AnnotationMap & expectedAnnotations)133     void CheckFunctionAnnotations(ark::pandasm::Program *program, const std::string &functionName,
134                                   const AnnotationMap &expectedAnnotations)
135     {
136         const auto &functionTable = program->functionTable;
137         auto found = functionTable.find(functionName);
138         ASSERT_NE(found, functionTable.end());
139 
140         for (const auto &annotation : found->second.metadata->GetAnnotations()) {
141             auto it = expectedAnnotations.find(annotation.GetName());
142             ASSERT_NE(it, expectedAnnotations.end()) << "Unexpected annotation: " << annotation.GetName();
143 
144             // Check the fields for the matched annotation name
145             CheckAnnotation(it->second, annotation);
146         }
147     }
148 
CompareActualWithExpected(const std::string & expectedValue,pandasm::ScalarValue * scalarValue,const std::string & field)149     void CompareActualWithExpected(const std::string &expectedValue, pandasm::ScalarValue *scalarValue,
150                                    const std::string &field) const
151     {
152         std::string actualValue = std::visit(
153             [](const auto &value) -> std::string {
154                 using ValueType = std::decay_t<decltype(value)>;
155                 if constexpr (std::is_same_v<ValueType, std::string>) {
156                     return value;
157                 } else if constexpr (std::is_arithmetic_v<ValueType>) {
158                     return std::to_string(value);
159                 } else {
160                     return "Unsupported type";
161                 }
162             },
163             scalarValue->GetValue());
164 
165         ASSERT_EQ(actualValue, expectedValue) << "Value mismatch for " + field;
166     }
167 
CheckAnnotation(const std::vector<std::pair<std::string,std::string>> & expectedValues,const pandasm::AnnotationData & annotation)168     void CheckAnnotation(const std::vector<std::pair<std::string, std::string>> &expectedValues,
169                          const pandasm::AnnotationData &annotation) const
170     {
171         for (const auto &element : annotation.GetElements()) {
172             auto it = std::find_if(expectedValues.begin(), expectedValues.end(),
173                                    [&element](const auto &pair) { return pair.first == element.GetName(); });
174             if (it != expectedValues.end()) {
175                 CompareActualWithExpected(it->second, element.GetValue()->GetAsScalar(), element.GetName());
176             }
177         }
178     }
179 
GetProgram(int argc,const char ** argv,std::string_view fileName,std::string_view src)180     static pandasm::Program *GetProgram(int argc, const char **argv, std::string_view fileName, std::string_view src)
181     {
182         auto options = std::make_unique<util::Options>();
183         if (!options->Parse(argc, argv)) {
184             std::cerr << options->ErrorMsg() << std::endl;
185             return nullptr;
186         }
187 
188         ark::Logger::ComponentMask mask {};
189         mask.set(ark::Logger::Component::ES2PANDA);
190         ark::Logger::InitializeStdLogging(ark::Logger::LevelFromString(options->LogLevel()), mask);
191 
192         ark::es2panda::Compiler compiler(options->Extension(), options->ThreadCount());
193         ark::es2panda::SourceFile input(fileName, src, options->ParseModule());
194         auto program = compiler.Compile(input, *options);
195         return program;
196     }
197 
198 private:
199     NO_COPY_SEMANTIC(AnnotationEmitTest);
200     NO_MOVE_SEMANTIC(AnnotationEmitTest);
201 };
202 
203 }  // namespace ark::es2panda::compiler::test
204 
205 #endif  // PANDA_ANNOTATIONS_EMIT_TEST_H
206