/*
 * Copyright (c) 2023-2024 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <cstddef>
#include "ecmascript/builtins/builtins.h"
#include "ecmascript/builtins/builtins_function.h"
#include "ecmascript/builtins/builtins_object.h"
#include "ecmascript/checkpoint/thread_state_transition.h"
#include "ecmascript/compiler/aot_file/an_file_data_manager.h"
#include "ecmascript/compiler/aot_file/aot_file_manager.h"
#include "ecmascript/compiler/circuit_builder_helper.h"
#include "ecmascript/deoptimizer/deoptimizer.h"
#include "ecmascript/ecma_global_storage.h"
#include "ecmascript/ecma_vm.h"
#include "ecmascript/global_env.h"
#include "ecmascript/js_api/js_api_tree_map.h"
#include "ecmascript/js_api/js_api_tree_set.h"
#include "ecmascript/js_api/js_api_vector.h"
#include "ecmascript/js_array.h"
#include "ecmascript/js_bigint.h"
#include "ecmascript/js_date_time_format.h"
#include "ecmascript/js_generator_object.h"
#include "ecmascript/js_map.h"
#include "ecmascript/js_map_iterator.h"
#include "ecmascript/js_object-inl.h"
#include "ecmascript/js_primitive_ref.h"
#include "ecmascript/js_regexp.h"
#include "ecmascript/js_runtime_options.h"
#include "ecmascript/js_set.h"
#include "ecmascript/js_set_iterator.h"
#include "ecmascript/js_tagged_value.h"
#include "ecmascript/js_typed_array.h"
#include "ecmascript/js_thread.h"
#include "ecmascript/js_weak_container.h"
#include "ecmascript/linked_hash_table.h"
#include "ecmascript/mem/mem_map_allocator.h"
#include "ecmascript/module/js_module_manager.h"
#include "ecmascript/module/js_module_source_text.h"
#include "ecmascript/napi/include/jsnapi.h"
#include "ecmascript/napi/include/jsnapi_internals.h"
#include "ecmascript/napi/jsnapi_helper.h"
#include "ecmascript/object_factory.h"
#include "ecmascript/pgo_profiler/pgo_profiler.h"
#include "ecmascript/pgo_profiler/pgo_profiler_decoder.h"
#include "ecmascript/pgo_profiler/pgo_profiler_encoder.h"
#include "ecmascript/pgo_profiler/pgo_profiler_manager.h"
#include "ecmascript/tagged_array.h"
#include "ecmascript/tests/test_helper.h"
#include "ecmascript/tagged_tree.h"
#include "ecmascript/weak_vector.h"
#include "gtest/gtest.h"

#define PROPERTY_COUNT_CASE1 10
#define PROPERTY_COUNT_CASE2 (PropertyAttributes::MAX_FAST_PROPS_CAPACITY + 1)

using namespace panda;
using namespace panda::ecmascript;
using namespace panda::ecmascript::kungfu;
static const char *TEST_KEY = "TestKey";
static const char *TEST_VALUE = "TestValue";
static const char *TEST_NUM1 = "-3.14";
static const char *TEST_NUM2 = "-123.3";
static int32_t TEST_NUM = 2;

namespace panda::test {
using BuiltinsFunction = ecmascript::builtins::BuiltinsFunction;
using PGOProfilerManager = panda::ecmascript::pgo::PGOProfilerManager;
using FunctionForRef = Local<JSValueRef> (*)(JsiRuntimeCallInfo *);
class JSNApiTests : public testing::Test {
public:
    static void SetUpTestCase()
    {
        GTEST_LOG_(INFO) << "SetUpTestCase";
    }

    static void TearDownTestCase()
    {
        GTEST_LOG_(INFO) << "TearDownCase";
    }

    void SetUp() override
    {
        RuntimeOption option;
        option.SetLogLevel(common::LOG_LEVEL::ERROR);
        vm_ = JSNApi::CreateJSVM(option);
        ASSERT_TRUE(vm_ != nullptr) << "Cannot create Runtime";
        thread_ = vm_->GetJSThread();
        vm_->SetEnableForceGC(true);
        thread_->ManagedCodeBegin();
    }

    void TearDown() override
    {
        thread_->ManagedCodeEnd();
        vm_->SetEnableForceGC(false);
        JSNApi::DestroyJSVM(vm_);
    }

    template <typename T> void TestNumberRef(T val, TaggedType expected)
    {
        LocalScope scope(vm_);
        Local<NumberRef> obj = NumberRef::New(vm_, val);
        ASSERT_TRUE(obj->IsNumber());
        JSTaggedType res = JSNApiHelper::ToJSTaggedValue(*obj).GetRawData();
        ASSERT_EQ(res, expected);
        if constexpr (std::is_floating_point_v<T>) {
            if (std::isnan(val)) {
                ASSERT_TRUE(std::isnan(obj->Value()));
            } else {
                ASSERT_EQ(obj->Value(), val);
            }
        } else if constexpr (sizeof(T) >= sizeof(int32_t)) {
            ASSERT_EQ(obj->IntegerValue(vm_), val);
        } else if constexpr (std::is_signed_v<T>) {
            ASSERT_EQ(obj->Int32Value(vm_), val);
        } else {
            ASSERT_EQ(obj->Uint32Value(vm_), val);
        }
    }

    TaggedType ConvertDouble(double val)
    {
        return base::bit_cast<JSTaggedType>(val) + JSTaggedValue::DOUBLE_ENCODE_OFFSET;
    }

protected:
    JSThread *thread_ = nullptr;
    EcmaVM *vm_ = nullptr;
};

Local<JSValueRef> FunctionCallback(JsiRuntimeCallInfo *info)
{
    EscapeLocalScope scope(info->GetVM());
    return scope.Escape(ArrayRef::New(info->GetVM(), info->GetArgsNumber()));
}

JSValueRef InternalFunctionCallback(JsiRuntimeCallInfo *info)
{
    EscapeLocalScope scope(info->GetVM());
    Local<JSValueRef> result = scope.Escape(ArrayRef::New(info->GetVM(), info->GetArgsNumber()));
    return **result;
}

void WeakRefCallback(EcmaVM *vm)
{
    LocalScope scope(vm);
    Local<ObjectRef> object = ObjectRef::New(vm);
    Global<ObjectRef> globalObject(vm, object);
    globalObject.SetWeak();
    Local<ObjectRef> object1 = ObjectRef::New(vm);
    Global<ObjectRef> globalObject1(vm, object1);
    globalObject1.SetWeak();
    vm->CollectGarbage(TriggerGCType::YOUNG_GC);
    vm->CollectGarbage(TriggerGCType::OLD_GC);
    globalObject.FreeGlobalHandleAddr();
}

void ThreadCheck(const EcmaVM *vm)
{
    EXPECT_TRUE(vm->GetJSThread()->GetThreadId() != JSThread::GetCurrentThreadId());
}

void CheckReject(JsiRuntimeCallInfo *info)
{
    ASSERT_EQ(info->GetArgsNumber(), 1U);
    Local<JSValueRef> reason = info->GetCallArgRef(0);
    ASSERT_TRUE(reason->IsString(info->GetVM()));
    ASSERT_EQ(Local<StringRef>(reason)->ToString(info->GetVM()), "Reject");
}

Local<JSValueRef> RejectCallback(JsiRuntimeCallInfo *info)
{
    LocalScope scope(info->GetVM());
    CheckReject(info);
    return JSValueRef::Undefined(info->GetVM());
}

/**
 * @tc.number: ffi_interface_api_054
 * @tc.name: NumberRef_uint32_int64
 * @tc.desc:Define the variable input of type uint32_t and int64_t to determine whether the object is of numerical type
 * @tc.type: FUNC
 * @tc.require:  parameter
 */
HWTEST_F_L0(JSNApiTests, NumberRef_uint32_int64)
{
    uint32_t input = 32;
    int64_t input1 = 1;
    Local<NumberRef> res = NumberRef::New(vm_, input);
    Local<NumberRef> res1 = NumberRef::New(vm_, input1);
    ASSERT_TRUE(res->IsNumber());
    ASSERT_TRUE(res1->IsNumber());
}

/**
 * @tc.number: ffi_interface_api_055
 * @tc.name: NumberRef_int32_t_double
 * @tc.desc:Define the variable input of type int32 and double to determine whether the object is of numerical type
 * @tc.type: FUNC
 * @tc.require:  parameter
 */
HWTEST_F_L0(JSNApiTests, NumberRef_int32_t_double)
{
    int32_t input = -1;
    double input1 = 1.1;
    Local<NumberRef> res = NumberRef::New(vm_, input);
    Local<NumberRef> res1 = NumberRef::New(vm_, input1);
    ASSERT_TRUE(res->IsNumber());
    ASSERT_TRUE(res1->IsNumber());
}

/**
 * @tc.number: ffi_interface_api_056
 * @tc.name: ObjectRef_Freeze
 * @tc.desc:Execute a Freeze operation and call the JSObject:: SetIntegrity Level method to achieve immutability
 * @tc.type: FUNC
 * @tc.require:  parameter
 */
HWTEST_F_L0(JSNApiTests, ObjectRef_Freeze)
{
    LocalScope scope(vm_);
    Local<ObjectRef> object = ObjectRef::New(vm_);
    thread_ = vm_->GetJSThread();
    JSHandle<GlobalEnv> env = vm_->GetGlobalEnv();
    JSHandle<JSTaggedValue> set = env->GetBuiltinsSetFunction();
    object->Freeze(vm_);
    ecmascript::ThreadManagedScope managedScope(thread_);
    bool status = JSObject::SetIntegrityLevel(thread_, JSHandle<JSObject>::Cast(set), IntegrityLevel::FROZEN);
    ASSERT_TRUE(status);
}

/**
 * @tc.number: ffi_interface_api_057
 * @tc.name: ObjectRef_Seal
 * @tc.desc:The function is to perform a closed (Seal) operation by calling the JSObject::SetIntegrity Level method
 * to ensure that its properties cannot be modified or deleted, and to set the integrity level of
 * the object to SEALED
 * @tc.type: FUNC
 * @tc.require:  parameter
 */
HWTEST_F_L0(JSNApiTests, ObjectRef_Seal)
{
    LocalScope scope(vm_);
    Local<ObjectRef> object = ObjectRef::New(vm_); // 创建一个新的空对象
    thread_ = vm_->GetJSThread();
    JSHandle<GlobalEnv> env = vm_->GetGlobalEnv();
    JSHandle<JSTaggedValue> set = env->GetBuiltinsSetFunction();
    object->Seal(vm_); // 尝试将对象封闭
    ecmascript::ThreadManagedScope managedScope(thread_);
    bool status = JSObject::SetIntegrityLevel(thread_, JSHandle<JSObject>::Cast(set), IntegrityLevel::SEALED);
    ASSERT_TRUE(status);
}

/**
 * @tc.number: ffi_interface_api_058
 * @tc.name: ObjectRef_GetAllPropertyNames
 * @tc.desc:Use the GetAllPropertyNames method to obtain all property names of the object and return an ArrayRef object.
 * @tc.type: FUNC
 * @tc.require:  parameter
 */
HWTEST_F_L0(JSNApiTests, ObjectRef_GetAllPropertyNames)
{
    LocalScope scope(vm_);
    Local<ObjectRef> object = ObjectRef::New(vm_);
    uint32_t filter = 3;
    Local<ArrayRef> res = object->GetAllPropertyNames(vm_, filter);
    ASSERT_FALSE(res->IsBigInt(vm_));
    ASSERT_TRUE(res->IsArray(vm_));
}

/**
 * @tc.number: ffi_interface_api_059
 * @tc.name: GetIndex
 * @tc.desc:Call the GetIndex() function to obtain the index value and use EXCECT_ EQ()
 * assertion is used to verify whether the result is 0, which is the initial index value.
 * @tc.type: FUNC
 * @tc.require:  parameter
 */
HWTEST_F_L0(JSNApiTests, GetIndex)
{
    ecmascript::ThreadManagedScope managedScope(vm_->GetJSThread());
    LocalScope scope(vm_);
    JSThread *thread = vm_->GetJSThread();
    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
    JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
    JSHandle<JSTaggedValue> constructor = env->GetBuiltinsMapFunction();
    JSHandle<JSMap> jsMap =
        JSHandle<JSMap>::Cast(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(constructor), constructor));
    JSHandle<LinkedHashMap> hashMap = LinkedHashMap::Create(thread);
    jsMap->SetLinkedMap(thread, hashMap);
    JSHandle<JSTaggedValue> mapTag = JSHandle<JSTaggedValue>::Cast(jsMap);
    JSHandle<JSTaggedValue> jsMapIteratorTag4 = JSMapIterator::CreateMapIterator(thread, mapTag, IterationKind::VALUE);
    JSHandle<JSMapIterator> jsMapIterator4(jsMapIteratorTag4);
    Local<MapIteratorRef> mapIterator4 = JSNApiHelper::ToLocal<MapIteratorRef>(jsMapIteratorTag4);
    int32_t res4 = mapIterator4->GetIndex();
    EXPECT_EQ(0, res4);
}

/**
 * @tc.number: ffi_interface_api_060
 * @tc.name: GetKind_entries_values_keys
 * @tc.desc:This test case is mainly used to verify whether the GetKind method of the JSMapIterator object can
 * correctly return the expected type.
 * @tc.type: FUNC
 * @tc.require:  parameter
 */
