1 /*
2 * Copyright (c) 2021 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 "ecmascript/ecma_vm.h"
17 #include "ecmascript/js_runtime_options.h"
18 #include "ecmascript/tests/test_helper.h"
19
20 #include <csetjmp>
21 #include <csignal>
22 using namespace panda::ecmascript;
23 using namespace common;
24
25 namespace panda::test {
26 class EcmaVMTest : public BaseTestWithOutScope {
27 };
28
29 static thread_local sigjmp_buf g_env;
30 static thread_local bool g_abortFlag = false;
31 static std::mutex g_signalMutex;
32
ProcessHandleAllocAbort(int sig)33 static void ProcessHandleAllocAbort(int sig)
34 {
35 ForceResetAssertData();
36 g_abortFlag = true;
37 siglongjmp(g_env, sig);
38 }
39
RegisterSignal(struct sigaction * oldAct=nullptr)40 static int RegisterSignal(struct sigaction* oldAct = nullptr)
41 {
42 std::lock_guard<std::mutex> lock(g_signalMutex);
43
44 struct sigaction act;
45 act.sa_handler = ProcessHandleAllocAbort;
46 sigemptyset(&act.sa_mask);
47 sigaddset(&act.sa_mask, SIGABRT);
48 act.sa_flags = 0;
49
50 return sigaction(SIGABRT, &act, oldAct);
51 }
52
RestoreSignal(const struct sigaction * oldAct)53 static void RestoreSignal(const struct sigaction* oldAct)
54 {
55 std::lock_guard<std::mutex> lock(g_signalMutex);
56 sigaction(SIGABRT, oldAct, nullptr);
57 }
58
ResetAbortFlag()59 static void ResetAbortFlag()
60 {
61 g_abortFlag = false;
62 }
63
64 class EcmaVmIterator : public ecmascript::RootVisitor {
65 public:
66 EcmaVmIterator() = default;
67 ~EcmaVmIterator() = default;
68
VisitRoot(Root type,ObjectSlot slot)69 void VisitRoot([[maybe_unused]] Root type, [[maybe_unused]] ObjectSlot slot) override {}
70
VisitRangeRoot(Root type,ObjectSlot start,ObjectSlot end)71 void VisitRangeRoot([[maybe_unused]] Root type, [[maybe_unused]] ObjectSlot start,
72 [[maybe_unused]] ObjectSlot end) override
73 {
74 CHECK_NO_HANDLE_ALLOC;
75 }
76
VisitBaseAndDerivedRoot(Root type,ObjectSlot base,ObjectSlot derived,uintptr_t baseOldObject)77 void VisitBaseAndDerivedRoot([[maybe_unused]] Root type, [[maybe_unused]] ObjectSlot base,
78 [[maybe_unused]] ObjectSlot derived, [[maybe_unused]] uintptr_t baseOldObject) override {}
79 };
80
81 /*
82 * @tc.name: CreateEcmaVMInTwoWays
83 * @tc.desc: Create EcmaVM in 2 ways, check the Options state
84 * @tc.type: FUNC
85 * @tc.require:
86 */
HWTEST_F_L0(EcmaVMTest,CreateEcmaVMInTwoWays)87 HWTEST_F_L0(EcmaVMTest, CreateEcmaVMInTwoWays)
88 {
89 RuntimeOption options;
90 options.SetLogLevel(common::LOG_LEVEL::ERROR);
91 EcmaVM::SetMultiThreadCheck(true);
92 EcmaVM *ecmaVm1 = JSNApi::CreateJSVM(options);
93 EXPECT_TRUE(ecmaVm1->GetMultiThreadCheck());
94 auto jsthread1 = ecmaVm1->GetJSThread();
95 EXPECT_TRUE(jsthread1 != nullptr);
96
97 std::thread t1([&]() {
98 JSRuntimeOptions options2;
99 options2.SetEnableArkTools(false);
100 options2.SetEnableForceGC(false);
101 options2.SetForceFullGC(false);
102 options2.SetArkProperties(ArkProperties::GC_STATS_PRINT);
103 options2.SetMemConfigProperty("jsHeap500");
104 // A non-production gc strategy. Prohibit stw-gc 10 times.
105 EcmaVM::SetMultiThreadCheck(false);
106 EcmaVM *ecmaVm2 = JSNApi::CreateEcmaVM(options2);
107 auto jsthread2 = ecmaVm2->GetJSThread();
108 EXPECT_FALSE(ecmaVm2->GetMultiThreadCheck());
109 EXPECT_TRUE(jsthread2 != nullptr);
110 EXPECT_TRUE(ecmaVm1 != ecmaVm2);
111
112 JSRuntimeOptions options1Out = ecmaVm1->GetJSOptions();
113 JSRuntimeOptions options2Out = ecmaVm2->GetJSOptions();
114
115 EXPECT_TRUE(&options1Out != &options2Out);
116
117 EXPECT_TRUE(options1Out.EnableArkTools() != options2Out.EnableArkTools());
118 EXPECT_TRUE(options1Out.EnableForceGC() != options2Out.EnableForceGC());
119 EXPECT_TRUE(options1Out.ForceFullGC() != options2Out.ForceFullGC());
120 EXPECT_TRUE(options1Out.GetArkProperties() != options2Out.GetArkProperties());
121 EXPECT_TRUE(options2Out.GetHeapSize() == 500_MB);
122
123 options2.SetAsmOpcodeDisableRange("1,10");
124 options2.ParseAsmInterOption();
125 EXPECT_TRUE(options2.GetAsmInterParsedOption().handleStart == 1); // 1 targer start
126 EXPECT_TRUE(options2.GetAsmInterParsedOption().handleEnd == 10); // 10 targer end
127
128 options2.SetAsmOpcodeDisableRange("0x1,0xa");
129 options2.ParseAsmInterOption();
130 EXPECT_TRUE(options2.GetAsmInterParsedOption().handleStart == 1); // 1 targer start
131 EXPECT_TRUE(options2.GetAsmInterParsedOption().handleEnd == 10); // 10 targer end
132
133 options2.SetAsmOpcodeDisableRange(",");
134 options2.ParseAsmInterOption();
135 EXPECT_TRUE(options2.GetAsmInterParsedOption().handleStart == 0);
136 EXPECT_TRUE(options2.GetAsmInterParsedOption().handleEnd == kungfu::BYTECODE_STUB_END_ID);
137
138 options2.SetAsmOpcodeDisableRange("@,@");
139 options2.ParseAsmInterOption();
140 EXPECT_TRUE(options2.GetAsmInterParsedOption().handleStart == 0);
141 EXPECT_TRUE(options2.GetAsmInterParsedOption().handleEnd == kungfu::BYTECODE_STUB_END_ID);
142
143 JSNApi::DestroyJSVM(ecmaVm2);
144 });
145 t1.join();
146 JSNApi::DestroyJSVM(ecmaVm1);
147 }
148
HWTEST_F_L0(EcmaVMTest,DumpExceptionObject)149 HWTEST_F_L0(EcmaVMTest, DumpExceptionObject)
150 {
151 RuntimeOption option;
152 option.SetLogLevel(common::LOG_LEVEL::ERROR);
153 EcmaVM *ecmaVm = JSNApi::CreateJSVM(option);
154 auto thread = ecmaVm->GetJSThread();
155 int arkProperties = thread->GetEcmaVM()->GetJSOptions().GetArkProperties();
156 ecmaVm->GetJSOptions().SetArkProperties(arkProperties | ArkProperties::EXCEPTION_BACKTRACE);
157 EXPECT_TRUE(ecmaVm->GetJSOptions().EnableExceptionBacktrace());
158 JSNApi::DestroyJSVM(ecmaVm);
159 }
160
HWTEST_F_L0(EcmaVMTest,LargeHeap)161 HWTEST_F_L0(EcmaVMTest, LargeHeap)
162 {
163 RuntimeOption option;
164 option.SetLargeHeap(true);
165 EcmaVM *ecmaVm = JSNApi::CreateJSVM(option);
166 EXPECT_TRUE(ecmaVm->GetJSOptions().GetLargeHeap());
167 JSNApi::DestroyJSVM(ecmaVm);
168 }
169
HWTEST_F_L0(EcmaVMTest,TestHandleAlocate)170 HWTEST_F_L0(EcmaVMTest, TestHandleAlocate)
171 {
172 RuntimeOption option;
173 option.SetLogLevel(RuntimeOption::LOG_LEVEL::ERROR);
174 EcmaVM *ecmaVm = JSNApi::CreateJSVM(option);
175 [[maybe_unused]]HeapProfilerInterface *heapProfile = HeapProfilerInterface::GetInstance(ecmaVm);
176
177 ObjectFactory *factory = ecmaVm->GetFactory();
178 // JS_ARRAY_BUFFER
179 factory->NewJSArrayBuffer(10);
180 // JS_SHARED_ARRAY_BUFFER
181 factory->NewJSSharedArrayBuffer(10);
182 // PROMISE_REACTIONS
183 factory->NewPromiseReaction();
184 // PROMISE_CAPABILITY
185 factory->NewPromiseCapability();
186 // PROMISE_RECORD
187 factory->NewPromiseRecord();
188 // RESOLVING_FUNCTIONS_RECORD
189 factory->NewResolvingFunctionsRecord();
190
191 struct sigaction oldAct;
192 ASSERT_TRUE(RegisterSignal(&oldAct) != -1);
193
194 {
195 EcmaVmIterator ecmaVmIterator;
196 auto ret = sigsetjmp(g_env, 1);
197 if (ret != SIGABRT) {
198 ecmaVm->Iterate(ecmaVmIterator);
199 } else {
200 EXPECT_TRUE(g_abortFlag);
201 }
202 }
203
204 RestoreSignal(&oldAct);
205 ResetAbortFlag();
206
207 ASSERT_TRUE(RegisterSignal(&oldAct) != -1);
208 {
209 EcmaVmIterator ecmaVmIterator;
210 auto ret = sigsetjmp(g_env, 1);
211 if (ret != SIGABRT) {
212 ecmaVm->IterateHandle(ecmaVmIterator);
213 } else {
214 EXPECT_TRUE(g_abortFlag);
215 }
216 }
217
218 RestoreSignal(&oldAct);
219 ResetAbortFlag();
220 JSNApi::DestroyJSVM(ecmaVm);
221 }
222 } // namespace panda::ecmascript
223