huangyu c658ccf319 Update runtime_core code
Issue: https://gitee.com/openharmony/arkcompiler_runtime_core/issues/I5G96F
Test: Test262 suit, ark unittest, rk3568 XTS, ark previewer demo

Signed-off-by: huangyu <huangyu76@huawei.com>
Change-Id: I3f63d129a07deaa27a390f556dcaa5651c098185
2022-07-17 10:20:32 +08:00

166 lines
5.3 KiB
C++

/**
* Copyright (c) 2021-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 <ctime>
#include "utils/hash.h"
#include "gtest/gtest.h"
#include "utils/logger.h"
#include "mem/mem.h"
#include "os/mem.h"
#include "utils/asan_interface.h"
namespace panda {
class HashTest : public testing::Test {
public:
HashTest()
{
#ifdef PANDA_NIGHTLY_TEST_ON
seed_ = std::time(NULL);
#else
seed_ = 0xDEADBEEF;
#endif
}
~HashTest() {}
protected:
template <class T>
void OneObject32bitsHashTest();
template <class T>
void OneStringHashTest();
template <class T>
void StringMemHashTest();
template <class T>
void EndOfPageStringHashTest();
static constexpr size_t KEY40INBYTES = 5;
static constexpr size_t KEY32INBYTES = 4;
static constexpr size_t KEY8INBYTES = 1;
// Some platforms have this macro so do not redefine it.
#ifndef PAGE_SIZE
static constexpr size_t PAGE_SIZE = SIZE_1K * 4;
#endif
unsigned seed_;
};
template <class T>
void HashTest::OneObject32bitsHashTest()
{
srand(seed_);
uint32_t object32 = rand();
uint32_t first_hash = T::GetHash32(reinterpret_cast<uint8_t *>(&object32), KEY32INBYTES);
uint32_t second_hash = T::GetHash32(reinterpret_cast<uint8_t *>(&object32), KEY32INBYTES);
if (first_hash != second_hash) {
std::cout << "Failed 32bit key hash on seed = 0x" << std::hex << seed_ << std::endl;
}
ASSERT_EQ(first_hash, second_hash);
uint8_t object8 = rand();
first_hash = T::GetHash32(reinterpret_cast<uint8_t *>(&object8), KEY8INBYTES);
second_hash = T::GetHash32(reinterpret_cast<uint8_t *>(&object8), KEY8INBYTES);
if (first_hash != second_hash) {
std::cout << "Failed 32bit key hash on seed = 0x" << std::hex << seed_ << std::endl;
}
ASSERT_EQ(first_hash, second_hash);
// Set up 64 bits value and use only 40 bits from it
uint64_t object40 = rand();
first_hash = T::GetHash32(reinterpret_cast<uint8_t *>(&object40), KEY40INBYTES);
second_hash = T::GetHash32(reinterpret_cast<uint8_t *>(&object40), KEY40INBYTES);
if (first_hash != second_hash) {
std::cout << "Failed 32bit key hash on seed = 0x" << std::hex << seed_ << std::endl;
}
ASSERT_EQ(first_hash, second_hash);
}
template <class T>
void HashTest::OneStringHashTest()
{
char string[] = "Over 1000!\0";
// Dummy check. Don't ask me why...
if (sizeof(char) != sizeof(uint8_t)) {
return;
}
uint8_t *mutf8_string = reinterpret_cast<uint8_t *>(string);
uint32_t first_hash = T::GetHash32String(mutf8_string);
uint32_t second_hash = T::GetHash32String(mutf8_string);
ASSERT_EQ(first_hash, second_hash);
}
template <class T>
void HashTest::StringMemHashTest()
{
char string[] = "COULD YOU CREATE MORE COMPLEX TESTS,OK?\0";
size_t string_size = strlen(string);
uint8_t *mutf8_string = reinterpret_cast<uint8_t *>(string);
uint32_t second_hash = T::GetHash32(mutf8_string, string_size);
uint32_t first_hash = T::GetHash32String(mutf8_string);
ASSERT_EQ(first_hash, second_hash);
}
template <class T>
void HashTest::EndOfPageStringHashTest()
{
constexpr const int64_t immTwo = 2;
size_t string_size = 3;
constexpr size_t ALLOC_SIZE = PAGE_SIZE * 2;
void *mem = panda::os::mem::MapRWAnonymousRaw(ALLOC_SIZE);
ASAN_UNPOISON_MEMORY_REGION(mem, ALLOC_SIZE);
panda::os::mem::MakeMemProtected(reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(mem) + PAGE_SIZE), PAGE_SIZE);
char *string =
reinterpret_cast<char *>((reinterpret_cast<uintptr_t>(mem) + PAGE_SIZE) - sizeof(char) * string_size);
string[0] = 'O';
string[1] = 'K';
string[immTwo] = '\0';
uint8_t *mutf8_string = reinterpret_cast<uint8_t *>(string);
uint32_t second_hash = T::GetHash32(mutf8_string, string_size - 1);
uint32_t first_hash = T::GetHash32String(mutf8_string);
ASSERT_EQ(first_hash, second_hash);
auto res = panda::os::mem::UnmapRaw(mem, ALLOC_SIZE);
ASSERT_FALSE(res);
}
// If we hash an object twice, it must return the same value
// Do it for 8 bits key, 32 bits and 40 bits key.
TEST_F(HashTest, OneObjectHashTest)
{
HashTest::OneObject32bitsHashTest<MurmurHash32<DEFAULT_SEED>>();
}
// If we hash a string twice, it must return the same value
TEST_F(HashTest, OneStringHashTest)
{
HashTest::OneStringHashTest<MurmurHash32<DEFAULT_SEED>>();
}
// If we hash a string with out string method,
// we should get the same result as we use a pointer to string as a raw memory.
TEST_F(HashTest, StringMemHashTest)
{
HashTest::StringMemHashTest<MurmurHash32<DEFAULT_SEED>>();
}
// Try to hash the string which located at the end of allocated page.
// Check that we will not have SEGERROR here.
TEST_F(HashTest, EndOfPageStringHashTest)
{
HashTest::EndOfPageStringHashTest<MurmurHash32<DEFAULT_SEED>>();
}
} // namespace panda