mirror of
https://gitee.com/openharmony/arkcompiler_ets_runtime
synced 2024-12-03 16:31:12 +00:00
add unittest case for transitions dictionary
Signed-off-by: zhaozhibo <zhaozhibo3@huawei.com>
This commit is contained in:
parent
385ec6fee8
commit
a1e5795fbd
@ -187,7 +187,7 @@ public:
|
||||
value_ = value_ & (~TAG_WEAK);
|
||||
}
|
||||
|
||||
inline JSTaggedValue CreateAndGetWeakRef()
|
||||
inline JSTaggedValue CreateAndGetWeakRef() const
|
||||
{
|
||||
ASSERT_PRINT(IsHeapObject() && ((value_ & TAG_WEAK) == 0U),
|
||||
"The least significant two bits of JSTaggedValue are not zero.");
|
||||
|
@ -151,6 +151,7 @@ host_unittest_action("EcmaVm_003_Test") {
|
||||
"tagged_value_test.cpp",
|
||||
"template_map_test.cpp",
|
||||
"template_string_test.cpp",
|
||||
"transitions_dictionary_test.cpp",
|
||||
"weak_ref_old_gc_test.cpp",
|
||||
"weak_ref_semi_gc_test.cpp",
|
||||
"weak_vector_test.cpp",
|
||||
|
289
ecmascript/tests/transitions_dictionary_test.cpp
Normal file
289
ecmascript/tests/transitions_dictionary_test.cpp
Normal file
@ -0,0 +1,289 @@
|
||||
/*
|
||||
* Copyright (c) 2022 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/ecma_vm.h"
|
||||
#include "ecmascript/js_symbol.h"
|
||||
#include "ecmascript/object_factory.h"
|
||||
#include "ecmascript/property_attributes.h"
|
||||
#include "ecmascript/tagged_hash_table.h"
|
||||
#include "ecmascript/tests/test_helper.h"
|
||||
#include "ecmascript/transitions_dictionary.h"
|
||||
|
||||
using namespace panda::ecmascript;
|
||||
|
||||
namespace panda::test {
|
||||
class TransitionsDictionaryTest : public testing::Test {
|
||||
public:
|
||||
static void SetUpTestCase()
|
||||
{
|
||||
GTEST_LOG_(INFO) << "SetUpTestCase";
|
||||
}
|
||||
|
||||
static void TearDownTestCase()
|
||||
{
|
||||
GTEST_LOG_(INFO) << "TearDownCase";
|
||||
}
|
||||
|
||||
void SetUp() override
|
||||
{
|
||||
TestHelper::CreateEcmaVMWithScope(instance, thread, scope);
|
||||
}
|
||||
|
||||
void TearDown() override
|
||||
{
|
||||
TestHelper::DestroyEcmaVMWithScope(instance, scope);
|
||||
}
|
||||
|
||||
EcmaVM *instance {nullptr};
|
||||
EcmaHandleScope *scope {nullptr};
|
||||
JSThread *thread {nullptr};
|
||||
};
|
||||
|
||||
HWTEST_F_L0(TransitionsDictionaryTest, IsMatch)
|
||||
{
|
||||
JSHandle<JSTaggedValue> key(thread, JSTaggedValue::True());
|
||||
JSHandle<JSTaggedValue> otherKey(thread, JSTaggedValue::False());
|
||||
JSHandle<JSTaggedValue> metaData(thread, JSTaggedValue::Undefined());
|
||||
JSHandle<JSTaggedValue> otherDetails(thread, JSTaggedValue::Null());
|
||||
bool result = TransitionsDictionary::IsMatch(key.GetTaggedValue(), metaData.GetTaggedValue(),
|
||||
otherKey.GetTaggedValue(), otherDetails.GetTaggedValue());
|
||||
EXPECT_FALSE(result);
|
||||
|
||||
result = TransitionsDictionary::IsMatch(key.GetTaggedValue(), metaData.GetTaggedValue(),
|
||||
key.GetTaggedValue(), metaData.GetTaggedValue());
|
||||
EXPECT_TRUE(result);
|
||||
}
|
||||
|
||||
HWTEST_F_L0(TransitionsDictionaryTest, Hash)
|
||||
{
|
||||
auto vm = thread->GetEcmaVM();
|
||||
auto factory = vm->GetFactory();
|
||||
|
||||
// test when key is string.
|
||||
JSHandle<JSTaggedValue> key1(factory->NewFromStdString("k"));
|
||||
JSHandle<JSTaggedValue> metaData1(thread, JSTaggedValue(1)); // test metaData : 1
|
||||
int hash = TransitionsDictionary::Hash(key1.GetTaggedValue(), metaData1.GetTaggedValue());
|
||||
// "k" : 107, hashSeed : 0, shift : 5, metaData : 1
|
||||
EXPECT_EQ(hash, 108); // 108 : (0 << 5) - 0 + 107 + 1
|
||||
|
||||
JSHandle<JSTaggedValue> key2(factory->NewFromStdString("key"));
|
||||
hash = TransitionsDictionary::Hash(key2.GetTaggedValue(), metaData1.GetTaggedValue());
|
||||
EXPECT_EQ(hash, 106080);
|
||||
|
||||
// test when key is symbol.
|
||||
JSHandle<JSTaggedValue> symbolName(factory->NewFromStdString("s"));
|
||||
JSHandle<JSSymbol> privateNameSymbol = factory->NewPrivateNameSymbol(symbolName);
|
||||
JSHandle<JSTaggedValue> symbolValue = JSHandle<JSTaggedValue>::Cast(privateNameSymbol);
|
||||
JSHandle<JSTaggedValue> metaData2(thread, JSTaggedValue(2)); // test metaData : 2
|
||||
hash = TransitionsDictionary::Hash(symbolValue.GetTaggedValue(), metaData2.GetTaggedValue());
|
||||
EXPECT_EQ(hash, 117); // 117 : 115 + 2
|
||||
}
|
||||
|
||||
HWTEST_F_L0(TransitionsDictionaryTest, GetKeyIndex)
|
||||
{
|
||||
int entry = 10;
|
||||
EXPECT_EQ(TransitionsDictionary::GetKeyIndex(entry), 33); // 33 : 3 + 10 * 3 + 0
|
||||
}
|
||||
|
||||
HWTEST_F_L0(TransitionsDictionaryTest, GetValueIndex)
|
||||
{
|
||||
int entry = 10;
|
||||
EXPECT_EQ(TransitionsDictionary::GetValueIndex(entry), 34); // 34 : 3 + 10 * 3 + 1
|
||||
}
|
||||
|
||||
HWTEST_F_L0(TransitionsDictionaryTest, GetEntryIndex)
|
||||
{
|
||||
int entry = 10;
|
||||
EXPECT_EQ(TransitionsDictionary::GetEntryIndex(entry), 33); // 33 : 3 + 10 * 3
|
||||
}
|
||||
|
||||
HWTEST_F_L0(TransitionsDictionaryTest, Create)
|
||||
{
|
||||
int numberOfElements = 8;
|
||||
JSHandle<TransitionsDictionary> transDic = TransitionsDictionary::Create(thread, numberOfElements);
|
||||
EXPECT_EQ(transDic->GetLength(), 27U); // 27 : 3 + 8 * 3
|
||||
EXPECT_EQ(transDic->EntriesCount(), 0);
|
||||
EXPECT_EQ(transDic->HoleEntriesCount(), 0);
|
||||
}
|
||||
|
||||
HWTEST_F_L0(TransitionsDictionaryTest, Shrink)
|
||||
{
|
||||
auto vm = thread->GetEcmaVM();
|
||||
auto factory = vm->GetFactory();
|
||||
int numberOfElements = 64;
|
||||
JSHandle<TransitionsDictionary> transDic = TransitionsDictionary::Create(thread, numberOfElements);
|
||||
EXPECT_EQ(transDic->GetLength(), 195U); // 195 : 3 + 64 * 3
|
||||
EXPECT_EQ(transDic->EntriesCount(), 0);
|
||||
|
||||
JSHandle<JSTaggedValue> metaData(thread, JSTaggedValue::Undefined());
|
||||
int eleNum = 7;
|
||||
for (int index = 0; index < eleNum; index++) {
|
||||
std::string keyStr = "key" + std::to_string(index);
|
||||
std::string valueStr = "value" + std::to_string(index);
|
||||
JSHandle<JSTaggedValue> key(factory->NewFromStdString(keyStr));
|
||||
JSHandle<JSTaggedValue> value(factory->NewFromStdString(valueStr));
|
||||
TransitionsDictionary::PutIfAbsent(thread, transDic, key, value, metaData);
|
||||
}
|
||||
JSHandle<TransitionsDictionary> transDicAfterShink = TransitionsDictionary::Shrink(thread, transDic);
|
||||
EXPECT_EQ(transDicAfterShink->GetLength(), 51U); // (1 << (32 - Clz((7 + (7 >> 1)) - 1))) * 3 + 3
|
||||
EXPECT_EQ(transDic->EntriesCount(), eleNum);
|
||||
}
|
||||
|
||||
HWTEST_F_L0(TransitionsDictionaryTest, Get_Set_Attributes)
|
||||
{
|
||||
int numberOfElements = 8;
|
||||
JSHandle<TransitionsDictionary> transDic = TransitionsDictionary::Create(thread, numberOfElements);
|
||||
uint32_t length = transDic->GetLength();
|
||||
EXPECT_EQ(length, 27U); // 27 : 3 + 8 * 3
|
||||
|
||||
for (int index = 0; index < numberOfElements; index++) {
|
||||
transDic->SetAttributes(thread, index, JSTaggedValue(index));
|
||||
JSTaggedValue value = transDic->GetAttributes(index);
|
||||
EXPECT_EQ(value, JSTaggedValue(index));
|
||||
}
|
||||
}
|
||||
|
||||
HWTEST_F_L0(TransitionsDictionaryTest, SetEntry)
|
||||
{
|
||||
auto vm = thread->GetEcmaVM();
|
||||
auto factory = vm->GetFactory();
|
||||
int numberOfElements = 8;
|
||||
JSHandle<TransitionsDictionary> transDic = TransitionsDictionary::Create(thread, numberOfElements);
|
||||
JSHandle<JSTaggedValue> metaData(thread, JSTaggedValue::Undefined());
|
||||
for (int index = 0; index < numberOfElements; index++) {
|
||||
std::string keyStr = "key" + std::to_string(index);
|
||||
std::string valueStr = "value" + std::to_string(index);
|
||||
JSHandle<JSTaggedValue> key(factory->NewFromStdString(keyStr));
|
||||
JSHandle<JSTaggedValue> value(factory->NewFromStdString(valueStr));
|
||||
transDic->SetEntry(thread, index, key.GetTaggedValue(), value.GetTaggedValue(), metaData.GetTaggedValue());
|
||||
EXPECT_EQ(transDic->GetKey(index), key.GetTaggedValue());
|
||||
}
|
||||
}
|
||||
|
||||
HWTEST_F_L0(TransitionsDictionaryTest, FindEntry)
|
||||
{
|
||||
auto vm = thread->GetEcmaVM();
|
||||
auto factory = vm->GetFactory();
|
||||
int numberOfElements = 8;
|
||||
JSHandle<TransitionsDictionary> transDic = TransitionsDictionary::Create(thread, numberOfElements);
|
||||
JSHandle<JSTaggedValue> metaData(thread, JSTaggedValue::Undefined());
|
||||
for (int index = 0; index < numberOfElements; index++) {
|
||||
std::string keyStr = "key" + std::to_string(index);
|
||||
std::string valueStr = "value" + std::to_string(index);
|
||||
JSHandle<JSTaggedValue> key(factory->NewFromStdString(keyStr));
|
||||
JSHandle<JSTaggedValue> value(factory->NewFromStdString(valueStr));
|
||||
transDic = TransitionsDictionary::PutIfAbsent(thread, transDic, key, value, metaData);
|
||||
int foundEntry = transDic->FindEntry(key.GetTaggedValue(), metaData.GetTaggedValue());
|
||||
EXPECT_EQ(index + 3, foundEntry); // 3 : table header size
|
||||
}
|
||||
}
|
||||
|
||||
HWTEST_F_L0(TransitionsDictionaryTest, RemoveElement)
|
||||
{
|
||||
auto vm = thread->GetEcmaVM();
|
||||
auto factory = vm->GetFactory();
|
||||
int numberOfElements = 8;
|
||||
JSHandle<TransitionsDictionary> transDic = TransitionsDictionary::Create(thread, numberOfElements);
|
||||
JSHandle<JSTaggedValue> metaData(thread, JSTaggedValue::Undefined());
|
||||
for (int index = 0; index < numberOfElements; index++) {
|
||||
std::string keyStr = "key" + std::to_string(index);
|
||||
std::string valueStr = "value" + std::to_string(index);
|
||||
JSHandle<JSTaggedValue> key(factory->NewFromStdString(keyStr));
|
||||
JSHandle<JSTaggedValue> value(factory->NewFromStdString(valueStr));
|
||||
transDic = TransitionsDictionary::PutIfAbsent(thread, transDic, key, value, metaData);
|
||||
}
|
||||
JSHandle<JSTaggedValue> key7(factory->NewFromStdString("key7")); // test remove element by "key7"
|
||||
int foundEntry = transDic->FindEntry(key7.GetTaggedValue(), metaData.GetTaggedValue());
|
||||
EXPECT_EQ(foundEntry, 7 + 3);
|
||||
EXPECT_EQ(transDic->EntriesCount(), 8);
|
||||
|
||||
transDic->RemoveElement(thread, foundEntry);
|
||||
foundEntry = transDic->FindEntry(key7.GetTaggedValue(), metaData.GetTaggedValue());
|
||||
EXPECT_EQ(foundEntry, -1); // -1 : not found entry
|
||||
EXPECT_EQ(transDic->EntriesCount(), 7);
|
||||
}
|
||||
|
||||
HWTEST_F_L0(TransitionsDictionaryTest, PutIfAbsent)
|
||||
{
|
||||
auto vm = thread->GetEcmaVM();
|
||||
auto factory = vm->GetFactory();
|
||||
int numberOfElements = 8;
|
||||
JSHandle<TransitionsDictionary> transDic = TransitionsDictionary::Create(thread, numberOfElements);
|
||||
JSHandle<JSTaggedValue> metaData(thread, JSTaggedValue::Undefined());
|
||||
for (int index = 0; index < numberOfElements; index++) {
|
||||
std::string keyStr = "key" + std::to_string(index);
|
||||
std::string valueStr = "value" + std::to_string(index);
|
||||
JSHandle<JSTaggedValue> key(factory->NewFromStdString(keyStr));
|
||||
JSHandle<JSTaggedValue> value(factory->NewFromStdString(valueStr));
|
||||
transDic = TransitionsDictionary::PutIfAbsent(thread, transDic, key, value, metaData);
|
||||
int foundEntry = transDic->FindEntry(key.GetTaggedValue(), metaData.GetTaggedValue());
|
||||
EXPECT_EQ(foundEntry, index + 3);
|
||||
|
||||
JSHandle<JSTaggedValue> foundValue(thread, transDic->GetValue(foundEntry));
|
||||
JSHandle<JSTaggedValue> weakValue(thread, value->CreateAndGetWeakRef());
|
||||
vm->SetEnableForceGC(false);
|
||||
EXPECT_EQ(foundValue.GetTaggedValue(), weakValue.GetTaggedValue());
|
||||
}
|
||||
}
|
||||
|
||||
HWTEST_F_L0(TransitionsDictionaryTest, Remove)
|
||||
{
|
||||
auto vm = thread->GetEcmaVM();
|
||||
auto factory = vm->GetFactory();
|
||||
int numberOfElements = 64;
|
||||
int eleNum = 7;
|
||||
JSHandle<TransitionsDictionary> transDic = TransitionsDictionary::Create(thread, numberOfElements);
|
||||
JSHandle<JSTaggedValue> metaData(thread, JSTaggedValue::Undefined());
|
||||
for (int index = 0; index < eleNum; index++) {
|
||||
std::string keyStr = "key" + std::to_string(index);
|
||||
std::string valueStr = "value" + std::to_string(index);
|
||||
JSHandle<JSTaggedValue> key(factory->NewFromStdString(keyStr));
|
||||
JSHandle<JSTaggedValue> value(factory->NewFromStdString(valueStr));
|
||||
transDic = TransitionsDictionary::PutIfAbsent(thread, transDic, key, value, metaData);
|
||||
}
|
||||
JSHandle<JSTaggedValue> key6(factory->NewFromStdString("key6")); // test remove element by "key6"
|
||||
EXPECT_EQ(transDic->EntriesCount(), 7);
|
||||
EXPECT_EQ(transDic->GetLength(), 195U); // 195 : 3 + 64 * 3
|
||||
|
||||
transDic = TransitionsDictionary::Remove(thread, transDic, key6, metaData.GetTaggedValue());
|
||||
EXPECT_EQ(transDic->EntriesCount(), 6); // 6 : 7 - 1
|
||||
EXPECT_EQ(transDic->GetLength(), 51U); // (1 << (32 - Clz((6 + (6 >> 1)) - 1))) * 3 + 3
|
||||
}
|
||||
|
||||
HWTEST_F_L0(TransitionsDictionaryTest, Rehash)
|
||||
{
|
||||
auto vm = thread->GetEcmaVM();
|
||||
auto factory = vm->GetFactory();
|
||||
int numberOfElements = 64;
|
||||
int eleNum = 7;
|
||||
JSHandle<TransitionsDictionary> transDic = TransitionsDictionary::Create(thread, numberOfElements);
|
||||
JSHandle<JSTaggedValue> metaData(thread, JSTaggedValue::Undefined());
|
||||
for (int index = 0; index < eleNum; index++) {
|
||||
std::string keyStr = "key" + std::to_string(index);
|
||||
std::string valueStr = "value" + std::to_string(index);
|
||||
JSHandle<JSTaggedValue> key(factory->NewFromStdString(keyStr));
|
||||
JSHandle<JSTaggedValue> value(factory->NewFromStdString(valueStr));
|
||||
transDic = TransitionsDictionary::PutIfAbsent(thread, transDic, key, value, metaData);
|
||||
}
|
||||
EXPECT_EQ(transDic->HoleEntriesCount(), 0);
|
||||
|
||||
int lastEntry = 7 + 3;
|
||||
transDic->RemoveElement(thread, lastEntry); // remove one element
|
||||
EXPECT_EQ(transDic->HoleEntriesCount(), 1);
|
||||
|
||||
transDic->Rehash(thread, *transDic);
|
||||
EXPECT_EQ(transDic->HoleEntriesCount(), 0);
|
||||
}
|
||||
} // namespace panda::test
|
@ -103,7 +103,7 @@ public:
|
||||
HashTableT::Set(thread, index, metaData);
|
||||
}
|
||||
|
||||
inline void SetEntry(const JSThread *thread, int entry, const JSTaggedValue &key, JSTaggedValue &value,
|
||||
inline void SetEntry(const JSThread *thread, int entry, const JSTaggedValue &key, const JSTaggedValue &value,
|
||||
const JSTaggedValue &metaData)
|
||||
{
|
||||
SetKey(thread, entry, key);
|
||||
|
Loading…
Reference in New Issue
Block a user