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
18 #include "assembler/assembly-program.h"
19 #include "generated/signatures.h"
20 #include "libpandabase/mem/mem.h"
21 #include "macros.h"
22 #include "mem/pool_manager.h"
23 #include "util/options.h"
24 #include "test/utils/asm_test.h"
25
26 namespace ark::es2panda::compiler::test {
27
28 class DeclareTest : public testing::Test {
29 public:
DeclareTest()30 DeclareTest()
31 {
32 mem::MemConfig::Initialize(0, 0, ark::es2panda::COMPILER_SIZE, 0, 0, 0);
33 PoolManager::Initialize(PoolType::MMAP);
34 }
~DeclareTest()35 ~DeclareTest() override
36 {
37 PoolManager::Finalize();
38 mem::MemConfig::Finalize();
39 }
40
SetCurrentProgram(std::string_view src)41 void SetCurrentProgram(std::string_view src)
42 {
43 static constexpr std::string_view FILE_NAME = "ets_decl_test.ets";
44 std::array<char const *, 2> args = {"../../../../bin/es2panda",
45 "--ets-unnamed"}; // NOLINT(modernize-avoid-c-arrays)
46
47 program_ = GetProgram({args.data(), args.size()}, FILE_NAME, src);
48 ASSERT_NE(program_.get(), nullptr);
49 }
50
CheckRecordExternalFlag(std::string_view recordName)51 void CheckRecordExternalFlag(std::string_view recordName)
52 {
53 pandasm::Record *record = GetRecord(recordName, program_);
54 ASSERT_TRUE(record != nullptr) << "Record '" << recordName << "' not found";
55 ASSERT_TRUE(HasExternalFlag(record)) << "Record '" << record->name << "' doesn't have External flag";
56 }
57
CheckFunctionExternalFlag(std::string_view functionName,bool isStatic=false)58 void CheckFunctionExternalFlag(std::string_view functionName, bool isStatic = false)
59 {
60 pandasm::Function *fn =
61 GetFunction(functionName, isStatic ? program_->functionStaticTable : program_->functionInstanceTable);
62 ASSERT_TRUE(fn != nullptr) << "Function '" << functionName << "' not found";
63 ASSERT_TRUE(HasExternalFlag(fn)) << "Function '" << fn->name << "' doesn't have External flag";
64 }
65
CheckFunctionNoExternalFlag(std::string_view functionName,bool isStatic=false)66 void CheckFunctionNoExternalFlag(std::string_view functionName, bool isStatic = false)
67 {
68 pandasm::Function *fn =
69 GetFunction(functionName, isStatic ? program_->functionStaticTable : program_->functionInstanceTable);
70 ASSERT_TRUE(fn != nullptr) << "Function '" << functionName << "' not found";
71 ASSERT_FALSE(HasExternalFlag(fn)) << "Function '" << fn->name << "' has External flag";
72 }
73
74 private:
HasExternalFlag(pandasm::Function * fn)75 bool HasExternalFlag(pandasm::Function *fn)
76 {
77 return (fn->metadata->GetAttribute("external"));
78 }
79
HasExternalFlag(pandasm::Record * record)80 bool HasExternalFlag(pandasm::Record *record)
81 {
82 return (record->metadata->GetAttribute("external"));
83 }
84
85 NO_COPY_SEMANTIC(DeclareTest);
86 NO_MOVE_SEMANTIC(DeclareTest);
87
GetProgram(ark::Span<const char * const> args,std::string_view fileName,std::string_view src)88 static std::unique_ptr<pandasm::Program> GetProgram(ark::Span<const char *const> args, std::string_view fileName,
89 std::string_view src)
90 {
91 auto de = util::DiagnosticEngine();
92 auto options = std::make_unique<es2panda::util::Options>(args[0], de);
93 if (!options->Parse(args)) {
94 return nullptr;
95 }
96
97 Logger::ComponentMask mask {};
98 mask.set(Logger::Component::ES2PANDA);
99 Logger::InitializeStdLogging(options->LogLevel(), mask);
100
101 es2panda::Compiler compiler(options->GetExtension(), options->GetThread());
102 es2panda::SourceFile input(fileName, src, options->IsModule());
103
104 return std::unique_ptr<pandasm::Program>(compiler.Compile(input, *options, de));
105 }
106
GetFunction(std::string_view functionName,const std::map<std::string,pandasm::Function> & table)107 pandasm::Function *GetFunction(std::string_view functionName, const std::map<std::string, pandasm::Function> &table)
108 {
109 auto it = table.find(functionName.data());
110 if (it == table.end()) {
111 return nullptr;
112 }
113 return const_cast<pandasm::Function *>(&it->second);
114 }
115
GetRecord(std::string_view recordName,const std::unique_ptr<ark::pandasm::Program> & program)116 pandasm::Record *GetRecord(std::string_view recordName, const std::unique_ptr<ark::pandasm::Program> &program)
117 {
118 auto it = program->recordTable.find(recordName.data());
119 if (it == program->recordTable.end()) {
120 return nullptr;
121 }
122 return &it->second;
123 }
124
125 private:
126 std::unique_ptr<pandasm::Program> program_ {};
127 };
128
129 // === Function ===
TEST_F(DeclareTest,function_without_overloads_0)130 TEST_F(DeclareTest, function_without_overloads_0)
131 {
132 SetCurrentProgram(R"(
133 declare function foo(tmp: double): string
134 )");
135 CheckFunctionExternalFlag("ETSGLOBAL.foo:f64;std.core.String;", true);
136 }
137
TEST_F(DeclareTest,function_with_overloads_0)138 TEST_F(DeclareTest, function_with_overloads_0)
139 {
140 SetCurrentProgram(R"(
141 declare function foo(tmp?: double): string
142 )");
143 CheckFunctionExternalFlag("ETSGLOBAL.foo:std.core.Double;std.core.String;", true);
144 }
145
146 // === Method of class ===
TEST_F(DeclareTest,noImplclass_def_with_overload_0)147 TEST_F(DeclareTest, noImplclass_def_with_overload_0)
148 {
149 SetCurrentProgram(R"(
150 declare class my_class {
151 public foo(arg?: int): string
152 }
153 )");
154 CheckFunctionExternalFlag("my_class.foo:std.core.Int;std.core.String;");
155 }
156
157 // === Constructor of class ===
TEST_F(DeclareTest,class_constructor_without_parameters_0)158 TEST_F(DeclareTest, class_constructor_without_parameters_0)
159 {
160 SetCurrentProgram(R"(
161 declare class A_class {
162 static x: double
163 }
164 )");
165 CheckFunctionExternalFlag("A_class.<ctor>:void;");
166 }
167
TEST_F(DeclareTest,class_constructor_without_parameters_1)168 TEST_F(DeclareTest, class_constructor_without_parameters_1)
169 {
170 SetCurrentProgram(R"(
171 declare class A {
172 constructor();
173 }
174 )");
175 CheckFunctionExternalFlag("A.<ctor>:void;");
176 }
177
TEST_F(DeclareTest,class_implicit_constructor_0)178 TEST_F(DeclareTest, class_implicit_constructor_0)
179 {
180 SetCurrentProgram(R"(
181 declare class A {
182 }
183 )");
184 CheckFunctionExternalFlag("A.<ctor>:void;");
185 }
186
187 // === Method of interface ===
TEST_F(DeclareTest,noImplinterface_def_with_overload_0)188 TEST_F(DeclareTest, noImplinterface_def_with_overload_0)
189 {
190 SetCurrentProgram(R"(
191 declare interface my_inter {
192 foo(arg?: int): void
193 }
194 )");
195 CheckFunctionExternalFlag("my_inter.foo:std.core.Int;void;");
196 }
197
TEST_F(DeclareTest,namespace_0)198 TEST_F(DeclareTest, namespace_0)
199 {
200 SetCurrentProgram(R"(
201 declare namespace A {
202 }
203 )");
204 CheckRecordExternalFlag("A");
205 }
206
207 } // namespace ark::es2panda::compiler::test
208