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