HWTEST_F_L0(JSNApiTests, GetKind_entries_values_keys)
{
    LocalScope scope(vm_);
    JSThread *thread = vm_->GetJSThread();
    ecmascript::ThreadManagedScope managedScope(thread);
    std::string expectedResult = "entries";
    std::string valuesResult = "values";
    std::string keysResult = "keys";
    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
    JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
    JSHandle<JSTaggedValue> constructor = env->GetBuiltinsMapFunction();
    JSHandle<JSMap> jsMap =
        JSHandle<JSMap>::Cast(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(constructor), constructor));
    JSHandle<LinkedHashMap> hashMap = LinkedHashMap::Create(thread);
    jsMap->SetLinkedMap(thread, hashMap);
    JSHandle<JSTaggedValue> mapTag = JSHandle<JSTaggedValue>::Cast(jsMap);
    JSHandle<JSTaggedValue> jsMapIteratorTag =
        JSMapIterator::CreateMapIterator(thread, mapTag, IterationKind::KEY_AND_VALUE);
    JSHandle<JSMapIterator> jsMapIterator(jsMapIteratorTag);
    EXPECT_EQ(JSTaggedValue::SameValue(thread, jsMapIterator->GetIteratedMap(thread), jsMap->GetLinkedMap(thread)),
              true);
    Local<MapIteratorRef> mapIterator = JSNApiHelper::ToLocal<MapIteratorRef>(jsMapIteratorTag);
    Local<JSValueRef> res = mapIterator->GetKind(vm_);
    EXPECT_EQ(expectedResult, res->ToString(vm_)->ToString(vm_));
    EXPECT_TRUE(mapIterator->IsMapIterator(vm_));
    JSHandle<JSTaggedValue> jsMapIteratorTag1 = JSMapIterator::CreateMapIterator(thread, mapTag, IterationKind::KEY);
    Local<MapIteratorRef> mapIterator1 = JSNApiHelper::ToLocal<MapIteratorRef>(jsMapIteratorTag1);
    Local<JSValueRef> res1 = mapIterator1->GetKind(vm_);
    EXPECT_EQ(keysResult, res1->ToString(vm_)->ToString(vm_));
    JSHandle<JSTaggedValue> jsMapIteratorTag2 = JSMapIterator::CreateMapIterator(thread, mapTag, IterationKind::VALUE);
    Local<MapIteratorRef> mapIterator2 = JSNApiHelper::ToLocal<MapIteratorRef>(jsMapIteratorTag2);
    Local<JSValueRef> res2 = mapIterator2->GetKind(vm_);
    EXPECT_EQ(valuesResult, res2->ToString(vm_)->ToString(vm_));
}

/**
 * @tc.number: ffi_interface_api_061
 * @tc.name: GetKind_001
 * @tc.desc:This test case is mainly used to verify whether the GetKind method of the JSMapIterator object can
 * correctly return the expected type (in this example, the expected type is "keys").
 * @tc.type: FUNC
 * @tc.require:  parameter
 */
HWTEST_F_L0(JSNApiTests, GetKind_001)
{
    ecmascript::ThreadManagedScope managedScope(vm_->GetJSThread());
    LocalScope scope(vm_);
    JSThread *thread = vm_->GetJSThread();
    std::string keysResult = "keys";
    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
    JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
    JSHandle<JSTaggedValue> constructor = env->GetBuiltinsMapFunction();
    JSHandle<JSMap> jsMap =
        JSHandle<JSMap>::Cast(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(constructor), constructor));
    JSHandle<LinkedHashMap> hashMap = LinkedHashMap::Create(thread);
    jsMap->SetLinkedMap(thread, hashMap);
    JSHandle<JSTaggedValue> mapTag = JSHandle<JSTaggedValue>::Cast(jsMap);
    JSHandle<JSTaggedValue> jsMapIteratorTag1 = JSMapIterator::CreateMapIterator(thread, mapTag, IterationKind::KEY);
    JSHandle<JSMapIterator> jsMapIterator1(jsMapIteratorTag1);
    EXPECT_EQ(JSTaggedValue::SameValue(thread, jsMapIterator1->GetIteratedMap(thread), jsMap->GetLinkedMap(thread)),
              true);
    Local<MapIteratorRef> mapIterator1 = JSNApiHelper::ToLocal<MapIteratorRef>(jsMapIteratorTag1);
    Local<JSValueRef> res1 = mapIterator1->GetKind(vm_);
    EXPECT_EQ(keysResult, res1->ToString(vm_)->ToString(vm_));
}

/**
 * @tc.number: ffi_interface_api_062
 * @tc.name: GetKind_002
 * @tc.desc:This test case is mainly used to verify whether the GetKind method of the JSMapIterator object can
 * correctly return the expected type (in this example, the expected type is "values").
 * @tc.type: FUNC
 * @tc.require:  parameter
 */
HWTEST_F_L0(JSNApiTests, GetKind_002)
{
    ecmascript::ThreadManagedScope managedScope(vm_->GetJSThread());
    LocalScope scope(vm_);
    JSThread *thread = vm_->GetJSThread();
    std::string valuesResult = "values";
    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
    JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
    JSHandle<JSTaggedValue> constructor = env->GetBuiltinsMapFunction();
    JSHandle<JSMap> jsMap =
        JSHandle<JSMap>::Cast(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(constructor), constructor));
    JSHandle<LinkedHashMap> hashMap = LinkedHashMap::Create(thread);
    jsMap->SetLinkedMap(thread, hashMap);
    JSHandle<JSTaggedValue> mapTag = JSHandle<JSTaggedValue>::Cast(jsMap);
    JSHandle<JSTaggedValue> jsMapIteratorTag2 = JSMapIterator::CreateMapIterator(thread, mapTag, IterationKind::VALUE);
    JSHandle<JSMapIterator> jsMapIterator2(jsMapIteratorTag2);
    EXPECT_EQ(JSTaggedValue::SameValue(thread, jsMapIterator2->GetIteratedMap(thread), jsMap->GetLinkedMap(thread)),
              true);
    Local<MapIteratorRef> mapIterator2 = JSNApiHelper::ToLocal<MapIteratorRef>(jsMapIteratorTag2);
    Local<JSValueRef> res2 = mapIterator2->GetKind(vm_);
    EXPECT_EQ(valuesResult, res2->ToString(vm_)->ToString(vm_));
}

/**
 * @tc.number: ffi_interface_api_063
 * @tc.name: GetKind_003
 * @tc.desc:Calling the GetKind method to obtain the iteration type KEY_AND_VALUE Compare with the string
 * variable 'entries' to assert whether the expected result is the same as the actual result
 * @tc.type: FUNC
 * @tc.require:  parameter
 */
HWTEST_F_L0(JSNApiTests, GetKind_003)
{
    ecmascript::ThreadManagedScope managedScope(vm_->GetJSThread());
    LocalScope scope(vm_);
    JSThread *thread = vm_->GetJSThread();
    std::string expectedResult = "entries";
    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
    JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
    // 从全局环境(GlobalEnv)中获取内置的Map构造函数
    JSHandle<JSTaggedValue> constructor = env->GetBuiltinsMapFunction();
    // 使用构造函数创建一个新的JSMap对象
    JSHandle<JSMap> jsMap =
        JSHandle<JSMap>::Cast(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(constructor), constructor));
    JSHandle<LinkedHashMap> hashMap = LinkedHashMap::Create(thread);
    // 将创建的LinkedHashMap设置为JSMap的内部数据结构
    jsMap->SetLinkedMap(thread, hashMap);
    // 将jsMap转换为JSTaggedValue的句柄
    JSHandle<JSTaggedValue> mapTag = JSHandle<JSTaggedValue>::Cast(jsMap);
    // 创建一个新的JSMapIterator对象,并将其迭代方式设置为KEY_AND_VALUE
    JSHandle<JSTaggedValue> jsMapIteratorTag =
        JSMapIterator::CreateMapIterator(thread, mapTag, IterationKind::KEY_AND_VALUE);
    JSHandle<JSMapIterator> jsMapIterator(jsMapIteratorTag);
    EXPECT_EQ(JSTaggedValue::SameValue(thread, jsMapIterator->GetIteratedMap(thread), jsMap->GetLinkedMap(thread)),
              true);
    // 将jsMapIteratorTag转换为本地代码可以使用的MapIteratorRef类型
    Local<MapIteratorRef> mapIterator = JSNApiHelper::ToLocal<MapIteratorRef>(jsMapIteratorTag);
    Local<JSValueRef> res = mapIterator->GetKind(vm_);
    EXPECT_EQ(expectedResult, res->ToString(vm_)->ToString(vm_));
    EXPECT_TRUE(mapIterator->IsMapIterator(vm_));
}

/*
 * @tc.number: ffi_interface_api_064
 * @tc.name: GetProperty_IsFunction
 * @tc.desc: Verify if the GetProperty function of the JavaScript virtual machine correctly returns a
 * function as the property of the 'Number' key.
 * @tc.type: FUNC
 * @tc.require:  parameter
 */
HWTEST_F_L0(JSNApiTests, GetProperty_IsFunction)
{
    LocalScope scope(vm_);
    Local<ObjectRef> globalObject = JSNApi::GetGlobalObject(vm_);
    ASSERT_FALSE(globalObject.IsEmpty());
    ASSERT_TRUE(globalObject->IsObject(vm_));

    Local<ObjectRef> key = StringRef::NewFromUtf8(vm_, "Number");
    Local<ObjectRef> property = globalObject->Get(vm_, key);
    ASSERT_TRUE(property->IsFunction(vm_));
}

/**
 * @tc.number: ffi_interface_api_065
 * @tc.name: NewClassFunction
 * @tc.desc:Check if the function created through the NewClassFunction method meets the specifications of the class
 * constructor, and obtain and verify the properties of the function.
 * @tc.type: FUNC
 * @tc.require:  parameter
 */
HWTEST_F_L0(JSNApiTests, NewClassFunction)
{
    LocalScope scope(vm_);
    Local<FunctionRef> cls = FunctionRef::NewClassFunction(vm_, FunctionCallback, nullptr, nullptr);

    JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(Local<JSValueRef>(cls));
    // 断言obj是一个类构造函数
    ASSERT_TRUE(obj->IsClassConstructor());
    // GetPropertyInlinedProps方法获取内联属性的方法,CLASS_PROTOTYPE_INLINE_PROPERTY_INDEX类原型的内联属性索引
    JSTaggedValue res =
        JSHandle<JSFunction>(obj)->GetPropertyInlinedProps(thread_, JSFunction::CLASS_PROTOTYPE_INLINE_PROPERTY_INDEX);
    // 断言获取的属性是一个内部访问器
    ASSERT_TRUE(res.IsInternalAccessor());
}

/**
 * @tc.number: ffi_interface_api_066
 * @tc.name: PromiseRef_Finally_IsPromise
 * @tc.desc:FunctionRef:: New Create a reject callback function reject. The function of the code is to test the
 * behavior of the Finally and Then methods of the Promise object
 * in various situations, ensuring that they all return Promise objects and meet the expected behavior.
 * @tc.type: FUNC
 * @tc.require:  parameter
 */
HWTEST_F_L0(JSNApiTests, PromiseRef_Finally_IsPromise)
{
    LocalScope scope(vm_);
    Local<PromiseCapabilityRef> capability = PromiseCapabilityRef::New(vm_);

    Local<PromiseRef> gitpromise = capability->GetPromise(vm_);
    Local<FunctionRef> rejectcallback = FunctionRef::New(vm_, RejectCallback);
    Local<PromiseRef> catchPromise = gitpromise->Finally(vm_, rejectcallback);
    ASSERT_TRUE(gitpromise->IsPromise(vm_));
    ASSERT_TRUE(catchPromise->IsPromise(vm_));
    Local<PromiseRef> catchPromise2 = gitpromise->Then(vm_, rejectcallback, rejectcallback);
    ASSERT_TRUE(catchPromise2->IsPromise(vm_));
    Local<FunctionRef> functioncallback = FunctionRef::New(vm_, FunctionCallback);
    ASSERT_TRUE(!functioncallback.IsEmpty());
    Local<PromiseRef> catchPromise3 = gitpromise->Then(vm_, functioncallback);
    ASSERT_TRUE(catchPromise3->IsPromise(vm_));
}

/**
 * @tc.number: ffi_interface_api_067
 * @tc.name: IsBuffer
 * @tc.desc: Construct a BufferRef function to determine whether it is a Buffer
 * @tc.type: FUNC
 * @tc.require:  parameter
 */
HWTEST_F_L0(JSNApiTests, IsBuffer)
{
    LocalScope scope(vm_);
    const int32_t length = 15;
    Local<BufferRef> buffer = BufferRef::New(vm_, length);
    ASSERT_TRUE(buffer->IsBuffer(vm_));
}

/**
 * @tc.number: ffi_interface_api_068
 * @tc.name: IsDataView
 * @tc.desc: Construct a BufferRef function to determine whether it is a dataView
 * @tc.type: FUNC
 * @tc.require:  parameter
 */
HWTEST_F_L0(JSNApiTests, IsDataView)
{
    LocalScope scope(vm_);
    const int32_t length = 15;
    Local<ArrayBufferRef> arrayBuffer = ArrayBufferRef::New(vm_, length);
    Local<DataViewRef> dataView = DataViewRef::New(vm_, arrayBuffer, 5, 7);
    ASSERT_TRUE(dataView->IsDataView(vm_));
}

/**
 * @tc.number: ffi_interface_api_071
 * @tc.name: IsSharedArrayBuffer
 * @tc.desc: Construct a BufferRef function to determine whether it is a SharedArrayBuffer
 * @tc.type: FUNC
 * @tc.require:  parameter
 */
HWTEST_F_L0(JSNApiTests, IsSharedArrayBuffer)
{
    LocalScope scope(vm_);
    const int32_t length = 15;
    Local<JSValueRef> sharedArrayBuffer = ArrayBufferRef::New(vm_, length);
    ASSERT_FALSE(sharedArrayBuffer->IsSharedArrayBuffer(vm_));
}


/**
 * @tc.number: ffi_interface_api_072
 * @tc.name: IsTrue
 * @tc.desc: Construct a BufferRef function to determine whether it is a IsTrue
 * @tc.type: FUNC
 * @tc.require:  parameter
 */
HWTEST_F_L0(JSNApiTests, IsTrue)
{
    LocalScope scope(vm_);
    Local<JSValueRef> b = JSValueRef::True(vm_);
    ASSERT_TRUE(b->IsTrue());
}


/**
 * @tc.number: ffi_interface_api_073
 * @tc.name: IsFalse
 * @tc.desc: Construct a BufferRef function to determine whether it is a IsFalse
 * @tc.type: FUNC
 * @tc.require:  parameter
 */
HWTEST_F_L0(JSNApiTests, IsFalse)
{
    LocalScope scope(vm_);
    Local<JSValueRef> c = JSValueRef::False(vm_);
    ASSERT_TRUE(c->IsFalse());
}

/**
 * @tc.number: ffi_interface_api_074
 * @tc.name: IsConstructor
 * @tc.desc: Construct a BufferRef function to determine whether it is a Constructor
 * @tc.require:  parameter
 */
HWTEST_F_L0(JSNApiTests, IsConstructor)
{
    LocalScope scope(vm_);
    Local<FunctionRef> target = FunctionRef::New(vm_, FunctionCallback);
    ASSERT_FALSE(target->IsConstructor(vm_));
}


/**
 * @tc.number: ffi_interface_api_076
 * @tc.name: GetOwnProperty
 * @tc.desc: Construct a BufferRef function to determine whether it is a GetOwnProperty  not Construct function
 * @tc.type: FUNC
 * @tc.require:  parameter
 */
