14514f5e3Sopenharmony_ci/*
24514f5e3Sopenharmony_ci * Copyright (c) 2022 Huawei Device Co., Ltd.
34514f5e3Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
44514f5e3Sopenharmony_ci * you may not use this file except in compliance with the License.
54514f5e3Sopenharmony_ci * You may obtain a copy of the License at
64514f5e3Sopenharmony_ci *
74514f5e3Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
84514f5e3Sopenharmony_ci *
94514f5e3Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
104514f5e3Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
114514f5e3Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
124514f5e3Sopenharmony_ci * See the License for the specific language governing permissions and
134514f5e3Sopenharmony_ci * limitations under the License.
144514f5e3Sopenharmony_ci */
154514f5e3Sopenharmony_ci
164514f5e3Sopenharmony_ci#include "ecmascript/layout_info-inl.h"
174514f5e3Sopenharmony_ci#include "ecmascript/property_attributes.h"
184514f5e3Sopenharmony_ci#include "ecmascript/tests/test_helper.h"
194514f5e3Sopenharmony_ci
204514f5e3Sopenharmony_ciusing namespace panda::ecmascript;
214514f5e3Sopenharmony_ci
224514f5e3Sopenharmony_cinamespace panda::test {
234514f5e3Sopenharmony_ciclass LayoutInfoTest : public BaseTestWithScope<false> {
244514f5e3Sopenharmony_ci};
254514f5e3Sopenharmony_ci
264514f5e3Sopenharmony_ciHWTEST_F_L0(LayoutInfoTest, SetNumberOfElements)
274514f5e3Sopenharmony_ci{
284514f5e3Sopenharmony_ci    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
294514f5e3Sopenharmony_ci    int32_t infoLength = 2; // 2: len
304514f5e3Sopenharmony_ci    JSHandle<LayoutInfo> layoutInfoHandle = factory->CreateLayoutInfo(infoLength);
314514f5e3Sopenharmony_ci    EXPECT_TRUE(*layoutInfoHandle != nullptr);
324514f5e3Sopenharmony_ci
334514f5e3Sopenharmony_ci    layoutInfoHandle->SetNumberOfElements(thread, 100);
344514f5e3Sopenharmony_ci    EXPECT_EQ(layoutInfoHandle->NumberOfElements(), 100);
354514f5e3Sopenharmony_ci}
364514f5e3Sopenharmony_ci
374514f5e3Sopenharmony_ciHWTEST_F_L0(LayoutInfoTest, SetPropertyInit)
384514f5e3Sopenharmony_ci{
394514f5e3Sopenharmony_ci    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
404514f5e3Sopenharmony_ci    int32_t infoLength = 3;
414514f5e3Sopenharmony_ci    PropertyAttributes defaultAttr = PropertyAttributes::Default();
424514f5e3Sopenharmony_ci    defaultAttr.SetNormalAttr(infoLength);
434514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> key(factory->NewFromASCII("key"));
444514f5e3Sopenharmony_ci    JSHandle<LayoutInfo> layoutInfoHandle = factory->CreateLayoutInfo(infoLength);
454514f5e3Sopenharmony_ci    EXPECT_TRUE(*layoutInfoHandle != nullptr);
464514f5e3Sopenharmony_ci
474514f5e3Sopenharmony_ci    layoutInfoHandle->SetPropertyInit(thread, 0, key.GetTaggedValue(), defaultAttr);
484514f5e3Sopenharmony_ci    EXPECT_EQ(layoutInfoHandle->GetKey(0), key.GetTaggedValue());
494514f5e3Sopenharmony_ci    EXPECT_EQ(layoutInfoHandle->GetAttr(0).GetNormalAttr(), static_cast<uint32_t>(infoLength));
504514f5e3Sopenharmony_ci}
514514f5e3Sopenharmony_ci
524514f5e3Sopenharmony_ciHWTEST_F_L0(LayoutInfoTest, SetSortedIndex)
534514f5e3Sopenharmony_ci{
544514f5e3Sopenharmony_ci    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
554514f5e3Sopenharmony_ci    int32_t infoLength = 5;
564514f5e3Sopenharmony_ci    PropertyAttributes defaultAttr = PropertyAttributes::Default();
574514f5e3Sopenharmony_ci    defaultAttr.SetNormalAttr(infoLength);
584514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> key1(factory->NewFromASCII("hello"));
594514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> key2(factory->NewFromASCII("world"));
604514f5e3Sopenharmony_ci    JSHandle<LayoutInfo> layoutInfoHandle = factory->CreateLayoutInfo(infoLength);
614514f5e3Sopenharmony_ci    EXPECT_TRUE(*layoutInfoHandle != nullptr);
624514f5e3Sopenharmony_ci
634514f5e3Sopenharmony_ci    layoutInfoHandle->SetPropertyInit(thread, 0, key1.GetTaggedValue(), defaultAttr);
644514f5e3Sopenharmony_ci    layoutInfoHandle->SetPropertyInit(thread, 1, key2.GetTaggedValue(), defaultAttr);
654514f5e3Sopenharmony_ci    layoutInfoHandle->SetSortedIndex(thread, 0, infoLength - 4);
664514f5e3Sopenharmony_ci    EXPECT_EQ(layoutInfoHandle->GetSortedIndex(0), 1U);
674514f5e3Sopenharmony_ci    EXPECT_EQ(layoutInfoHandle->GetSortedKey(0), key2.GetTaggedValue());
684514f5e3Sopenharmony_ci}
694514f5e3Sopenharmony_ci
704514f5e3Sopenharmony_ciHWTEST_F_L0(LayoutInfoTest, FindElementWithCache)
714514f5e3Sopenharmony_ci{
724514f5e3Sopenharmony_ci    int infoLength = 5;
734514f5e3Sopenharmony_ci    int newPropertiesLength = 11;
744514f5e3Sopenharmony_ci    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
754514f5e3Sopenharmony_ci    PropertyAttributes defaultAttr = PropertyAttributes::Default();
764514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> key1(factory->NewFromASCII("1"));
774514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> key4(factory->NewFromASCII("4"));
784514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> key5(factory->NewFromASCII("5"));
794514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> key10(factory->NewFromASCII("10"));
804514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> key11(factory->NewFromASCII("11"));
814514f5e3Sopenharmony_ci    JSHandle<LayoutInfo> layoutInfoHandle = factory->CreateLayoutInfo(infoLength);
824514f5e3Sopenharmony_ci    EXPECT_TRUE(*layoutInfoHandle != nullptr);
834514f5e3Sopenharmony_ci    for (int i = 0; i < infoLength; i++) {
844514f5e3Sopenharmony_ci        JSHandle<JSTaggedValue> elements(thread, JSTaggedValue(i));
854514f5e3Sopenharmony_ci        JSHandle<JSTaggedValue> elementsKey(JSTaggedValue::ToString(thread, elements));
864514f5e3Sopenharmony_ci        defaultAttr.SetOffset(i);
874514f5e3Sopenharmony_ci        layoutInfoHandle->AddKey(thread, i, elementsKey.GetTaggedValue(), defaultAttr);
884514f5e3Sopenharmony_ci    }
894514f5e3Sopenharmony_ci    int propertiesNumber = layoutInfoHandle->NumberOfElements();
904514f5e3Sopenharmony_ci    int result = 0;
914514f5e3Sopenharmony_ci    result = layoutInfoHandle->FindElementWithCache(thread, nullptr, key1.GetTaggedValue(), propertiesNumber);
924514f5e3Sopenharmony_ci    EXPECT_EQ(result, 1); // 1: Index corresponding to key1
934514f5e3Sopenharmony_ci    result = layoutInfoHandle->FindElementWithCache(thread, nullptr, key5.GetTaggedValue(), propertiesNumber);
944514f5e3Sopenharmony_ci    EXPECT_EQ(result, -1); // -1: not find
954514f5e3Sopenharmony_ci    // extend layoutInfo
964514f5e3Sopenharmony_ci    JSHandle<LayoutInfo> newLayoutInfo = factory->ExtendLayoutInfo(layoutInfoHandle, newPropertiesLength);
974514f5e3Sopenharmony_ci    for (int i = 5; i < newPropertiesLength; i++) {
984514f5e3Sopenharmony_ci        JSHandle<JSTaggedValue> elements(thread, JSTaggedValue(i));
994514f5e3Sopenharmony_ci        JSHandle<JSTaggedValue> elementsKey(JSTaggedValue::ToString(thread, elements));
1004514f5e3Sopenharmony_ci        defaultAttr.SetOffset(i);
1014514f5e3Sopenharmony_ci        newLayoutInfo->AddKey(thread, i, elementsKey.GetTaggedValue(), defaultAttr);
1024514f5e3Sopenharmony_ci    }
1034514f5e3Sopenharmony_ci    result = newLayoutInfo->FindElementWithCache(thread, nullptr, key4.GetTaggedValue(), newPropertiesLength);
1044514f5e3Sopenharmony_ci    EXPECT_EQ(result, 4); // 4: Index corresponding to key4
1054514f5e3Sopenharmony_ci    result = newLayoutInfo->FindElementWithCache(thread, nullptr, key10.GetTaggedValue(), newPropertiesLength);
1064514f5e3Sopenharmony_ci    EXPECT_EQ(result, 10); // 10: Index corresponding to key10
1074514f5e3Sopenharmony_ci    result = newLayoutInfo->FindElementWithCache(thread, nullptr, key5.GetTaggedValue(), newPropertiesLength);
1084514f5e3Sopenharmony_ci    EXPECT_EQ(result, 5); // 5: Index corresponding to key5
1094514f5e3Sopenharmony_ci    result = newLayoutInfo->FindElementWithCache(thread, nullptr, key11.GetTaggedValue(), newPropertiesLength);
1104514f5e3Sopenharmony_ci    EXPECT_EQ(result, -1); // -1: not find
1114514f5e3Sopenharmony_ci}
1124514f5e3Sopenharmony_ci
1134514f5e3Sopenharmony_civoid GetAllKeysCommon(JSThread *thread, bool enumKeys = false)
1144514f5e3Sopenharmony_ci{
1154514f5e3Sopenharmony_ci    int infoLength = 5;
1164514f5e3Sopenharmony_ci    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
1174514f5e3Sopenharmony_ci    PropertyAttributes defaultAttr = PropertyAttributes::Default();
1184514f5e3Sopenharmony_ci    JSHandle<JSTaggedValue> key3(factory->NewFromASCII("3"));
1194514f5e3Sopenharmony_ci
1204514f5e3Sopenharmony_ci    JSHandle<JSObject> objectHandle = factory->NewEmptyJSObject();
1214514f5e3Sopenharmony_ci    JSHandle<TaggedArray> keyArray = factory->NewTaggedArray(infoLength);
1224514f5e3Sopenharmony_ci    JSHandle<LayoutInfo> layoutInfoHandle = factory->CreateLayoutInfo(infoLength);
1234514f5e3Sopenharmony_ci    EXPECT_TRUE(*layoutInfoHandle != nullptr);
1244514f5e3Sopenharmony_ci    std::vector<JSTaggedValue> keyVector;
1254514f5e3Sopenharmony_ci    // Add key to layout info
1264514f5e3Sopenharmony_ci    for (int i = 0; i < infoLength; i++) {
1274514f5e3Sopenharmony_ci        JSHandle<JSTaggedValue> elements(thread, JSTaggedValue(i));
1284514f5e3Sopenharmony_ci        JSHandle<JSTaggedValue> elementsKey(JSTaggedValue::ToString(thread, elements));
1294514f5e3Sopenharmony_ci        defaultAttr.SetOffset(i);
1304514f5e3Sopenharmony_ci        if (enumKeys) {
1314514f5e3Sopenharmony_ci            if (i != 3) { // 3: index
1324514f5e3Sopenharmony_ci                defaultAttr.SetEnumerable(false);
1334514f5e3Sopenharmony_ci            } else {
1344514f5e3Sopenharmony_ci                defaultAttr.SetEnumerable(true);
1354514f5e3Sopenharmony_ci            }
1364514f5e3Sopenharmony_ci        }
1374514f5e3Sopenharmony_ci        layoutInfoHandle->AddKey(thread, i, elementsKey.GetTaggedValue(), defaultAttr);
1384514f5e3Sopenharmony_ci    }
1394514f5e3Sopenharmony_ci    if (enumKeys) {
1404514f5e3Sopenharmony_ci        uint32_t keys = 0;
1414514f5e3Sopenharmony_ci        layoutInfoHandle->GetAllEnumKeys(thread, infoLength, 0, keyArray, &keys, objectHandle); // 0: offset
1424514f5e3Sopenharmony_ci        EXPECT_EQ(keyArray->Get(0), key3.GetTaggedValue());
1434514f5e3Sopenharmony_ci        EXPECT_EQ(keys, 1U);
1444514f5e3Sopenharmony_ci    } else {
1454514f5e3Sopenharmony_ci        layoutInfoHandle->GetAllKeys(thread, infoLength, 0, *keyArray, objectHandle); // 0: offset
1464514f5e3Sopenharmony_ci        layoutInfoHandle->GetAllKeysForSerialization(infoLength, keyVector);
1474514f5e3Sopenharmony_ci        EXPECT_EQ(keyArray->GetLength(), keyVector.size());
1484514f5e3Sopenharmony_ci
1494514f5e3Sopenharmony_ci        for (int i = 0;i < infoLength; i++) {
1504514f5e3Sopenharmony_ci            bool result = JSTaggedValue::SameValue(keyArray->Get(i), keyVector[i]);
1514514f5e3Sopenharmony_ci            EXPECT_TRUE(result);
1524514f5e3Sopenharmony_ci        }
1534514f5e3Sopenharmony_ci    }
1544514f5e3Sopenharmony_ci}
1554514f5e3Sopenharmony_ci
1564514f5e3Sopenharmony_ciHWTEST_F_L0(LayoutInfoTest, GetAllKeys)
1574514f5e3Sopenharmony_ci{
1584514f5e3Sopenharmony_ci    GetAllKeysCommon(thread);
1594514f5e3Sopenharmony_ci}
1604514f5e3Sopenharmony_ci
1614514f5e3Sopenharmony_ciHWTEST_F_L0(LayoutInfoTest, GetAllEnumKeys)
1624514f5e3Sopenharmony_ci{
1634514f5e3Sopenharmony_ci    GetAllKeysCommon(thread, true);
1644514f5e3Sopenharmony_ci}
1654514f5e3Sopenharmony_ci}  // namespace panda::ecmascript
166