1 /**
2 * Copyright (c) 2021-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 #include <gtest/gtest.h>
17
18 #include "macros.h"
19 #include <libpandafile/include/source_lang_enum.h>
20
21 #include "libpandabase/utils/logger.h"
22 #include "plugins/ets/runtime/ets_class_linker_extension.h"
23 #include "plugins/ets/runtime/ets_vm.h"
24 #include "runtime/include/class_linker_extension.h"
25 #include "runtime/include/class_root.h"
26 #include "runtime/include/coretypes/class.h"
27 #include "runtime/include/managed_thread.h"
28 #include "runtime/include/panda_vm.h"
29 #include "runtime/include/runtime_options.h"
30 #include "runtime/include/runtime.h"
31
32 namespace ark::ets::test {
33
34 class EtsVMTest : public testing::Test {
35 public:
EtsVMTest()36 EtsVMTest()
37 {
38 RuntimeOptions options;
39 options.SetShouldLoadBootPandaFiles(true);
40 options.SetShouldInitializeIntrinsics(false);
41 options.SetCompilerEnableJit(false);
42 options.SetGcType("epsilon");
43 options.SetLoadRuntimes({"ets"});
44
45 Logger::InitializeStdLogging(Logger::Level::ERROR, 0);
46
47 auto stdlib = std::getenv("PANDA_STD_LIB");
48 if (stdlib == nullptr) {
49 std::cerr << "PANDA_STD_LIB env variable should be set and point to mock_stdlib.abc" << std::endl;
50 std::abort();
51 }
52 options.SetBootPandaFiles({stdlib});
53
54 ark::Runtime::Create(options);
55 }
~EtsVMTest()56 ~EtsVMTest() override
57 {
58 Runtime::Destroy();
59 }
60
61 NO_COPY_SEMANTIC(EtsVMTest);
62 NO_MOVE_SEMANTIC(EtsVMTest);
63 };
64
AssertCompoundClassRoot(EtsClassLinker * classLinker,EtsClassRoot root)65 static void AssertCompoundClassRoot(EtsClassLinker *classLinker, EtsClassRoot root)
66 {
67 EtsClass *klass = classLinker->GetClassRoot(root);
68 Class *coreClass = klass->GetRuntimeClass();
69
70 ASSERT_NE(klass, nullptr);
71 ASSERT_TRUE(klass->IsInitialized());
72 ASSERT_TRUE(coreClass->IsInstantiable());
73 ASSERT_FALSE(klass->IsArrayClass());
74 ASSERT_FALSE(klass->IsPrimitive());
75 ASSERT_TRUE(klass->IsClass());
76 ASSERT_FALSE(klass->IsInterface());
77 ASSERT_FALSE(klass->IsAbstract());
78 ASSERT_FALSE(coreClass->IsProxy());
79 ASSERT_EQ(coreClass->GetLoadContext(), classLinker->GetEtsClassLinkerExtension()->GetBootContext());
80
81 if (root == EtsClassRoot::OBJECT) {
82 ASSERT_TRUE(coreClass->IsObjectClass());
83 ASSERT_EQ(klass->GetBase(), nullptr);
84 } else {
85 ASSERT_FALSE(coreClass->IsObjectClass());
86 ASSERT_NE(klass->GetBase(), nullptr);
87 ASSERT_EQ(klass->GetBase(), classLinker->GetClassRoot(EtsClassRoot::OBJECT));
88 }
89 }
90
AssertCompoundContainerClassRoot(EtsClassLinker * classLinker,EtsClassRoot root)91 static void AssertCompoundContainerClassRoot(EtsClassLinker *classLinker, EtsClassRoot root)
92 {
93 EtsClass *klass = classLinker->GetClassRoot(root);
94 Class *coreClass = klass->GetRuntimeClass();
95
96 ASSERT_NE(klass, nullptr);
97 ASSERT_TRUE(klass->IsInitialized());
98 ASSERT_TRUE(coreClass->IsInstantiable());
99 ASSERT_TRUE(klass->IsArrayClass());
100 ASSERT_FALSE(klass->IsPrimitive());
101 ASSERT_TRUE(klass->IsClass());
102 ASSERT_FALSE(klass->IsInterface());
103 ASSERT_TRUE(klass->IsAbstract());
104 ASSERT_FALSE(coreClass->IsProxy());
105 ASSERT_EQ(coreClass->GetLoadContext(), classLinker->GetEtsClassLinkerExtension()->GetBootContext());
106 ASSERT_FALSE(coreClass->IsObjectClass());
107 ASSERT_NE(klass->GetBase(), nullptr);
108 ASSERT_EQ(klass->GetBase(), classLinker->GetClassRoot(EtsClassRoot::OBJECT));
109 }
110
AssertPrimitiveClassRoot(EtsClassLinker * classLinker,EtsClassRoot root)111 static void AssertPrimitiveClassRoot(EtsClassLinker *classLinker, EtsClassRoot root)
112 {
113 EtsClass *klass = classLinker->GetClassRoot(root);
114 Class *coreClass = klass->GetRuntimeClass();
115
116 ASSERT_NE(klass, nullptr);
117 ASSERT_TRUE(klass->IsInitialized());
118 ASSERT_FALSE(coreClass->IsInstantiable());
119 ASSERT_FALSE(klass->IsArrayClass());
120 ASSERT_TRUE(klass->IsPrimitive());
121 ASSERT_TRUE(klass->IsPublic());
122 ASSERT_TRUE(klass->IsFinal());
123 ASSERT_FALSE(klass->IsClass());
124 ASSERT_FALSE(klass->IsInterface());
125 ASSERT_TRUE(klass->IsAbstract());
126 ASSERT_FALSE(coreClass->IsProxy());
127 ASSERT_EQ(coreClass->GetLoadContext(), classLinker->GetEtsClassLinkerExtension()->GetBootContext());
128 ASSERT_EQ(klass->GetBase(), nullptr);
129 }
130
AssertPrimitiveContainerClassRoot(EtsClassLinker * classLinker,EtsClassRoot root)131 static void AssertPrimitiveContainerClassRoot(EtsClassLinker *classLinker, EtsClassRoot root)
132 {
133 EtsClass *klass = classLinker->GetClassRoot(root);
134 Class *coreClass = klass->GetRuntimeClass();
135
136 ASSERT_NE(klass, nullptr);
137 ASSERT_TRUE(klass->IsInitialized());
138 ASSERT_TRUE(coreClass->IsInstantiable());
139 ASSERT_TRUE(klass->IsArrayClass());
140 ASSERT_FALSE(klass->IsPrimitive());
141 ASSERT_TRUE(klass->IsPublic());
142 ASSERT_TRUE(klass->IsFinal());
143 ASSERT_TRUE(klass->IsClass());
144 ASSERT_FALSE(klass->IsInterface());
145 ASSERT_TRUE(klass->IsAbstract());
146 ASSERT_FALSE(coreClass->IsProxy());
147 ASSERT_EQ(coreClass->GetLoadContext(), classLinker->GetEtsClassLinkerExtension()->GetBootContext());
148 ASSERT_NE(klass->GetBase(), nullptr);
149 ASSERT_EQ(klass->GetBase(), classLinker->GetClassRoot(EtsClassRoot::OBJECT));
150 }
151
AssertPrimitiveClassRoots(EtsClassLinker * classLinker)152 static void AssertPrimitiveClassRoots(EtsClassLinker *classLinker)
153 {
154 AssertPrimitiveClassRoot(classLinker, EtsClassRoot::BOOLEAN);
155 AssertPrimitiveClassRoot(classLinker, EtsClassRoot::BYTE);
156 AssertPrimitiveClassRoot(classLinker, EtsClassRoot::SHORT);
157 AssertPrimitiveClassRoot(classLinker, EtsClassRoot::CHAR);
158 AssertPrimitiveClassRoot(classLinker, EtsClassRoot::INT);
159 AssertPrimitiveClassRoot(classLinker, EtsClassRoot::LONG);
160 AssertPrimitiveClassRoot(classLinker, EtsClassRoot::FLOAT);
161 AssertPrimitiveClassRoot(classLinker, EtsClassRoot::DOUBLE);
162 }
163
TEST_F(EtsVMTest,InitTest)164 TEST_F(EtsVMTest, InitTest)
165 {
166 auto runtime = Runtime::GetCurrent();
167 ASSERT_NE(runtime, nullptr);
168
169 PandaEtsVM *etsVm = PandaEtsVM::GetCurrent();
170 ASSERT_NE(etsVm, nullptr);
171
172 EtsClassLinker *classLinker = etsVm->GetClassLinker();
173 ASSERT_NE(classLinker, nullptr);
174
175 EtsClassLinkerExtension *ext = classLinker->GetEtsClassLinkerExtension();
176 ASSERT_NE(ext, nullptr);
177 ASSERT_EQ(ext->GetLanguage(), panda_file::SourceLang::ETS);
178 ASSERT_TRUE(ext->IsInitialized());
179
180 AssertCompoundClassRoot(classLinker, EtsClassRoot::OBJECT);
181 AssertCompoundClassRoot(classLinker, EtsClassRoot::CLASS);
182 AssertCompoundClassRoot(classLinker, EtsClassRoot::STRING);
183
184 AssertCompoundContainerClassRoot(classLinker, EtsClassRoot::STRING_ARRAY);
185
186 AssertPrimitiveClassRoots(classLinker);
187
188 AssertPrimitiveContainerClassRoot(classLinker, EtsClassRoot::BOOLEAN_ARRAY);
189 AssertPrimitiveContainerClassRoot(classLinker, EtsClassRoot::BYTE_ARRAY);
190 AssertPrimitiveContainerClassRoot(classLinker, EtsClassRoot::SHORT_ARRAY);
191 AssertPrimitiveContainerClassRoot(classLinker, EtsClassRoot::CHAR_ARRAY);
192 AssertPrimitiveContainerClassRoot(classLinker, EtsClassRoot::INT_ARRAY);
193 AssertPrimitiveContainerClassRoot(classLinker, EtsClassRoot::LONG_ARRAY);
194 AssertPrimitiveContainerClassRoot(classLinker, EtsClassRoot::FLOAT_ARRAY);
195 AssertPrimitiveContainerClassRoot(classLinker, EtsClassRoot::DOUBLE_ARRAY);
196
197 EtsCoroutine *etsCoroutine = EtsCoroutine::GetCurrent();
198 ASSERT_NE(etsCoroutine, nullptr);
199
200 auto vm = etsCoroutine->GetVM();
201 ASSERT_EQ(vm->GetAssociatedThread(), etsCoroutine);
202
203 ASSERT_NE(vm, nullptr);
204 ASSERT_EQ(ext->GetLanguage(), vm->GetLanguageContext().GetLanguage());
205
206 ASSERT_NE(vm->GetHeapManager(), nullptr);
207 ASSERT_NE(vm->GetMemStats(), nullptr);
208
209 ASSERT_NE(vm->GetGC(), nullptr);
210 ASSERT_NE(vm->GetGCTrigger(), nullptr);
211 ASSERT_NE(vm->GetGCStats(), nullptr);
212 ASSERT_NE(vm->GetReferenceProcessor(), nullptr);
213
214 ASSERT_NE(vm->GetGlobalObjectStorage(), nullptr);
215 ASSERT_NE(vm->GetStringTable(), nullptr);
216
217 ASSERT_NE(vm->GetMonitorPool(), nullptr);
218 ASSERT_NE(vm->GetThreadManager(), nullptr);
219 ASSERT_NE(vm->GetRendezvous(), nullptr);
220
221 ASSERT_NE(vm->GetCompiler(), nullptr);
222 ASSERT_NE(vm->GetCompilerRuntimeInterface(), nullptr);
223 }
224
225 } // namespace ark::ets::test
226