HWTEST_F_L0(JSNApiTests, GetOwnProperty)
{
    LocalScope scope(vm_);
    Local<ObjectRef> object = ObjectRef::New(vm_);
    Local<JSValueRef> key = StringRef::NewFromUtf8(vm_, TEST_KEY);
    Local<JSValueRef> value = ObjectRef::New(vm_);
    PropertyAttribute attribute(value, true, true, true);

    ASSERT_TRUE(object->DefineProperty(vm_, key, attribute));
    Local<JSValueRef> value1 = object->Get(vm_, key);
    ASSERT_TRUE(value->IsStrictEquals(vm_, value1));
}

/**
 * @tc.number: ffi_interface_api_078
 * @tc.name: IsTreeMap
 * @tc.desc: Used to verify whether the given object is a TreeMap.
 * @tc.type: FUNC
 * @tc.require:  parameter
 */
HWTEST_F_L0(JSNApiTests, JSValueRef_IsTreeMap)
{
    LocalScope scope(vm_);
    JSThread *thread = vm_->GetJSThread();
    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
    auto globalEnv = thread->GetEcmaVM()->GetGlobalEnv();
    JSHandle<JSTaggedValue> proto = globalEnv->GetObjectFunctionPrototype();
    JSHandle<JSHClass> mapClass = factory->NewEcmaHClass(JSAPITreeMap::SIZE, JSType::JS_API_TREE_MAP, proto);
    JSHandle<JSAPITreeMap> jsTreeMap = JSHandle<JSAPITreeMap>::Cast(factory->NewJSObjectWithInit(mapClass));
    JSHandle<TaggedTreeMap> treeMap(thread, TaggedTreeMap::Create(thread));
    jsTreeMap->SetTreeMap(thread, treeMap);
    JSHandle<JSTaggedValue> argumentTag = JSHandle<JSTaggedValue>::Cast(jsTreeMap);
    Local<JSValueRef> TreeMap = JSNApiHelper::ToLocal<JSAPITreeSet>(argumentTag);
    EXPECT_TRUE(TreeMap->IsTreeMap(vm_));
}

/**
 * @tc.number: ffi_interface_api_079
 * @tc.name: IsTreeSet
 * @tc.desc: Used to verify whether the given object is a TreeSet.
 * @tc.type: FUNC
 * @tc.require:  parameter
 */
HWTEST_F_L0(JSNApiTests, JSValueRef_IsTreeSet)
{
    LocalScope scope(vm_);
    JSThread *thread = vm_->GetJSThread();
    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
    auto globalEnv = thread->GetEcmaVM()->GetGlobalEnv();
    JSHandle<JSTaggedValue> proto = globalEnv->GetObjectFunctionPrototype();
    JSHandle<JSHClass> setClass = factory->NewEcmaHClass(JSAPITreeSet::SIZE, JSType::JS_API_TREE_SET, proto);
    JSHandle<JSAPITreeSet> jsTreeSet = JSHandle<JSAPITreeSet>::Cast(factory->NewJSObjectWithInit(setClass));
    JSHandle<TaggedTreeSet> treeSet(thread, TaggedTreeSet::Create(thread));
    jsTreeSet->SetTreeSet(thread, treeSet);
    JSHandle<JSTaggedValue> argumentTag = JSHandle<JSTaggedValue>::Cast(jsTreeSet);
    Local<JSValueRef> TreeSet = JSNApiHelper::ToLocal<JSAPITreeSet>(argumentTag);
    EXPECT_TRUE(TreeSet->IsTreeSet(vm_));
}

/**
 * @tc.number: ffi_interface_api_080
 * @tc.name: IsVector
 * @tc.desc: Used to verify whether the given object is a Vector.
 * @tc.type: FUNC
 * @tc.require:  parameter
 */
HWTEST_F_L0(JSNApiTests, JSValueRef_IsVector)
{
    LocalScope scope(vm_);
    JSThread *thread = vm_->GetJSThread();
    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
    auto globalEnv = thread->GetEcmaVM()->GetGlobalEnv();
    JSHandle<JSTaggedValue> proto = globalEnv->GetObjectFunctionPrototype();
    JSHandle<JSHClass> vectorClass = factory->NewEcmaHClass(JSAPIVector::SIZE, JSType::JS_API_VECTOR, proto);
    JSHandle<JSAPIVector> jsVector = JSHandle<JSAPIVector>::Cast(factory->NewJSObjectWithInit(vectorClass));
    jsVector->SetLength(0);
    JSHandle<JSTaggedValue> argumentTag = JSHandle<JSTaggedValue>::Cast(jsVector);
    Local<JSValueRef> Vector = JSNApiHelper::ToLocal<JSAPIVector>(argumentTag);
    EXPECT_TRUE(Vector->IsVector(vm_));
}

/**
 * @tc.number: ffi_interface_api_081
 * @tc.name: IsJSArray
 * @tc.desc: Used to verify whether the given object is a JSArray.
 * @tc.type: FUNC
 * @tc.require:  parameter
 */
HWTEST_F_L0(JSNApiTests, JSValueRef_IsJSArray)
{
    LocalScope scope(vm_);
    JSHandle<JSTaggedValue> jsArrayTag = JSArray::ArrayCreate(vm_->GetJSThread(), JSTaggedNumber(0));
    Local<JSValueRef> jsArray = JSNApiHelper::ToLocal<JSTypedArray>(jsArrayTag);
    EXPECT_TRUE(jsArray->IsJSArray(vm_));
    Local<JSValueRef> array = JSNApiHelper::ToLocal<ArrayRef>(jsArrayTag);
    EXPECT_TRUE(array->IsArray(vm_));
}

/**
 * @tc.number: ffi_interface_api_082
 * @tc.name: IsMap
 * @tc.desc: Used to verify whether the given object is a map container.
 * @tc.type: FUNC
 * @tc.require:  parameter
 */
HWTEST_F_L0(JSNApiTests, JSValueRef_IsMap)
{
    LocalScope scope(vm_);
    Local<MapRef> map = MapRef::New(vm_);
    EXPECT_TRUE(map->IsMap(vm_));
}

/**
 * @tc.number: ffi_interface_api_083
 * @tc.name: IsSet
 * @tc.desc: Used to verify whether the given object is a Set container.
 * @tc.type: FUNC
 * @tc.require:  parameter
 */
HWTEST_F_L0(JSNApiTests, SetRef_IsSet)
{
    LocalScope scope(vm_);
    JSThread *thread = vm_->GetJSThread();
    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
    JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
    JSHandle<JSTaggedValue> constructor = env->GetBuiltinsSetFunction();
    JSHandle<JSSet> set =
        JSHandle<JSSet>::Cast(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(constructor), constructor));
    JSHandle<LinkedHashSet> hashSet = LinkedHashSet::Create(thread);
    set->SetLinkedSet(thread, hashSet);
    JSHandle<JSTaggedValue> setTag = JSHandle<JSTaggedValue>::Cast(set);
    Local<SetRef> Set = JSNApiHelper::ToLocal<SetRef>(setTag);
    EXPECT_TRUE(Set->IsSet(vm_));
}

/**
 * @tc.number: ffi_interface_api_084
 * @tc.name: ObjectRef_NEW
 * @tc.desc: Creating a new Object Ref object is not NULL if successfully created.
 * @tc.type: FUNC
 * @tc.require:  parameter
 */
HWTEST_F_L0(JSNApiTests, ObjectRef_NEW)
{
    LocalScope scope(vm_);
    Local<ObjectRef> object = ObjectRef::New(vm_);
    ASSERT_FALSE(object.IsNull());
}

/**
 * @tc.number: ffi_interface_api_085
 * @tc.name: IsFalse
 * @tc.desc: Used to verify whether the given object is false.
 * @tc.type: FUNC
 * @tc.require:  parameter
 */
HWTEST_F_L0(JSNApiTests, JSNAPI_IsFalse)
{
    LocalScope scope(vm_);
    Local<PrimitiveRef> res = JSValueRef::False(vm_);
    EXPECT_TRUE(res->IsFalse());
}

/**
 * @tc.number: ffi_interface_api_086
 * @tc.name: GetDescription
 * @tc.desc: Used to verify whether the object used to obtain descriptive information was successful.
 * @tc.type: FUNC
 * @tc.require:  parameter
 */
HWTEST_F_L0(JSNApiTests, SymbolRef_GetDescription)
{
    LocalScope scope(vm_);
    Local<StringRef> description = StringRef::NewFromUtf8(vm_, "test");
    Local<SymbolRef> symbol = SymbolRef::New(vm_, description);
    Local<StringRef> desc = symbol->GetDescription(vm_);
    EXPECT_EQ(description->ToString(vm_), desc->ToString(vm_));
    EXPECT_FALSE(symbol.IsNull());
    EXPECT_FALSE(description.IsEmpty());
}

/**
 * @tc.number: ffi_interface_api_087
 * @tc.name: ArrayRefNew_uint32Length_SetValueAt_GetValueAt
 * @tc.desc: Used to verify whether obtaining the length of the array, setting the value of the specified
 * index position of the array, and obtaining the value of the specified index position of the
 * array were successful
 * @tc.type: FUNC
 * @tc.require:  parameter
 */
HWTEST_F_L0(JSNApiTests, ArrayRefNew_uint32Length_SetValueAt_GetValueAt)
{
    LocalScope scope(vm_);
    Local<ObjectRef> globalObject = JSNApi::GetGlobalObject(vm_);
    ASSERT_FALSE(globalObject.IsEmpty());
    ASSERT_TRUE(globalObject->IsObject(vm_));
    Local<ArrayRef> property = ArrayRef::New(vm_, 3); // 3 : length
    ASSERT_TRUE(property->IsArray(vm_));
    ASSERT_EQ(property->Length(vm_), 3); // 3 : test case of input
    uint32_t index = 1;
    Local<JSValueRef> value = ObjectRef::New(vm_);
    bool result = property->SetValueAt(vm_, globalObject, index, value);
    ASSERT_TRUE(result);
    Local<JSValueRef> value1 = property->GetValueAt(vm_, globalObject, index);
    ASSERT_FALSE(value1.IsNull());
}

/**
 * @tc.number: ffi_interface_api_088
 * @tc.name: WeakSetRef_GetSize_GetTotalElements_GetValue
 * @tc.desc: Used to verify whether the size of the weakset for obtaining settings, the total number of
 * elements obtained, and the value of the specified index position obtained were successful
 * @tc.type: FUNC
 * @tc.require:  parameter
 */
HWTEST_F_L0(JSNApiTests, WeakSetRef_GetSize_GetTotalElements_GetValue)
{
    LocalScope scope(vm_);
    JSThread *thread = vm_->GetJSThread();
    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
    JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
    JSHandle<JSTaggedValue> constructor = env->GetBuiltinsWeakSetFunction();
    JSHandle<JSWeakSet> weakSet =
        JSHandle<JSWeakSet>::Cast(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(constructor), constructor));
    JSHandle<LinkedHashSet> hashSet = LinkedHashSet::Create(thread);
    weakSet->SetLinkedSet(thread, hashSet);
    JSHandle<JSTaggedValue> weakSetTag = JSHandle<JSTaggedValue>::Cast(weakSet);
    Local<JSValueRef> set1 = JSNApiHelper::ToLocal<WeakSetRef>(weakSetTag);
    EXPECT_TRUE(set1->IsWeakSet(vm_));
    Local<WeakSetRef> set = JSNApiHelper::ToLocal<WeakSetRef>(weakSetTag);
    JSHandle<JSTaggedValue> value(factory->NewFromASCII("value"));
    JSWeakSet::Add(thread, weakSet, value);
    int32_t num = set->GetSize(vm_);
    int32_t num1 = set->GetTotalElements(vm_);
    ASSERT_EQ(num, 1);
    ASSERT_EQ(num1, 1);
    Local<JSValueRef> res2 = set->GetValue(vm_, 0);
    ASSERT_EQ(res2->ToString(vm_)->ToString(vm_), "value");
}

/**
 * @tc.number: ffi_interface_api_089
 * @tc.name: GetOwnPropertyNames
 * @tc.desc: An array of self owned property names used to validate the acquisition of objects.
 * @tc.type: FUNC
 * @tc.require:  parameter
 */
HWTEST_F_L0(JSNApiTests, ObjectRef_GetOwnPropertyNames)
{
    LocalScope scope(vm_);
    Local<ObjectRef> object = ObjectRef::New(vm_);
    Local<ArrayRef> res = object->GetOwnPropertyNames(vm_);
    EXPECT_TRUE(res->IsArray(vm_));
}

/**
 * @tc.number: ffi_interface_api_090
 * @tc.name: SetBundle
 * @tc.desc: Used to verify whether the initialization resource package was successfully set.
 * @tc.type: FUNC
 * @tc.require:  parameter
 */
HWTEST_F_L0(JSNApiTests, SetBundle)
{
    LocalScope scope(vm_);
    bool value = true;
    JSNApi::SetBundle(vm_, value);
    bool res = JSNApi::IsBundle(vm_);
    EXPECT_TRUE(res);
}

/**
 * @tc.number: ffi_interface_api_091
 * @tc.name: SetMockModuleList
 * @tc.desc: Used to verify whether the function of setting the map container module was successful.
 * @tc.type: FUNC
 * @tc.require:  parameter
 */
HWTEST_F_L0(JSNApiTests, JSNApi_SetMockModuleList)
{
    LocalScope scope(vm_);
    std::map<std::string, std::string> str = { { TEST_NUM1, TEST_NUM2 } };
    JSNApi::SetMockModuleList(vm_, str);
    ASSERT_EQ(std::string(vm_->GetMockModule(TEST_NUM1)), TEST_NUM2);
}

/**
 * @tc.number: ffi_interface_api_092
 * @tc.name: SetSourceMapTranslateCallback
 * @tc.desc: Whether the source mapping translation callback function used to verify the settings.
 * was successfully set
 * @tc.type: FUNC
 * @tc.require:  parameter
 */
HWTEST_F_L0(JSNApiTests, JSNAPI_SetSourceMapTranslateCallback)
{
    LocalScope scope(vm_);
    SourceMapTranslateCallback tag { nullptr };
    JSNApi::SetSourceMapTranslateCallback(vm_, tag);
    SourceMapTranslateCallback cur = vm_->GetSourceMapTranslateCallback();
    ASSERT_EQ(nullptr, cur);
}

/**
 * @tc.number: ffi_interface_api_093
 * @tc.name: ExecutePendingJob
 * @tc.desc: Used to verify whether the pending task has been successfully executed.
 * @tc.type: FUNC
 * @tc.require:  parameter
 */
