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_runtime_call_info.h" 21 #include "ecmascript/ecma_vm.h" 22 #include "ecmascript/js_function.h" 23 #include "ecmascript/js_handle.h" 24 #include "ecmascript/mem/mem_common.h" 25 #include "ecmascript/napi/include/jsnapi.h" 26 #include "ecmascript/object_factory.h" 27 #include "gtest/gtest.h" 28 29 namespace panda::test { 30 using panda::ecmascript::EcmaHandleScope; 31 using panda::ecmascript::EcmaRuntimeCallInfo; 32 using panda::ecmascript::EcmaVM; 33 using panda::ecmascript::InterpretedFrame; 34 using panda::ecmascript::InterpretedBuiltinFrame; 35 using panda::ecmascript::InterpretedEntryFrame; 36 using panda::ecmascript::JSTaggedType; 37 using panda::ecmascript::JSTaggedValue; 38 using panda::ecmascript::JSThread; 39 using panda::ecmascript::NUM_MANDATORY_JSFUNC_ARGS; 40 using ecmascript::JSRuntimeOptions; 41 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 #define EXPECT_EXCEPTION() \ 45 EXPECT_TRUE(thread->HasPendingException()); \ 46 EXPECT_TRUE(thread->GetException().IsJSError()); \ 47 thread->ClearException() 48 49 class TestHelper { 50 public: CreateEcmaRuntimeCallInfo(JSThread * thread,JSTaggedValue newTgt,uint32_t argvLength)51 static EcmaRuntimeCallInfo* CreateEcmaRuntimeCallInfo(JSThread *thread, JSTaggedValue newTgt, uint32_t argvLength) 52 { 53 const uint8_t testDecodedSize = 2; 54 // argvLength includes number of int64_t to store value and tag of function, 'this' and call args 55 // It doesn't include new.target argument 56 int32_t numActualArgs = argvLength / testDecodedSize + 1; 57 JSTaggedType *sp = const_cast<JSTaggedType *>(thread->GetCurrentSPFrame()); 58 59 size_t frameSize = 0; 60 if (thread->IsAsmInterpreter()) { 61 frameSize = InterpretedEntryFrame::NumOfMembers() + numActualArgs; 62 } else { 63 frameSize = InterpretedFrame::NumOfMembers() + numActualArgs; 64 } 65 JSTaggedType *newSp = sp - frameSize; // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic) 66 for (int i = numActualArgs; i > 0; i--) { 67 newSp[i - 1] = JSTaggedValue::Undefined().GetRawData(); 68 } 69 EcmaRuntimeCallInfo *ecmaRuntimeCallInfo = reinterpret_cast<EcmaRuntimeCallInfo *>(newSp - 2); 70 *(--newSp) = numActualArgs; 71 *(--newSp) = panda::ecmascript::ToUintPtr(thread); 72 ecmaRuntimeCallInfo->SetNewTarget(newTgt); 73 return ecmaRuntimeCallInfo; 74 } 75 SetupFrame(JSThread * thread,EcmaRuntimeCallInfo * info)76 static JSTaggedType *SetupFrame(JSThread *thread, EcmaRuntimeCallInfo *info) 77 { 78 JSTaggedType *sp = const_cast<JSTaggedType *>(thread->GetCurrentSPFrame()); 79 size_t frameSize = 0; 80 if (thread->IsAsmInterpreter()) { 81 // 2 means thread and numArgs 82 frameSize = InterpretedEntryFrame::NumOfMembers() + info->GetArgsNumber() + NUM_MANDATORY_JSFUNC_ARGS + 2; 83 } else { 84 // 2 means thread and numArgs 85 frameSize = InterpretedFrame::NumOfMembers() + info->GetArgsNumber() + NUM_MANDATORY_JSFUNC_ARGS + 2; 86 } 87 JSTaggedType *newSp = sp - frameSize; // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic) 88 89 InterpretedEntryFrame *state = reinterpret_cast<InterpretedEntryFrame *>(newSp) - 1; 90 state->base.type = ecmascript::FrameType::INTERPRETER_ENTRY_FRAME; 91 state->base.prev = sp; 92 state->pc = nullptr; 93 thread->SetCurrentSPFrame(newSp); 94 return sp; 95 } 96 TearDownFrame(JSThread * thread,JSTaggedType * prev)97 static void TearDownFrame(JSThread *thread, JSTaggedType *prev) 98 { 99 thread->SetCurrentSPFrame(prev); 100 } 101 102 // If you want to call once create, you can refer to BuiltinsMathTest for detail. 103 static void CreateEcmaVMWithScope(EcmaVM *&instance, JSThread *&thread, EcmaHandleScope *&scope, 104 bool tryLoadStubFile = false, bool useCInterpreter = false) 105 { 106 JSRuntimeOptions options; 107 options.SetEnableForceGC(true); 108 if (tryLoadStubFile) { 109 options.SetEnableAsmInterpreter(true); 110 } 111 if (useCInterpreter) { 112 options.SetEnableAsmInterpreter(false); 113 } 114 instance = JSNApi::CreateEcmaVM(options); 115 instance->SetEnableForceGC(true); 116 ASSERT_TRUE(instance != nullptr) << "Cannot create EcmaVM"; 117 thread = instance->GetJSThread(); 118 scope = new EcmaHandleScope(thread); 119 auto globalEnv = instance->GetGlobalEnv(); 120 methodFunction_ = instance->GetFactory()->NewJSFunction(globalEnv); 121 } 122 DestroyEcmaVMWithScope(EcmaVM * instance,EcmaHandleScope * scope)123 static inline void DestroyEcmaVMWithScope(EcmaVM *instance, EcmaHandleScope *scope) 124 { 125 delete scope; 126 scope = nullptr; 127 instance->SetEnableForceGC(false); 128 auto thread = instance->GetJSThread(); 129 thread->ClearException(); 130 JSNApi::DestroyJSVM(instance); 131 } 132 133 private: 134 inline static ecmascript::JSHandle<ecmascript::JSFunction> methodFunction_; 135 }; 136 } // namespace panda::test 137 #endif // ECMASCRIPT_TESTS_TEST_HELPER_H 138