1/* 2 * Copyright (c) 2022 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/layout_info-inl.h" 17#include "ecmascript/property_attributes.h" 18#include "ecmascript/tests/test_helper.h" 19 20using namespace panda::ecmascript; 21 22namespace panda::test { 23class LayoutInfoTest : public BaseTestWithScope<false> { 24}; 25 26HWTEST_F_L0(LayoutInfoTest, SetNumberOfElements) 27{ 28 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 29 int32_t infoLength = 2; // 2: len 30 JSHandle<LayoutInfo> layoutInfoHandle = factory->CreateLayoutInfo(infoLength); 31 EXPECT_TRUE(*layoutInfoHandle != nullptr); 32 33 layoutInfoHandle->SetNumberOfElements(thread, 100); 34 EXPECT_EQ(layoutInfoHandle->NumberOfElements(), 100); 35} 36 37HWTEST_F_L0(LayoutInfoTest, SetPropertyInit) 38{ 39 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 40 int32_t infoLength = 3; 41 PropertyAttributes defaultAttr = PropertyAttributes::Default(); 42 defaultAttr.SetNormalAttr(infoLength); 43 JSHandle<JSTaggedValue> key(factory->NewFromASCII("key")); 44 JSHandle<LayoutInfo> layoutInfoHandle = factory->CreateLayoutInfo(infoLength); 45 EXPECT_TRUE(*layoutInfoHandle != nullptr); 46 47 layoutInfoHandle->SetPropertyInit(thread, 0, key.GetTaggedValue(), defaultAttr); 48 EXPECT_EQ(layoutInfoHandle->GetKey(0), key.GetTaggedValue()); 49 EXPECT_EQ(layoutInfoHandle->GetAttr(0).GetNormalAttr(), static_cast<uint32_t>(infoLength)); 50} 51 52HWTEST_F_L0(LayoutInfoTest, SetSortedIndex) 53{ 54 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 55 int32_t infoLength = 5; 56 PropertyAttributes defaultAttr = PropertyAttributes::Default(); 57 defaultAttr.SetNormalAttr(infoLength); 58 JSHandle<JSTaggedValue> key1(factory->NewFromASCII("hello")); 59 JSHandle<JSTaggedValue> key2(factory->NewFromASCII("world")); 60 JSHandle<LayoutInfo> layoutInfoHandle = factory->CreateLayoutInfo(infoLength); 61 EXPECT_TRUE(*layoutInfoHandle != nullptr); 62 63 layoutInfoHandle->SetPropertyInit(thread, 0, key1.GetTaggedValue(), defaultAttr); 64 layoutInfoHandle->SetPropertyInit(thread, 1, key2.GetTaggedValue(), defaultAttr); 65 layoutInfoHandle->SetSortedIndex(thread, 0, infoLength - 4); 66 EXPECT_EQ(layoutInfoHandle->GetSortedIndex(0), 1U); 67 EXPECT_EQ(layoutInfoHandle->GetSortedKey(0), key2.GetTaggedValue()); 68} 69 70HWTEST_F_L0(LayoutInfoTest, FindElementWithCache) 71{ 72 int infoLength = 5; 73 int newPropertiesLength = 11; 74 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 75 PropertyAttributes defaultAttr = PropertyAttributes::Default(); 76 JSHandle<JSTaggedValue> key1(factory->NewFromASCII("1")); 77 JSHandle<JSTaggedValue> key4(factory->NewFromASCII("4")); 78 JSHandle<JSTaggedValue> key5(factory->NewFromASCII("5")); 79 JSHandle<JSTaggedValue> key10(factory->NewFromASCII("10")); 80 JSHandle<JSTaggedValue> key11(factory->NewFromASCII("11")); 81 JSHandle<LayoutInfo> layoutInfoHandle = factory->CreateLayoutInfo(infoLength); 82 EXPECT_TRUE(*layoutInfoHandle != nullptr); 83 for (int i = 0; i < infoLength; i++) { 84 JSHandle<JSTaggedValue> elements(thread, JSTaggedValue(i)); 85 JSHandle<JSTaggedValue> elementsKey(JSTaggedValue::ToString(thread, elements)); 86 defaultAttr.SetOffset(i); 87 layoutInfoHandle->AddKey(thread, i, elementsKey.GetTaggedValue(), defaultAttr); 88 } 89 int propertiesNumber = layoutInfoHandle->NumberOfElements(); 90 int result = 0; 91 result = layoutInfoHandle->FindElementWithCache(thread, nullptr, key1.GetTaggedValue(), propertiesNumber); 92 EXPECT_EQ(result, 1); // 1: Index corresponding to key1 93 result = layoutInfoHandle->FindElementWithCache(thread, nullptr, key5.GetTaggedValue(), propertiesNumber); 94 EXPECT_EQ(result, -1); // -1: not find 95 // extend layoutInfo 96 JSHandle<LayoutInfo> newLayoutInfo = factory->ExtendLayoutInfo(layoutInfoHandle, newPropertiesLength); 97 for (int i = 5; i < newPropertiesLength; i++) { 98 JSHandle<JSTaggedValue> elements(thread, JSTaggedValue(i)); 99 JSHandle<JSTaggedValue> elementsKey(JSTaggedValue::ToString(thread, elements)); 100 defaultAttr.SetOffset(i); 101 newLayoutInfo->AddKey(thread, i, elementsKey.GetTaggedValue(), defaultAttr); 102 } 103 result = newLayoutInfo->FindElementWithCache(thread, nullptr, key4.GetTaggedValue(), newPropertiesLength); 104 EXPECT_EQ(result, 4); // 4: Index corresponding to key4 105 result = newLayoutInfo->FindElementWithCache(thread, nullptr, key10.GetTaggedValue(), newPropertiesLength); 106 EXPECT_EQ(result, 10); // 10: Index corresponding to key10 107 result = newLayoutInfo->FindElementWithCache(thread, nullptr, key5.GetTaggedValue(), newPropertiesLength); 108 EXPECT_EQ(result, 5); // 5: Index corresponding to key5 109 result = newLayoutInfo->FindElementWithCache(thread, nullptr, key11.GetTaggedValue(), newPropertiesLength); 110 EXPECT_EQ(result, -1); // -1: not find 111} 112 113void GetAllKeysCommon(JSThread *thread, bool enumKeys = false) 114{ 115 int infoLength = 5; 116 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 117 PropertyAttributes defaultAttr = PropertyAttributes::Default(); 118 JSHandle<JSTaggedValue> key3(factory->NewFromASCII("3")); 119 120 JSHandle<JSObject> objectHandle = factory->NewEmptyJSObject(); 121 JSHandle<TaggedArray> keyArray = factory->NewTaggedArray(infoLength); 122 JSHandle<LayoutInfo> layoutInfoHandle = factory->CreateLayoutInfo(infoLength); 123 EXPECT_TRUE(*layoutInfoHandle != nullptr); 124 std::vector<JSTaggedValue> keyVector; 125 // Add key to layout info 126 for (int i = 0; i < infoLength; i++) { 127 JSHandle<JSTaggedValue> elements(thread, JSTaggedValue(i)); 128 JSHandle<JSTaggedValue> elementsKey(JSTaggedValue::ToString(thread, elements)); 129 defaultAttr.SetOffset(i); 130 if (enumKeys) { 131 if (i != 3) { // 3: index 132 defaultAttr.SetEnumerable(false); 133 } else { 134 defaultAttr.SetEnumerable(true); 135 } 136 } 137 layoutInfoHandle->AddKey(thread, i, elementsKey.GetTaggedValue(), defaultAttr); 138 } 139 if (enumKeys) { 140 uint32_t keys = 0; 141 layoutInfoHandle->GetAllEnumKeys(thread, infoLength, 0, keyArray, &keys, objectHandle); // 0: offset 142 EXPECT_EQ(keyArray->Get(0), key3.GetTaggedValue()); 143 EXPECT_EQ(keys, 1U); 144 } else { 145 layoutInfoHandle->GetAllKeys(thread, infoLength, 0, *keyArray, objectHandle); // 0: offset 146 layoutInfoHandle->GetAllKeysForSerialization(infoLength, keyVector); 147 EXPECT_EQ(keyArray->GetLength(), keyVector.size()); 148 149 for (int i = 0;i < infoLength; i++) { 150 bool result = JSTaggedValue::SameValue(keyArray->Get(i), keyVector[i]); 151 EXPECT_TRUE(result); 152 } 153 } 154} 155 156HWTEST_F_L0(LayoutInfoTest, GetAllKeys) 157{ 158 GetAllKeysCommon(thread); 159} 160 161HWTEST_F_L0(LayoutInfoTest, GetAllEnumKeys) 162{ 163 GetAllKeysCommon(thread, true); 164} 165} // namespace panda::ecmascript 166