HWTEST_F_L0(JSNApiTests, JSNApi_ExecutePendingJob)
{
    LocalScope scope(vm_);
    JSNApi::ExecutePendingJob(vm_);
    bool res = EcmaVM::ConstCast(vm_)->ExecutePromisePendingJob();
    EXPECT_TRUE(res);
}

/**
 * @tc.number: ffi_interface_api_096
 * @tc.name: IsRegExp
 * @tc.desc: Used to determine whether a given object is a regular expression.
 * @tc.type: FUNC
 * @tc.require:  parameter
 */
HWTEST_F_L0(JSNApiTests, JSValueRef_IsRegExp)
{
    LocalScope scope(vm_);
    JSThread *thread = vm_->GetJSThread();
    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
    auto globalEnv = thread->GetEcmaVM()->GetGlobalEnv();
    JSHandle<JSTaggedValue> proto = globalEnv->GetObjectFunctionPrototype();
    JSHandle<JSHClass> jSRegExpClass = factory->NewEcmaHClass(JSRegExp::SIZE, JSType::JS_REG_EXP, proto);
    JSHandle<JSRegExp> jSRegExp = JSHandle<JSRegExp>::Cast(factory->NewJSObject(jSRegExpClass));
    jSRegExp->SetByteCodeBuffer(thread, JSTaggedValue::Undefined());
    jSRegExp->SetOriginalSource(thread, JSTaggedValue::Undefined());
    jSRegExp->SetGroupName(thread, JSTaggedValue::Undefined());
    jSRegExp->SetOriginalFlags(thread, JSTaggedValue(0));
    jSRegExp->SetLength(0);
    JSHandle<JSTaggedValue> argumentTag = JSHandle<JSTaggedValue>::Cast(jSRegExp);
    Local<JSValueRef> regexp = JSNApiHelper::ToLocal<JSRegExp>(argumentTag);
    EXPECT_TRUE(regexp->IsRegExp(vm_));
}

/**
 * @tc.number: ffi_interface_api_097
 * @tc.name: GetAndClearUncaughtException
 * @tc.desc: Used to verify the success of obtaining and clearing uncaught exceptions
 * @tc.type: FUNC
 * @tc.require:  parameter
 */
HWTEST_F_L0(JSNApiTests, GetAndClearUncaughtException)
{
    LocalScope scope(vm_);
    TryCatch tryCatch(vm_);
    EXPECT_FALSE(tryCatch.HasCaught());
    Local<StringRef> message = StringRef::NewFromUtf8(vm_, "ErrorTest");
    Local<JSValueRef> error = Exception::Error(vm_, message);
    EXPECT_TRUE(error->IsError(vm_));
    JSNApi::ThrowException(vm_, error);
    EXPECT_TRUE(vm_->GetJSThread()->HasPendingException());
    JSNApi::GetAndClearUncaughtException(vm_);
    EXPECT_FALSE(vm_->GetJSThread()->HasPendingException());
}

/**
 * @tc.number: ffi_interface_api_098
 * @tc.name: IsJSPrimitiveNumber
 * @tc.desc: Verify if the given JSValueRef object is a primativenumber.
 * @tc.type: FUNC
 * @tc.require:  parameter
 */
HWTEST_F_L0(JSNApiTests, JSValueRef_IsJSPrimitiveNumber)
{
    LocalScope scope(vm_);
    ObjectFactory *factory = vm_->GetFactory();
    JSHandle<JSTaggedValue> jstagvalue;
    JSHandle<JSPrimitiveRef> jsprimitive = factory->NewJSPrimitiveRef(PrimitiveType::PRIMITIVE_NUMBER, jstagvalue);
    JSHandle<JSTaggedValue> jspri = JSHandle<JSTaggedValue>::Cast(jsprimitive);
    Local<JSValueRef> object = JSNApiHelper::ToLocal<JSValueRef>(jspri);
    EXPECT_FALSE(object->IsJSPrimitiveNumber(vm_));
}


/**
 * @tc.number: ffi_interface_api_099
 * @tc.name: StringUtf16_NewFromUtf16_Length_WriteUtf16_01
 * @tc.desc:
 * NewFromUtf16:Create StringRef in UTF8 format
 * WriteUtf16:Write the value of StringRef to char16_ T array buffer, testing Chinese
 * @tc.type: FUNC
 * @tc.require:  parameter
 */
HWTEST_F_L0(JSNApiTests, StringUtf16_NewFromUtf16_Length_WriteUtf16_01)
{
    LocalScope scope(vm_);
    const char16_t *test = u"年度";
    Local<StringRef> testString = StringRef::NewFromUtf16(vm_, test);
    EXPECT_EQ(testString->Length(vm_), 2);              // 2 : length of testString("年度")
    char16_t buffer[3];                              // 3 : length of testString + 1
    EXPECT_EQ(testString->WriteUtf16(vm_, buffer, 2), 2); // 2 : length of testString("年度")
    GTEST_LOG_(WARNING) << "年度test =" << buffer;
    ASSERT_EQ(buffer[0], u'年');
    ASSERT_EQ(buffer[1], u'度');
}

/**
 * @tc.number: ffi_interface_api_100
 * @tc.name: StringUtf16_NewFromUtf16_Length_WriteUtf16_01
 * @tc.desc: Write the value of StringRef to char16_ T array buffer, testing non Chinese
 * @tc.type: FUNC
 * @tc.require:  parameter
 */
HWTEST_F_L0(JSNApiTests, StringUtf16_NewFromUtf16_Length_WriteUtf16_02)
{
    LocalScope scope(vm_);
    const char16_t *test = u"hello world!0?";
    Local<StringRef> testString = StringRef::NewFromUtf16(vm_, test);

    EXPECT_EQ(testString->Length(vm_), 14);
    char16_t buffer[15];                               // 15 : length of testString + 1
    EXPECT_EQ(testString->WriteUtf16(vm_, buffer, 14), 14); // 14 : length of testString("hello world!!!")
    ASSERT_EQ(buffer[0], u'h');
    ASSERT_EQ(buffer[13], u'?');
}

/**
 * @tc.number: ffi_interface_api_101
 * @tc.name: SetRef_IsSet_GetSize_GetTotalElements_GetValue
 * @tc.desc:
 * IsSet:Determine if it is a set container object
 * GetSize:Get set length size
 * GetTotalElements:Get the total number of set elements
 * GetValue:Obtain the element values of the set container according to the following table
 * @tc.type: FUNC
 * @tc.require:  parameter
 */
HWTEST_F_L0(JSNApiTests, SetRef_IsSet_GetSize_GetTotalElements_GetValue)
{
    LocalScope scope(vm_);
    JSThread *thread = vm_->GetJSThread();
    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
    JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
    JSHandle<JSTaggedValue> constructor = env->GetBuiltinsSetFunction();
    JSHandle<JSSet> jsSet =
        JSHandle<JSSet>::Cast(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(constructor), constructor));
    JSHandle<LinkedHashSet> hashSet = LinkedHashSet::Create(thread);
    jsSet->SetLinkedSet(thread, hashSet);
    JSHandle<JSTaggedValue> setTag = JSHandle<JSTaggedValue>::Cast(jsSet);
    Local<SetRef> set = JSNApiHelper::ToLocal<SetRef>(setTag);
    EXPECT_TRUE(set->IsSet(vm_));
    JSHandle<JSTaggedValue> fristValue(factory->NewFromASCII("vlue1"));
    JSSet::Add(thread, jsSet, fristValue);
    JSSet::Add(thread, jsSet, fristValue);
    int32_t num = set->GetSize(vm_);
    int32_t num1 = set->GetTotalElements(vm_);
    ASSERT_EQ(num, 1);
    ASSERT_EQ(num1, 1);
    JSHandle<JSTaggedValue> secondValue(factory->NewFromASCII("vlue2"));
    JSSet::Add(thread, jsSet, secondValue);
    num = set->GetSize(vm_);
    num1 = set->GetTotalElements(vm_);
    ASSERT_EQ(num, 2);
    ASSERT_EQ(num1, 2);
    Local<JSValueRef> res1 = set->GetValue(vm_, 0);
    ASSERT_EQ(res1->ToString(vm_)->ToString(vm_), "vlue1");
    Local<JSValueRef> res2 = set->GetValue(vm_, 1);
    ASSERT_EQ(res2->ToString(vm_)->ToString(vm_), "vlue2");
}

static JSSet *CreateJSSet(JSThread *thread)
{
    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
    JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
    JSHandle<JSTaggedValue> constructor = env->GetBuiltinsSetFunction();
    JSHandle<JSSet> set =
        JSHandle<JSSet>::Cast(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(constructor), constructor));
    JSHandle<LinkedHashSet> hashSet = LinkedHashSet::Create(thread);
    set->SetLinkedSet(thread, hashSet);
    return JSSet::Cast(set.GetTaggedValue().GetTaggedObject());
}

/**
 * @tc.number: ffi_interface_api_102
 * @tc.name: JSSetIterator_IsSetIterator_GetIndex_GetKind
 * @tc.desc:
 * IsSetIterator:Determine if it is a set iterator
 * GetIndex:Gets the index of the subscript position currently pointed to by the set iterator
 * GetKind:Obtain the index type 'key/value/key_and_value' for the set iterator
 * @tc.type: FUNC
 * @tc.require:  parameter
 */
HWTEST_F_L0(JSNApiTests, JSSetIterator_IsSetIterator_GetIndex_GetKind)
{
    LocalScope scope(vm_);
    JSThread *thread = vm_->GetJSThread();
    JSHandle<JSSet> jsSet(thread, CreateJSSet(thread));
    EXPECT_TRUE(*jsSet != nullptr);
    JSHandle<JSTaggedValue> jsTagSetIterator =
        JSSetIterator::CreateSetIterator(thread, JSHandle<JSTaggedValue>(jsSet), IterationKind::KEY);
    JSHandle<JSSetIterator> jsSetIterator1(jsTagSetIterator);
    EXPECT_EQ(JSTaggedValue::SameValue(thread, jsSetIterator1->GetIteratedSet(thread), jsSet->GetLinkedSet(thread)),
              true);
    Local<SetIteratorRef> setIterator = JSNApiHelper::ToLocal<SetIteratorRef>(jsTagSetIterator);
    EXPECT_TRUE(setIterator->IsSetIterator(vm_));
    EXPECT_EQ(setIterator->GetIndex(), 0U);
    Local<JSValueRef> resultKey = StringRef::NewFromUtf8(vm_, "keys");
    EXPECT_EQ(setIterator->GetKind(vm_)->ToString(vm_)->ToString(vm_), resultKey->ToString(vm_)->ToString(vm_));
}

/**
 * @tc.number: ffi_interface_api_103
 * @tc.name: JSValueRef_IsMapIterator
 * @tc.desc: Determine if it is a Map iterator
 * @tc.type: FUNC
 * @tc.require:  parameter
 */
HWTEST_F_L0(JSNApiTests, JSValueRef_IsMapIterator)
{
    LocalScope scope(vm_);
    JSThread *thread = vm_->GetJSThread();
    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
    JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
    JSHandle<JSTaggedValue> constructor = env->GetBuiltinsMapFunction();
    JSHandle<JSMap> jsMap =
        JSHandle<JSMap>::Cast(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(constructor), constructor));
    JSHandle<LinkedHashMap> hashMap = LinkedHashMap::Create(thread);
    jsMap->SetLinkedMap(thread, hashMap);
    JSHandle<JSTaggedValue> mapTag = JSHandle<JSTaggedValue>::Cast(jsMap);
    JSHandle<JSTaggedValue> jsMapIteratorTag =
        JSMapIterator::CreateMapIterator(thread, mapTag, IterationKind::KEY_AND_VALUE);
    JSHandle<JSMapIterator> jsMapIterator(jsMapIteratorTag);
    EXPECT_EQ(JSTaggedValue::SameValue(thread, jsMapIterator->GetIteratedMap(thread), jsMap->GetLinkedMap(thread)),
              true);
    Local<JSValueRef> mapIterator = JSNApiHelper::ToLocal<MapIteratorRef>(jsMapIteratorTag);
    EXPECT_TRUE(mapIterator->IsMapIterator(vm_));
}

/**
 * @tc.number: ffi_interface_api_104
 * @tc.name: JSValueRef_IsModuleNamespaceObject
 * @tc.desc: Determine if it is a module space object
 * @tc.type: FUNC
 * @tc.require:  parameter
 */
HWTEST_F_L0(JSNApiTests, JSValueRef_IsModuleNamespaceObject)
{
    LocalScope scope(vm_);
    ObjectFactory *objectFactory = thread_->GetEcmaVM()->GetFactory();
    JSHandle<SourceTextModule> module = objectFactory->NewSourceTextModule();
    JSHandle<LocalExportEntry> localExportEntry1 = objectFactory->NewLocalExportEntry();
    SourceTextModule::AddLocalExportEntry(thread_, module, localExportEntry1, 0, 2);
    JSHandle<LocalExportEntry> localExportEntry2 = objectFactory->NewLocalExportEntry();
    SourceTextModule::AddLocalExportEntry(thread_, module, localExportEntry2, 1, 2);
    JSHandle<TaggedArray> localExportEntries(thread_, module->GetLocalExportEntries(thread_));
    CString baseFileName = "a.abc";
    module->SetEcmaModuleFilenameString(baseFileName);
    ModuleManager *moduleManager = thread_->GetModuleManager();
    moduleManager->AddResolveImportedModule(baseFileName, module.GetTaggedValue());
    JSHandle<ModuleNamespace> np =
        ModuleNamespace::ModuleNamespaceCreate(thread_, JSHandle<JSTaggedValue>::Cast(module), localExportEntries);
    EXPECT_TRUE(ModuleNamespace::PreventExtensions());
    JSHandle<JSTaggedValue> moduleNamespaceTag = JSHandle<JSTaggedValue>::Cast(np);
    Local<JSValueRef> moduleNamespace = JSNApiHelper::ToLocal<ModuleNamespace>(moduleNamespaceTag);
    ASSERT_TRUE(moduleNamespace->IsModuleNamespaceObject(vm_));
}


/**
 * @tc.number: ffi_interface_api_105
 * @tc.name: IsHole
 * @tc.desc: Determine if it is a hole
 * @tc.type: FUNC
 * @tc.require:  parameter
 */
HWTEST_F_L0(JSNApiTests, IsHole)
{
    LocalScope scope(vm_);
    Local<JSValueRef> b = JSValueRef::Hole(vm_);
    ASSERT_TRUE(b->IsHole());
}


