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 #ifndef ECMASCRIPT_TESTS_TEST_HELPER_H 17 #define ECMASCRIPT_TESTS_TEST_HELPER_H 18 19 #include "ecmascript/interpreter/interpreter.h" 20 #include "ecmascript/ecma_language_context.h" 21 #include "ecmascript/ecma_runtime_call_info.h" 22 #include "ecmascript/ecma_vm.h" 23 #include "ecmascript/js_function.h" 24 #include "ecmascript/js_handle.h" 25 #include "ecmascript/napi/include/jsnapi.h" 26 #include "ecmascript/object_factory.h" 27 #include "gtest/gtest.h" 28 #include "include/runtime_options.h" 29 30 namespace panda::test { 31 using panda::ecmascript::EcmaHandleScope; 32 using panda::ecmascript::EcmaRuntimeCallInfo; 33 using panda::ecmascript::EcmaVM; 34 using panda::ecmascript::InterpretedFrame; 35 using panda::ecmascript::JSTaggedType; 36 using panda::ecmascript::JSTaggedValue; 37 using panda::ecmascript::JSThread; 38 using panda::ecmascript::NUM_MANDATORY_JSFUNC_ARGS; 39 using ecmascript::JSRuntimeOptions; 40 41 // Add for hmf tests platform, define to TEST_F or TEST_P when running gtest in gitlab 42 #define HWTEST_F_L0(testsuit, testcase) HWTEST_F(testsuit, testcase, testing::ext::TestSize.Level0) 43 #define HWTEST_P_L0(testsuit, testcase) HWTEST_P(testsuit, testcase, testing::ext::TestSize.Level0) 44 45 class TestHelper { 46 public: CreateEcmaRuntimeCallInfo(JSThread * thread,JSTaggedValue newTgt,uint32_t argvLength)47 static std::unique_ptr<EcmaRuntimeCallInfo> CreateEcmaRuntimeCallInfo(JSThread *thread, JSTaggedValue newTgt, 48 uint32_t argvLength) 49 { 50 const uint8_t testDecodedSize = 2; 51 // argvLength includes number of int64_t to store value and tag of function, 'this' and call args 52 // It doesn't include new.target argument 53 uint32_t numActualArgs = argvLength / testDecodedSize + 1; 54 JSTaggedType *sp = const_cast<JSTaggedType *>(thread->GetCurrentSPFrame()); 55 size_t frameSize = ecmascript::FRAME_STATE_SIZE + numActualArgs; 56 JSTaggedType *newSp = sp - frameSize; // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic) 57 58 auto callInfo = 59 std::make_unique<EcmaRuntimeCallInfo>(thread, numActualArgs, reinterpret_cast<JSTaggedValue *>(newSp)); 60 callInfo->SetNewTarget(newTgt); 61 return callInfo; 62 } 63 SetupFrame(JSThread * thread,EcmaRuntimeCallInfo * info)64 static JSTaggedType *SetupFrame(JSThread *thread, EcmaRuntimeCallInfo *info) 65 { 66 JSTaggedType *sp = const_cast<JSTaggedType *>(thread->GetCurrentSPFrame()); 67 size_t frameSize = ecmascript::FRAME_STATE_SIZE + info->GetArgsNumber() + NUM_MANDATORY_JSFUNC_ARGS; 68 JSTaggedType *newSp = sp - frameSize; // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic) 69 70 InterpretedFrame *state = reinterpret_cast<InterpretedFrame *>(newSp) - 1; 71 state->base.type = ecmascript::FrameType::INTERPRETER_FRAME; 72 state->base.prev = sp; 73 state->pc = nullptr; 74 state->sp = newSp; 75 state->function = methodFunction_.GetTaggedValue(); 76 thread->SetCurrentSPFrame(newSp); 77 return sp; 78 } 79 TearDownFrame(JSThread * thread,JSTaggedType * prev)80 static void TearDownFrame(JSThread *thread, JSTaggedType *prev) 81 { 82 thread->SetCurrentSPFrame(prev); 83 } 84 85 // If you want to call once create, you can refer to BuiltinsMathTest for detail. 86 static void CreateEcmaVMWithScope(PandaVM *&instance, JSThread *&thread, EcmaHandleScope *&scope, 87 const char *libraryPath = nullptr) 88 { 89 JSRuntimeOptions options; 90 options.SetShouldLoadBootPandaFiles(false); 91 options.SetShouldInitializeIntrinsics(false); 92 options.SetBootClassSpaces({"ecmascript"}); 93 options.SetRuntimeType("ecmascript"); 94 options.SetPreGcHeapVerifyEnabled(true); 95 options.SetEnableForceGC(true); 96 if (libraryPath != nullptr) { 97 // for class Runtime to StartDebugger 98 options.SetDebuggerLibraryPath(libraryPath); 99 } 100 static EcmaLanguageContext lcEcma; 101 [[maybe_unused]] bool success = Runtime::Create(options, {&lcEcma}); 102 ASSERT_TRUE(success) << "Cannot create Runtime"; 103 instance = Runtime::GetCurrent()->GetPandaVM(); 104 EcmaVM::Cast(instance)->SetEnableForceGC(true); 105 ASSERT_TRUE(instance != nullptr) << "Cannot create EcmaVM"; 106 thread = EcmaVM::Cast(instance)->GetJSThread(); 107 scope = new EcmaHandleScope(thread); 108 EcmaVM *ecmaVm = thread->GetEcmaVM(); 109 auto globalEnv = ecmaVm->GetGlobalEnv(); 110 methodFunction_ = ecmaVm->GetFactory()->NewJSFunction(globalEnv); 111 } 112 DestroyEcmaVMWithScope(PandaVM * instance,EcmaHandleScope * scope)113 static inline void DestroyEcmaVMWithScope(PandaVM *instance, EcmaHandleScope *scope) 114 { 115 delete scope; 116 EcmaVM::Cast(instance)->SetEnableForceGC(false); 117 auto thread = EcmaVM::Cast(instance)->GetJSThread(); 118 thread->ClearException(); 119 JSNApi::DestroyJSVM(EcmaVM::Cast(instance)); 120 } 121 122 private: 123 inline static ecmascript::JSHandle<ecmascript::JSFunction> methodFunction_; 124 }; 125 } // namespace panda::test 126 #endif // ECMASCRIPT_TESTS_TEST_HELPER_H 127