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