/**
 * @tc.number: ffi_interface_api_106
 * @tc.name: GetValueDouble
 * @tc.desc: Get value double from isNumber
 * @tc.type: FUNC
 * @tc.require:  parameter
 */
HWTEST_F_L0(JSNApiTests, GetValueDouble)
{
    LocalScope scope(vm_);
    bool isNumber = true;
    panda::JSValueRef* nativeValue = new JSValueRef();
    ASSERT_FALSE(nativeValue->GetValueDouble(isNumber));
    isNumber = false;
    ASSERT_FALSE(nativeValue->GetValueDouble(isNumber));

    delete nativeValue;
}


/**
 * @tc.number: ffi_interface_api_107
 * @tc.name: GetValueInt32
 * @tc.desc: Get value int32 from isNumber
 * @tc.type: FUNC
 * @tc.require:  parameter
 */
HWTEST_F_L0(JSNApiTests, GetValueInt32)
{
    LocalScope scope(vm_);
    bool isNumber = true;
    panda::JSValueRef* nativeValue = new JSValueRef();
    ASSERT_FALSE(nativeValue->GetValueInt32(isNumber));
    isNumber = false;
    ASSERT_FALSE(nativeValue->GetValueInt32(isNumber));

    delete nativeValue;
}


/**
 * @tc.number: ffi_interface_api_108
 * @tc.name: GetValueUint32
 * @tc.desc: Get value uint32 from isNumber
 * @tc.type: FUNC
 * @tc.require:  parameter
 */
HWTEST_F_L0(JSNApiTests, GetValueUint32)
{
    LocalScope scope(vm_);
    bool isNumber = true;
    panda::JSValueRef* nativeValue = new JSValueRef();
    ASSERT_FALSE(nativeValue->GetValueUint32(isNumber));
    isNumber = false;
    ASSERT_FALSE(nativeValue->GetValueUint32(isNumber));

    delete nativeValue;
}


/**
 * @tc.number: ffi_interface_api_109
 * @tc.name: GetValueInt64
 * @tc.desc: Get value int64 from isNumber
 * @tc.type: FUNC
 * @tc.require:  parameter
 */
HWTEST_F_L0(JSNApiTests, GetValueInt64)
{
    LocalScope scope(vm_);
    bool isNumber = true;
    panda::JSValueRef* nativeValue = new JSValueRef();
    ASSERT_FALSE(nativeValue->GetValueInt64(isNumber));
    isNumber = false;
    ASSERT_FALSE(nativeValue->GetValueInt64(isNumber));

    delete nativeValue;
}


/**
 * @tc.number: ffi_interface_api_110
 * @tc.name: GetValueBool
 * @tc.desc: Get value bool from isNumber
 * @tc.type: FUNC
 * @tc.require:  parameter
 */
HWTEST_F_L0(JSNApiTests, GetValueBool)
{
    LocalScope scope(vm_);
    bool isNumber = true;
    panda::JSValueRef* nativeValue = new JSValueRef();
    ASSERT_FALSE(nativeValue->GetValueBool(isNumber));
    isNumber = false;
    ASSERT_FALSE(nativeValue->GetValueBool(isNumber));

    delete nativeValue;
}


/**
 * @tc.number: ffi_interface_api_111
 * @tc.name: ToBigInt
 * @tc.desc: String to big int
 * @tc.type: FUNC
 * @tc.require:  parameter
 */
HWTEST_F_L0(JSNApiTests, ToBigInt)
{
    LocalScope scope(vm_);
    Local<StringRef> toString = StringRef::NewFromUtf8(vm_, TEST_NUM2);
    Local<JSValueRef> toValue(toString);
    EXPECT_FALSE(toValue->ToBigInt(vm_)->IsBigInt(vm_));
}


/**
 * @tc.number: ffi_interface_api_112
 * @tc.name: IsInt && WithinInt32
 * @tc.desc: Determine if it is int && Within Int32
 * @tc.type: FUNC
 * @tc.require:  parameter
 */
HWTEST_F_L0(JSNApiTests, IsInt)
{
    LocalScope scope(vm_);
    bool input = true;
    Local<IntegerRef> res = IntegerRef::New(vm_, input);
    EXPECT_TRUE(res->IsInt());
    EXPECT_TRUE(res->WithinInt32());
}


/**
 * @tc.number: ffi_interface_api_113
 * @tc.name: IsJSFunction
 * @tc.desc: Determine if it is JSFunction
 * @tc.type: FUNC
 * @tc.require:  parameter
 */
HWTEST_F_L0(JSNApiTests, IsJSFunction)
{
    LocalScope scope(vm_);
    bool input = true;
    Local<FunctionRef> res = IntegerRef::New(vm_, input);
    EXPECT_FALSE(res->IsJSFunction(vm_));
}


/**
 * @tc.number: ffi_interface_api_114
 * @tc.name: IsWeakRef
 * @tc.desc: Determine if it is JSFunction
 * @tc.type: FUNC
 * @tc.require:  parameter
 */
HWTEST_F_L0(JSNApiTests, IsWeakRef)
{
    LocalScope scope(vm_);
    Local<JSValueRef> tag = BooleanRef::New(vm_, true);
    EXPECT_FALSE(tag->IsWeakRef(vm_));
}


/**
 * @tc.number: ffi_interface_api_115
 * @tc.name: IsArrayIterator
 * @tc.desc: Determine if it is arrayIterator
 * @tc.type: FUNC
 * @tc.require:  parameter
 */
HWTEST_F_L0(JSNApiTests, IsArrayIterator)
{
    LocalScope scope(vm_);
    Local<JSValueRef> tag = ArrayRef::New(vm_, true);
    EXPECT_FALSE(tag->IsArrayIterator(vm_));
}


/**
 * @tc.number: ffi_interface_api_116
 * @tc.name: IsStringIterator
 * @tc.desc: Determine if it is string Iterator
 * @tc.type: FUNC
 * @tc.require:  parameter
 */
HWTEST_F_L0(JSNApiTests, IsStringIterator)
{
    LocalScope scope(vm_);
    Local<StringRef> toString = StringRef::NewFromUtf8(vm_, TEST_NUM2);
    EXPECT_FALSE(toString->IsStringIterator(vm_));
    std::string str = TEST_NUM2;
    EXPECT_EQ(toString->DebuggerToString(vm_), str);
}


/**
 * @tc.number: ffi_interface_api_116
 * @tc.name: IsJSSharedInt8Array
 * @tc.desc: Determine if it is JSSharedArray
 * @tc.type: FUNC
 * @tc.require:  parameter
 */
HWTEST_F_L0(JSNApiTests, IsJSSharedInt8Array)
{
    LocalScope scope(vm_);
    Local<JSValueRef> tag = ArrayRef::New(vm_, true);
    EXPECT_FALSE(tag->IsJSSharedInt8Array(vm_));
    EXPECT_FALSE(tag->IsJSSharedUint8Array(vm_));
    EXPECT_FALSE(tag->IsJSSharedUint8ClampedArray(vm_));
    EXPECT_FALSE(tag->IsJSSharedInt16Array(vm_));
    EXPECT_FALSE(tag->IsJSSharedUint16Array(vm_));
    EXPECT_FALSE(tag->IsJSSharedInt32Array(vm_));
    EXPECT_FALSE(tag->IsJSSharedFloat32Array(vm_));
    EXPECT_FALSE(tag->IsJSSharedUint32Array(vm_));
}


/**
 * @tc.number: ffi_interface_api_117
 * @tc.name: IsNativeModuleFailureInfoObject
 * @tc.desc: Determine if it is nativeModuleFailureInfoObject
 * @tc.type: FUNC
 * @tc.require:  parameter
 */
HWTEST_F_L0(JSNApiTests, IsNativeModuleFailureInfoObject)
{
    LocalScope scope(vm_);
    Local<JSValueRef> tag = ArrayRef::New(vm_, true);
    EXPECT_FALSE(tag->IsNativeModuleFailureInfoObject(vm_));
    EXPECT_FALSE(tag->IsSendableArrayBuffer(vm_));
    EXPECT_FALSE(tag->IsJSLocale(vm_));
    EXPECT_FALSE(tag->IsJSDateTimeFormat(vm_));
    EXPECT_FALSE(tag->IsJSRelativeTimeFormat(vm_));
    EXPECT_FALSE(tag->IsJSIntl(vm_));
    EXPECT_FALSE(tag->IsJSNumberFormat(vm_));
    EXPECT_FALSE(tag->IsJSCollator(vm_));
    EXPECT_FALSE(tag->IsJSPluralRules(vm_));
    EXPECT_FALSE(tag->IsJSListFormat(vm_));
    EXPECT_FALSE(tag->IsAsyncGeneratorObject(vm_));
}


/**
 * @tc.number: ffi_interface_api_118
 * @tc.name: IsAsyncGeneratorObject
 * @tc.desc: Determine if it is asyncGeneratorObject
 * @tc.type: FUNC
 * @tc.require:  parameter
 */
HWTEST_F_L0(JSNApiTests, IsAsyncGeneratorObject)
{
    LocalScope scope(vm_);
    Local<JSValueRef> tag = ArrayRef::New(vm_, true);
    EXPECT_FALSE(tag->IsAsyncGeneratorObject(vm_));
    EXPECT_FALSE(tag->IsArrayList(vm_));
    EXPECT_FALSE(tag->IsDeque(vm_));
    EXPECT_FALSE(tag->IsHashMap(vm_));
    EXPECT_FALSE(tag->IsHashSet(vm_));
    EXPECT_FALSE(tag->IsLightWeightMap(vm_));
    EXPECT_FALSE(tag->IsLightWeightSet(vm_));
    EXPECT_FALSE(tag->IsLinkedList(vm_));
    EXPECT_FALSE(tag->IsLinkedListIterator(vm_));
    EXPECT_FALSE(tag->IsList(vm_));
    EXPECT_FALSE(tag->IsPlainArray(vm_));
    EXPECT_FALSE(tag->IsQueue(vm_));
    EXPECT_FALSE(tag->IsStack(vm_));
}


/**
 * @tc.number: ffi_interface_api_119
 * @tc.name: IsSendableObject
 * @tc.desc: Determine if it is sendableObject
 * @tc.type: FUNC
 * @tc.require:  parameter
 */
HWTEST_F_L0(JSNApiTests, IsSendableObject)
{
    LocalScope scope(vm_);
    Local<JSValueRef> value = ObjectRef::New(vm_);
    EXPECT_FALSE(value->IsSendableObject(vm_));
    EXPECT_FALSE(value->IsJSShared(vm_));
    EXPECT_FALSE(value->IsSharedArray(vm_));
    EXPECT_FALSE(value->IsSharedTypedArray(vm_));
    EXPECT_FALSE(value->IsSharedSet(vm_));
    EXPECT_FALSE(value->IsSharedMap(vm_));
    EXPECT_FALSE(value->IsSharedMapIterator(vm_));
    EXPECT_TRUE(value->IsHeapObject());
}


/**
 * @tc.number: ffi_interface_api_120
 * @tc.name: GetNativePointerValue
 * @tc.desc: GetNativePointerValue
 * @tc.type: FUNC
 * @tc.require:  parameter
 */
HWTEST_F_L0(JSNApiTests, GetNativePointerValue)
{
    LocalScope scope(vm_);
    Local<JSValueRef> value = ObjectRef::New(vm_);
    bool isNativePointer = true;
    EXPECT_FALSE(value->GetNativePointerValue(vm_, isNativePointer));
}


/**
 * @tc.number: ffi_interface_api_121
 * @tc.name: IsDetachedArraybuffer
 * @tc.desc: IsDetachedArraybuffer
 * @tc.type: FUNC
 * @tc.require:  parameter
 */
HWTEST_F_L0(JSNApiTests, IsDetachedArraybuffer)
{
    LocalScope scope(vm_);
    const int32_t length = 15;
    Local<JSValueRef> sharedArrayBuffer = ArrayBufferRef::New(vm_, length);
    bool isNativePointer = true;
    EXPECT_FALSE(sharedArrayBuffer->IsDetachedArraybuffer(vm_, isNativePointer));
    sharedArrayBuffer->DetachedArraybuffer(vm_, isNativePointer);
    EXPECT_TRUE(isNativePointer);
}


/**
 * @tc.number: ffi_interface_api_122
 * @tc.name: MapRefGet
 * @tc.desc: MapRef Get
 * @tc.type: FUNC
 * @tc.require:  parameter
 */
HWTEST_F_L0(JSNApiTests, MapRefGet)
{
    LocalScope scope(vm_);
    Local<MapRef> object = MapRef::New(vm_);
    Local<JSValueRef> key = StringRef::NewFromUtf8(vm_, TEST_KEY);
    Local<JSValueRef> value = StringRef::NewFromUtf8(vm_, TEST_VALUE);
    EXPECT_FALSE(object->Has(vm_, key));
    object->Set(vm_, key, value);
    EXPECT_TRUE(object->Has(vm_, key));
    Local<JSValueRef> mapRef = object->Get(vm_, TEST_KEY);
    EXPECT_FALSE(object->Has(vm_, mapRef));
    object->Delete(vm_, key);
    object->GetEntries(vm_);
    object->GetKeys(vm_);
    object->GetValues(vm_);
    EXPECT_FALSE(object->Has(vm_, TEST_KEY));
    object->Clear(vm_);
}


/**
 * @tc.number: ffi_interface_api_123
 * @tc.name: SendableMapRef
 * @tc.desc: SendableMapRef test
 * @tc.type: FUNC
 * @tc.require:  parameter
 */
HWTEST_F_L0(JSNApiTests, SendableMapRef)
{
    LocalScope scope(vm_);
    Local<SendableMapRef> object = SendableMapRef::New(vm_);
    Local<JSValueRef> key = StringRef::NewFromUtf8(vm_, TEST_KEY);
    Local<JSValueRef> value = StringRef::NewFromUtf8(vm_, TEST_VALUE);
    EXPECT_FALSE(object->Has(vm_, key));
    object->Set(vm_, key, value);
    object->Set(vm_, TEST_KEY, value);
    EXPECT_TRUE(object->Has(vm_, key));
    Local<JSValueRef> sendableMapRef = object->Get(vm_, TEST_KEY);
    sendableMapRef = object->Get(vm_, key);
    EXPECT_FALSE(object->Has(vm_, sendableMapRef));
    Local<SendableMapIteratorRef> sendableMapIteratorRef = object->GetEntries(vm_);
    sendableMapIteratorRef->Next(vm_);
    object->GetKey(vm_, 0);
    object->GetKeys(vm_);
    object->GetValue(vm_, 0);
    object->GetValues(vm_);
    object->GetSize(vm_);
    object->GetTotalElements(vm_);
    EXPECT_TRUE(object->Has(vm_, TEST_KEY));
    object->Delete(vm_, key);
    object->Clear(vm_);
}


