/*
 * Copyright (c) 2021 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 "ecmascript/base/json_helper.h"
#include "ecmascript/builtins/builtins_json.h"

#include "gtest/gtest.h"
#include <algorithm>
#include <iomanip>
#include <sstream>

#include "ecmascript/base/builtins_base.h"
#include "ecmascript/builtins/builtins_bigint.h"
#include "ecmascript/builtins/builtins_errors.h"
#include "ecmascript/builtins/builtins_proxy.h"
#include "ecmascript/builtins/builtins_typedarray.h"
#include "ecmascript/ecma_runtime_call_info.h"
#include "ecmascript/ecma_string-inl.h"
#include "ecmascript/ecma_vm.h"
#include "ecmascript/global_env.h"
#include "ecmascript/js_array.h"
#include "ecmascript/js_function.h"
#include "ecmascript/js_handle.h"
#include "ecmascript/js_object-inl.h"
#include "ecmascript/js_primitive_ref.h"
#include "ecmascript/js_tagged_value-inl.h"
#include "ecmascript/js_tagged_value.h"
#include "ecmascript/js_thread.h"
#include "ecmascript/object_factory.h"
#include "ecmascript/tests/test_helper.h"

using namespace panda::ecmascript;
using namespace panda::ecmascript::builtins;

namespace panda::test {
class BuiltinsJsonTest : public BaseTestWithScope<false> {
public:
    class TestClass : public base::BuiltinsBase {
    public:
        static JSTaggedValue TestForCommon(EcmaRuntimeCallInfo *argv)
        {
            JSTaggedValue key = GetCallArg(argv, 0).GetTaggedValue();
            if (key.IsUndefined()) {
                return JSTaggedValue::Undefined();
            }
            JSTaggedValue value = GetCallArg(argv, 1).GetTaggedValue();
            if (value.IsUndefined()) {
                return JSTaggedValue::Undefined();
            }

            return JSTaggedValue(value);
        }

        static JSTaggedValue TestForParse(EcmaRuntimeCallInfo *argv)
        {
            return TestForCommon(argv);
        }

        static JSTaggedValue TestForParse1(EcmaRuntimeCallInfo *argv)
        {
            (void)argv;
            return JSTaggedValue::Undefined();
        }

        static JSTaggedValue TestForStringfy(EcmaRuntimeCallInfo *argv)
        {
            uint32_t argc = argv->GetArgsNumber();
            if (argc > 0) {
                return TestForCommon(argv);
            }

            return JSTaggedValue::Undefined();
        }
    };
};

JSTaggedValue CreateBuiltinJSObject1(JSThread *thread, const CString keyCStr)
{
    EcmaVM *ecmaVM = thread->GetEcmaVM();
    JSHandle<GlobalEnv> globalEnv = ecmaVM->GetGlobalEnv();
    ObjectFactory *factory = ecmaVM->GetFactory();
    JSHandle<JSTaggedValue> objectFunc(globalEnv->GetObjectFunction());

    JSHandle<JSObject> jsobject(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objectFunc), objectFunc));
    EXPECT_TRUE(*jsobject != nullptr);

    JSHandle<JSTaggedValue> key(factory->NewFromASCII(&keyCStr[0]));
    JSHandle<JSTaggedValue> value(thread, JSTaggedValue(1));
    JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(jsobject), key, value);

    CString str2 = "y";
    JSHandle<JSTaggedValue> key2(factory->NewFromASCII(str2));
    JSHandle<JSTaggedValue> value2(thread, JSTaggedValue(2.5)); // 2.5 : test case
    JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(jsobject), key2, value2);

    CString str3 = "z";
    JSHandle<JSTaggedValue> key3(factory->NewFromASCII(str3));
    JSHandle<JSTaggedValue> value3(factory->NewFromASCII("abc"));
    JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(jsobject), key3, value3);

    return jsobject.GetTaggedValue();
}
// Math.abs(-10)

HWTEST_F_L0(BuiltinsJsonTest, Parse10)
{
    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();

    JSHandle<JSTaggedValue> msg(factory->NewFromASCII(
        "\t\r \n{\t\r \n \"property\"\t\r \n:\t\r \n{\t\r \n}\t\r \n,\t\r \n \"prop2\"\t\r \n:\t\r \n [\t\r \ntrue\t\r "
        "\n,\t\r \nnull\t\r \n,123.456\t\r \n] \t\r \n}\t\r \n"));
    JSHandle<EcmaString> str(JSTaggedValue::ToString(thread, msg));

    auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
    ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetCallArg(0, str.GetTaggedValue());

    [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
    JSTaggedValue result = BuiltinsJson::Parse(ecmaRuntimeCallInfo);
    ASSERT_TRUE(result.IsECMAObject());
}

HWTEST_F_L0(BuiltinsJsonTest, Parse21)
{
    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
    JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();

    JSHandle<JSTaggedValue> msg(factory->NewFromASCII("[100,2.5,\"abc\"]"));

    JSHandle<JSFunction> handleFunc = factory->NewJSFunction(env, reinterpret_cast<void *>(TestClass::TestForParse));
    JSHandle<EcmaString> str(JSTaggedValue::ToString(thread, msg));

    auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8);
    ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetCallArg(0, str.GetTaggedValue());
    ecmaRuntimeCallInfo->SetCallArg(1, handleFunc.GetTaggedValue());

    [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
    JSTaggedValue result = BuiltinsJson::Parse(ecmaRuntimeCallInfo);
    ASSERT_TRUE(result.IsECMAObject());
}

HWTEST_F_L0(BuiltinsJsonTest, Parse)
{
    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
    JSHandle<JSTaggedValue> lengthKeyHandle = thread->GlobalConstants()->GetHandledLengthString();

    JSHandle<JSTaggedValue> msg(factory->NewFromASCII("[100,2.5,\"abc\"]"));
    JSHandle<EcmaString> str(JSTaggedValue::ToString(thread, msg));
    std::vector<JSTaggedValue> args{str.GetTaggedValue()};
    auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, args, 6);

    [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
    JSTaggedValue result = BuiltinsJson::Parse(ecmaRuntimeCallInfo);
    JSTaggedValue value(static_cast<JSTaggedType>(result.GetRawData()));
    ASSERT_TRUE(value.IsECMAObject());
    JSHandle<JSObject> valueHandle(thread, value);
    JSHandle<JSTaggedValue> lenResult =
        JSObject::GetProperty(thread, JSHandle<JSTaggedValue>(valueHandle), lengthKeyHandle).GetValue();
    uint32_t length = JSTaggedValue::ToLength(thread, lenResult).ToUint32();
    EXPECT_EQ(length, 3U);
}

HWTEST_F_L0(BuiltinsJsonTest, Parse2)
{
    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
    JSHandle<JSTaggedValue> msg(factory->NewFromASCII("{\"epf\":100,\"key1\":200}"));
    JSHandle<EcmaString> str(JSTaggedValue::ToString(thread, msg));

    std::vector<JSTaggedValue> args{str.GetTaggedValue()};
    auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, args, 6);

    [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
    JSTaggedValue result = BuiltinsJson::Parse(ecmaRuntimeCallInfo);
    JSTaggedValue value(static_cast<JSTaggedType>(result.GetRawData()));
    ASSERT_TRUE(value.IsECMAObject());
    JSHandle<JSObject> valueHandle(thread, value);

    JSHandle<TaggedArray> nameList(JSObject::EnumerableOwnNames(thread, valueHandle));
    JSHandle<JSArray> nameResult = JSArray::CreateArrayFromList(thread, nameList);

    JSHandle<JSTaggedValue> handleKey(nameResult);
    JSHandle<JSTaggedValue> lengthKey(factory->NewFromASCII("length"));
    JSHandle<JSTaggedValue> lenResult = JSObject::GetProperty(thread, handleKey, lengthKey).GetValue();
    uint32_t length = JSTaggedValue::ToLength(thread, lenResult).ToUint32();
    ASSERT_EQ(length, 2U);
}

HWTEST_F_L0(BuiltinsJsonTest, Parse3)
{
    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
    JSHandle<EcmaString> str = factory->NewFromStdString("\"\\u0000\"");

    auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
    ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetCallArg(0, str.GetTaggedValue());

    [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
    JSTaggedValue result = BuiltinsJson::Parse(ecmaRuntimeCallInfo);
    uint32_t length = EcmaStringAccessor(result).GetLength();
    ASSERT_EQ(length, 1U);
}

HWTEST_F_L0(BuiltinsJsonTest, Parse4)
{
    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
    JSHandle<EcmaString> str = factory->NewFromStdString("{\n\t\"on\":\t0\n}");
    JSHandle<EcmaString> key = factory->NewFromStdString("on");

    auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
    ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetCallArg(0, str.GetTaggedValue());

    [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
    JSTaggedValue result = BuiltinsJson::Parse(ecmaRuntimeCallInfo);
    JSHandle<JSTaggedValue> value =
        JSTaggedValue::GetProperty(thread, JSHandle<JSTaggedValue>(thread, result), JSHandle<JSTaggedValue>(key))
            .GetValue();
    int32_t number = JSTaggedValue::ToInt32(thread, value);
    ASSERT_EQ(number, 0);
}


HWTEST_F_L0(BuiltinsJsonTest, Stringify11)
{
    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
    JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
    JSHandle<JSTaggedValue> obj = JSHandle<JSTaggedValue>(thread, CreateBuiltinJSObject1(thread, "x"));
    JSHandle<JSFunction> handleFunc =
        factory->NewJSFunction(env, reinterpret_cast<void *>(TestClass::TestForStringfy));

    auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 8);
    ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetCallArg(0, obj.GetTaggedValue());
    ecmaRuntimeCallInfo->SetCallArg(1, handleFunc.GetTaggedValue());

    [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
    JSTaggedValue result = BuiltinsJson::Stringify(ecmaRuntimeCallInfo);
    ASSERT_TRUE(result.IsString());
}

HWTEST_F_L0(BuiltinsJsonTest, Stringify12)
{
    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
    JSHandle<JSTaggedValue> obj = JSHandle<JSTaggedValue>(thread, CreateBuiltinJSObject1(thread, "x"));
    JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
    JSHandle<JSFunction> handleFunc =
        factory->NewJSFunction(env, reinterpret_cast<void *>(TestClass::TestForStringfy));

    auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 10);
    ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetCallArg(0, obj.GetTaggedValue());
    ecmaRuntimeCallInfo->SetCallArg(1, handleFunc.GetTaggedValue());
    ecmaRuntimeCallInfo->SetCallArg(2, JSTaggedValue(static_cast<int32_t>(10)));

    [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
    JSTaggedValue result = BuiltinsJson::Stringify(ecmaRuntimeCallInfo);
    ASSERT_TRUE(result.IsString());
}

HWTEST_F_L0(BuiltinsJsonTest, Stringify13)
{
    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
    JSHandle<JSTaggedValue> obj = JSHandle<JSTaggedValue>(thread, CreateBuiltinJSObject1(thread, "x"));
    JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
    JSHandle<JSFunction> handleFunc =
        factory->NewJSFunction(env, reinterpret_cast<void *>(TestClass::TestForStringfy));
    JSHandle<JSTaggedValue> msg(factory->NewFromASCII("tttt"));
    JSHandle<EcmaString> str(JSTaggedValue::ToString(thread, msg));

    std::vector<JSTaggedValue> args{obj.GetTaggedValue(), handleFunc.GetTaggedValue(), str.GetTaggedValue()};
    auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, args, 10);

    [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
    JSTaggedValue result = BuiltinsJson::Stringify(ecmaRuntimeCallInfo);
    ASSERT_TRUE(result.IsString());
}

HWTEST_F_L0(BuiltinsJsonTest, Stringify14)
{
    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
    JSHandle<JSTaggedValue> obj = JSHandle<JSTaggedValue>(thread, CreateBuiltinJSObject1(thread, "x"));
    JSArray *arr = JSArray::Cast(JSArray::ArrayCreate(thread, JSTaggedNumber(0)).GetTaggedValue().GetTaggedObject());

    JSHandle<JSObject> obj1(thread, arr);
    JSHandle<JSTaggedValue> key0(thread, JSTaggedValue(0));
    JSHandle<JSTaggedValue> value0(factory->NewFromASCII("x"));
    JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj), key0, value0);
    JSHandle<JSTaggedValue> key1(thread, JSTaggedValue(1));
    JSHandle<JSTaggedValue> value1(factory->NewFromASCII("z"));
    JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj), key1, value1);

    JSHandle<JSTaggedValue> msg(factory->NewFromASCII("tttt"));
    JSHandle<EcmaString> str(JSTaggedValue::ToString(thread, msg));

    auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 10);
    ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetCallArg(0, obj.GetTaggedValue());
    ecmaRuntimeCallInfo->SetCallArg(1, obj1.GetTaggedValue());
    ecmaRuntimeCallInfo->SetCallArg(2, str.GetTaggedValue());

    [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
    JSTaggedValue result = BuiltinsJson::Stringify(ecmaRuntimeCallInfo);
    ASSERT_TRUE(result.IsString());
}

HWTEST_F_L0(BuiltinsJsonTest, Stringify)
{
    JSHandle<JSTaggedValue> obj = JSHandle<JSTaggedValue>(thread, CreateBuiltinJSObject1(thread, "x"));
    auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
    ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetCallArg(0, obj.GetTaggedValue());

    [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
    JSTaggedValue result = BuiltinsJson::Stringify(ecmaRuntimeCallInfo);
    ASSERT_TRUE(result.IsString());
}

HWTEST_F_L0(BuiltinsJsonTest, Stringify1)
{
    auto ecmaVM = thread->GetEcmaVM();
    ObjectFactory *factory = ecmaVM->GetFactory();
    JSHandle<GlobalEnv> env = ecmaVM->GetGlobalEnv();

    JSArray *arr = JSArray::Cast(JSArray::ArrayCreate(thread, JSTaggedNumber(0)).GetTaggedValue().GetTaggedObject());

    EXPECT_TRUE(arr != nullptr);
    JSHandle<JSObject> obj(thread, arr);
    JSHandle<JSTaggedValue> key0(thread, JSTaggedValue(0));

    JSHandle<JSTaggedValue> value(factory->NewFromASCII("def"));
    JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj), key0, value);

    JSHandle<JSTaggedValue> key1(thread, JSTaggedValue(1));
    PropertyDescriptor desc1(thread, JSHandle<JSTaggedValue>(thread, JSTaggedValue(200)), true, true, true);
    JSArray::DefineOwnProperty(thread, obj, key1, desc1);

    JSHandle<JSTaggedValue> key2(thread, JSTaggedValue(2));
    JSHandle<JSTaggedValue> value2(factory->NewFromASCII("abc"));
    JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj), key2, value2);

    JSHandle<JSFunction> handleFunc =
        factory->NewJSFunction(env, reinterpret_cast<void *>(TestClass::TestForStringfy));
    JSHandle<JSTaggedValue> msg(factory->NewFromASCII("tttt"));
    JSHandle<EcmaString> str(JSTaggedValue::ToString(thread, msg));

    std::vector<JSTaggedValue> args{obj.GetTaggedValue(), handleFunc.GetTaggedValue(), str.GetTaggedValue()};
    auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, args, 10);

    [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
    JSTaggedValue result = BuiltinsJson::Stringify(ecmaRuntimeCallInfo);
    ASSERT_TRUE(result.IsString());
}

HWTEST_F_L0(BuiltinsJsonTest, Stringify2)
{
    auto ecmaVM = thread->GetEcmaVM();
    ObjectFactory *factory = ecmaVM->GetFactory();

    JSArray *arr = JSArray::Cast(JSArray::ArrayCreate(thread, JSTaggedNumber(0)).GetTaggedValue().GetTaggedObject());
    EXPECT_TRUE(arr != nullptr);
    JSHandle<JSObject> obj(thread, arr);

    JSHandle<JSTaggedValue> key0(thread, JSTaggedValue(0));
    PropertyDescriptor desc0(thread, JSHandle<JSTaggedValue>(thread, JSTaggedValue(1)), true, true, true);
    JSArray::DefineOwnProperty(thread, obj, key0, desc0);
    JSHandle<JSTaggedValue> key1(thread, JSTaggedValue(1));
    // 2.5 : test case
    PropertyDescriptor desc1(thread, JSHandle<JSTaggedValue>(thread, JSTaggedValue(2.5)), true, true, true);
    JSArray::DefineOwnProperty(thread, obj, key1, desc1);
    // 2 : test case
    JSHandle<JSTaggedValue> key2(thread, JSTaggedValue(2));
    JSHandle<JSTaggedValue> value2(factory->NewFromASCII("abc"));
    JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(obj), key2, value2);

    auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
    ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetCallArg(0, obj.GetTaggedValue());

    [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
    JSTaggedValue result = BuiltinsJson::Stringify(ecmaRuntimeCallInfo);
    ASSERT_TRUE(result.IsString());
}

HWTEST_F_L0(BuiltinsJsonTest, Stringify3)
{
    auto ecmaVM = thread->GetEcmaVM();
    ObjectFactory *factory = ecmaVM->GetFactory();

    uint16_t data[1];
    data[0] = 0;
    JSHandle<EcmaString> str = factory->NewFromUtf16(data, 1);
    JSHandle<EcmaString> test = factory->NewFromStdString("\"\\u0000\"");

    auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
    ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetCallArg(0, str.GetTaggedValue());

    [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
    JSTaggedValue result = BuiltinsJson::Stringify(ecmaRuntimeCallInfo);
    ASSERT_TRUE(EcmaStringAccessor::StringsAreEqual(thread, *test, EcmaString::Cast(result.GetTaggedObject())));
}

JSHandle<JSTaggedValue> CreateJSObject(JSThread *thread)
{
    EcmaVM *ecmaVM = thread->GetEcmaVM();
    JSHandle<GlobalEnv> globalEnv = ecmaVM->GetGlobalEnv();
    JSHandle<JSTaggedValue> objFun = globalEnv->GetObjectFunction();
    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();

    JSHandle<JSTaggedValue> obj(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objFun), objFun));
    JSHandle<JSTaggedValue> key(factory->NewFromStdString("x"));
    JSHandle<JSTaggedValue> value(thread, JSTaggedValue(1));
    JSObject::SetProperty(thread, obj, key, value);
    return obj;
}

JSHandle<JSTaggedValue> CreateProxy(JSThread *thread)
{
    JSHandle<JSTaggedValue> target = CreateJSObject(thread);
    JSHandle<JSTaggedValue> handler = CreateJSObject(thread);

    auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Null(), 8);
    ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetCallArg(0, target.GetTaggedValue());
    ecmaRuntimeCallInfo->SetCallArg(1, handler.GetTaggedValue());

    [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
    JSTaggedValue result = BuiltinsProxy::ProxyConstructor(ecmaRuntimeCallInfo);
    TestHelper::TearDownFrame(thread, prev);
    return JSHandle<JSTaggedValue>(thread, result);
}

HWTEST_F_L0(BuiltinsJsonTest, Stringify4)  // Test for proxy object
{
    auto ecmaVM = thread->GetEcmaVM();
    ObjectFactory *factory = ecmaVM->GetFactory();

    JSHandle<JSTaggedValue> proxy = CreateProxy(thread);
    JSHandle<EcmaString> test = factory->NewFromStdString("{\"x\":1}");

    auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
    ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetCallArg(0, proxy.GetTaggedValue());

    [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
    JSTaggedValue result = BuiltinsJson::Stringify(ecmaRuntimeCallInfo);
    ASSERT_TRUE(EcmaStringAccessor::StringsAreEqual(thread, *test, EcmaString::Cast(result.GetTaggedObject())));
    TestHelper::TearDownFrame(thread, prev);
}

HWTEST_F_L0(BuiltinsJsonTest, Stringify5)  // Test for typedarray object
{
    auto ecmaVM = thread->GetEcmaVM();
    ObjectFactory *factory = ecmaVM->GetFactory();
    [[maybe_unused]] JSHandle<TaggedArray> array(factory->NewTaggedArray(3));
    array->Set(thread, 0, JSTaggedValue(2));
    array->Set(thread, 1, JSTaggedValue(3));
    array->Set(thread, 2, JSTaggedValue(4));

    JSHandle<GlobalEnv> env = ecmaVM->GetGlobalEnv();
    JSHandle<JSTaggedValue> jsArray(JSArray::CreateArrayFromList(thread, array));
    JSHandle<JSFunction> int8Func(env->GetInt8ArrayFunction());
    JSHandle<JSObject> globalObject(thread, env->GetGlobalObject());
    auto ecmaRuntimeCallInfo1 = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
    ecmaRuntimeCallInfo1->SetNewTarget(JSTaggedValue(*int8Func));
    ecmaRuntimeCallInfo1->SetThis(JSTaggedValue(*globalObject));
    ecmaRuntimeCallInfo1->SetCallArg(0, jsArray.GetTaggedValue());

    [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo1);
    JSHandle<JSTaggedValue> int8Array(thread, BuiltinsTypedArray::Int8ArrayConstructor(ecmaRuntimeCallInfo1));
    TestHelper::TearDownFrame(thread, prev);

    JSHandle<EcmaString> test = factory->NewFromStdString("{\"0\":2,\"1\":3,\"2\":4}");

    auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
    ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetCallArg(0, int8Array.GetTaggedValue());

    prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
    JSTaggedValue result = BuiltinsJson::Stringify(ecmaRuntimeCallInfo);
    TestHelper::TearDownFrame(thread, prev);
    ASSERT_TRUE(result.IsString());
    ASSERT_TRUE(EcmaStringAccessor::StringsAreEqual(thread, *test, EcmaString::Cast(result.GetTaggedObject())));
}

HWTEST_F_L0(BuiltinsJsonTest, Stringify6)  // Test for bigint object
{
    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
    JSHandle<JSTaggedValue> numericValue(factory->NewFromASCII("123456789123456789"));

    auto ecmaRuntimeCallInfo1 = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
    ecmaRuntimeCallInfo1->SetFunction(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo1->SetThis(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo1->SetCallArg(0, numericValue.GetTaggedValue());

    [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo1);
    JSTaggedValue result1 = BuiltinsBigInt::BigIntConstructor(ecmaRuntimeCallInfo1);
    TestHelper::TearDownFrame(thread, prev);

    JSHandle<JSTaggedValue> bigIntHandle(thread, result1);

    auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
    ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetCallArg(0, bigIntHandle.GetTaggedValue());

    prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
    [[maybe_unused]] JSTaggedValue result = BuiltinsJson::Stringify(ecmaRuntimeCallInfo);
    bool hasPendingException = false;
    if (thread->HasPendingException()) {
        hasPendingException = true;
        thread->ClearException();
    }
    ASSERT_TRUE(hasPendingException);
}

HWTEST_F_L0(BuiltinsJsonTest, StringifyAndParse)
{
    auto ecmaVM = thread->GetEcmaVM();
    ObjectFactory *factory = ecmaVM->GetFactory();
    JSHandle<JSTaggedValue> obj = CreateJSObject(thread);
    JSHandle<JSTaggedValue> ykey(factory->NewFromASCII("y"));
    JSHandle<JSTaggedValue> yvalue(thread, JSTaggedValue(2.2)); // 2.2: use to test double value
    JSObject::SetProperty(thread, obj, ykey, yvalue);

    auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
    ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetCallArg(0, obj.GetTaggedValue());
    JSMutableHandle<JSTaggedValue> result(thread, JSTaggedValue::Hole());
    {
        [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
        result.Update(BuiltinsJson::Stringify(ecmaRuntimeCallInfo));
        TestHelper::TearDownFrame(thread, prev);
    }
    {
        ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
        ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
        ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
        ecmaRuntimeCallInfo->SetCallArg(0, result.GetTaggedValue());
        [[maybe_unused]] auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
        result.Update(BuiltinsJson::Parse(ecmaRuntimeCallInfo));
        TestHelper::TearDownFrame(thread, prev);
    }
    ASSERT_TRUE(result->IsECMAObject());

    JSHandle<JSObject> resultObj(result);
    JSHandle<JSTaggedValue> key(factory->NewFromASCII("x"));
    JSHandle<JSTaggedValue> res = JSObject::GetProperty(thread, resultObj, key).GetValue();
    ASSERT_TRUE(res->IsInt());
    ASSERT_EQ(res->GetInt(), 1);

    res = JSObject::GetProperty(thread, resultObj, ykey).GetValue();
    ASSERT_TRUE(res->IsDouble());
    ASSERT_EQ(res->GetDouble(), 2.2); // 2.2:use to test double value
}

HWTEST_F_L0(BuiltinsJsonTest, ParseErrorMessageUtf16)
{
    auto ecmaVM = thread->GetEcmaVM();
    ObjectFactory *factory = ecmaVM->GetFactory();

    JSHandle<JSTaggedValue> str(
        factory->NewFromUtf8("{\"姓名\": \"小明\",\n \"age\": 30,\"表情\":\"aaaaaaaaaa😄🙃😇😄🙃😇😄🙃😇aaa\""));
    auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
    ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetCallArg(0, str.GetTaggedValue());
    auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
    BuiltinsJson::Parse(ecmaRuntimeCallInfo);
    TestHelper::TearDownFrame(thread, prev);
    bool hasPendingException = false;
    if (thread->HasPendingException()) {
        hasPendingException = true;
        thread->ClearException();
    }
    ASSERT_TRUE(hasPendingException);
    JSHandle<JSTaggedValue> extraErrorMessage(thread, thread->GetExtraErrorMessage());
    uint32_t position = thread->GetJsonErrorPosition();
    ASSERT_TRUE(extraErrorMessage->IsString());
    std::pair<std::string, uint32_t> res =
        base::JsonHelper::AnonymizeJsonString(thread, extraErrorMessage, position, 15);
    std::string str1 = "a*a*🙃*😄*😇*🙃*a*a\"";
    ASSERT_EQ(str1.length(), res.first.length());
    ASSERT_EQ(str1, res.first);
}

HWTEST_F_L0(BuiltinsJsonTest, ParseErrorMessageUtf8)
{
    auto ecmaVM = thread->GetEcmaVM();
    ObjectFactory *factory = ecmaVM->GetFactory();

    JSHandle<JSTaggedValue> str(factory->NewFromUtf8(
        "{\"namxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxe\":\"tom\","
        "sex:\"F\",age:18,email:\"123@qq.com\"}"));
    auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
    ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetCallArg(0, str.GetTaggedValue());
    auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
    BuiltinsJson::Parse(ecmaRuntimeCallInfo);
    TestHelper::TearDownFrame(thread, prev);
    bool hasPendingException = false;
    if (thread->HasPendingException()) {
        hasPendingException = true;
        thread->ClearException();
    }
    ASSERT_TRUE(hasPendingException);
    JSHandle<JSTaggedValue> extraErrorMessage(thread, thread->GetExtraErrorMessage());
    uint32_t position = thread->GetJsonErrorPosition();
    ASSERT_TRUE(extraErrorMessage->IsString());
    std::pair<std::string, uint32_t> res =
        base::JsonHelper::AnonymizeJsonString(thread, extraErrorMessage, position, 15);
    std::string str1 = "x*x*x*e\":\"t*m\",s*x:\"F\",a*e:1*,";
    ASSERT_EQ(str1.length(), res.first.length());
    ASSERT_EQ(str1, res.first);
}

HWTEST_F_L0(BuiltinsJsonTest, ParseErrorMissingComma)
{
    auto ecmaVM = thread->GetEcmaVM();
    ObjectFactory *factory = ecmaVM->GetFactory();

    JSHandle<JSTaggedValue> str(factory->NewFromASCII("{\"name\":\"tom\"\"age\":18}"));
    auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
    ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetCallArg(0, str.GetTaggedValue());
    auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
    BuiltinsJson::Parse(ecmaRuntimeCallInfo);
    TestHelper::TearDownFrame(thread, prev);
    bool hasPendingException = false;
    if (thread->HasPendingException()) {
        hasPendingException = true;
        thread->ClearException();
    }
    ASSERT_TRUE(hasPendingException);
    JSHandle<JSTaggedValue> extraErrorMessage(thread, thread->GetExtraErrorMessage());
    uint32_t position = thread->GetJsonErrorPosition();
    ASSERT_TRUE(extraErrorMessage->IsString());
    std::pair<std::string, uint32_t> res =
        base::JsonHelper::AnonymizeJsonString(thread, extraErrorMessage, position, 15);
    ASSERT_EQ(res.first, "{\"n*m*\":\"t*m\"\"a*e\":1*}");
    ASSERT_EQ(res.second, 13U);
}

HWTEST_F_L0(BuiltinsJsonTest, ParseErrorUnclosedObject)
{
    auto ecmaVM = thread->GetEcmaVM();
    ObjectFactory *factory = ecmaVM->GetFactory();

    JSHandle<JSTaggedValue> str(factory->NewFromASCII("{\"name\":\"tom\",\"age\":18"));
    auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
    ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetCallArg(0, str.GetTaggedValue());
    auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
    BuiltinsJson::Parse(ecmaRuntimeCallInfo);
    TestHelper::TearDownFrame(thread, prev);
    bool hasPendingException = false;
    if (thread->HasPendingException()) {
        hasPendingException = true;
        thread->ClearException();
    }
    ASSERT_TRUE(hasPendingException);
    JSHandle<JSTaggedValue> extraErrorMessage(thread, thread->GetExtraErrorMessage());
    uint32_t position = thread->GetJsonErrorPosition();
    ASSERT_TRUE(extraErrorMessage->IsString());
    std::pair<std::string, uint32_t> res =
        base::JsonHelper::AnonymizeJsonString(thread, extraErrorMessage, position, 15);
    ASSERT_EQ(res.first, "\":\"t*m\",\"a*e\":1*");
    ASSERT_EQ(res.second, 15U);
}

HWTEST_F_L0(BuiltinsJsonTest, ParseErrorUnclosedArray)
{
    auto ecmaVM = thread->GetEcmaVM();
    ObjectFactory *factory = ecmaVM->GetFactory();

    JSHandle<JSTaggedValue> str(factory->NewFromASCII("[1,2,3"));
    auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
    ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetCallArg(0, str.GetTaggedValue());
    auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
    BuiltinsJson::Parse(ecmaRuntimeCallInfo);
    TestHelper::TearDownFrame(thread, prev);
    bool hasPendingException = false;
    if (thread->HasPendingException()) {
        hasPendingException = true;
        thread->ClearException();
    }
    ASSERT_TRUE(hasPendingException);
    JSHandle<JSTaggedValue> extraErrorMessage(thread, thread->GetExtraErrorMessage());
    uint32_t position = thread->GetJsonErrorPosition();
    ASSERT_TRUE(extraErrorMessage->IsString());
    std::pair<std::string, uint32_t> res =
        base::JsonHelper::AnonymizeJsonString(thread, extraErrorMessage, position, 15);
    ASSERT_EQ(res.first, "[1,2,3");
    ASSERT_EQ(res.second, 5U);
}

HWTEST_F_L0(BuiltinsJsonTest, ParseErrorTrailingCommaInObject)
{
    auto ecmaVM = thread->GetEcmaVM();
    ObjectFactory *factory = ecmaVM->GetFactory();

    JSHandle<JSTaggedValue> str(factory->NewFromASCII("{\"name\":\"tom\",\"age\":18,}"));
    auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
    ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetCallArg(0, str.GetTaggedValue());
    auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
    BuiltinsJson::Parse(ecmaRuntimeCallInfo);
    TestHelper::TearDownFrame(thread, prev);
    bool hasPendingException = false;
    if (thread->HasPendingException()) {
        hasPendingException = true;
        thread->ClearException();
    }
    ASSERT_TRUE(hasPendingException);
    JSHandle<JSTaggedValue> extraErrorMessage(thread, thread->GetExtraErrorMessage());
    uint32_t position = thread->GetJsonErrorPosition();
    ASSERT_TRUE(extraErrorMessage->IsString());
    std::pair<std::string, uint32_t> res =
        base::JsonHelper::AnonymizeJsonString(thread, extraErrorMessage, position, 15);
    ASSERT_EQ(res.first, "\"t*m\",\"a*e\":1*,}");
    ASSERT_EQ(res.second, 15U);
}

HWTEST_F_L0(BuiltinsJsonTest, ParseErrorTrailingCommaInArray)
{
    auto ecmaVM = thread->GetEcmaVM();
    ObjectFactory *factory = ecmaVM->GetFactory();

    JSHandle<JSTaggedValue> str(factory->NewFromASCII("[1,2,3,]"));
    auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
    ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetCallArg(0, str.GetTaggedValue());
    auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
    BuiltinsJson::Parse(ecmaRuntimeCallInfo);
    TestHelper::TearDownFrame(thread, prev);
    bool hasPendingException = false;
    if (thread->HasPendingException()) {
        hasPendingException = true;
        thread->ClearException();
    }
    ASSERT_TRUE(hasPendingException);
    JSHandle<JSTaggedValue> extraErrorMessage(thread, thread->GetExtraErrorMessage());
    uint32_t position = thread->GetJsonErrorPosition();
    ASSERT_TRUE(extraErrorMessage->IsString());
    std::pair<std::string, uint32_t> res =
        base::JsonHelper::AnonymizeJsonString(thread, extraErrorMessage, position, 15);
    ASSERT_EQ(res.first, "[1,2,3,]");
    ASSERT_EQ(res.second, 7U);
}

HWTEST_F_L0(BuiltinsJsonTest, ParseErrorMissingColon)
{
    auto ecmaVM = thread->GetEcmaVM();
    ObjectFactory *factory = ecmaVM->GetFactory();

    JSHandle<JSTaggedValue> str(factory->NewFromASCII("{\"name\"\"tom\"}"));
    auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
    ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetCallArg(0, str.GetTaggedValue());
    auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
    BuiltinsJson::Parse(ecmaRuntimeCallInfo);
    TestHelper::TearDownFrame(thread, prev);
    bool hasPendingException = false;
    if (thread->HasPendingException()) {
        hasPendingException = true;
        thread->ClearException();
    }
    ASSERT_TRUE(hasPendingException);
    JSHandle<JSTaggedValue> extraErrorMessage(thread, thread->GetExtraErrorMessage());
    uint32_t position = thread->GetJsonErrorPosition();
    ASSERT_TRUE(extraErrorMessage->IsString());
    std::pair<std::string, uint32_t> res =
        base::JsonHelper::AnonymizeJsonString(thread, extraErrorMessage, position, 15);
    ASSERT_EQ(res.first, "{\"n*m*\"\"t*m\"}");
    ASSERT_EQ(res.second, 7U);
}

HWTEST_F_L0(BuiltinsJsonTest, ParseErrorInvalidStringEscape)
{
    auto ecmaVM = thread->GetEcmaVM();
    ObjectFactory *factory = ecmaVM->GetFactory();

    JSHandle<JSTaggedValue> str(factory->NewFromASCII("{\"name\":\"tom\\x\"}"));
    auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
    ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetCallArg(0, str.GetTaggedValue());
    auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
    BuiltinsJson::Parse(ecmaRuntimeCallInfo);
    TestHelper::TearDownFrame(thread, prev);
    bool hasPendingException = false;
    if (thread->HasPendingException()) {
        hasPendingException = true;
        thread->ClearException();
    }
    ASSERT_TRUE(hasPendingException);
    JSHandle<JSTaggedValue> extraErrorMessage(thread, thread->GetExtraErrorMessage());
    uint32_t position = thread->GetJsonErrorPosition();
    ASSERT_TRUE(extraErrorMessage->IsString());
    std::pair<std::string, uint32_t> res =
        base::JsonHelper::AnonymizeJsonString(thread, extraErrorMessage, position, 15);
    ASSERT_EQ(res.first, "{\"n*m*\":\"t*m*x\"}");
    ASSERT_EQ(res.second, 13U);
}

HWTEST_F_L0(BuiltinsJsonTest, ParseErrorUnclosedString)
{
    auto ecmaVM = thread->GetEcmaVM();
    ObjectFactory *factory = ecmaVM->GetFactory();

    JSHandle<JSTaggedValue> str(factory->NewFromASCII("{\"name\":\"tom"));
    auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
    ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetCallArg(0, str.GetTaggedValue());
    auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
    BuiltinsJson::Parse(ecmaRuntimeCallInfo);
    TestHelper::TearDownFrame(thread, prev);
    bool hasPendingException = false;
    if (thread->HasPendingException()) {
        hasPendingException = true;
        thread->ClearException();
    }
    ASSERT_TRUE(hasPendingException);
    JSHandle<JSTaggedValue> extraErrorMessage(thread, thread->GetExtraErrorMessage());
    uint32_t position = thread->GetJsonErrorPosition();
    ASSERT_TRUE(extraErrorMessage->IsString());
    std::pair<std::string, uint32_t> res =
        base::JsonHelper::AnonymizeJsonString(thread, extraErrorMessage, position, 15);
    ASSERT_EQ(res.first, "{\"n*m*\":\"t*m");
    ASSERT_EQ(res.second, 11U);
}

HWTEST_F_L0(BuiltinsJsonTest, ParseErrorInvalidNumber)
{
    auto ecmaVM = thread->GetEcmaVM();
    ObjectFactory *factory = ecmaVM->GetFactory();

    JSHandle<JSTaggedValue> str(factory->NewFromASCII("{\"age\":01}"));
    auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
    ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetCallArg(0, str.GetTaggedValue());
    auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
    BuiltinsJson::Parse(ecmaRuntimeCallInfo);
    TestHelper::TearDownFrame(thread, prev);
    bool hasPendingException = false;
    if (thread->HasPendingException()) {
        hasPendingException = true;
        thread->ClearException();
    }
    ASSERT_TRUE(hasPendingException);
    JSHandle<JSTaggedValue> extraErrorMessage(thread, thread->GetExtraErrorMessage());
    uint32_t position = thread->GetJsonErrorPosition();
    ASSERT_TRUE(extraErrorMessage->IsString());
    std::pair<std::string, uint32_t> res =
        base::JsonHelper::AnonymizeJsonString(thread, extraErrorMessage, position, 15);
    ASSERT_EQ(res.first, "{\"a*e\":0*}");
    ASSERT_EQ(res.second, 8U);
}

HWTEST_F_L0(BuiltinsJsonTest, ParseErrorInvalidLiteral)
{
    auto ecmaVM = thread->GetEcmaVM();
    ObjectFactory *factory = ecmaVM->GetFactory();

    JSHandle<JSTaggedValue> str(factory->NewFromASCII("{\"active\":tru}"));
    auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
    ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetCallArg(0, str.GetTaggedValue());
    auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
    BuiltinsJson::Parse(ecmaRuntimeCallInfo);
    TestHelper::TearDownFrame(thread, prev);
    bool hasPendingException = false;
    if (thread->HasPendingException()) {
        hasPendingException = true;
        thread->ClearException();
    }
    ASSERT_TRUE(hasPendingException);
    JSHandle<JSTaggedValue> extraErrorMessage(thread, thread->GetExtraErrorMessage());
    uint32_t position = thread->GetJsonErrorPosition();
    ASSERT_TRUE(extraErrorMessage->IsString());
    std::pair<std::string, uint32_t> res =
        base::JsonHelper::AnonymizeJsonString(thread, extraErrorMessage, position, 15);
    ASSERT_EQ(res.first, "{\"a*t*v*\":t*u}");
    ASSERT_EQ(res.second, 10U);
}

HWTEST_F_L0(BuiltinsJsonTest, ParseErrorUnquotedKey)
{
    auto ecmaVM = thread->GetEcmaVM();
    ObjectFactory *factory = ecmaVM->GetFactory();

    JSHandle<JSTaggedValue> str(factory->NewFromASCII("{name:\"tom\"}"));
    auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
    ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetCallArg(0, str.GetTaggedValue());
    auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
    BuiltinsJson::Parse(ecmaRuntimeCallInfo);
    TestHelper::TearDownFrame(thread, prev);
    bool hasPendingException = false;
    if (thread->HasPendingException()) {
        hasPendingException = true;
        thread->ClearException();
    }
    ASSERT_TRUE(hasPendingException);
    JSHandle<JSTaggedValue> extraErrorMessage(thread, thread->GetExtraErrorMessage());
    uint32_t position = thread->GetJsonErrorPosition();
    ASSERT_TRUE(extraErrorMessage->IsString());
    std::pair<std::string, uint32_t> res =
        base::JsonHelper::AnonymizeJsonString(thread, extraErrorMessage, position, 15);
    ASSERT_EQ(res.first, "{n*m*:\"t*m\"}");
    ASSERT_EQ(res.second, 1U);
}

HWTEST_F_L0(BuiltinsJsonTest, ParseErrorUnexpectedEnd)
{
    auto ecmaVM = thread->GetEcmaVM();
    ObjectFactory *factory = ecmaVM->GetFactory();

    JSHandle<JSTaggedValue> str(factory->NewFromASCII("{\"name\":"));
    auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
    ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetCallArg(0, str.GetTaggedValue());
    auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
    BuiltinsJson::Parse(ecmaRuntimeCallInfo);
    TestHelper::TearDownFrame(thread, prev);
    bool hasPendingException = false;
    if (thread->HasPendingException()) {
        hasPendingException = true;
        thread->ClearException();
    }
    ASSERT_TRUE(hasPendingException);
    JSHandle<JSTaggedValue> extraErrorMessage(thread, thread->GetExtraErrorMessage());
    uint32_t position = thread->GetJsonErrorPosition();
    ASSERT_TRUE(extraErrorMessage->IsString());
    std::pair<std::string, uint32_t> res =
        base::JsonHelper::AnonymizeJsonString(thread, extraErrorMessage, position, 15);
    ASSERT_EQ(res.first, "{\"n*m*\":");
    ASSERT_EQ(res.second, 8U);
}

HWTEST_F_L0(BuiltinsJsonTest, ParseErrorControlCharInString)
{
    auto ecmaVM = thread->GetEcmaVM();
    ObjectFactory *factory = ecmaVM->GetFactory();

    JSHandle<JSTaggedValue> str(factory->NewFromASCII("{\"name\":\"to\x01m\"}"));
    auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
    ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetCallArg(0, str.GetTaggedValue());
    auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
    BuiltinsJson::Parse(ecmaRuntimeCallInfo);
    TestHelper::TearDownFrame(thread, prev);
    bool hasPendingException = false;
    if (thread->HasPendingException()) {
        hasPendingException = true;
        thread->ClearException();
    }
    ASSERT_TRUE(hasPendingException);
    JSHandle<JSTaggedValue> extraErrorMessage(thread, thread->GetExtraErrorMessage());
    uint32_t position = thread->GetJsonErrorPosition();
    ASSERT_TRUE(extraErrorMessage->IsString());
    std::pair<std::string, uint32_t> res =
        base::JsonHelper::AnonymizeJsonString(thread, extraErrorMessage, position, 15);
    ASSERT_EQ(res.first, "{\"n*m*\":\"t*\x01*\"}");
    ASSERT_EQ(res.second, 11U);
}

HWTEST_F_L0(BuiltinsJsonTest, ParseErrorNewlineInString)
{
    auto ecmaVM = thread->GetEcmaVM();
    ObjectFactory *factory = ecmaVM->GetFactory();

    JSHandle<JSTaggedValue> str(factory->NewFromASCII("{\"name\":\"tom\n\"}"));
    auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
    ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetCallArg(0, str.GetTaggedValue());
    auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
    BuiltinsJson::Parse(ecmaRuntimeCallInfo);
    TestHelper::TearDownFrame(thread, prev);
    bool hasPendingException = false;
    if (thread->HasPendingException()) {
        hasPendingException = true;
        thread->ClearException();
    }
    ASSERT_TRUE(hasPendingException);
    JSHandle<JSTaggedValue> extraErrorMessage(thread, thread->GetExtraErrorMessage());
    uint32_t position = thread->GetJsonErrorPosition();
    ASSERT_TRUE(extraErrorMessage->IsString());
    std::pair<std::string, uint32_t> res =
        base::JsonHelper::AnonymizeJsonString(thread, extraErrorMessage, position, 15);
    ASSERT_EQ(res.first, "{\"n*m*\":\"t*m\n\"}");
    ASSERT_EQ(res.second, 12U);
}

HWTEST_F_L0(BuiltinsJsonTest, ParseErrorTabInString)
{
    auto ecmaVM = thread->GetEcmaVM();
    ObjectFactory *factory = ecmaVM->GetFactory();

    JSHandle<JSTaggedValue> str(factory->NewFromASCII("{\"name\":\"to\tm\"}"));
    auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
    ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetCallArg(0, str.GetTaggedValue());
    auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
    BuiltinsJson::Parse(ecmaRuntimeCallInfo);
    TestHelper::TearDownFrame(thread, prev);
    bool hasPendingException = false;
    if (thread->HasPendingException()) {
        hasPendingException = true;
        thread->ClearException();
    }
    ASSERT_TRUE(hasPendingException);
    JSHandle<JSTaggedValue> extraErrorMessage(thread, thread->GetExtraErrorMessage());
    uint32_t position = thread->GetJsonErrorPosition();
    ASSERT_TRUE(extraErrorMessage->IsString());
    std::pair<std::string, uint32_t> res =
        base::JsonHelper::AnonymizeJsonString(thread, extraErrorMessage, position, 15);
    ASSERT_EQ(res.first, "{\"n*m*\":\"t*\tm\"}");
    ASSERT_EQ(res.second, 11U);
}

HWTEST_F_L0(BuiltinsJsonTest, ParseErrorNullByteInString)
{
    auto ecmaVM = thread->GetEcmaVM();
    ObjectFactory *factory = ecmaVM->GetFactory();

    std::string data = "{\"name\":\"tom";
    data += '\x00';
    data += "\"}";
    JSHandle<EcmaString> str = factory->NewFromStdString(data);
    auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
    ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetCallArg(0, str.GetTaggedValue());
    auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
    BuiltinsJson::Parse(ecmaRuntimeCallInfo);
    TestHelper::TearDownFrame(thread, prev);
    bool hasPendingException = false;
    if (thread->HasPendingException()) {
        hasPendingException = true;
        thread->ClearException();
    }
    ASSERT_TRUE(hasPendingException);
    JSHandle<JSTaggedValue> extraErrorMessage(thread, thread->GetExtraErrorMessage());
    uint32_t position = thread->GetJsonErrorPosition();
    ASSERT_TRUE(extraErrorMessage->IsString());
    std::pair<std::string, uint32_t> res =
        base::JsonHelper::AnonymizeJsonString(thread, extraErrorMessage, position, 15);
    ASSERT_EQ(res.first, "{\"n*m*\":\"t*m*\"}");
    ASSERT_EQ(res.second, 12U);
}

HWTEST_F_L0(BuiltinsJsonTest, ParseErrorMissingOpeningQuote)
{
    auto ecmaVM = thread->GetEcmaVM();
    ObjectFactory *factory = ecmaVM->GetFactory();

    JSHandle<JSTaggedValue> str(factory->NewFromASCII("{name:\"tom\"}"));
    auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
    ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetCallArg(0, str.GetTaggedValue());
    auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
    BuiltinsJson::Parse(ecmaRuntimeCallInfo);
    TestHelper::TearDownFrame(thread, prev);
    bool hasPendingException = false;
    if (thread->HasPendingException()) {
        hasPendingException = true;
        thread->ClearException();
    }
    ASSERT_TRUE(hasPendingException);
    JSHandle<JSTaggedValue> extraErrorMessage(thread, thread->GetExtraErrorMessage());
    uint32_t position = thread->GetJsonErrorPosition();
    ASSERT_TRUE(extraErrorMessage->IsString());
    std::pair<std::string, uint32_t> res =
        base::JsonHelper::AnonymizeJsonString(thread, extraErrorMessage, position, 15);
    ASSERT_EQ(res.first, "{n*m*:\"t*m\"}");
    ASSERT_EQ(res.second, 1U);
}

HWTEST_F_L0(BuiltinsJsonTest, ParseErrorMissingClosingQuote)
{
    auto ecmaVM = thread->GetEcmaVM();
    ObjectFactory *factory = ecmaVM->GetFactory();

    JSHandle<JSTaggedValue> str(factory->NewFromASCII("{\"name:\"tom\"}"));
    auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
    ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetCallArg(0, str.GetTaggedValue());
    auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
    BuiltinsJson::Parse(ecmaRuntimeCallInfo);
    TestHelper::TearDownFrame(thread, prev);
    bool hasPendingException = false;
    if (thread->HasPendingException()) {
        hasPendingException = true;
        thread->ClearException();
    }
    ASSERT_TRUE(hasPendingException);
    JSHandle<JSTaggedValue> extraErrorMessage(thread, thread->GetExtraErrorMessage());
    uint32_t position = thread->GetJsonErrorPosition();
    ASSERT_TRUE(extraErrorMessage->IsString());
    std::pair<std::string, uint32_t> res =
        base::JsonHelper::AnonymizeJsonString(thread, extraErrorMessage, position, 15);
    ASSERT_EQ(res.first, "{\"n*m*:\"t*m\"}");
    ASSERT_EQ(res.second, 8U);
}

HWTEST_F_L0(BuiltinsJsonTest, ParseErrorSingleQuotes)
{
    auto ecmaVM = thread->GetEcmaVM();
    ObjectFactory *factory = ecmaVM->GetFactory();

    JSHandle<JSTaggedValue> str(factory->NewFromASCII("{'name':'tom'}"));
    auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
    ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetCallArg(0, str.GetTaggedValue());
    auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
    BuiltinsJson::Parse(ecmaRuntimeCallInfo);
    TestHelper::TearDownFrame(thread, prev);
    bool hasPendingException = false;
    if (thread->HasPendingException()) {
        hasPendingException = true;
        thread->ClearException();
    }
    ASSERT_TRUE(hasPendingException);
    JSHandle<JSTaggedValue> extraErrorMessage(thread, thread->GetExtraErrorMessage());
    uint32_t position = thread->GetJsonErrorPosition();
    ASSERT_TRUE(extraErrorMessage->IsString());
    std::pair<std::string, uint32_t> res =
        base::JsonHelper::AnonymizeJsonString(thread, extraErrorMessage, position, 15);
    ASSERT_EQ(res.first, "{'*a*e*:'*o*'}");
    ASSERT_EQ(res.second, 1U);
}

HWTEST_F_L0(BuiltinsJsonTest, ParseErrorInvalidUnicodeEscape)
{
    auto ecmaVM = thread->GetEcmaVM();
    ObjectFactory *factory = ecmaVM->GetFactory();

    JSHandle<JSTaggedValue> str(factory->NewFromASCII("{\"name\":\"\\u00\"}"));
    auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
    ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetCallArg(0, str.GetTaggedValue());
    auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
    BuiltinsJson::Parse(ecmaRuntimeCallInfo);
    TestHelper::TearDownFrame(thread, prev);
    bool hasPendingException = false;
    if (thread->HasPendingException()) {
        hasPendingException = true;
        thread->ClearException();
    }
    ASSERT_TRUE(hasPendingException);
    JSHandle<JSTaggedValue> extraErrorMessage(thread, thread->GetExtraErrorMessage());
    uint32_t position = thread->GetJsonErrorPosition();
    ASSERT_TRUE(extraErrorMessage->IsString());
    std::pair<std::string, uint32_t> res =
        base::JsonHelper::AnonymizeJsonString(thread, extraErrorMessage, position, 15);
    ASSERT_EQ(res.first, "{\"n*m*\":\"\\*0*\"}");
    ASSERT_EQ(res.second, 10U);
}

HWTEST_F_L0(BuiltinsJsonTest, ParseErrorInvalidHexInUnicode)
{
    auto ecmaVM = thread->GetEcmaVM();
    ObjectFactory *factory = ecmaVM->GetFactory();

    JSHandle<JSTaggedValue> str(factory->NewFromASCII("{\"name\":\"\\u00GG\"}"));
    auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
    ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetCallArg(0, str.GetTaggedValue());
    auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
    BuiltinsJson::Parse(ecmaRuntimeCallInfo);
    TestHelper::TearDownFrame(thread, prev);
    bool hasPendingException = false;
    if (thread->HasPendingException()) {
        hasPendingException = true;
        thread->ClearException();
    }
    ASSERT_TRUE(hasPendingException);
    JSHandle<JSTaggedValue> extraErrorMessage(thread, thread->GetExtraErrorMessage());
    uint32_t position = thread->GetJsonErrorPosition();
    ASSERT_TRUE(extraErrorMessage->IsString());
    std::pair<std::string, uint32_t> res =
        base::JsonHelper::AnonymizeJsonString(thread, extraErrorMessage, position, 15);
    ASSERT_EQ(res.first, "{\"n*m*\":\"\\*0*G*\"}");
    ASSERT_EQ(res.second, 13U);
}

HWTEST_F_L0(BuiltinsJsonTest, ParseErrorEmptyString)
{
    auto ecmaVM = thread->GetEcmaVM();
    ObjectFactory *factory = ecmaVM->GetFactory();

    JSHandle<EcmaString> str = factory->NewFromStdString("");
    auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
    ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetCallArg(0, str.GetTaggedValue());
    auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
    BuiltinsJson::Parse(ecmaRuntimeCallInfo);
    TestHelper::TearDownFrame(thread, prev);
    bool hasPendingException = false;
    if (thread->HasPendingException()) {
        hasPendingException = true;
        thread->ClearException();
    }
    ASSERT_TRUE(hasPendingException);
    JSHandle<JSTaggedValue> extraErrorMessage(thread, thread->GetExtraErrorMessage());
    uint32_t position = thread->GetJsonErrorPosition();
    ASSERT_TRUE(extraErrorMessage->IsString());
    std::pair<std::string, uint32_t> res =
        base::JsonHelper::AnonymizeJsonString(thread, extraErrorMessage, position, 15);
    ASSERT_EQ(res.first, "");
    ASSERT_EQ(res.second, 0U);
}

HWTEST_F_L0(BuiltinsJsonTest, ParseErrorWhitespaceOnly)
{
    auto ecmaVM = thread->GetEcmaVM();
    ObjectFactory *factory = ecmaVM->GetFactory();

    JSHandle<JSTaggedValue> str(factory->NewFromASCII("   \t\n\r  "));
    auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
    ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetCallArg(0, str.GetTaggedValue());
    auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
    BuiltinsJson::Parse(ecmaRuntimeCallInfo);
    TestHelper::TearDownFrame(thread, prev);
    bool hasPendingException = false;
    if (thread->HasPendingException()) {
        hasPendingException = true;
        thread->ClearException();
    }
    ASSERT_TRUE(hasPendingException);
    JSHandle<JSTaggedValue> extraErrorMessage(thread, thread->GetExtraErrorMessage());
    uint32_t position = thread->GetJsonErrorPosition();
    ASSERT_TRUE(extraErrorMessage->IsString());
    std::pair<std::string, uint32_t> res =
        base::JsonHelper::AnonymizeJsonString(thread, extraErrorMessage, position, 15);
    ASSERT_EQ(res.first, "   \t\n\r  ");
    ASSERT_EQ(res.second, 8U);
}

HWTEST_F_L0(BuiltinsJsonTest, ParseErrorNegativeNumberWithLeadingZero)
{
    auto ecmaVM = thread->GetEcmaVM();
    ObjectFactory *factory = ecmaVM->GetFactory();

    JSHandle<JSTaggedValue> str(factory->NewFromASCII("{\"age\": 01}"));
    auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
    ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetCallArg(0, str.GetTaggedValue());
    auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
    BuiltinsJson::Parse(ecmaRuntimeCallInfo);
    TestHelper::TearDownFrame(thread, prev);
    bool hasPendingException = false;
    if (thread->HasPendingException()) {
        hasPendingException = true;
        thread->ClearException();
    }
    ASSERT_TRUE(hasPendingException);
    JSHandle<JSTaggedValue> extraErrorMessage(thread, thread->GetExtraErrorMessage());
    uint32_t position = thread->GetJsonErrorPosition();
    ASSERT_TRUE(extraErrorMessage->IsString());
    std::pair<std::string, uint32_t> res =
        base::JsonHelper::AnonymizeJsonString(thread, extraErrorMessage, position, 15);
    ASSERT_EQ(res.first, "{\"a*e\": 0*}");
    ASSERT_EQ(res.second, 9U);
}

HWTEST_F_L0(BuiltinsJsonTest, ParseErrorMultipleDecimalPoints)
{
    auto ecmaVM = thread->GetEcmaVM();
    ObjectFactory *factory = ecmaVM->GetFactory();

    JSHandle<JSTaggedValue> str(factory->NewFromASCII("{\"v\": 1..}"));
    auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
    ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetCallArg(0, str.GetTaggedValue());
    auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
    BuiltinsJson::Parse(ecmaRuntimeCallInfo);
    TestHelper::TearDownFrame(thread, prev);
    bool hasPendingException = false;
    if (thread->HasPendingException()) {
        hasPendingException = true;
        thread->ClearException();
    }
    ASSERT_TRUE(hasPendingException);
    JSHandle<JSTaggedValue> extraErrorMessage(thread, thread->GetExtraErrorMessage());
    uint32_t position = thread->GetJsonErrorPosition();
    ASSERT_TRUE(extraErrorMessage->IsString());
    std::pair<std::string, uint32_t> res =
        base::JsonHelper::AnonymizeJsonString(thread, extraErrorMessage, position, 15);
    ASSERT_EQ(res.first, "{\"v\": 1*.}");
    ASSERT_EQ(res.second, 8U);
}

HWTEST_F_L0(BuiltinsJsonTest, ParseErrorIncompleteScientificNotation)
{
    auto ecmaVM = thread->GetEcmaVM();
    ObjectFactory *factory = ecmaVM->GetFactory();

    JSHandle<JSTaggedValue> str(factory->NewFromASCII("{\"v\": 1e}"));
    auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
    ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetCallArg(0, str.GetTaggedValue());
    auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
    BuiltinsJson::Parse(ecmaRuntimeCallInfo);
    TestHelper::TearDownFrame(thread, prev);
    bool hasPendingException = false;
    if (thread->HasPendingException()) {
        hasPendingException = true;
        thread->ClearException();
    }
    ASSERT_TRUE(hasPendingException);
    JSHandle<JSTaggedValue> extraErrorMessage(thread, thread->GetExtraErrorMessage());
    uint32_t position = thread->GetJsonErrorPosition();
    ASSERT_TRUE(extraErrorMessage->IsString());
    std::pair<std::string, uint32_t> res =
        base::JsonHelper::AnonymizeJsonString(thread, extraErrorMessage, position, 15);
    ASSERT_EQ(res.first, "{\"v\": 1*}");
    ASSERT_EQ(res.second, 7U);
}

HWTEST_F_L0(BuiltinsJsonTest, ParseErrorScientificNotationMissingExponent)
{
    auto ecmaVM = thread->GetEcmaVM();
    ObjectFactory *factory = ecmaVM->GetFactory();

    JSHandle<JSTaggedValue> str(factory->NewFromASCII("{\"v\": 1e+}"));
    auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
    ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetCallArg(0, str.GetTaggedValue());
    auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
    BuiltinsJson::Parse(ecmaRuntimeCallInfo);
    TestHelper::TearDownFrame(thread, prev);
    bool hasPendingException = false;
    if (thread->HasPendingException()) {
        hasPendingException = true;
        thread->ClearException();
    }
    ASSERT_TRUE(hasPendingException);
    JSHandle<JSTaggedValue> extraErrorMessage(thread, thread->GetExtraErrorMessage());
    uint32_t position = thread->GetJsonErrorPosition();
    ASSERT_TRUE(extraErrorMessage->IsString());
    std::pair<std::string, uint32_t> res =
        base::JsonHelper::AnonymizeJsonString(thread, extraErrorMessage, position, 15);
    ASSERT_EQ(res.first, "{\"v\": 1*+}");
    ASSERT_EQ(res.second, 8U);
}

HWTEST_F_L0(BuiltinsJsonTest, ParseErrorNegativeSignWithoutNumber)
{
    auto ecmaVM = thread->GetEcmaVM();
    ObjectFactory *factory = ecmaVM->GetFactory();

    JSHandle<JSTaggedValue> str(factory->NewFromASCII("{\"v\": -}"));
    auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
    ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetCallArg(0, str.GetTaggedValue());
    auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
    BuiltinsJson::Parse(ecmaRuntimeCallInfo);
    TestHelper::TearDownFrame(thread, prev);
    bool hasPendingException = false;
    if (thread->HasPendingException()) {
        hasPendingException = true;
        thread->ClearException();
    }
    ASSERT_TRUE(hasPendingException);
    JSHandle<JSTaggedValue> extraErrorMessage(thread, thread->GetExtraErrorMessage());
    uint32_t position = thread->GetJsonErrorPosition();
    ASSERT_TRUE(extraErrorMessage->IsString());
    std::pair<std::string, uint32_t> res =
        base::JsonHelper::AnonymizeJsonString(thread, extraErrorMessage, position, 15);
    ASSERT_EQ(res.first, "{\"v\": -}");
    ASSERT_EQ(res.second, 6U);
}

HWTEST_F_L0(BuiltinsJsonTest, ParseErrorCommentNotAllowed)
{
    auto ecmaVM = thread->GetEcmaVM();
    ObjectFactory *factory = ecmaVM->GetFactory();

    JSHandle<JSTaggedValue> str(factory->NewFromASCII("{\"name\": \"tom\" // comment}"));
    auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
    ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetCallArg(0, str.GetTaggedValue());
    auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
    BuiltinsJson::Parse(ecmaRuntimeCallInfo);
    TestHelper::TearDownFrame(thread, prev);
    bool hasPendingException = false;
    if (thread->HasPendingException()) {
        hasPendingException = true;
        thread->ClearException();
    }
    ASSERT_TRUE(hasPendingException);
    JSHandle<JSTaggedValue> extraErrorMessage(thread, thread->GetExtraErrorMessage());
    uint32_t position = thread->GetJsonErrorPosition();
    ASSERT_TRUE(extraErrorMessage->IsString());
    std::pair<std::string, uint32_t> res =
        base::JsonHelper::AnonymizeJsonString(thread, extraErrorMessage, position, 15);
    ASSERT_EQ(res.first, "{\"n*m*\": \"t*m\" /* c*m*e*t}");
    ASSERT_EQ(res.second, 15U);
}

HWTEST_F_L0(BuiltinsJsonTest, ParseErrorNestedObjectError)
{
    auto ecmaVM = thread->GetEcmaVM();
    ObjectFactory *factory = ecmaVM->GetFactory();

    JSHandle<JSTaggedValue> str(factory->NewFromASCII("{\"outer\": {\"inner\": {\"key\": \"unclosed}}"));
    auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
    ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetCallArg(0, str.GetTaggedValue());
    auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
    BuiltinsJson::Parse(ecmaRuntimeCallInfo);
    TestHelper::TearDownFrame(thread, prev);
    bool hasPendingException = false;
    if (thread->HasPendingException()) {
        hasPendingException = true;
        thread->ClearException();
    }
    ASSERT_TRUE(hasPendingException);
    JSHandle<JSTaggedValue> extraErrorMessage(thread, thread->GetExtraErrorMessage());
    uint32_t position = thread->GetJsonErrorPosition();
    ASSERT_TRUE(extraErrorMessage->IsString());
    std::pair<std::string, uint32_t> res =
        base::JsonHelper::AnonymizeJsonString(thread, extraErrorMessage, position, 15);
    ASSERT_EQ(res.first, "e*\": \"u*c*o*e*}}");
    ASSERT_EQ(res.second, 15U);
}

HWTEST_F_L0(BuiltinsJsonTest, ParseErrorString)
{
    auto ecmaVM = thread->GetEcmaVM();
    ObjectFactory *factory = ecmaVM->GetFactory();

    JSHandle<JSTaggedValue> str(factory->NewFromASCII("\"abcdefghijk"));
    auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
    ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetCallArg(0, str.GetTaggedValue());
    auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
    BuiltinsJson::Parse(ecmaRuntimeCallInfo);
    TestHelper::TearDownFrame(thread, prev);
    bool hasPendingException = false;
    if (thread->HasPendingException()) {
        hasPendingException = true;
        thread->ClearException();
    }
    ASSERT_TRUE(hasPendingException);
    JSHandle<JSTaggedValue> extraErrorMessage(thread, thread->GetExtraErrorMessage());
    uint32_t position = thread->GetJsonErrorPosition();
    ASSERT_TRUE(extraErrorMessage->IsString());
    std::pair<std::string, uint32_t> res =
        base::JsonHelper::AnonymizeJsonString(thread, extraErrorMessage, position, 15);
    ASSERT_EQ(res.first, "\"a*c*e*g*i*k");
    ASSERT_EQ(res.second, 11U);
}

HWTEST_F_L0(BuiltinsJsonTest, ParseErrorNestedArrayError)
{
    auto ecmaVM = thread->GetEcmaVM();
    ObjectFactory *factory = ecmaVM->GetFactory();

    JSHandle<JSTaggedValue> str(factory->NewFromASCII("[[1, 2, [3, 4, \"err]], 5]"));
    auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
    ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetCallArg(0, str.GetTaggedValue());
    auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
    BuiltinsJson::Parse(ecmaRuntimeCallInfo);
    TestHelper::TearDownFrame(thread, prev);
    bool hasPendingException = false;
    if (thread->HasPendingException()) {
        hasPendingException = true;
        thread->ClearException();
    }
    ASSERT_TRUE(hasPendingException);
    JSHandle<JSTaggedValue> extraErrorMessage(thread, thread->GetExtraErrorMessage());
    uint32_t position = thread->GetJsonErrorPosition();
    ASSERT_TRUE(extraErrorMessage->IsString());
    std::pair<std::string, uint32_t> res =
        base::JsonHelper::AnonymizeJsonString(thread, extraErrorMessage, position, 15);
    ASSERT_EQ(res.first, "3, 4, \"e*r]], 5]");
    ASSERT_EQ(res.second, 15U);
}

HWTEST_F_L0(BuiltinsJsonTest, ParseErrorAtBeginning)
{
    auto ecmaVM = thread->GetEcmaVM();
    ObjectFactory *factory = ecmaVM->GetFactory();

    JSHandle<JSTaggedValue> str(factory->NewFromASCII("@{\"name\": \"tom\"}"));
    auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
    ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetCallArg(0, str.GetTaggedValue());
    auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
    BuiltinsJson::Parse(ecmaRuntimeCallInfo);
    TestHelper::TearDownFrame(thread, prev);
    bool hasPendingException = false;
    if (thread->HasPendingException()) {
        hasPendingException = true;
        thread->ClearException();
    }
    ASSERT_TRUE(hasPendingException);
    JSHandle<JSTaggedValue> extraErrorMessage(thread, thread->GetExtraErrorMessage());
    uint32_t position = thread->GetJsonErrorPosition();
    ASSERT_TRUE(extraErrorMessage->IsString());
    std::pair<std::string, uint32_t> res =
        base::JsonHelper::AnonymizeJsonString(thread, extraErrorMessage, position, 15);
    ASSERT_EQ(res.first, "@{\"n*m*\": \"t*m\"");
    ASSERT_EQ(res.second, 0U);
}

HWTEST_F_L0(BuiltinsJsonTest, ParseErrorAtEnd)
{
    auto ecmaVM = thread->GetEcmaVM();
    ObjectFactory *factory = ecmaVM->GetFactory();

    JSHandle<JSTaggedValue> str(factory->NewFromASCII("{\"name\": \"tom\""));
    auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
    ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetCallArg(0, str.GetTaggedValue());
    auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
    BuiltinsJson::Parse(ecmaRuntimeCallInfo);
    TestHelper::TearDownFrame(thread, prev);
    bool hasPendingException = false;
    if (thread->HasPendingException()) {
        hasPendingException = true;
        thread->ClearException();
    }
    ASSERT_TRUE(hasPendingException);
    JSHandle<JSTaggedValue> extraErrorMessage(thread, thread->GetExtraErrorMessage());
    uint32_t position = thread->GetJsonErrorPosition();
    ASSERT_TRUE(extraErrorMessage->IsString());
    std::pair<std::string, uint32_t> res =
        base::JsonHelper::AnonymizeJsonString(thread, extraErrorMessage, position, 15);
    ASSERT_EQ(res.first, "{\"n*m*\": \"t*m\"");
    ASSERT_EQ(res.second, 13U);
}

HWTEST_F_L0(BuiltinsJsonTest, ParseErrorSingleOpenBrace)
{
    auto ecmaVM = thread->GetEcmaVM();
    ObjectFactory *factory = ecmaVM->GetFactory();

    JSHandle<JSTaggedValue> str(factory->NewFromASCII("{"));
    auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
    ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetCallArg(0, str.GetTaggedValue());
    auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
    BuiltinsJson::Parse(ecmaRuntimeCallInfo);
    TestHelper::TearDownFrame(thread, prev);
    bool hasPendingException = false;
    if (thread->HasPendingException()) {
        hasPendingException = true;
        thread->ClearException();
    }
    ASSERT_TRUE(hasPendingException);
    JSHandle<JSTaggedValue> extraErrorMessage(thread, thread->GetExtraErrorMessage());
    uint32_t position = thread->GetJsonErrorPosition();
    ASSERT_TRUE(extraErrorMessage->IsString());
    std::pair<std::string, uint32_t> res =
        base::JsonHelper::AnonymizeJsonString(thread, extraErrorMessage, position, 15);
    ASSERT_EQ(res.first, "{");
    ASSERT_EQ(res.second, 1U);
}

HWTEST_F_L0(BuiltinsJsonTest, ParseErrorSingleOpenBracket)
{
    auto ecmaVM = thread->GetEcmaVM();
    ObjectFactory *factory = ecmaVM->GetFactory();

    JSHandle<JSTaggedValue> str(factory->NewFromASCII("["));
    auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
    ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetCallArg(0, str.GetTaggedValue());
    auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
    BuiltinsJson::Parse(ecmaRuntimeCallInfo);
    TestHelper::TearDownFrame(thread, prev);
    bool hasPendingException = false;
    if (thread->HasPendingException()) {
        hasPendingException = true;
        thread->ClearException();
    }
    ASSERT_TRUE(hasPendingException);
    JSHandle<JSTaggedValue> extraErrorMessage(thread, thread->GetExtraErrorMessage());
    uint32_t position = thread->GetJsonErrorPosition();
    ASSERT_TRUE(extraErrorMessage->IsString());
    std::pair<std::string, uint32_t> res =
        base::JsonHelper::AnonymizeJsonString(thread, extraErrorMessage, position, 15);
    ASSERT_EQ(res.first, "[");
    ASSERT_EQ(res.second, 1U);
}

HWTEST_F_L0(BuiltinsJsonTest, ParseErrorMultipleErrorsFirstPosition)
{
    auto ecmaVM = thread->GetEcmaVM();
    ObjectFactory *factory = ecmaVM->GetFactory();

    JSHandle<JSTaggedValue> str(factory->NewFromASCII("{'name': 'tom'}"));
    auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
    ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetCallArg(0, str.GetTaggedValue());
    auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
    BuiltinsJson::Parse(ecmaRuntimeCallInfo);
    TestHelper::TearDownFrame(thread, prev);
    bool hasPendingException = false;
    if (thread->HasPendingException()) {
        hasPendingException = true;
        thread->ClearException();
    }
    ASSERT_TRUE(hasPendingException);
    JSHandle<JSTaggedValue> extraErrorMessage(thread, thread->GetExtraErrorMessage());
    uint32_t position = thread->GetJsonErrorPosition();
    ASSERT_TRUE(extraErrorMessage->IsString());
    std::pair<std::string, uint32_t> res =
        base::JsonHelper::AnonymizeJsonString(thread, extraErrorMessage, position, 15);
    ASSERT_EQ(res.first, "{'*a*e*: '*o*'}");
    ASSERT_EQ(res.second, 1U);
}

HWTEST_F_L0(BuiltinsJsonTest, ParseErrorDuplicateKey)
{
    auto ecmaVM = thread->GetEcmaVM();
    ObjectFactory *factory = ecmaVM->GetFactory();

    JSHandle<JSTaggedValue> str(factory->NewFromASCII("{\"name\": \"tom\", \"name\": \"jerry\"}"));
    auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
    ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetCallArg(0, str.GetTaggedValue());
    auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
    BuiltinsJson::Parse(ecmaRuntimeCallInfo);
    TestHelper::TearDownFrame(thread, prev);

    bool hasPendingException = false;
    if (thread->HasPendingException()) {
        hasPendingException = true;
        thread->ClearException();
    }
    ASSERT_FALSE(hasPendingException);

    uint32_t position = thread->GetJsonErrorPosition();
    ASSERT_EQ(position, 0U);

    JSHandle<JSTaggedValue> extraErrorMessage(thread, thread->GetExtraErrorMessage());
    if (extraErrorMessage->IsString()) {
        ASSERT_EQ(EcmaStringAccessor(extraErrorMessage.GetTaggedValue()).GetLength(), 0U);
    }
}

HWTEST_F_L0(BuiltinsJsonTest, ParseErrorVeryLongString)
{
    auto ecmaVM = thread->GetEcmaVM();
    ObjectFactory *factory = ecmaVM->GetFactory();

    std::string longJson = "{\"key\": \"";
    for (int i = 0; i < 500; i++) {
        longJson += "a";
    }
    longJson += "\"}";
    JSHandle<EcmaString> str = factory->NewFromStdString(longJson);
    auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
    ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetCallArg(0, str.GetTaggedValue());
    auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
    BuiltinsJson::Parse(ecmaRuntimeCallInfo);
    TestHelper::TearDownFrame(thread, prev);

    bool hasPendingException = false;
    if (thread->HasPendingException()) {
        hasPendingException = true;
        thread->ClearException();
    }
    ASSERT_FALSE(hasPendingException);

    uint32_t position = thread->GetJsonErrorPosition();
    ASSERT_EQ(position, 0U);
}

HWTEST_F_L0(BuiltinsJsonTest, ParseErrorVeryLongStringWithError)
{
    auto ecmaVM = thread->GetEcmaVM();
    ObjectFactory *factory = ecmaVM->GetFactory();

    std::string longJson = "{\"key\": \"";
    for (int i = 0; i < 100; i++) {
        longJson += "a";
    }
    longJson += "\n";
    for (int i = 0; i < 100; i++) {
        longJson += "a";
    }
    longJson += "\"}";
    JSHandle<EcmaString> str = factory->NewFromStdString(longJson);
    auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
    ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetCallArg(0, str.GetTaggedValue());
    auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
    BuiltinsJson::Parse(ecmaRuntimeCallInfo);
    TestHelper::TearDownFrame(thread, prev);
    bool hasPendingException = false;
    if (thread->HasPendingException()) {
        hasPendingException = true;
        thread->ClearException();
    }
    ASSERT_TRUE(hasPendingException);
    JSHandle<JSTaggedValue> extraErrorMessage(thread, thread->GetExtraErrorMessage());
    uint32_t position = thread->GetJsonErrorPosition();
    ASSERT_TRUE(extraErrorMessage->IsString());
    std::pair<std::string, uint32_t> res =
        base::JsonHelper::AnonymizeJsonString(thread, extraErrorMessage, position, 15);
    ASSERT_EQ(res.first, "a*a*a*a*a*a*a*a\na*a*a*a*a*a*a*");
    ASSERT_EQ(res.second, 15U);
}

HWTEST_F_L0(BuiltinsJsonTest, ParseErrorWithError)
{
    auto ecmaVM = thread->GetEcmaVM();
    ObjectFactory *factory = ecmaVM->GetFactory();

    std::string longJson = "{\"key\": \"";
    for (int i = 0; i < 100; i++) {
        longJson += "a";
    }
    longJson += "\n";
    for (int i = 0; i < 100; i++) {
        longJson += "a";
    }
    longJson += "\"}";
    JSHandle<EcmaString> str = factory->NewFromStdString(longJson);
    auto ecmaRuntimeCallInfo = TestHelper::CreateEcmaRuntimeCallInfo(thread, JSTaggedValue::Undefined(), 6);
    ecmaRuntimeCallInfo->SetFunction(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetThis(JSTaggedValue::Undefined());
    ecmaRuntimeCallInfo->SetCallArg(0, str.GetTaggedValue());
    auto prev = TestHelper::SetupFrame(thread, ecmaRuntimeCallInfo);
    BuiltinsJson::Parse(ecmaRuntimeCallInfo);
    TestHelper::TearDownFrame(thread, prev);
    bool hasPendingException = false;
    if (thread->HasPendingException()) {
        hasPendingException = true;
        thread->ClearException();
    }
    ASSERT_TRUE(hasPendingException);
    JSHandle<JSTaggedValue> extraErrorMessage(thread, thread->GetExtraErrorMessage());
    uint32_t position = thread->GetJsonErrorPosition();
    ASSERT_TRUE(extraErrorMessage->IsString());
    std::pair<std::string, uint32_t> res =
        base::JsonHelper::AnonymizeJsonString(thread, extraErrorMessage, position, 15);
    ASSERT_EQ(res.first, "a*a*a*a*a*a*a*a\na*a*a*a*a*a*a*");
    ASSERT_EQ(res.second, 15U);
}

}  // namespace panda::test