1/* 2 * Copyright (c) 2021 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16#include "ecmascript/base/json_stringifier.h" 17#include "ecmascript/js_array.h" 18#include "ecmascript/tests/test_helper.h" 19 20using namespace panda::ecmascript; 21using namespace panda::ecmascript::base; 22 23namespace panda::test { 24class JsonStringifierTest : public BaseTestWithScope<false> { 25}; 26 27static JSTaggedValue CreateBaseJSObject(JSThread *thread, const CString keyCStr) 28{ 29 EcmaVM *ecmaVM = thread->GetEcmaVM(); 30 JSHandle<GlobalEnv> globalEnv = ecmaVM->GetGlobalEnv(); 31 ObjectFactory *factory = ecmaVM->GetFactory(); 32 JSHandle<JSTaggedValue> objectFunc(globalEnv->GetObjectFunction()); 33 34 JSHandle<JSObject> jsObject(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objectFunc), objectFunc)); 35 EXPECT_TRUE(*jsObject != nullptr); 36 37 JSHandle<JSTaggedValue> handleKey1(factory->NewFromASCII(&keyCStr[0])); 38 JSHandle<JSTaggedValue> handleValue1(thread, JSTaggedValue(1)); // 1 : test case 39 JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(jsObject), handleKey1, handleValue1); 40 41 CString str2 = "x"; 42 JSHandle<JSTaggedValue> handleKey2(factory->NewFromASCII(str2)); 43 JSHandle<JSTaggedValue> handleValue2(thread, JSTaggedValue(3.6)); // 3.6 : test case 44 JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(jsObject), handleKey2, handleValue2); 45 46 CString str3 = "y"; 47 JSHandle<JSTaggedValue> handleKey3(factory->NewFromASCII(str3)); 48 JSHandle<JSTaggedValue> handleValue3(factory->NewFromASCII("abc")); 49 JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(jsObject), handleKey3, handleValue3); 50 51 return jsObject.GetTaggedValue(); 52} 53 54static JSTaggedValue TestForStringfy1([[maybe_unused]] EcmaRuntimeCallInfo *argv) 55{ 56 // false: test case 57 return JSTaggedValue(JSTaggedValue::False()); 58} 59 60static JSTaggedValue TestForStringfy2([[maybe_unused]] EcmaRuntimeCallInfo *argv) 61{ 62 // 10.12: test case 63 return JSTaggedValue(10.12); 64} 65 66/** 67 * @tc.name: Stringify_001 68 * @tc.desc: Check whether the result returned through "Stringify" function is within expectations 69 * the first parameter of the ECMAObject,the second parameter is JSFunction,the third parameter 70 * is Undefined.if the second parameter is JSFunction,the return value is the parameter stringification 71 * after through "call" function. 72 * @tc.type: FUNC 73 * @tc.require: 74 */ 75HWTEST_F_L0(JsonStringifierTest, Stringify_001) 76{ 77 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 78 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv(); 79 80 JSHandle<JSTaggedValue> handleObj = JSHandle<JSTaggedValue>(thread, CreateBaseJSObject(thread, "z")); 81 JSHandle<JSFunction> handleFunc1 = factory->NewJSFunction(env, reinterpret_cast<void *>(TestForStringfy1)); 82 JSHandle<JSFunction> handleFunc2 = factory->NewJSFunction(env, reinterpret_cast<void *>(TestForStringfy2)); 83 JSHandle<JSTaggedValue> handleValue(thread, handleObj.GetTaggedValue()); 84 JSHandle<JSTaggedValue> handleReplacer1(thread, handleFunc1.GetTaggedValue()); 85 JSHandle<JSTaggedValue> handleReplacer2(thread, handleFunc2.GetTaggedValue()); 86 JSHandle<JSTaggedValue> handleGap(thread, JSTaggedValue::Undefined()); 87 88 JsonStringifier stringifier1(thread); 89 JSHandle<JSTaggedValue> resultString1 = stringifier1.Stringify(handleValue, handleReplacer1, handleGap); 90 EXPECT_TRUE(resultString1->IsString()); 91 JSHandle<EcmaString> handleEcmaStr1(resultString1); 92 EXPECT_STREQ("false", EcmaStringAccessor(handleEcmaStr1).ToCString().c_str()); 93 94 JsonStringifier stringifier2(thread); 95 JSHandle<JSTaggedValue> resultString2 = stringifier2.Stringify(handleValue, handleReplacer2, handleGap); 96 EXPECT_TRUE(resultString2->IsString()); 97 JSHandle<EcmaString> handleEcmaStr2(resultString2); 98 EXPECT_STREQ("10.12", EcmaStringAccessor(handleEcmaStr2).ToCString().c_str()); 99} 100 101/** 102 * @tc.name: Stringify_002 103 * @tc.desc: Check whether the result returned through "Stringify" function is within expectations 104 * the first parameter of the ECMAObject,the second parameter is Undefined,the third parameter 105 * is Number.This situation will stringize parameters through "SerializeJSONObject" function. 106 * @tc.type: FUNC 107 * @tc.require: 108 */ 109HWTEST_F_L0(JsonStringifierTest, Stringify_002) 110{ 111 JsonStringifier stringifier(thread); 112 113 JSHandle<JSTaggedValue> handleObj = JSHandle<JSTaggedValue>(thread, CreateBaseJSObject(thread, "z")); 114 JSHandle<JSTaggedValue> handleValue(thread, handleObj.GetTaggedValue()); 115 JSHandle<JSTaggedValue> handleReplacer(thread, JSTaggedValue::Undefined()); 116 JSHandle<JSTaggedValue> handleGap(thread, JSTaggedValue(static_cast<int32_t>(10))); 117 118 JSHandle<JSTaggedValue> resultString = stringifier.Stringify(handleValue, handleReplacer, handleGap); 119 EXPECT_TRUE(resultString->IsString()); 120 JSHandle<EcmaString> handleEcmaStr(resultString); 121 EXPECT_STREQ("{\n \"z\": 1,\n \"x\": 3.6,\n \"y\": \"abc\"\n}", 122 EcmaStringAccessor(handleEcmaStr).ToCString().c_str()); 123} 124 125/** 126 * @tc.name: Stringify_003 127 * @tc.desc: Check whether the result returned through "Stringify" function is within expectations 128 * the first parameter of the ECMAObject,the second parameter is Undefined,the third parameter 129 * is String,This situation will stringize parameters through "SerializeJSONObject" function. 130 * @tc.type: FUNC 131 * @tc.require: 132 */ 133HWTEST_F_L0(JsonStringifierTest, Stringify_003) 134{ 135 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 136 JsonStringifier stringifier(thread); 137 138 JSHandle<JSTaggedValue> handleObj = JSHandle<JSTaggedValue>(thread, CreateBaseJSObject(thread, "z")); 139 JSHandle<JSTaggedValue> handleMsg(factory->NewFromASCII("tttt")); 140 JSHandle<EcmaString> handleStr(JSTaggedValue::ToString(thread, handleMsg)); 141 142 JSHandle<JSTaggedValue> handleValue(thread, handleObj.GetTaggedValue()); 143 JSHandle<JSTaggedValue> handleReplacer(thread, JSTaggedValue::Undefined()); 144 JSHandle<JSTaggedValue> handleGap(thread, handleStr.GetTaggedValue()); 145 146 JSHandle<JSTaggedValue> resultString = stringifier.Stringify(handleValue, handleReplacer, handleGap); 147 EXPECT_TRUE(resultString->IsString()); 148 JSHandle<EcmaString> resultStr = 149 factory->NewFromASCII("{\ntttt\"z\": 1,\ntttt\"x\": 3.6,\ntttt\"y\": \"abc\"\n}"); 150 EXPECT_EQ(EcmaStringAccessor::Compare(instance, resultStr, JSHandle<EcmaString>(resultString)), 0); 151} 152 153/** 154 * @tc.name: Stringify_004 155 * @tc.desc: Check whether the result returned through "Stringify" function is within expectations 156 * the first parameter of the ECMAObject,the second parameter is JSArray,the third parameter 157 * is String.This situation will stringize parameters through "SerializeJSONObject" function. 158 * @tc.type: FUNC 159 * @tc.require: 160 */ 161HWTEST_F_L0(JsonStringifierTest, Stringify_004) 162{ 163 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 164 JsonStringifier stringifier(thread); 165 166 JSHandle<JSTaggedValue> handleObj1 = JSHandle<JSTaggedValue>(thread, CreateBaseJSObject(thread, "z")); 167 168 JSArray *handleArr = 169 JSArray::Cast(JSArray::ArrayCreate(thread, JSTaggedNumber(0)).GetTaggedValue().GetTaggedObject()); 170 JSHandle<JSObject> handleObj2(thread, handleArr); 171 JSHandle<JSTaggedValue> handleKey0(thread, JSTaggedValue(0)); 172 JSHandle<JSTaggedValue> handleValue0(factory->NewFromASCII("z")); 173 JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(handleObj2), handleKey0, handleValue0); 174 175 JSHandle<JSTaggedValue> handleKey1(thread, JSTaggedValue(1)); 176 JSHandle<JSTaggedValue> handleValue1(factory->NewFromASCII("x")); 177 JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(handleObj2), handleKey1, handleValue1); 178 179 JSHandle<JSTaggedValue> handleMsg(factory->NewFromASCII("tttt")); 180 JSHandle<EcmaString> handleStr(JSTaggedValue::ToString(thread, handleMsg)); 181 182 JSHandle<JSTaggedValue> handleValue(thread, handleObj1.GetTaggedValue()); 183 JSHandle<JSTaggedValue> handleReplacer(thread, handleObj2.GetTaggedValue()); 184 JSHandle<JSTaggedValue> handleGap(thread, handleStr.GetTaggedValue()); 185 186 JSHandle<JSTaggedValue> resultString = stringifier.Stringify(handleValue, handleReplacer, handleGap); 187 EXPECT_TRUE(resultString->IsString()); 188 JSHandle<EcmaString> handleEcmaStr(resultString); 189 EXPECT_STREQ("{\ntttt\"z\": 1,\ntttt\"x\": 3.6\n}", EcmaStringAccessor(handleEcmaStr).ToCString().c_str()); 190} 191 192/** 193 * @tc.name: Stringify_005 194 * @tc.desc: Check whether the result returned through "Stringify" function is within expectations 195 * the first parameter of the ECMAObject,the second parameter is Undefined,the third parameter 196 * is Undefined.This situation will stringize the first parameter through "SerializeJSONObject" function. 197 * @tc.type: FUNC 198 * @tc.require: 199 */ 200HWTEST_F_L0(JsonStringifierTest, Stringify_005) 201{ 202 JsonStringifier stringifier(thread); 203 JSHandle<JSTaggedValue> handleObj = JSHandle<JSTaggedValue>(thread, CreateBaseJSObject(thread, "z")); 204 205 JSHandle<JSTaggedValue> handleValue(thread, handleObj.GetTaggedValue()); 206 JSHandle<JSTaggedValue> handleReplacer(thread, JSTaggedValue::Undefined()); 207 JSHandle<JSTaggedValue> handleGap(thread, JSTaggedValue::Undefined()); 208 209 JSHandle<JSTaggedValue> resultString = stringifier.Stringify(handleValue, handleReplacer, handleGap); 210 EXPECT_TRUE(resultString->IsString()); 211 JSHandle<EcmaString> handleEcmaStr(resultString); 212 EXPECT_STREQ("{\"z\":1,\"x\":3.6,\"y\":\"abc\"}", EcmaStringAccessor(handleEcmaStr).ToCString().c_str()); 213} 214 215/** 216 * @tc.name: Stringify_006 217 * @tc.desc: Check whether the result returned through "Stringify" function is within expectations 218 * the first parameter of the JSArray,the second parameter is Undefined,the third parameter 219 * is String,This situation will stringize parameters through "SerializeJSArray" function. 220 * @tc.type: FUNC 221 * @tc.require: 222 */ 223HWTEST_F_L0(JsonStringifierTest, Stringify_006) 224{ 225 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 226 JsonStringifier stringifier(thread); 227 228 JSArray *handleArr = 229 JSArray::Cast(JSArray::ArrayCreate(thread, JSTaggedNumber(0)).GetTaggedValue().GetTaggedObject()); 230 JSHandle<JSObject> handleObj(thread, handleArr); 231 232 JSHandle<JSTaggedValue> handleKey0(thread, JSTaggedValue(0)); 233 JSHandle<JSTaggedValue> handleValue0(factory->NewFromASCII("json")); 234 JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(handleObj), handleKey0, handleValue0); 235 236 JSHandle<JSTaggedValue> handleKey1(thread, JSTaggedValue(1)); 237 PropertyDescriptor handleDesc(thread, JSHandle<JSTaggedValue>(thread, JSTaggedValue(100)), true, true, true); 238 JSArray::DefineOwnProperty(thread, handleObj, handleKey1, handleDesc); 239 240 JSHandle<JSTaggedValue> handleKey2(thread, JSTaggedValue(2)); 241 JSHandle<JSTaggedValue> handleValue2(factory->NewFromASCII("abc")); 242 JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(handleObj), handleKey2, handleValue2); 243 244 JSHandle<JSTaggedValue> handleMsg(factory->NewFromASCII("tttt")); 245 JSHandle<EcmaString> handleStr(JSTaggedValue::ToString(thread, handleMsg)); 246 247 JSHandle<JSTaggedValue> handleValue(thread, handleObj.GetTaggedValue()); 248 JSHandle<JSTaggedValue> handleReplacer(thread, JSTaggedValue::Undefined()); 249 JSHandle<JSTaggedValue> handleGap(thread, handleStr.GetTaggedValue()); 250 251 JSHandle<JSTaggedValue> resultString = stringifier.Stringify(handleValue, handleReplacer, handleGap); 252 EXPECT_TRUE(resultString->IsString()); 253 JSHandle<EcmaString> handleEcmaStr(resultString); 254 EXPECT_STREQ("[\ntttt\"json\",\ntttt100,\ntttt\"abc\"\n]", EcmaStringAccessor(handleEcmaStr).ToCString().c_str()); 255} 256 257/** 258 * @tc.name: Stringify_007 259 * @tc.desc: Check whether the result returned through "Stringify" function is within expectations 260 * the first parameter of the JSObject,the second parameter is Undefined,the third parameter 261 * is Undefined.This situation will stringize the first parameter through "SerializeJSArray" function. 262 * @tc.type: FUNC 263 * @tc.require: 264 */ 265HWTEST_F_L0(JsonStringifierTest, Stringify_007) 266{ 267 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 268 JsonStringifier stringifier(thread); 269 270 JSArray *handleArr = 271 JSArray::Cast(JSArray::ArrayCreate(thread, JSTaggedNumber(0)).GetTaggedValue().GetTaggedObject()); 272 JSHandle<JSObject> handleObj(thread, handleArr); 273 274 JSHandle<JSTaggedValue> handleKey0(thread, JSTaggedValue(0)); 275 PropertyDescriptor handleDesc0(thread, JSHandle<JSTaggedValue>(thread, JSTaggedValue(1)), true, true, true); 276 JSArray::DefineOwnProperty(thread, handleObj, handleKey0, handleDesc0); 277 278 JSHandle<JSTaggedValue> handleKey1(thread, JSTaggedValue(1)); 279 PropertyDescriptor handleDesc1(thread, JSHandle<JSTaggedValue>(thread, JSTaggedValue(3.6)), true, true, true); 280 JSArray::DefineOwnProperty(thread, handleObj, handleKey1, handleDesc1); 281 282 JSHandle<JSTaggedValue> handleKey2(thread, JSTaggedValue(2)); 283 JSHandle<JSTaggedValue> handleValue2(factory->NewFromASCII("abc")); 284 JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(handleObj), handleKey2, handleValue2); 285 286 JSHandle<JSTaggedValue> handleValue(thread, handleObj.GetTaggedValue()); 287 JSHandle<JSTaggedValue> handleReplacer(thread, JSTaggedValue::Undefined()); 288 JSHandle<JSTaggedValue> handleGap(thread, JSTaggedValue::Undefined()); 289 290 JSHandle<JSTaggedValue> resultString = stringifier.Stringify(handleValue, handleReplacer, handleGap); 291 EXPECT_TRUE(resultString->IsString()); 292 JSHandle<EcmaString> handleEcmaStr(resultString); 293 EXPECT_STREQ("[1,3.6,\"abc\"]", EcmaStringAccessor(handleEcmaStr).ToCString().c_str()); 294} 295 296/** 297 * @tc.name: Stringify_008 298 * @tc.desc: Check whether the result returned through "Stringify" function is within expectations 299 * the first parameter of the JSObject,the second parameter is Undefined,the third parameter 300 * is Undefined.This situation will stringize the first parameter through "SerializePrimitiveRef" 301 * function. 302 * @tc.type: FUNC 303 * @tc.require: 304 */ 305HWTEST_F_L0(JsonStringifierTest, Stringify_008) 306{ 307 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 308 JsonStringifier stringifier(thread); 309 310 JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined(); 311 JSHandle<JSTaggedValue> handleStr(factory->NewFromASCII("\"\\\b\f\n\r\t")); 312 JSHandle<JSPrimitiveRef> handlePrimitiveRef = factory->NewJSString(handleStr, undefined); 313 JSHandle<JSObject> handleObj(thread, handlePrimitiveRef.GetTaggedValue()); 314 315 JSHandle<JSTaggedValue> handleValue(thread, handleObj.GetTaggedValue()); 316 JSHandle<JSTaggedValue> handleReplacer(thread, JSTaggedValue::Undefined()); 317 JSHandle<JSTaggedValue> handleGap(thread, JSTaggedValue::Undefined()); 318 319 JSHandle<JSTaggedValue> resultString = stringifier.Stringify(handleValue, handleReplacer, handleGap); 320 EXPECT_TRUE(resultString->IsString()); 321 JSHandle<EcmaString> handleEcmaStr(resultString); 322 EXPECT_STREQ("\"\\\"\\\\\\b\\f\\n\\r\\t\"", EcmaStringAccessor(handleEcmaStr).ToCString().c_str()); 323} 324 325static void* Detach(void *param1, void *param2, void *hint, void *detachData) 326{ 327 GTEST_LOG_(INFO) << "detach is running"; 328 if (param1 == nullptr && param2 == nullptr) { 329 GTEST_LOG_(INFO) << "detach: two params is nullptr"; 330 } 331 if (hint == nullptr && detachData) { 332 GTEST_LOG_(INFO) << "detach: hint is nullptr"; 333 } 334 return nullptr; 335} 336 337static void* Attach([[maybe_unused]] void *enginePointer, [[maybe_unused]] void *buffer, [[maybe_unused]] void *hint, 338 [[maybe_unused]] void *attachData) 339{ 340 GTEST_LOG_(INFO) << "attach is running"; 341 return nullptr; 342} 343 344static panda::JSNApi::NativeBindingInfo* CreateNativeBindingInfo(void* attach, void* detach) 345{ 346 GTEST_LOG_(INFO) << "CreateNativeBindingInfo"; 347 auto info = panda::JSNApi::NativeBindingInfo::CreateNewInstance(); 348 info->attachFunc = attach; 349 info->detachFunc = detach; 350 return info; 351} 352 353HWTEST_F_L0(JsonStringifierTest, Stringify_009) 354{ 355 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 356 JsonStringifier stringifier(thread); 357 358 EcmaVM *ecmaVM = thread->GetEcmaVM(); 359 JSHandle<GlobalEnv> globalEnv = ecmaVM->GetGlobalEnv(); 360 JSHandle<JSTaggedValue> objectFunc(globalEnv->GetObjectFunction()); 361 JSHandle<JSObject> jsObject(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(objectFunc), objectFunc)); 362 EXPECT_TRUE(*jsObject != nullptr); 363 364 JSHandle<JSTaggedValue> key1(factory->NewFromASCII("key1")); 365 auto info = CreateNativeBindingInfo(reinterpret_cast<void*>(Attach), reinterpret_cast<void*>(Detach)); 366 JSHandle<JSTaggedValue> value1(factory->NewJSNativePointer(reinterpret_cast<void*>(info))); 367 JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(jsObject), key1, value1); 368 369 JSHandle<JSTaggedValue> key2(factory->NewFromASCII("key2")); 370 JSHandle<JSTaggedValue> value2(factory->NewFromASCII("abc")); 371 JSObject::SetProperty(thread, JSHandle<JSTaggedValue>(jsObject), key2, value2); 372 373 JSHandle<JSTaggedValue> handleValue(thread, jsObject.GetTaggedValue()); 374 JSHandle<JSTaggedValue> handleReplacer(thread, JSTaggedValue::Undefined()); 375 JSHandle<JSTaggedValue> handleGap(thread, JSTaggedValue::Undefined()); 376 377 JSHandle<JSTaggedValue> resultString = stringifier.Stringify(handleValue, handleReplacer, handleGap); 378 EXPECT_TRUE(resultString->IsString()); 379 JSHandle<EcmaString> handleEcmaStr(resultString); 380 EXPECT_STREQ("{\"key1\":{},\"key2\":\"abc\"}", EcmaStringAccessor(handleEcmaStr).ToCString().c_str()); 381} 382} // namespace panda::test 383