/**
 * @tc.number: ffi_interface_api_124
 * @tc.name: MapIteratorRef
 * @tc.desc: MapIteratorRef test
 * @tc.type: FUNC
 * @tc.require:  parameter
 */
HWTEST_F_L0(JSNApiTests, MapIteratorRef)
{
    LocalScope scope(vm_);
    Local<MapRef> mapRef = MapRef::New(vm_);
    Local<MapIteratorRef> object = MapIteratorRef::New(vm_, mapRef);
    Local<JSValueRef> key = StringRef::NewFromUtf8(vm_, TEST_KEY);
    Local<JSValueRef> value = StringRef::NewFromUtf8(vm_, TEST_VALUE);
    EXPECT_FALSE(object->Has(vm_, key));
    ecmascript::EcmaRuntimeCallInfo *ecmaRuntimeCallInfo = object->GetEcmaRuntimeCallInfo(vm_);
    object->Next(vm_, ecmaRuntimeCallInfo);
    object->Next(vm_);
    object->Set(vm_, key, value);
    object->Set(vm_, TEST_KEY, value);
    EXPECT_TRUE(object->Has(vm_, key));
    Local<JSValueRef> mapIteratorRef = object->Get(vm_, TEST_KEY);
    mapIteratorRef = object->Get(vm_, key);
    object->Delete(vm_, key);
    EXPECT_FALSE(object->Has(vm_, mapIteratorRef));
}


/**
 * @tc.number: ffi_interface_api_125
 * @tc.name: SetIteratorRef
 * @tc.desc: SetIteratorRef test
 * @tc.type: FUNC
 * @tc.require:  parameter
 */
HWTEST_F_L0(JSNApiTests, SetIteratorRef)
{
    LocalScope scope(vm_);
    JSThread *thread = vm_->GetJSThread();
    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
    JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
    JSHandle<JSTaggedValue> constructor = env->GetBuiltinsSetFunction();
    JSHandle<JSSet> set =
        JSHandle<JSSet>::Cast(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(constructor), constructor));
    JSHandle<LinkedHashSet> hashSet = LinkedHashSet::Create(thread);
    set->SetLinkedSet(thread, hashSet);
    JSHandle<JSTaggedValue> setTag = JSHandle<JSTaggedValue>::Cast(set);
    Local<SetRef> setRef = JSNApiHelper::ToLocal<SetRef>(setTag);
    Local<MapIteratorRef> object = SetIteratorRef::New(vm_, setRef);
    EXPECT_TRUE(object->IsHeapObject());
}


/**
 * @tc.number: ffi_interface_api_126
 * @tc.name: PromiseRejectInfo
 * @tc.desc: PromiseRejectInfo test
 * @tc.type: FUNC
 * @tc.require:  parameter
 */
HWTEST_F_L0(JSNApiTests, PromiseRejectInfo)
{
    LocalScope scope(vm_);
    Local<StringRef> toStringPromise = StringRef::NewFromUtf8(vm_, TEST_NUM1);
    Local<JSValueRef> promise(toStringPromise);
    Local<StringRef> toStringReason = StringRef::NewFromUtf8(vm_, TEST_NUM1);
    Local<JSValueRef> reason(toStringReason);
    std::string* str = new std::string(TEST_VALUE);
    void *data = static_cast<void *>(str);
    PromiseRejectInfo promisereject(promise, reason, PromiseRejectInfo::PROMISE_REJECTION_EVENT::REJECT, data);
    EXPECT_EQ(promisereject.GetOperation(), PromiseRejectInfo::PROMISE_REJECTION_EVENT::REJECT);

    delete str;
}

/**
 * @tc.number: ffi_interface_api_127
 * @tc.name: ObjectRef
 * @tc.desc: ObjectRef test
 * @tc.type: FUNC
 * @tc.require:  parameter
 */
HWTEST_F_L0(JSNApiTests, ObjectRef)
{
    LocalScope scope(vm_);
    Local<ObjectRef> object = ObjectRef::New(vm_);
    object = ObjectRef::NewS(vm_);
    std::string str = TEST_VALUE;
    object->CreateNativeModuleFailureInfo(vm_, str);
    bool input = true;
    Local<FunctionRef> res = IntegerRef::New(vm_, input);
    object->CreateAccessorData(vm_, res, res);
    uintptr_t addr = ObjectRef::NewObject(vm_);
    Local<StringRef> key = StringRef::NewFromUtf8(vm_, TEST_VALUE);
    Local<JSValueRef> value = ObjectRef::New(vm_);
    PropertyAttribute property(value, true, true, true);
    object->SetConcurrentNativePointerField(vm_, 0);
    EXPECT_FALSE(object->SetPrototype(vm_, object));
    EXPECT_FALSE(object->HasOwnProperty(vm_, key));
    EXPECT_FALSE(object->GetOwnProperty(vm_, key, property));
    EXPECT_NE(addr, 1);
}

/**
 * @tc.number: ffi_interface_api_128
 * @tc.name: SendableArrayBufferRef
 * @tc.desc: SendableArrayBufferRef test
 * @tc.type: FUNC
 * @tc.require:  parameter
 */
HWTEST_F_L0(JSNApiTests, SendableArrayBufferRef)
{
    LocalScope scope(vm_);
    Local<SendableArrayBufferRef> res = SendableArrayBufferRef::New(vm_, 0);
    const int32_t length = 33;
    res->GetBuffer(vm_);
    EXPECT_NE(res->ByteLength(vm_), length);
    res->Detach(vm_);
    EXPECT_NE(res->IsDetach(vm_), length);
}

/**
 * @tc.number: ffi_interface_api_129
 * @tc.name: JSNApiSetPkgAliasList
 * @tc.desc: Used to verify whether the function of setting the map container module was successful.
 * @tc.type: FUNC
 * @tc.require:  parameter
 */
HWTEST_F_L0(JSNApiTests, JSNApiSetPkgAliasList)
{
    LocalScope scope(vm_);
    std::map<std::string, std::string> str = { { TEST_NUM1, TEST_NUM2 } };
    JSNApi::SetPkgAliasList(vm_, str);
    std::string moduleName = TEST_NUM1;
    EXPECT_EQ(std::string(vm_->GetPkgNameWithAlias(TEST_NUM1)), TEST_NUM2);
}

/**
 * @tc.number: ffi_interface_api_130
 * @tc.name: InitForConcurrentFunction
 * @tc.desc: Used to verify whether the function of setting the map container module was successful.
 * @tc.type: FUNC
 * @tc.require:  parameter
 */
HWTEST_F_L0(JSNApiTests, JSNApiInitForConcurrentFunction)
{
    LocalScope scope(vm_);
    void *taskInfo = reinterpret_cast<void *>(BuiltinsFunction::FunctionPrototypeInvokeSelf);
    Local<JSValueRef> function = FunctionRef::New(vm_, FunctionCallback);
    EXPECT_FALSE(JSNApi::InitForConcurrentFunction(vm_, function, taskInfo));
}

/**
 * @tc.number: ffi_interface_api_131
 * @tc.name: GetStackBeforeCallNapiSuccess
 * @tc.desc: Used to verify whether the function of setting the map container module was successful.
 * @tc.type: FUNC
 * @tc.require:  parameter
 */
HWTEST_F_L0(JSNApiTests, GetStackBeforeCallNapiSuccess)
{
    LocalScope scope(vm_);
    SourceMapCallback callback { nullptr };
    JSNApi::SetSourceMapCallback(vm_, callback);
    vm_->GetJSThread()->SetIsProfiling(false);
    bool getStackBeforeCallNapiSuccess = false;
    JSNApi::GetStackBeforeCallNapiSuccess(vm_, getStackBeforeCallNapiSuccess);
    JSNApi::GetStackAfterCallNapi(vm_);
    EXPECT_FALSE(getStackBeforeCallNapiSuccess);
}

/**
 * @tc.number: ffi_interface_api_132
 * @tc.name: NewConcurrentWithName
 * @tc.desc: Check if the function created through the NewConcurrentWithName returns the same value to native callee
 * @tc.type: FUNC
 * @tc.require: parameter
 */
HWTEST_F_L0(JSNApiTests, NewConcurrentWithName)
{
    LocalScope scope(vm_);
    Local<JSValueRef> context = JSNApiHelper::ToLocal<JSValueRef>(JSHandle<JSTaggedValue>(thread_->GetGlobalEnv()));
    std::string name = "MyFunction";
    Local<FunctionRef> func = FunctionRef::NewConcurrentWithName(
        vm_, context,
        [](JsiRuntimeCallInfo *runtimeInfo) -> JSValueRef {
            EcmaVM *vm = runtimeInfo->GetVM();
            LocalScope scope(vm);
            return **StringRef::NewFromUtf8WithoutStringTable(vm, "funcResult");
        },
        nullptr, name.c_str());
    JSHandle<JSTaggedValue> handle = JSNApiHelper::ToJSHandle(func);
    ASSERT_EQ(handle.GetTaggedValue().GetTaggedObject()->GetClass()->GetObjectType(), JSType::JS_FUNCTION);
    Local<JSValueRef> res = func->Call(vm_, JSValueRef::Undefined(vm_), nullptr, 0);
    ASSERT_EQ("funcResult", res->ToString(vm_)->ToString(vm_));
    Local<StringRef> funcName = func->GetName(vm_);
    std::string funcNameStr = funcName->ToString(vm_);
    ASSERT_EQ(name, funcNameStr);
}

/**
 * @tc.number: ffi_interface_api_140
 * @tc.name: NewConcurrentClassFunctionWithNameCase0
 * @tc.desc: While property count is 0, check if the class created through the NewConcurrentClassFunctionWithName
 * method meets the specifications of the class constructor and the name property of class.
 * @tc.type: FUNC
 * @tc.require: parameter
 */
HWTEST_F_L0(JSNApiTests, NewConcurrentClassFunctionWithNameCase0)
{
    LocalScope scope(vm_);
    Local<JSValueRef> context = JSNApiHelper::ToLocal<JSValueRef>(JSHandle<JSTaggedValue>(thread_->GetGlobalEnv()));
    std::string name = "MyClassFunction";
    Local<FunctionRef> cls = FunctionRef::NewConcurrentClassFunctionWithName(vm_, context, InternalFunctionCallback,
                                                                             nullptr, name.c_str(), nullptr);
    JSHandle<JSTaggedValue> funcHandle = JSNApiHelper::ToJSHandle(cls);
#if defined(ENABLE_API_FUNCTION_OPTIMIZATION) && ENABLE_MEMORY_OPTIMIZATION
    ASSERT_EQ(funcHandle.GetTaggedValue().GetTaggedObject()->GetClass()->GetObjectType(), JSType::JS_API_FUNCTION);
#else // defined(ENABLE_API_FUNCTION_OPTIMIZATION) && ENABLE_MEMORY_OPTIMIZATION
    ASSERT_EQ(funcHandle.GetTaggedValue().GetTaggedObject()->GetClass()->GetObjectType(), JSType::JS_FUNCTION);
#endif // defined(ENABLE_API_FUNCTION_OPTIMIZATION) && ENABLE_MEMORY_OPTIMIZATION
    JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(Local<JSValueRef>(cls));
    // Asserting that obj is a class constructor
    ASSERT_TRUE(obj->IsClassConstructor());
    // The GetPropertyInlinedProps method gets the method of an inline property,
    // CLASS_PROTOTYPE_INLINE_PROPERTY_INDEX is the inline property index of the class prototype.
    JSTaggedValue res =
        JSHandle<JSFunction>(obj)->GetPropertyInlinedProps(thread_, JSFunction::CLASS_PROTOTYPE_INLINE_PROPERTY_INDEX);
    // The property that the assertion gets is an internal accessor
    ASSERT_TRUE(res.IsInternalAccessor());
    Local<StringRef> funcName = cls->GetName(vm_);
    std::string funcNameStr = funcName->ToString(vm_);
    ASSERT_EQ(name, funcNameStr);
}

/**
 * @tc.number: ffi_interface_api_141
 * @tc.name: NewConcurrentClassFunctionWithNameCase1
 * @tc.desc: While property count is smaller than 1024, check if the keys and attrs were successfully set in the class
 * that created through the NewConcurrentClassFunctionWithName method.
 * @tc.type: FUNC
 * @tc.require: parameter
 */
HWTEST_F_L0(JSNApiTests, NewConcurrentClassFunctionWithNameCase1)
{
    LocalScope scope(vm_);
    JSHandle<GlobalEnv> env = thread_->GetGlobalEnv();
    Local<JSValueRef> context = JSNApiHelper::ToLocal<JSValueRef>(JSHandle<JSTaggedValue>(env));
    std::string name = "MyClassFunction";
    size_t staticPropCount = 5;
    size_t nonStaticPropCount = PROPERTY_COUNT_CASE1 - staticPropCount;
    Local<panda::JSValueRef> keys[PROPERTY_COUNT_CASE1];
    PropertyAttribute attrs[PROPERTY_COUNT_CASE1];
    // There are 10 properties totally, and the last two keys and first two keys are duplicate, so expectedVals[8] will
    // overwrite expectedVals[9], expectedVals[1] will overwrite expectedVals[0]
    const std::string keyNames[10] = {"key0", "key0", "key2", "key3", "key4", "key5", "key6", "key7", "key8", "key8"};
    const int expectedVals[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
    for (size_t i = 0; i < PROPERTY_COUNT_CASE1; ++i) {
        keys[i] = StringRef::NewFromUtf8(vm_, keyNames[i].c_str());
        Local<JSValueRef> curValue =
            JSNApiHelper::ToLocal<JSValueRef>(JSHandle<JSTaggedValue>(thread_, JSTaggedValue(expectedVals[i])));
        attrs[i].SetValue(curValue);
        attrs[i].SetConfigurable(true);
        attrs[i].SetWritable(true);
    }

    Local<FunctionRef> cls = FunctionRef::NewConcurrentClassFunctionWithName(
        vm_, context, InternalFunctionCallback, nullptr, name.c_str(), nullptr, true, PROPERTY_COUNT_CASE1,
        staticPropCount, keys, attrs);

    JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(Local<JSValueRef>(cls));
    JSHandle<JSFunction> clsFunc(obj);
    JSThread *thread = vm_->GetJSThread();
    JSHandle<JSObject> clsPrototype(thread_, clsFunc->GetProtoOrHClass(thread));
    JSHandle<JSHClass> clsFuncHClass(thread_, clsFunc->GetJSHClass());
    JSHandle<JSHClass> clsProtoHClass(thread_, clsPrototype->GetJSHClass());
    uint32_t clsInlPropNum = clsFuncHClass->GetInlinedProperties();
    uint32_t clsProtoInlPropNum = clsProtoHClass->GetInlinedProperties();

    JSHandle<JSHClass> defaultClsFuncHClass(env->GetFunctionClassWithoutName());
    JSHandle<JSHClass> defaultClsProtoHClass(env->GetObjectFunctionClass());
    uint32_t defaultClsInlPropNum = defaultClsFuncHClass->GetInlinedProperties();
    uint32_t defaultProtoInlPropNum = defaultClsProtoHClass->GetInlinedProperties();
    // In current NewConcurrentClassFunctionWithName method, all properties were stored as inlined properties.
    ASSERT_EQ(clsInlPropNum, defaultClsInlPropNum + staticPropCount);
    ASSERT_EQ(clsProtoInlPropNum, defaultProtoInlPropNum + PROPERTY_COUNT_CASE1 - staticPropCount);

    for (size_t i = 0; i < staticPropCount; ++i) {
        auto realProp = JSObject::GetProperty(thread_, obj, JSNApiHelper::ToJSHandle(keys[i])).GetValue();
        uint32_t realVal = JSTaggedValue::ToUint32(thread_, realProp);
        if (i == 0) {
            // expectedVals[0] was overwritten by expectedVals[1].
            ASSERT_EQ(realVal, expectedVals[1]);
        } else {
            ASSERT_EQ(realVal, expectedVals[i]);
        }
    }
    JSHandle<JSTaggedValue> clsProtoVal(thread_, clsFunc->GetProtoOrHClass(thread));
    for (size_t i = 0; i < nonStaticPropCount; ++i) {
        size_t trueIdx = PROPERTY_COUNT_CASE1 - 1 - i;
        auto realProp = JSObject::GetProperty(thread_, clsProtoVal, JSNApiHelper::ToJSHandle(keys[trueIdx])).GetValue();
        uint32_t realVal = JSTaggedValue::ToUint32(thread_, realProp);
        if (i == 0) {
            // expectedVals[9] was overwritten by expectedVals[8].
            ASSERT_EQ(realVal, expectedVals[trueIdx - 1]);
        } else {
            ASSERT_EQ(realVal, expectedVals[trueIdx]);
        }
    }
}

/**
 * @tc.number: ffi_interface_api_148
 * @tc.name: NewNormalFunctionUseApiFunctionType
 * @tc.desc: NewNormalFunctionUseApiFunctionType
 * @tc.type: FUNC
 * @tc.require: parameter
 */
HWTEST_F_L0(JSNApiTests, NewNormalFunctionUseApiFunctionType)
{
    LocalScope scope(vm_);
    Local<FunctionRef> func = FunctionRef::New(vm_, FunctionCallback);
    JSHandle<JSTaggedValue> handle = JSNApiHelper::ToJSHandle(func);
    JSHClass* hClass = handle.GetTaggedValue().GetTaggedObject()->GetClass();
#if defined(ENABLE_API_FUNCTION_OPTIMIZATION) && ENABLE_MEMORY_OPTIMIZATION
    ASSERT_EQ(handle.GetTaggedValue().GetTaggedObject()->GetClass()->GetObjectType(), JSType::JS_API_FUNCTION);
    JSHClass* normalApiFunctionClass =
        JSHClass::Cast(vm_->GetGlobalEnv()->GetNormalApiFunctionClass().GetTaggedValue().GetTaggedObject());
    ASSERT_EQ(hClass, normalApiFunctionClass);
#else // defined(ENABLE_API_FUNCTION_OPTIMIZATION) && ENABLE_MEMORY_OPTIMIZATION
    JSHClass* normalFunctionClass =
        JSHClass::Cast(vm_->GetGlobalEnv()->GetNormalFunctionClass().GetTaggedValue().GetTaggedObject());
    ASSERT_EQ(handle.GetTaggedValue().GetTaggedObject()->GetClass()->GetObjectType(), JSType::JS_FUNCTION);
    ASSERT_EQ(hClass, normalFunctionClass);
#endif // defined(ENABLE_API_FUNCTION_OPTIMIZATION) && ENABLE_MEMORY_OPTIMIZATION
    // Call will not crash
    Local<JSValueRef> res = func->Call(vm_, JSValueRef::Undefined(vm_), nullptr, 0);
    ASSERT_TRUE(res->IsArray(vm_));
}

/**
 * @tc.number: ffi_interface_api_149
 * @tc.name: NewConcurrentNormalFunctionUseApiFunctionType
 * @tc.desc: NewConcurrentNormalFunctionUseApiFunctionType
 * @tc.type: FUNC
 * @tc.require: parameter
 */
HWTEST_F_L0(JSNApiTests, NewConcurrentNormalFunctionUseApiFunctionType)
{
    LocalScope scope(vm_);
    Local<FunctionRef> concurrentFunc = FunctionRef::NewConcurrent(vm_, FunctionCallback);
    JSHandle<JSTaggedValue> funcHandle = JSNApiHelper::ToJSHandle(concurrentFunc);
    JSHClass* hClass = funcHandle.GetTaggedValue().GetTaggedObject()->GetClass();
#if defined(ENABLE_API_FUNCTION_OPTIMIZATION) && ENABLE_MEMORY_OPTIMIZATION
    ASSERT_EQ(funcHandle.GetTaggedValue().GetTaggedObject()->GetClass()->GetObjectType(), JSType::JS_API_FUNCTION);
    JSHClass* normalApiFunctionClass =
        JSHClass::Cast(vm_->GetGlobalEnv()->GetNormalApiFunctionClass().GetTaggedValue().GetTaggedObject());
    ASSERT_EQ(hClass, normalApiFunctionClass);
#else // defined(ENABLE_API_FUNCTION_OPTIMIZATION) && ENABLE_MEMORY_OPTIMIZATION
    JSHClass* normalFunctionClass =
        JSHClass::Cast(vm_->GetGlobalEnv()->GetNormalFunctionClass().GetTaggedValue().GetTaggedObject());
    ASSERT_EQ(funcHandle.GetTaggedValue().GetTaggedObject()->GetClass()->GetObjectType(), JSType::JS_FUNCTION);
    ASSERT_EQ(hClass, normalFunctionClass);
#endif // defined(ENABLE_API_FUNCTION_OPTIMIZATION) && ENABLE_MEMORY_OPTIMIZATION
    // Call will not crash
    Local<JSValueRef> res = concurrentFunc->Call(vm_, JSValueRef::Undefined(vm_), nullptr, 0);
    ASSERT_TRUE(res->IsArray(vm_));
}
/**
 * @tc.number: ffi_interface_api_150
 * @tc.name: NewInternalNormalFunctionUseApiFunctionType
 * @tc.desc: NewInternalNormalFunctionUseApiFunctionType
 * @tc.type: FUNC
 * @tc.require: parameter
 */
HWTEST_F_L0(JSNApiTests, NewInternalNormalFunctionUseApiFunctionType)
{
    LocalScope scope(vm_);
    Local<FunctionRef> func = FunctionRef::New(vm_, InternalFunctionCallback, nullptr);
    JSHandle<JSTaggedValue> handle = JSNApiHelper::ToJSHandle(func);
    JSHClass* hClass = handle.GetTaggedValue().GetTaggedObject()->GetClass();
#if defined(ENABLE_API_FUNCTION_OPTIMIZATION) && ENABLE_MEMORY_OPTIMIZATION
    ASSERT_EQ(handle.GetTaggedValue().GetTaggedObject()->GetClass()->GetObjectType(), JSType::JS_API_FUNCTION);
    JSHClass* normalApiFunctionClass =
        JSHClass::Cast(vm_->GetGlobalEnv()->GetNormalApiFunctionClass().GetTaggedValue().GetTaggedObject());
    ASSERT_EQ(hClass, normalApiFunctionClass);
#else // defined(ENABLE_API_FUNCTION_OPTIMIZATION) && ENABLE_MEMORY_OPTIMIZATION
    JSHClass* normalFunctionClass =
        JSHClass::Cast(vm_->GetGlobalEnv()->GetNormalFunctionClass().GetTaggedValue().GetTaggedObject());
    ASSERT_EQ(handle.GetTaggedValue().GetTaggedObject()->GetClass()->GetObjectType(), JSType::JS_FUNCTION);
    ASSERT_EQ(hClass, normalFunctionClass);
#endif // defined(ENABLE_API_FUNCTION_OPTIMIZATION) && ENABLE_MEMORY_OPTIMIZATION
    // Call will not crash
    Local<JSValueRef> res = func->Call(vm_, JSValueRef::Undefined(vm_), nullptr, 0);
    ASSERT_TRUE(res->IsArray(vm_));
}

/**
 * @tc.number: ffi_interface_api_151
 * @tc.name: NewInternalConcurrentNormalFunctionUseApiFunctionType
 * @tc.desc: NewInternalConcurrentNormalFunctionUseApiFunctionType
 * @tc.type: FUNC
 * @tc.require: parameter
 */
HWTEST_F_L0(JSNApiTests, NewInternalConcurrentNormalFunctionUseApiFunctionType)
{
    LocalScope scope(vm_);
    Local<FunctionRef> concurrentFunc = FunctionRef::NewConcurrent(vm_, InternalFunctionCallback, nullptr);
    JSHandle<JSTaggedValue> funcHandle = JSNApiHelper::ToJSHandle(concurrentFunc);
    JSHClass* hClass = funcHandle.GetTaggedValue().GetTaggedObject()->GetClass();
    JSHClass* normalFunctionClass =
        JSHClass::Cast(vm_->GetGlobalEnv()->GetNormalFunctionClass().GetTaggedValue().GetTaggedObject());
    ASSERT_EQ(funcHandle.GetTaggedValue().GetTaggedObject()->GetClass()->GetObjectType(), JSType::JS_FUNCTION);
    ASSERT_EQ(hClass, normalFunctionClass);
    // Call will not crash
    Local<JSValueRef> res = concurrentFunc->Call(vm_, JSValueRef::Undefined(vm_), nullptr, 0);
    ASSERT_TRUE(res->IsArray(vm_));
}

/**
 * @tc.number: ffi_interface_api_152
 * @tc.name: NewConstructorFunctionUseApiFunctionType
 * @tc.desc: NewConstructorFunctionUseApiFunctionType
 * @tc.type: FUNC
 * @tc.require: parameter
 */
HWTEST_F_L0(JSNApiTests, NewConstructorFunctionUseApiFunctionType)
{
    LocalScope scope(vm_);
    Local<FunctionRef> func = FunctionRef::NewClassFunction(vm_, FunctionCallback, nullptr, nullptr);
    JSHandle<JSTaggedValue> funcHandle = JSNApiHelper::ToJSHandle(func);
    JSHClass* hClass = funcHandle.GetTaggedValue().GetTaggedObject()->GetClass();
#if defined(ENABLE_API_FUNCTION_OPTIMIZATION) && ENABLE_MEMORY_OPTIMIZATION
    ASSERT_EQ(funcHandle.GetTaggedValue().GetTaggedObject()->GetClass()->GetObjectType(), JSType::JS_API_FUNCTION);
    JSHClass* constructorApiFunctionClass =
        JSHClass::Cast(vm_->GetGlobalEnv()->GetApiFunctionClassWithoutName().GetTaggedValue().GetTaggedObject());
    ASSERT_EQ(hClass, constructorApiFunctionClass);
#else // defined(ENABLE_API_FUNCTION_OPTIMIZATION) && ENABLE_MEMORY_OPTIMIZATION
    JSHClass* constructorFunctionClass =
        JSHClass::Cast(vm_->GetGlobalEnv()->GetFunctionClassWithoutName().GetTaggedValue().GetTaggedObject());
    ASSERT_EQ(funcHandle.GetTaggedValue().GetTaggedObject()->GetClass()->GetObjectType(), JSType::JS_FUNCTION);
    ASSERT_EQ(hClass, constructorFunctionClass);
#endif // defined(ENABLE_API_FUNCTION_OPTIMIZATION) && ENABLE_MEMORY_OPTIMIZATION
}

/**
 * @tc.number: ffi_interface_api_153
 * @tc.name: NewInternalConstructorFunctionUseApiFunctionType
 * @tc.desc: NewInternalConstructorFunctionUseApiFunctionType
 * @tc.type: FUNC
 * @tc.require: parameter
 */
HWTEST_F_L0(JSNApiTests, NewInternalConstructorFunctionUseApiFunctionType)
{
    LocalScope scope(vm_);
    Local<FunctionRef> func = FunctionRef::NewClassFunction(vm_, InternalFunctionCallback, nullptr, nullptr);
    JSHandle<JSTaggedValue> funcHandle = JSNApiHelper::ToJSHandle(func);
    JSHClass* hClass = funcHandle.GetTaggedValue().GetTaggedObject()->GetClass();
#if defined(ENABLE_API_FUNCTION_OPTIMIZATION) && ENABLE_MEMORY_OPTIMIZATION
    ASSERT_EQ(funcHandle.GetTaggedValue().GetTaggedObject()->GetClass()->GetObjectType(), JSType::JS_API_FUNCTION);
    JSHClass* constructorApiFunctionClass =
        JSHClass::Cast(vm_->GetGlobalEnv()->GetApiFunctionClassWithoutName().GetTaggedValue().GetTaggedObject());
    ASSERT_EQ(hClass, constructorApiFunctionClass);
#else // defined(ENABLE_API_FUNCTION_OPTIMIZATION) && ENABLE_MEMORY_OPTIMIZATION
    JSHClass* constructorFunctionClass =
        JSHClass::Cast(vm_->GetGlobalEnv()->GetFunctionClassWithoutName().GetTaggedValue().GetTaggedObject());
    ASSERT_EQ(funcHandle.GetTaggedValue().GetTaggedObject()->GetClass()->GetObjectType(), JSType::JS_FUNCTION);
    ASSERT_EQ(hClass, constructorFunctionClass);
#endif // defined(ENABLE_API_FUNCTION_OPTIMIZATION) && ENABLE_MEMORY_OPTIMIZATION
}

/**
 * @tc.number: ffi_interface_api_154
 * @tc.name: NewInternalConcurrentConstructorFunctionUseApiFunctionType
 * @tc.desc: NewInternalConcurrentConstructorFunctionUseApiFunctionType
 * @tc.type: FUNC
 * @tc.require: parameter
 */
HWTEST_F_L0(JSNApiTests, NewInternalConcurrentConstructorFunctionUseApiFunctionType)
{
    LocalScope scope(vm_);
    Local<FunctionRef> func = FunctionRef::NewConcurrentClassFunction(vm_, InternalFunctionCallback, nullptr, nullptr);
    JSHandle<JSTaggedValue> funcHandle = JSNApiHelper::ToJSHandle(func);
    JSHClass* hClass = funcHandle.GetTaggedValue().GetTaggedObject()->GetClass();
#if defined(ENABLE_API_FUNCTION_OPTIMIZATION) && ENABLE_MEMORY_OPTIMIZATION
    ASSERT_EQ(funcHandle.GetTaggedValue().GetTaggedObject()->GetClass()->GetObjectType(), JSType::JS_API_FUNCTION);
    JSHClass* constructorApiFunctionClass =
        JSHClass::Cast(vm_->GetGlobalEnv()->GetApiFunctionClassWithoutName().GetTaggedValue().GetTaggedObject());
    ASSERT_EQ(hClass, constructorApiFunctionClass);
#else // defined(ENABLE_API_FUNCTION_OPTIMIZATION) && ENABLE_MEMORY_OPTIMIZATION
    JSHClass* constructorFunctionClass =
        JSHClass::Cast(vm_->GetGlobalEnv()->GetFunctionClassWithoutName().GetTaggedValue().GetTaggedObject());
    ASSERT_EQ(funcHandle.GetTaggedValue().GetTaggedObject()->GetClass()->GetObjectType(), JSType::JS_FUNCTION);
    ASSERT_EQ(hClass, constructorFunctionClass);
#endif // defined(ENABLE_API_FUNCTION_OPTIMIZATION) && ENABLE_MEMORY_OPTIMIZATION
}

/**
 * @tc.number: ffi_interface_api_155
 * @tc.name: GetNativePointerWrapperDataValue
 * @tc.desc: Test GetNativePointerWrapperDataValue with a normal JS object (not a native pointer)
 * @tc.type: FUNC
 * @tc.require: parameter
 */
HWTEST_F_L0(JSNApiTests, GetNativePointerWrapperDataValueWithObjectRefNEW)
{
    LocalScope scope(vm_);
    Local<JSValueRef> normalObj = ObjectRef::New(vm_);
    bool isNativePointer = true;
    bool isWrapperData = false;
    void* result = normalObj->GetNativePointerWrapperDataValue(vm_, isNativePointer, isWrapperData);

    EXPECT_FALSE(isNativePointer);
    EXPECT_FALSE(isWrapperData);
    EXPECT_EQ(result, nullptr);
}

/**
 * @tc.number: ffi_interface_api_156
 * @tc.name: GetNativePointerWrapperDataValue_RegularNativePointer
 * @tc.desc: Test GetNativePointerWrapperDataValue with a regular native pointer (not WRAPPER_DATA)
 * @tc.type: FUNC
 * @tc.require: parameter
 */
HWTEST_F_L0(JSNApiTests, GetNativePointerWrapperDataValueWithNativePointerRefNew)
{
    LocalScope scope(vm_);
    Local<NativePointerRef> object = NativePointerRef::New(
        vm_, &TEST_NUM, nullptr, nullptr, 0);
        
    Local<JSValueRef> jsVal = object;
    bool isNativePointer = false;
    bool isWrapperData = true;
    void* result = jsVal->GetNativePointerWrapperDataValue(vm_, isNativePointer, isWrapperData);

    EXPECT_TRUE(isNativePointer);
    EXPECT_FALSE(isWrapperData);
    EXPECT_EQ(result, nullptr);
}

/**
 * @tc.number: ffi_interface_api_157
 * @tc.name: GetNativePointerWrapperDataValue_WrapperData
 * @tc.desc: Test GetNativePointerWrapperDataValue with a native pointer created as WRAPPER_DATA
 * @tc.type: FUNC
 * @tc.require: parameter
 */
HWTEST_F_L0(JSNApiTests, GetNativePointerWrapperDataValueWithNewWrapperData)
{
    LocalScope scope(vm_);
    Local<NativePointerRef> wrapper = NativePointerRef::NewWrapperData(
        vm_, &TEST_NUM, nullptr, nullptr, 0);
    Local<JSValueRef> jsVal = wrapper;

    bool isNativePointer = false;
    bool isWrapperData = false;
    void* result = jsVal->GetNativePointerWrapperDataValue(vm_, isNativePointer, isWrapperData);

    EXPECT_TRUE(isNativePointer);
    EXPECT_TRUE(isWrapperData);
    EXPECT_EQ(result, &TEST_NUM);
}

/**
 * @tc.number: ffi_interface_api_158
 * @tc.name: NativePointerRef_NewWrapperData_DirectFlagCheck
 * @tc.desc: Directly verify that NewWrapperData sets NativeFlag::WRAPPER_DATA
 * @tc.type: FUNC
 * @tc.require: parameter
 */
HWTEST_F_L0(JSNApiTests, NativePointerRefNewWrapperDataFlagCheck)
{
    LocalScope scope(vm_);
    Local<NativePointerRef> wrapper = NativePointerRef::NewWrapperData(
        vm_, &TEST_NUM, nullptr, nullptr, 0);
    EXPECT_FALSE(wrapper.IsEmpty());

    Local<JSValueRef> jsVal = wrapper;
    JSTaggedValue tagged = JSNApiHelper::ToJSTaggedValue(*jsVal);
    EXPECT_TRUE(tagged.IsJSNativePointer());

    JSHandle<JSTaggedValue> nativePointerHandle = JSNApiHelper::ToJSHandle(jsVal);
    ecmascript::NativeFlag nativeflag = JSHandle<JSNativePointer>(nativePointerHandle)->GetNativeFlag();
    EXPECT_EQ(nativeflag, ecmascript::NativeFlag::WRAPPER_DATA);

    void* externalPtr = JSHandle<JSNativePointer>(nativePointerHandle)->GetExternalPointer();
    EXPECT_EQ(externalPtr, &TEST_NUM);
}

/**
 * @tc.number: ffi_interface_api_159
 * @tc.name: NewConcurrentClassFunctionWithNameCase2_PropTagsIndexBugFix
 * @tc.desc: Test that when nonStaticPropCount is large (close to MAX_FAST_PROPS_CAPACITY),
 *           the propTags array index is correctly handled. This tests the fix for the bug where
 *           propTags[curNonStaticPropIdx] was used instead of propTags[i], causing incorrect
 *           property values due to out-of-bounds access when propertyCount approaches MAX_FAST_PROPS_CAPACITY.
 *           propertyCount = MAX_FAST_PROPS_CAPACITY + 1 = 1024 is used to truly trigger the bug.
 * @tc.type: FUNC
 * @tc.require: parameter
 */
HWTEST_F_L0(JSNApiTests, NewConcurrentClassFunctionWithNameCase2_PropTagsIndexBugFix)
{
    LocalScope scope(vm_);
    JSHandle<GlobalEnv> env = thread_->GetGlobalEnv();
    Local<JSValueRef> context = JSNApiHelper::ToLocal<JSValueRef>(JSHandle<JSTaggedValue>(env));
    std::string name = "MyClassFunctionWithManyProps";

    // Use PROPERTY_COUNT_CASE2 = MAX_FAST_PROPS_CAPACITY + 1 to truly trigger the bug
    // Old code: propTags[curNonStaticPropIdx] would overflow when curNonStaticPropIdx >= MAX_FAST_PROPS_CAPACITY
    const size_t propertyCount = PROPERTY_COUNT_CASE2;  // MAX_FAST_PROPS_CAPACITY + 1 = 1024
    const size_t staticPropCount = 5;

    Local<panda::JSValueRef> keys[PROPERTY_COUNT_CASE2];
    PropertyAttribute attrs[PROPERTY_COUNT_CASE2];

    // Initialize keys and attrs with unique values
    for (size_t i = 0; i < propertyCount; ++i) {
        std::string keyName = "key" + std::to_string(i);
        keys[i] = StringRef::NewFromUtf8(vm_, keyName.c_str());
        Local<JSValueRef> curValue =
            JSNApiHelper::ToLocal<JSValueRef>(JSHandle<JSTaggedValue>(thread_, JSTaggedValue(static_cast<int32_t>(i))));
        attrs[i].SetValue(curValue);
        attrs[i].SetConfigurable(true);
        attrs[i].SetWritable(true);
    }

    // Create class with MAX_FAST_PROPS_CAPACITY + 1 properties
    Local<FunctionRef> cls = FunctionRef::NewConcurrentClassFunctionWithName(
        vm_, context, InternalFunctionCallback, nullptr, name.c_str(), nullptr, true, propertyCount,
        staticPropCount, keys, attrs);

    JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(Local<JSValueRef>(cls));
    JSHandle<JSFunction> clsFunc(obj);
    JSThread *thread = vm_->GetJSThread();

    // Verify static property values
    for (size_t i = 0; i < staticPropCount; ++i) {
        auto realProp = JSObject::GetProperty(thread_, obj, JSNApiHelper::ToJSHandle(keys[i])).GetValue();
        uint32_t realVal = JSTaggedValue::ToUint32(thread_, realProp);
        ASSERT_EQ(realVal, i) << "Static property key[" << i << "] has incorrect value";
    }

    // Verify non-static property values on prototype
    // Properties are added in reverse order (last nonStaticProp first)
    // We verify only the first few properties to ensure the fix works correctly
    JSHandle<JSTaggedValue> clsProtoVal(thread_, clsFunc->GetProtoOrHClass(thread));
    constexpr size_t verifyCount = 20;  // Verify first 20 non-static properties
    for (size_t i = 0; i < verifyCount; ++i) {
        size_t trueIdx = propertyCount - 1 - i;  // Reverse order
        auto realProp = JSObject::GetProperty(thread_, clsProtoVal, JSNApiHelper::ToJSHandle(keys[trueIdx])).GetValue();
        uint32_t realVal = JSTaggedValue::ToUint32(thread_, realProp);
        ASSERT_EQ(realVal, static_cast<uint32_t>(trueIdx))
            << "Non-static property key[" << trueIdx << "] has incorrect value, expected " << trueIdx << " but got "
            << realVal;
    }
}

/**
 * @tc.number: ffi_interface_api_160
 * @tc.name: NewConcurrentClassFunctionWithNameCase3_InlinePropLimit
 * @tc.desc: Test that the inline property count is correctly limited by maxInlPropCountForClassFunc.
 *           This verifies the fix for limiting inlNonStaticPropCount using maxInlPropCountForClassFunc
 *           instead of MAX_FAST_PROPS_CAPACITY, to prevent IC offset overflow.
 *           The limit is MAX_FAST_PROPS_CAPACITY - JSFunction::SIZE/TaggedTypeSize - DEFAULT_CAPACITY_OF_IN_OBJECTS.
 *           propertyCount = MAX_FAST_PROPS_CAPACITY + 1 = 1024 is used to truly test the limit.
 * @tc.type: FUNC
 * @tc.require: parameter
 */
HWTEST_F_L0(JSNApiTests, NewConcurrentClassFunctionWithNameCase3_InlinePropLimit)
{
    LocalScope scope(vm_);
    JSHandle<GlobalEnv> env = thread_->GetGlobalEnv();
    Local<JSValueRef> context = JSNApiHelper::ToLocal<JSValueRef>(JSHandle<JSTaggedValue>(env));
    std::string name = "MyClassFunctionInlineLimitTest";

    // Use PROPERTY_COUNT_CASE2 = MAX_FAST_PROPS_CAPACITY + 1 to truly test the limit
    const size_t propertyCount = PROPERTY_COUNT_CASE2;  // MAX_FAST_PROPS_CAPACITY + 1 = 1024
    const size_t staticPropCount = 5;

    Local<panda::JSValueRef> keys[PROPERTY_COUNT_CASE2];
    PropertyAttribute attrs[PROPERTY_COUNT_CASE2];

    // Initialize keys and attrs with unique values
    for (size_t i = 0; i < propertyCount; ++i) {
        std::string keyName = "key" + std::to_string(i);
        keys[i] = StringRef::NewFromUtf8(vm_, keyName.c_str());
        Local<JSValueRef> curValue =
            JSNApiHelper::ToLocal<JSValueRef>(JSHandle<JSTaggedValue>(thread_, JSTaggedValue(static_cast<int32_t>(i))));
        attrs[i].SetValue(curValue);
        attrs[i].SetConfigurable(true);
        attrs[i].SetWritable(true);
    }

    // Create class with MAX_FAST_PROPS_CAPACITY + 1 properties
    Local<FunctionRef> cls = FunctionRef::NewConcurrentClassFunctionWithName(
        vm_, context, InternalFunctionCallback, nullptr, name.c_str(), nullptr, true, propertyCount,
        staticPropCount, keys, attrs);

    JSHandle<JSTaggedValue> obj = JSNApiHelper::ToJSHandle(Local<JSValueRef>(cls));
    JSHandle<JSFunction> clsFunc(obj);
    JSThread *thread = vm_->GetJSThread();

    // Verify static property values on class function
    for (size_t i = 0; i < staticPropCount; ++i) {
        auto realProp = JSObject::GetProperty(thread_, obj, JSNApiHelper::ToJSHandle(keys[i])).GetValue();
        uint32_t realVal = JSTaggedValue::ToUint32(thread_, realProp);
        ASSERT_EQ(realVal, i) << "Static property key[" << i << "] has incorrect value";
    }

    // Verify non-static property values exist on prototype
    // We verify only the first few properties to ensure the fix works correctly
    JSHandle<JSTaggedValue> clsProtoVal(thread_, clsFunc->GetProtoOrHClass(thread));
    constexpr size_t verifyCount = 20;  // Verify first 20 non-static properties
    for (size_t i = 0; i < verifyCount; ++i) {
        size_t trueIdx = propertyCount - 1 - i;
        auto realProp = JSObject::GetProperty(thread_, clsProtoVal, JSNApiHelper::ToJSHandle(keys[trueIdx])).GetValue();
        uint32_t realVal = JSTaggedValue::ToUint32(thread_, realProp);
        ASSERT_EQ(realVal, static_cast<uint32_t>(trueIdx))
            << "Non-static property key[" << trueIdx << "] has incorrect value, expected " << trueIdx << " but got "
            << realVal;
    }
}
} // namespace panda::test