diff --git a/BUILD.gn b/BUILD.gn index ffd401dc522daaeeaef4dcc152e6e51802546f1c..3b1027e43b6d72c557ac9059674cb157017e84e4 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -159,16 +159,21 @@ group("common_components_js_unittest") { deps += [ "common_components/base/tests:unittest", "common_components/common_runtime/tests:unittest", - - #"common_components/heap/allocator/tests:unittest", + "common_components/common/tests:unittest", + "common_components/heap/allocator/tests:unittest", "common_components/heap/barrier/tests:unittest", - - #"common_components/heap/collector/tests:unittest", + "common_components/heap/collector/tests:unittest", + "common_components/heap/space/tests:unittest", "common_components/heap/w_collector/tests:unittest", + "common_components/heap/tests:unittest", "common_components/mutator/tests:unittest", "common_components/objects/tests:unittest", + "common_components/profiler/tests:unittest", + "common_components/serialize/tests:unittest", "common_components/thread/tests:unittest", "common_components/log/tests:unittest", + "common_components/platform/unix/tests:unittest", + "common_components/taskpool/tests:unittest", ] } } @@ -181,16 +186,21 @@ group("common_components_unittest") { deps += [ "common_components/base/tests:host_unittest", "common_components/common_runtime/tests:host_unittest", - - #"common_components/heap/allocator/tests:host_unittest", + "common_components/common/tests:host_unittest", + "common_components/heap/allocator/tests:host_unittest", "common_components/heap/barrier/tests:host_unittest", - - #"common_components/heap/collector/tests:host_unittest", + "common_components/heap/collector/tests:host_unittest", + "common_components/heap/space/tests:host_unittest", "common_components/heap/w_collector/tests:host_unittest", + "common_components/heap/tests:host_unittest", "common_components/mutator/tests:host_unittest", "common_components/objects/tests:host_unittest", + "common_components/profiler/tests:host_unittest", + "common_components/serialize/tests:host_unittest", "common_components/thread/tests:host_unittest", "common_components/log/tests:host_unittest", + "common_components/platform/unix/tests:host_unittest", + "common_components/taskpool/tests:host_unittest", ] } } diff --git a/common_components/base/c_string.cpp b/common_components/base/c_string.cpp index 64631c39ceffc15baa23bf3cd41d6b7e5a000225..ac15016ad014fe57c19d71552814bba943e0ab1b 100755 --- a/common_components/base/c_string.cpp +++ b/common_components/base/c_string.cpp @@ -183,6 +183,7 @@ void CString::EnsureSpace(size_t addLen) } char* newStr = reinterpret_cast(malloc(capacity_)); LOGF_IF(newStr == nullptr) << "CString::Init failed"; + LOGF_IF(memset_s(newStr, capacity_, 0, capacity_) != EOK) << "CString::EnsureSpace memset_s failed"; LOGF_IF(memcpy_s(newStr, capacity_, str_, length_) != EOK) << "CString::EnsureSpace memcpy_s failed"; if (str_ != nullptr) { free(str_); diff --git a/common_components/base/tests/BUILD.gn b/common_components/base/tests/BUILD.gn index 39e86f58d2ed0cbdc56ec3a7cdcd8f967e4197f8..b539cdb7f81c7f641bda9ad704d9cdf2f5f84b22 100755 --- a/common_components/base/tests/BUILD.gn +++ b/common_components/base/tests/BUILD.gn @@ -30,6 +30,52 @@ host_unittest_action("C_String_Test") { deps = [ "//arkcompiler/ets_runtime/common_components:libark_common_components_test" ] + # hiviewdfx libraries + external_deps = [ + "icu:shared_icui18n", + "icu:shared_icuuc", + "zlib:libz", + ] +} + +host_unittest_action("Mem_Utils_Test") { + module_out_path = module_output_path + + sources = [ + # test file + "mem_utils_test.cpp", + ] + + configs = [ + "//arkcompiler/ets_runtime/common_components:common_components_test_config", + "//arkcompiler/ets_runtime:icu_path_test_config", + ] + + deps = [ "//arkcompiler/ets_runtime/common_components:libark_common_components_test" ] + + # hiviewdfx libraries + external_deps = [ + "icu:shared_icui18n", + "icu:shared_icuuc", + "runtime_core:libarkassembler_static", + ] +} + +host_unittest_action("Utf_Helper_Test") { + module_out_path = module_output_path + + sources = [ + # test file + "utf_helper_test.cpp", + ] + + configs = [ + "//arkcompiler/ets_runtime/common_components:common_components_test_config", + "//arkcompiler/ets_runtime:icu_path_test_config", + ] + + deps = [ "//arkcompiler/ets_runtime/common_components:libark_common_components_test" ] + # hiviewdfx libraries external_deps = [ "icu:shared_icui18n", @@ -44,6 +90,8 @@ group("unittest") { # deps file deps = [ ":C_String_Test", + ":Mem_Utils_Test", + ":Utf_Helper_Test", ] } @@ -53,5 +101,7 @@ group("host_unittest") { # deps file deps = [ ":C_String_TestAction", + ":Mem_Utils_TestAction", + ":Utf_Helper_TestAction", ] } \ No newline at end of file diff --git a/common_components/base/tests/c_string_test.cpp b/common_components/base/tests/c_string_test.cpp index 56b0436ac55873a17bfd6cd19d706b945a9fa16b..704e27c7287386eee700ecb206a5e7fa13187923 100755 --- a/common_components/base/tests/c_string_test.cpp +++ b/common_components/base/tests/c_string_test.cpp @@ -15,7 +15,6 @@ #include "common_components/base/c_string.h" #include "common_components/tests/test_helper.h" -#include using namespace common; namespace common::test { @@ -274,4 +273,137 @@ HWTEST_F_L0(CStringTest, ConstructTest) EXPECT_EQ(nonEmptyStr.Length(), static_cast(0)); EXPECT_EQ(nonEmptyStr.Str()[0], '\0'); } + +HWTEST_F_L0(CStringTest, FormatStringBasicTest) +{ + CString result = CString::FormatString("Hello, %s!", "World"); + EXPECT_STREQ(result.Str(), "Hello, World!"); +} + +HWTEST_F_L0(CStringTest, FormatString_InvalidArguments_ReturnsError) +{ + CString result = CString::FormatString("%n", nullptr); + EXPECT_STREQ(result.Str(), "invalid arguments for FormatString"); +} + +HWTEST_F_L0(CStringTest, InsertMiddle_Success) +{ + CString str("helloworld"); + EXPECT_STREQ(str.Insert(5, ", ").Str(), "hello, world"); +} + +HWTEST_F_L0(CStringTest, TruncateValidIndex_Success) +{ + CString str("hello world"); + EXPECT_STREQ(str.Truncate(5).Str(), "hello"); + EXPECT_EQ(str.Length(), static_cast(5)); +} + +HWTEST_F_L0(CStringTest, GetStr_NonEmptyString_ReturnsCorrect) +{ + CString str("test string"); + EXPECT_STREQ(str.GetStr(), "test string"); +} + +HWTEST_F_L0(CStringTest, CombineWithEmptyString_ReturnsOriginal) +{ + CString str("original"); + CString emptyStr; + CString combined = str.Combine(emptyStr); + EXPECT_STREQ(combined.Str(), "original"); + EXPECT_EQ(combined.Length(), str.Length()); +} + +HWTEST_F_L0(CStringTest, CombineWithEmptyCStr_ReturnsOriginal) +{ + CString str("original"); + const char* emptyCStr = ""; + CString combined = str.Combine(emptyCStr); + EXPECT_STREQ(combined.Str(), "original"); + EXPECT_EQ(combined.Length(), str.Length()); +} + +HWTEST_F_L0(CStringTest, AppendNullptr_NoChange) +{ + CString str("original"); + str.Append(nullptr, 5); + EXPECT_STREQ(str.Str(), "original"); + EXPECT_EQ(str.Length(), strlen("original")); +} + +HWTEST_F_L0(CStringTest, AppendZeroLength_NoChange) +{ + CString str("test"); + CString emptyStr; + + str.Append(emptyStr, 0); + + EXPECT_STREQ(str.Str(), "test"); + EXPECT_EQ(str.Length(), strlen("test")); +} + +HWTEST_F_L0(CStringTest, AppendSelf_ValidResult) +{ + CString str("abc"); + str.Append(str.Str(), str.Length()); + EXPECT_STREQ(str.Str(), "abcabc"); + EXPECT_EQ(str.Length(), strlen("abcabc")); +} + +HWTEST_F_L0(CStringTest, AppendEmptyCString_NoChange) +{ + CString str("original"); + CString emptyStr; + str.Append(emptyStr); + EXPECT_STREQ(str.Str(), "original"); + EXPECT_EQ(str.Length(), strlen("original")); +} + +HWTEST_F_L0(CStringTest, AppendEmptyCStringZeroLength_NoChange) +{ + CString str("test"); + CString emptyStr; + + str.Append(emptyStr, 0); + + EXPECT_STREQ(str.Str(), "test"); + EXPECT_EQ(str.Length(), strlen("test")); +} + +HWTEST_F_L0(CStringTest, AppendValidCString_CorrectResult) +{ + CString str("hello"); + CString addStr(" world!"); + str.Append(addStr, strlen(addStr.Str())); + EXPECT_STREQ(str.Str(), "hello world!"); + EXPECT_EQ(str.Length(), strlen("hello world!")); +} + +HWTEST_F_L0(CStringTest, EnsureMultipleCalls_CapacityGrowsCorrectly) +{ + CString str("initial"); + char* firstPtr = str.GetStr(); + + str.EnsureSpace(16); + char* secondPtr = str.GetStr(); + + EXPECT_NE(firstPtr, secondPtr); + + str.EnsureSpace(100); + char* thirdPtr = str.GetStr(); + + EXPECT_NE(secondPtr, thirdPtr); + EXPECT_EQ(str.Length(), strlen("initial")); + EXPECT_STREQ(str.Str(), "initial"); +} + +HWTEST_F_L0(CStringTest, CStringSubscriptOperatorTest) +{ + const CString constStr("hello world"); + EXPECT_EQ(constStr[0], 'h'); + + CString mutableStr("mutable"); + mutableStr[0] = 'M'; + EXPECT_EQ(mutableStr[0], 'M'); +} } \ No newline at end of file diff --git a/common_components/base/tests/mem_utils_test.cpp b/common_components/base/tests/mem_utils_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..49c7f470777faef7612c761fe143eaa1fe88078b --- /dev/null +++ b/common_components/base/tests/mem_utils_test.cpp @@ -0,0 +1,50 @@ +/* +* Copyright (c) 2025 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 +#include + +#include "common_components/base/mem_utils.h" +#include "common_components/tests/test_helper.h" + +using namespace common; +namespace common::test { +class MemUtilsTest : public common::test::BaseTestWithScope { +}; + +HWTEST_F_L0(MemUtilsTest, CopyZeroBytes) +{ + char dest[100] = {}; + const char* src = "hello world"; + MemoryCopy(reinterpret_cast(dest), 0, + reinterpret_cast(src), strlen(src) + 1); + EXPECT_EQ(dest[0], '\0'); +} + +HWTEST_F_L0(MemUtilsTest, CopyTwoChunks) +{ + constexpr size_t totalSize = 100; + char dest[totalSize] = {}; + char src[totalSize] = {}; + for (size_t i = 0; i < totalSize; ++i) { + src[i] = static_cast('A' + (i % 26)); + } + + MemoryCopy(reinterpret_cast(dest), totalSize, + reinterpret_cast(src), totalSize); + + EXPECT_EQ(memcmp(dest, src, totalSize), 0); +} +} // namespace common::test \ No newline at end of file diff --git a/common_components/base/tests/utf_helper_test.cpp b/common_components/base/tests/utf_helper_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a6bd777ea9adb40927c6dcc211cf5c928aec32cf --- /dev/null +++ b/common_components/base/tests/utf_helper_test.cpp @@ -0,0 +1,329 @@ +/* + * Copyright (c) 2025 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 "common_components/base/utf_helper.h" +#include "common_components/tests/test_helper.h" + +using namespace common; +namespace common::test { +class UtfHelperTest : public common::test::BaseTestWithScope { +}; + +HWTEST_F_L0(UtfHelperTest, DecodeUTF16Test1) +{ + uint16_t utf16[] = {0xD7FF}; + size_t index = 0; + size_t len = 1; + uint32_t result = utf_helper::DecodeUTF16(utf16, len, &index, false); + EXPECT_EQ(result, 0xD7FF); + + uint16_t utf16In[] = {0xDC00}; + result = utf_helper::DecodeUTF16(utf16In, len, &index, false); + EXPECT_EQ(result, 0xDC00); + + uint16_t utf16In1[] = {0xD800}; + result = utf_helper::DecodeUTF16(utf16In1, len, &index, false); + EXPECT_EQ(result, 0xD800); + + uint16_t utf16In2[] = {0xD7FF}; + len = 2; + result = utf_helper::DecodeUTF16(utf16In2, len, &index, false); + EXPECT_EQ(result, 0xD7FF); + + len = 1; + result = utf_helper::DecodeUTF16(utf16In2, len, &index, false); + EXPECT_EQ(result, 0xD7FF); + + result = utf_helper::DecodeUTF16(utf16In, len, &index, false); + EXPECT_EQ(result, 0xDC00); +} + +HWTEST_F_L0(UtfHelperTest, DecodeUTF16Test2) +{ + size_t index = 0; + uint16_t utf16[] = {0xD800, 0xDC00}; + size_t len = 2; + utf16[1] = 0xFFFF; + uint32_t result = utf_helper::DecodeUTF16(utf16, len, &index, false); + EXPECT_EQ(result, 0xD800); +} + +HWTEST_F_L0(UtfHelperTest, DecodeUTF16Test3) +{ + size_t index = 0; + uint16_t utf16[] = {0xD800, 0xDC00}; + size_t len = 2; + uint32_t result = utf_helper::DecodeUTF16(utf16, len, &index, true); + EXPECT_EQ(result, 0xD800); + + uint16_t utf16In[] = {0xD800, 0x0041}; + result = utf_helper::DecodeUTF16(utf16In, len, &index, false); + EXPECT_EQ(result, 0xD800); +} + +HWTEST_F_L0(UtfHelperTest, HandleAndDecodeInvalidUTF16Test1) +{ + uint16_t input[] = {0xDC00}; + size_t index = 0; + size_t len = sizeof(input) / sizeof(input[0]); + uint32_t result = utf_helper::HandleAndDecodeInvalidUTF16(input, len, &index); + EXPECT_EQ(result, utf_helper::UTF16_REPLACEMENT_CHARACTER); +} + +HWTEST_F_L0(UtfHelperTest, HandleAndDecodeInvalidUTF16Test2) +{ + uint16_t input[] = {0xD800}; + size_t index = 0; + size_t len = sizeof(input) / sizeof(input[0]); + uint32_t result = utf_helper::HandleAndDecodeInvalidUTF16(input, len, &index); + EXPECT_EQ(result, utf_helper::UTF16_REPLACEMENT_CHARACTER); + + uint16_t input1[] = {0xD800, 0xD800}; + size_t len1 = sizeof(input1) / sizeof(input1[0]); + result = utf_helper::HandleAndDecodeInvalidUTF16(input1, len1, &index); + EXPECT_EQ(result, utf_helper::UTF16_REPLACEMENT_CHARACTER); + + uint16_t input2[] = {'A'}; + size_t len2 = sizeof(input2) / sizeof(input2[0]); + result = utf_helper::HandleAndDecodeInvalidUTF16(input2, len2, &index); + EXPECT_EQ(result, 'A'); + + uint16_t input3[] = {0xD800 ^ 0x01}; + size_t len3 = sizeof(input3) / sizeof(input3[0]); + result = utf_helper::HandleAndDecodeInvalidUTF16(input3, len3, &index); + EXPECT_EQ(result, utf_helper::UTF16_REPLACEMENT_CHARACTER); +} + +HWTEST_F_L0(UtfHelperTest, HandleAndDecodeInvalidUTF16Test3) +{ + uint16_t input[] = {0xDBFF, 0xDFFF}; + size_t index = 0; + size_t len = sizeof(input) / sizeof(input[0]); + uint32_t expected = ((0xDBFF - utf_helper::DECODE_LEAD_LOW) << utf_helper::UTF16_OFFSET) + + (0xDFFF - utf_helper::DECODE_TRAIL_LOW) + utf_helper::DECODE_SECOND_FACTOR; + uint32_t result = utf_helper::HandleAndDecodeInvalidUTF16(input, len, &index); + EXPECT_EQ(result, expected); +} + +HWTEST_F_L0(UtfHelperTest, HandleAndDecodeInvalidUTF16Test4) +{ + uint16_t input[] = {0xD800, 0xDC00}; + size_t index = 0; + size_t len = sizeof(input) / sizeof(input[0]); + uint32_t expected = ((0xD800 - utf_helper::DECODE_LEAD_LOW) << utf_helper::UTF16_OFFSET) + + (0xDC00 - utf_helper::DECODE_TRAIL_LOW) + utf_helper::DECODE_SECOND_FACTOR; + uint32_t result = utf_helper::HandleAndDecodeInvalidUTF16(input, len, &index); + EXPECT_EQ(result, expected); + EXPECT_EQ(index, 1); +} + +HWTEST_F_L0(UtfHelperTest, IsValidUTF8Test1) +{ + std::vector data = {0xED, 0xA0, 0x80}; + EXPECT_FALSE(utf_helper::IsValidUTF8(data)); + + std::vector data1 = {0xED, 0x90, 0x80}; + EXPECT_TRUE(utf_helper::IsValidUTF8(data1)); + + std::vector data2 = {0xED, 0xC0, 0x80}; + EXPECT_FALSE(utf_helper::IsValidUTF8(data2)); + + std::vector data3 = {0xED, 0x80, 0x80}; + EXPECT_TRUE(utf_helper::IsValidUTF8(data3)); + + std::vector data4 = {0xE0, 0xA0, 0x80}; + EXPECT_TRUE(utf_helper::IsValidUTF8(data4)); +} + +HWTEST_F_L0(UtfHelperTest, IsValidUTF8Test2) +{ + std::vector data = {0xF4, 0x90, 0x80, 0x80}; + EXPECT_FALSE(utf_helper::IsValidUTF8(data)); + + std::vector data1 = {0xF5, 0x80, 0x80, 0x80}; + EXPECT_FALSE(utf_helper::IsValidUTF8(data1)); + + std::vector data2 = {0xF0, 0x90, 0x80, 0x80}; + EXPECT_TRUE(utf_helper::IsValidUTF8(data2)); + + std::vector data3 = {0xF1, 0x80, 0x80, 0x80}; + EXPECT_TRUE(utf_helper::IsValidUTF8(data3)); + + std::vector data4 = {0xF4, 0x80, 0x80, 0x80}; + EXPECT_TRUE(utf_helper::IsValidUTF8(data4)); +} + +HWTEST_F_L0(UtfHelperTest, ConvertRegionUtf16ToUtf8Test3) +{ + uint8_t utf8Out[10]; + size_t result = utf_helper::ConvertRegionUtf16ToUtf8(nullptr, utf8Out, 5, 10, 0, false, false, false); + EXPECT_EQ(result, 0); + + uint16_t utf16In[] = {0x0041}; + result = utf_helper::ConvertRegionUtf16ToUtf8(utf16In, nullptr, 1, sizeof(utf16In), 0, false, false, false); + EXPECT_EQ(result, 0); + + result = utf_helper::ConvertRegionUtf16ToUtf8(utf16In, utf8Out, 1, 0, 0, false, false, false); + EXPECT_EQ(result, 0); + + result = utf_helper::ConvertRegionUtf16ToUtf8(nullptr, utf8Out, 1, 0, 0, false, false, false); + EXPECT_EQ(result, 0); + + result = utf_helper::ConvertRegionUtf16ToUtf8(utf16In, nullptr, 1, 0, 0, false, false, false); + EXPECT_EQ(result, 0); + + result = utf_helper::ConvertRegionUtf16ToUtf8(nullptr, nullptr, 1, sizeof(utf8Out), 0, false, false, false); + EXPECT_EQ(result, 0); + + result = utf_helper::ConvertRegionUtf16ToUtf8(nullptr, nullptr, 1, 0, 0, false, false, false); + EXPECT_EQ(result, 0); + + result = utf_helper::ConvertRegionUtf16ToUtf8(utf16In, utf8Out, 1, sizeof(utf8Out), 0, false, false, false); + EXPECT_EQ(result, 1); +} + +HWTEST_F_L0(UtfHelperTest, ConvertRegionUtf16ToLatin1Test) +{ + uint8_t utf8Out[10]; + size_t result = utf_helper::ConvertRegionUtf16ToLatin1(nullptr, utf8Out, 5, 10); + EXPECT_EQ(result, 0); + + uint16_t utf16In[] = {0x0041}; + result = utf_helper::ConvertRegionUtf16ToLatin1(utf16In, nullptr, 1, sizeof(utf16In)); + EXPECT_EQ(result, 0); + + result = utf_helper::ConvertRegionUtf16ToLatin1(utf16In, utf8Out, 1, 0); + EXPECT_EQ(result, 0); + + result = utf_helper::ConvertRegionUtf16ToLatin1(nullptr, utf8Out, 1, 0); + EXPECT_EQ(result, 0); + + result = utf_helper::ConvertRegionUtf16ToLatin1(utf16In, nullptr, 1, 0); + EXPECT_EQ(result, 0); + + result = utf_helper::ConvertRegionUtf16ToLatin1(nullptr, nullptr, 1, sizeof(utf8Out)); + EXPECT_EQ(result, 0); + + result = utf_helper::ConvertRegionUtf16ToLatin1(nullptr, nullptr, 1, 0); + EXPECT_EQ(result, 0); + + result = utf_helper::ConvertRegionUtf16ToLatin1(utf16In, utf8Out, 1, sizeof(utf8Out)); + EXPECT_EQ(result, 1); + + const uint16_t input[] = {0x0041, 0x0042, 0x0043}; + uint8_t output[2] = {0}; + result = utf_helper::ConvertRegionUtf16ToLatin1(input, output, 3, 2); + EXPECT_EQ(result, 2); +} + +HWTEST_F_L0(UtfHelperTest, DebuggerConvertRegionUtf16ToUtf8Test) +{ + uint8_t utf8Out[10]; + size_t result = utf_helper::DebuggerConvertRegionUtf16ToUtf8(nullptr, utf8Out, 5, sizeof(utf8Out), 0, false, false); + EXPECT_EQ(result, 0); + + uint16_t utf16In[] = {0x0041}; + result = utf_helper::DebuggerConvertRegionUtf16ToUtf8(utf16In, nullptr, 1, sizeof(utf16In), 0, false, false); + EXPECT_EQ(result, 0); + + result = utf_helper::DebuggerConvertRegionUtf16ToUtf8(nullptr, nullptr, 1, sizeof(utf8Out), 0, false, false); + EXPECT_EQ(result, 0); + + result = utf_helper::DebuggerConvertRegionUtf16ToUtf8(nullptr, utf8Out, 1, 0, 0, false, false); + EXPECT_EQ(result, 0); + + result = utf_helper::DebuggerConvertRegionUtf16ToUtf8(nullptr, utf8Out, 1, 0, 0, false, false); + EXPECT_EQ(result, 0); + + result = utf_helper::DebuggerConvertRegionUtf16ToUtf8(nullptr, nullptr, 1, 0, 0, false, false); + EXPECT_EQ(result, 0); + + result = utf_helper::DebuggerConvertRegionUtf16ToUtf8(utf16In, utf8Out, 1, 0, 0, false, false); + EXPECT_EQ(result, 0); + + result = utf_helper::DebuggerConvertRegionUtf16ToUtf8(utf16In, utf8Out, 1, sizeof(utf8Out), 0, false, false); + EXPECT_EQ(result, 1); + + uint16_t utf16In1[] = {0x0041, 0x0042, 0x0043}; + result = utf_helper::DebuggerConvertRegionUtf16ToUtf8(utf16In1, nullptr, 3, 0, 0, false, false); + EXPECT_EQ(result, 0); +} + +HWTEST_F_L0(UtfHelperTest, DecodeUTF16Test4) +{ + uint16_t utf16[] = {0xD800, 0xDC00}; + size_t index = 0; + size_t len = sizeof(utf16) / sizeof(utf16[0]); + + uint32_t result = utf_helper::DecodeUTF16(utf16, len, &index, false); + EXPECT_EQ(result, 0x10000); + EXPECT_EQ(index, 1); +} + +HWTEST_F_L0(UtfHelperTest, Utf8ToUtf16Size_LastByteIsTwoByteStart_TrimLastByte) +{ + const uint8_t utf8[] = {0xC0}; + size_t utf8Len = sizeof(utf8); + + size_t result = utf_helper::Utf8ToUtf16Size(utf8, utf8Len); + EXPECT_EQ(result, 1); +} + +HWTEST_F_L0(UtfHelperTest, Utf8ToUtf16Size_LastTwoBytesStartWithThreeByteHeader_TrimTwoBytes) +{ + const uint8_t utf8[] = {0xE2, 0x82}; + size_t utf8Len = sizeof(utf8); + + size_t result = utf_helper::Utf8ToUtf16Size(utf8, utf8Len); + EXPECT_EQ(result, 2); +} + +HWTEST_F_L0(UtfHelperTest, Utf8ToUtf16Size_IncompleteSequenceAtEnd_ReturnsSizeWithoutInvalid) +{ + const uint8_t utf8[] = {0xF0, 0x90, 0x8D}; + size_t result = utf_helper::Utf8ToUtf16Size(utf8, 3); + EXPECT_EQ(result, 3); +} + +HWTEST_F_L0(UtfHelperTest, DebuggerConvertRegionUtf16ToUtf8_ZeroCodepoint_WriteNulChar) +{ + uint16_t utf16In[] = {0x0000}; + uint8_t utf8Out[10] = {0}; + size_t utf16Len = 1; + size_t utf8Len = sizeof(utf8Out); + size_t start = 0; + bool modify = false; + bool isWriteBuffer = true; + + size_t result = utf_helper::DebuggerConvertRegionUtf16ToUtf8( + utf16In, utf8Out, utf16Len, utf8Len, start, modify, isWriteBuffer); + + EXPECT_EQ(result, 1); + EXPECT_EQ(utf8Out[0], 0x00U); +} + +HWTEST_F_L0(UtfHelperTest, ConvertUtf16ToUtf8_NulChar_WriteBufferMode_ReturnsZeroByte) +{ + uint16_t d0 = 0x0000; + uint16_t d1 = 0; + bool modify = false; + bool isWriteBuffer = true; + + utf_helper::Utf8Char result = utf_helper::ConvertUtf16ToUtf8(d0, d1, modify, isWriteBuffer); + + EXPECT_EQ(result.n, 1); + EXPECT_EQ(result.ch[0], 0x00U); +} +} // namespace common::test \ No newline at end of file diff --git a/common_components/heap/allocator/tests/BUILD.gn b/common_components/heap/allocator/tests/BUILD.gn index 5acba71f6e2fabafcfebe26ac448b6791542e237..cd1f06bb2d442f550a33a03e1a17c520b013a0db 100755 --- a/common_components/heap/allocator/tests/BUILD.gn +++ b/common_components/heap/allocator/tests/BUILD.gn @@ -103,6 +103,7 @@ host_unittest_action("Region_Space_Test") { # hiviewdfx libraries external_deps = [ + "bounds_checking_function:libsec_shared", "icu:shared_icui18n", "icu:shared_icuuc", "zlib:libz", diff --git a/common_components/heap/allocator/tests/allocator_test.cpp b/common_components/heap/allocator/tests/allocator_test.cpp index 58820668fc412f0c90fe2b225f6a2104e32c26eb..9ad634eb4eb5c6e6e7572f32c1576c4cbed26bec 100755 --- a/common_components/heap/allocator/tests/allocator_test.cpp +++ b/common_components/heap/allocator/tests/allocator_test.cpp @@ -44,6 +44,7 @@ public: bool IsHeapObject(HeapAddress) const override { return false; } #endif void FeedHungryBuffers() override {} + size_t GetSurvivedSize() const override { return 0; } }; class AllocatorTest : public common::test::BaseTestWithScope { }; @@ -51,8 +52,14 @@ class AllocatorTest : public common::test::BaseTestWithScope { HWTEST_F_L0(AllocatorTest, EnvNotSet) { unsetenv("arkEnableAsyncAllocation"); + TestAllocator allocator; - EXPECT_FALSE(allocator.GetIsAsyncAllocationEnable()); + bool result = allocator.GetIsAsyncAllocationEnable(); +#if defined(PANDA_TARGET_OHOS) + EXPECT_TRUE(result); +#else + EXPECT_FALSE(result); +#endif } HWTEST_F_L0(AllocatorTest, InvalidLength) diff --git a/common_components/heap/allocator/tests/heap_allocator_test.cpp b/common_components/heap/allocator/tests/heap_allocator_test.cpp index f23fb161ee0de85b4495a7ea18221b3cc8ba43db..be2b6faa6f60271f7443851ff4041ff8ca3c3df1 100644 --- a/common_components/heap/allocator/tests/heap_allocator_test.cpp +++ b/common_components/heap/allocator/tests/heap_allocator_test.cpp @@ -13,15 +13,11 @@ * limitations under the License. */ -#include - #include "common_interfaces/heap/heap_allocator.h" +#include "common_components/heap/allocator/region_desc.h" #include "common_components/heap/allocator/region_space.h" -#include "common_components/heap/collector/trace_collector.h" -#include "common_components/heap/heap.cpp" -#include "common_components/common_runtime/base_runtime_param.h" -#include "common_components/heap/heap_manager.h" #include "common_components/tests/test_helper.h" +#include "common_interfaces/base_runtime.h" using namespace common; @@ -36,7 +32,11 @@ class HeapAllocatorTest : public BaseTestWithScope { void TearDown() override { - delete scope_; + if (scope_ != nullptr) { + delete scope_; + scope_ = nullptr; + } + BaseRuntime::GetInstance()->Fini(); } @@ -46,7 +46,7 @@ class HeapAllocatorTest : public BaseTestWithScope { HWTEST_F_L0(HeapAllocatorTest, AllocLargeObject) { - uintptr_t addr = common::HeapAllocator::Allocate(Heap::NORMAL_UNIT_SIZE, common::LanguageType::DYNAMIC); + uintptr_t addr = common::HeapAllocator::AllocateInHuge(Heap::NORMAL_UNIT_SIZE, common::LanguageType::DYNAMIC); ASSERT(addr > 0); RegionDesc* region = RegionDesc::GetAliveRegionDescAt(addr); ASSERT(region->IsLargeRegion()); diff --git a/common_components/heap/allocator/tests/region_manager_test.cpp b/common_components/heap/allocator/tests/region_manager_test.cpp index 8fe0bece36eef744cc514973352a06faa14998c3..e2ce92a02c7654d1b12a043dc245c5fa93fe0211 100755 --- a/common_components/heap/allocator/tests/region_manager_test.cpp +++ b/common_components/heap/allocator/tests/region_manager_test.cpp @@ -156,9 +156,8 @@ HWTEST_F_L0(RegionManagerTest, VisitAllObjectsBeforeFix1) uintptr_t start = region->GetRegionStart(); region->SetRegionAllocPtr(start + SIZE_SIXTEEN); - region->SetFixLine(); bool callbackCalled = false; - region->VisitAllObjectsBeforeFix([&](BaseObject* obj) { + region->VisitAllObjectsBeforeCopy([&](BaseObject* obj) { callbackCalled = true; EXPECT_EQ(obj, reinterpret_cast(region->GetRegionStart())); }); @@ -175,9 +174,8 @@ HWTEST_F_L0(RegionManagerTest, VisitAllObjectsBeforeFix2) uintptr_t start = region->GetRegionStart(); region->SetRegionAllocPtr(start + SIZE_SIXTEEN); - region->SetFixLine(); bool callbackCalled = false; - region->VisitAllObjectsBeforeFix([&](BaseObject* obj) { + region->VisitAllObjectsBeforeCopy([&](BaseObject* obj) { callbackCalled = true; EXPECT_EQ(obj, reinterpret_cast(region->GetRegionStart())); }); @@ -191,9 +189,9 @@ HWTEST_F_L0(RegionManagerTest, VisitAllObjectsBeforeFix3) RegionDesc* region = RegionDesc::InitRegion(unitIdx, nUnit, RegionDesc::UnitRole::LARGE_SIZED_UNITS); ASSERT_NE(region, nullptr); - region->SetFixLine(); + bool callbackCalled = false; - region->VisitAllObjectsBeforeFix([&](BaseObject* obj) { + region->VisitAllObjectsBeforeCopy([&](BaseObject* obj) { callbackCalled = true; EXPECT_EQ(obj, reinterpret_cast(region->GetRegionStart())); }); @@ -207,9 +205,9 @@ HWTEST_F_L0(RegionManagerTest, VisitAllObjectsBeforeFix4) RegionDesc* region = RegionDesc::InitRegion(unitIdx, nUnit, RegionDesc::UnitRole::SMALL_SIZED_UNITS); ASSERT_NE(region, nullptr); - region->SetFixLine(); + bool callbackCalled = false; - region->VisitAllObjectsBeforeFix([&](BaseObject* obj) { + region->VisitAllObjectsBeforeCopy([&](BaseObject* obj) { callbackCalled = true; EXPECT_EQ(obj, reinterpret_cast(region->GetRegionStart())); }); @@ -301,9 +299,9 @@ HWTEST_F_L0(RegionManagerTest, TakeRegion2) size_t nUnit = 1; manager.Initialize(SIZE_MAX_TEST, reinterpret_cast(regionMemory_)); RegionDesc* garbageRegion = RegionDesc::InitRegion(SIZE_HALF_MAX_TEST, nUnit, - RegionDesc::UnitRole::SMALL_SIZED_UNITS); + RegionDesc::UnitRole::LARGE_SIZED_UNITS); auto size = manager.CollectRegion(garbageRegion); - RegionDesc* region = manager.TakeRegion(16, RegionDesc::UnitRole::SMALL_SIZED_UNITS, true, false); + RegionDesc* region = manager.TakeRegion(16, RegionDesc::UnitRole::LARGE_SIZED_UNITS, true, false); EXPECT_NE(region, nullptr); } @@ -316,15 +314,6 @@ HWTEST_F_L0(RegionManagerTest, AllocPinnedFromFreeList) EXPECT_EQ(manager.AllocPinnedFromFreeList(0), 0); } -HWTEST_F_L0(RegionManagerTest, FixAllRegionLists) -{ - Heap::GetHeap().SetGCReason(GCReason::GC_REASON_YOUNG); - RegionManager manager; - manager.Initialize(SIZE_MAX_TEST, reinterpret_cast(regionMemory_)); - manager.FixAllRegionLists(); - EXPECT_EQ(Heap::GetHeap().GetGCReason(), GCReason::GC_REASON_YOUNG); -} - HWTEST_F_L0(RegionManagerTest, AllocReadOnly1) { auto* mutator = common::Mutator::GetMutator(); @@ -345,11 +334,7 @@ HWTEST_F_L0(RegionManagerTest, AllocReadOnly2) manager.ClearAllGCInfo(); ThreadLocal::SetThreadType(ThreadType::ARK_PROCESSOR); uintptr_t ret = manager.AllocReadOnly(sizeof(RegionDesc), false); - RegionDesc* region = RegionDesc::GetRegionDescAt(ret); EXPECT_NE(ret, 0); - EXPECT_EQ(region->GetTraceLine(), region->GetRegionStart()); - EXPECT_EQ(region->GetCopyLine(), std::numeric_limits::max()); - EXPECT_EQ(region->GetFixLine(), std::numeric_limits::max()); } HWTEST_F_L0(RegionManagerTest, AllocReadOnly3) @@ -361,11 +346,7 @@ HWTEST_F_L0(RegionManagerTest, AllocReadOnly3) manager.ClearAllGCInfo(); ThreadLocal::SetThreadType(ThreadType::ARK_PROCESSOR); uintptr_t ret = manager.AllocReadOnly(sizeof(RegionDesc), false); - RegionDesc* region = RegionDesc::GetRegionDescAt(ret); EXPECT_NE(ret, 0); - EXPECT_EQ(region->GetTraceLine(), region->GetRegionStart()); - EXPECT_EQ(region->GetCopyLine(), std::numeric_limits::max()); - EXPECT_EQ(region->GetFixLine(), std::numeric_limits::max()); } HWTEST_F_L0(RegionManagerTest, AllocReadOnly4) @@ -377,10 +358,7 @@ HWTEST_F_L0(RegionManagerTest, AllocReadOnly4) manager.ClearAllGCInfo(); ThreadLocal::SetThreadType(ThreadType::ARK_PROCESSOR); uintptr_t ret = manager.AllocReadOnly(sizeof(RegionDesc), false); - RegionDesc* region = RegionDesc::GetRegionDescAt(ret); EXPECT_NE(ret, 0); - EXPECT_EQ(region->GetCopyLine(), region->GetRegionStart()); - EXPECT_EQ(region->GetFixLine(), std::numeric_limits::max()); } HWTEST_F_L0(RegionManagerTest, AllocReadOnly5) @@ -392,10 +370,7 @@ HWTEST_F_L0(RegionManagerTest, AllocReadOnly5) manager.ClearAllGCInfo(); ThreadLocal::SetThreadType(ThreadType::ARK_PROCESSOR); uintptr_t ret = manager.AllocReadOnly(sizeof(RegionDesc), false); - RegionDesc* region = RegionDesc::GetRegionDescAt(ret); EXPECT_NE(ret, 0); - EXPECT_EQ(region->GetCopyLine(), region->GetRegionStart()); - EXPECT_EQ(region->GetFixLine(), std::numeric_limits::max()); } HWTEST_F_L0(RegionManagerTest, AllocReadOnly6) @@ -407,10 +382,7 @@ HWTEST_F_L0(RegionManagerTest, AllocReadOnly6) manager.ClearAllGCInfo(); ThreadLocal::SetThreadType(ThreadType::ARK_PROCESSOR); uintptr_t ret = manager.AllocReadOnly(sizeof(RegionDesc), false); - RegionDesc* region = RegionDesc::GetRegionDescAt(ret); EXPECT_NE(ret, 0); - EXPECT_EQ(region->GetCopyLine(), region->GetRegionStart()); - EXPECT_EQ(region->GetFixLine(), region->GetRegionStart()); } HWTEST_F_L0(RegionManagerTest, AllocReadOnly7) @@ -422,10 +394,96 @@ HWTEST_F_L0(RegionManagerTest, AllocReadOnly7) manager.ClearAllGCInfo(); ThreadLocal::SetThreadType(ThreadType::ARK_PROCESSOR); uintptr_t ret = manager.AllocReadOnly(sizeof(RegionDesc), false); - RegionDesc* region = RegionDesc::GetRegionDescAt(ret); EXPECT_NE(ret, 0); - EXPECT_EQ(region->GetTraceLine(), std::numeric_limits::max()); - EXPECT_EQ(region->GetCopyLine(), std::numeric_limits::max()); - EXPECT_EQ(region->GetFixLine(), std::numeric_limits::max()); +} + +HWTEST_F_L0(RegionManagerTest, VisitRememberSetTest) +{ + size_t totalUnits = 1024; + size_t heapSize = totalUnits * RegionDesc::UNIT_SIZE; + + void* regionMemory = malloc(heapSize + 4096); + ASSERT_NE(regionMemory, nullptr); + + uintptr_t heapStartAddress = reinterpret_cast(regionMemory); + uintptr_t regionInfoAddr = heapStartAddress + 4096; + + RegionManager manager; + manager.Initialize(totalUnits, regionInfoAddr); + + size_t unitIdx = 0; + size_t nUnit = 4; + RegionDesc* region = RegionDesc::InitRegion(unitIdx, nUnit, RegionDesc::UnitRole::LARGE_SIZED_UNITS); + ASSERT_NE(region, nullptr); + + manager.MarkRememberSet([&](BaseObject* obj) {}); + + int callbackCount = 0; + region->VisitRememberSet([&](BaseObject* obj) { + callbackCount++; + }); + + EXPECT_GE(callbackCount, 0); + free(regionMemory); +} + +HWTEST_F_L0(RegionManagerTest, VisitRememberSetBeforeCopyTest) +{ + size_t totalUnits = 1024; + size_t heapSize = totalUnits * RegionDesc::UNIT_SIZE; + + void* regionMemory = malloc(heapSize + 4096); + ASSERT_NE(regionMemory, nullptr); + + uintptr_t heapStartAddress = reinterpret_cast(regionMemory); + uintptr_t regionInfoAddr = heapStartAddress + 4096; + + RegionManager manager; + manager.Initialize(totalUnits, regionInfoAddr); + + size_t unitIdx = 0; + size_t nUnit = 4; + RegionDesc* region = RegionDesc::InitRegion(unitIdx, nUnit, RegionDesc::UnitRole::LARGE_SIZED_UNITS); + ASSERT_NE(region, nullptr); + + manager.MarkRememberSet([&](BaseObject* obj) {}); + + int callbackCount = 0; + region->VisitRememberSetBeforeCopy([&](BaseObject* obj) { + callbackCount++; + }); + + EXPECT_GE(callbackCount, 0); + free(regionMemory); +} + +HWTEST_F_L0(RegionManagerTest, VisitRememberSetBeforeTraceTest) +{ + size_t totalUnits = 1024; + size_t heapSize = totalUnits * RegionDesc::UNIT_SIZE; + + void* regionMemory = malloc(heapSize + 4096); + ASSERT_NE(regionMemory, nullptr); + + uintptr_t heapStartAddress = reinterpret_cast(regionMemory); + uintptr_t regionInfoAddr = heapStartAddress + 4096; + + RegionManager manager; + manager.Initialize(totalUnits, regionInfoAddr); + + size_t unitIdx = 0; + size_t nUnit = 4; + RegionDesc* region = RegionDesc::InitRegion(unitIdx, nUnit, RegionDesc::UnitRole::LARGE_SIZED_UNITS); + ASSERT_NE(region, nullptr); + + manager.MarkRememberSet([&](BaseObject* obj) {}); + + int callbackCount = 0; + region->VisitRememberSetBeforeTrace([&](BaseObject* obj) { + callbackCount++; + }); + + EXPECT_GE(callbackCount, 0); + free(regionMemory); } } diff --git a/common_components/heap/allocator/tests/region_space_test.cpp b/common_components/heap/allocator/tests/region_space_test.cpp index f7ccc043a57f5264c8bc2d0916b8e5e3c96d2ca5..11b0bbef35777b0f52f87baa4f70f8ee59ac53da 100755 --- a/common_components/heap/allocator/tests/region_space_test.cpp +++ b/common_components/heap/allocator/tests/region_space_test.cpp @@ -13,96 +13,56 @@ * limitations under the License. */ -#include "common_interfaces/heap/heap_allocator.h" +#include "common_components/heap/allocator/region_desc.h" #include "common_components/heap/allocator/region_space.h" -#include "common_components/heap/collector/trace_collector.h" -#include "common_components/heap/heap.cpp" -#include "common_components/common_runtime/base_runtime_param.h" -#include "common_components/heap/heap_manager.h" +#include "common_components/heap/allocator/region_space.cpp" +#include "common_components/heap/collector/collector_resources.h" #include "common_components/tests/test_helper.h" -#include +#include "common_interfaces/base_runtime.h" using namespace common; namespace common::test { class RegionSpaceTest : public common::test::BaseTestWithScope { -protected: - void* regionMemory_; - size_t totalUnits_ = 1024; - size_t heapSize_; - Mutator* mutator_ = nullptr; - - static void SetUpTestCase() - { - BaseRuntime::GetInstance()->Init(); - } - - static void TearDownTestCase() - { - BaseRuntime::GetInstance()->Fini(); - } - void SetUp() override { - heapSize_ = totalUnits_ * RegionDesc::UNIT_SIZE; - size_t allocSize = heapSize_ + totalUnits_ * sizeof(RegionDesc); - regionMemory_ = malloc(allocSize); - ASSERT_NE(regionMemory_, nullptr); - uintptr_t unitInfoStart = reinterpret_cast(regionMemory_); - size_t metadataSize = totalUnits_ * sizeof(RegionDesc); - uintptr_t heapStartAddress = unitInfoStart + metadataSize; - RegionDesc::Initialize(totalUnits_, unitInfoStart, heapStartAddress); - mutator_ = Mutator::NewMutator(); - ASSERT_NE(mutator_, nullptr); - mutator_->InitTid(); - ThreadLocal::GetThreadLocalData()->mutator = mutator_; - BaseRuntime::GetInstance()->GetHeapParam().regionSize = 64; // 64:region size - RegionSpace& theAllocator = reinterpret_cast(Heap::GetHeap().GetAllocator()); - RegionManager& regionManager = theAllocator.GetRegionManager(); - regionManager.SetMaxUnitCountForRegion(); + BaseRuntime::GetInstance()->Init(); + holder_ = ThreadHolder::CreateAndRegisterNewThreadHolder(nullptr); + scope_ = new ThreadHolder::TryBindMutatorScope(holder_); } void TearDown() override { - if (mutator_) { - delete mutator_; - mutator_ = nullptr; - } - if (regionMemory_) { - free(regionMemory_); - regionMemory_ = nullptr; + if (scope_ != nullptr) { + delete scope_; + scope_ = nullptr; } + + BaseRuntime::GetInstance()->Fini(); } -}; -HWTEST_F_L0(RegionSpaceTest, ShouldRetryAllocation) -{ - auto* mutator = common::Mutator::GetMutator(); - mutator->SetMutatorPhase(GCPhase::GC_PHASE_UNDEF); - ThreadLocal::SetThreadType(ThreadType::GC_THREAD); - Heap::GetHeap().EnableGC(false); - Heap::GetHeap().GetCollectorResources().SetGcStarted(true); - Allocator *regionSpace = RegionSpace::CreateAllocator(); - EXPECT_EQ(regionSpace->Allocate(16, AllocType::MOVEABLE_OBJECT), 0); -} + ThreadHolder *holder_ {nullptr}; + ThreadHolder::TryBindMutatorScope *scope_ {nullptr}; +}; HWTEST_F_L0(RegionSpaceTest, FeedHungryBuffers2) { auto* mutator = common::Mutator::GetMutator(); mutator->SetMutatorPhase(GCPhase::GC_PHASE_FIX); - RegionSpace& theAllocator = reinterpret_cast(Heap::GetHeap().GetAllocator()); - RegionManager& manager = theAllocator.GetRegionManager(); ThreadLocal::SetThreadType(ThreadType::ARK_PROCESSOR); - manager.Initialize(1024, reinterpret_cast(regionMemory_)); AllocationBuffer* buffer1 = new (std::nothrow) AllocationBuffer(); AllocationBuffer* buffer2 = new (std::nothrow) AllocationBuffer(); - RegionDesc* Region = RegionDesc::InitRegion(0, 1, RegionDesc::UnitRole::SMALL_SIZED_UNITS); - buffer1->SetPreparedRegion(Region); + RegionDesc* region = RegionDesc::InitRegion(0, 1, RegionDesc::UnitRole::LARGE_SIZED_UNITS); + region->InitFreeUnits(); + buffer1->SetPreparedRegion(region); + buffer2->SetPreparedRegion(region); Heap::GetHeap().GetAllocator().AddHungryBuffer(*buffer1); Heap::GetHeap().GetAllocator().AddHungryBuffer(*buffer2); Heap::GetHeap().GetAllocator().FeedHungryBuffers(); EXPECT_NE(buffer2->GetPreparedRegion(), nullptr); + delete buffer1; + delete buffer2; } HWTEST_F_L0(RegionSpaceTest, FeedHungryBuffers3) @@ -115,57 +75,52 @@ HWTEST_F_L0(RegionSpaceTest, FeedHungryBuffers3) EXPECT_EQ(hungryBuffers.size(), 0); } - HWTEST_F_L0(RegionSpaceTest, AllocRegion_PhaseEnum) { - ASSERT_NE(mutator_, nullptr); - mutator_->SetMutatorPhase(GCPhase::GC_PHASE_ENUM); + auto* mutator = common::Mutator::GetMutator(); + mutator->SetMutatorPhase(GCPhase::GC_PHASE_ENUM); RegionSpace& theAllocator = reinterpret_cast(Heap::GetHeap().GetAllocator()); uintptr_t addr = theAllocator.AllocOldRegion(); ASSERT_NE(addr, 0); RegionDesc* region = RegionDesc::GetAliveRegionDescAt(addr); EXPECT_EQ(region->GetTraceLine(), region->GetRegionStart()); EXPECT_EQ(region->GetCopyLine(), std::numeric_limits::max()); - EXPECT_EQ(region->GetFixLine(), std::numeric_limits::max()); } HWTEST_F_L0(RegionSpaceTest, AllocRegion_PhaseMark) { - ASSERT_NE(mutator_, nullptr); - mutator_->SetMutatorPhase(GCPhase::GC_PHASE_MARK); + auto* mutator = common::Mutator::GetMutator(); + mutator->SetMutatorPhase(GCPhase::GC_PHASE_MARK); RegionSpace& theAllocator = reinterpret_cast(Heap::GetHeap().GetAllocator()); uintptr_t addr = theAllocator.AllocOldRegion(); ASSERT_NE(addr, 0); RegionDesc* region = RegionDesc::GetAliveRegionDescAt(addr); EXPECT_EQ(region->GetTraceLine(), region->GetRegionStart()); EXPECT_EQ(region->GetCopyLine(), std::numeric_limits::max()); - EXPECT_EQ(region->GetFixLine(), std::numeric_limits::max()); } HWTEST_F_L0(RegionSpaceTest, AllocRegion_PhaseRemarkStab) { - ASSERT_NE(mutator_, nullptr); - mutator_->SetMutatorPhase(GCPhase::GC_PHASE_REMARK_SATB); + auto* mutator = common::Mutator::GetMutator(); + mutator->SetMutatorPhase(GCPhase::GC_PHASE_REMARK_SATB); RegionSpace& theAllocator = reinterpret_cast(Heap::GetHeap().GetAllocator()); uintptr_t addr = theAllocator.AllocOldRegion(); ASSERT_NE(addr, 0); RegionDesc* region = RegionDesc::GetAliveRegionDescAt(addr); EXPECT_EQ(region->GetTraceLine(), region->GetRegionStart()); EXPECT_EQ(region->GetCopyLine(), std::numeric_limits::max()); - EXPECT_EQ(region->GetFixLine(), std::numeric_limits::max()); } HWTEST_F_L0(RegionSpaceTest, AllocRegion_PhasePostMark) { - ASSERT_NE(mutator_, nullptr); - mutator_->SetMutatorPhase(GCPhase::GC_PHASE_POST_MARK); + auto* mutator = common::Mutator::GetMutator(); + mutator->SetMutatorPhase(GCPhase::GC_PHASE_POST_MARK); RegionSpace& theAllocator = reinterpret_cast(Heap::GetHeap().GetAllocator()); uintptr_t addr = theAllocator.AllocOldRegion(); ASSERT_NE(addr, 0); RegionDesc* region = RegionDesc::GetAliveRegionDescAt(addr); EXPECT_EQ(region->GetTraceLine(), region->GetRegionStart()); EXPECT_EQ(region->GetCopyLine(), std::numeric_limits::max()); - EXPECT_EQ(region->GetFixLine(), std::numeric_limits::max()); } HWTEST_F_L0(RegionSpaceTest, AllocRegion_PhasePrecopy) @@ -199,7 +154,6 @@ HWTEST_F_L0(RegionSpaceTest, AllocRegion_PhaseFix) ASSERT_NE(addr, 0); RegionDesc* region = RegionDesc::GetAliveRegionDescAt(addr); EXPECT_EQ(region->GetCopyLine(), region->GetRegionStart()); - EXPECT_EQ(region->GetFixLine(), region->GetRegionStart()); } HWTEST_F_L0(RegionSpaceTest, AllocRegion_PhaseUndef) @@ -211,59 +165,54 @@ HWTEST_F_L0(RegionSpaceTest, AllocRegion_PhaseUndef) ASSERT_NE(addr, 0); RegionDesc* region = RegionDesc::GetAliveRegionDescAt(addr); EXPECT_EQ(region->GetCopyLine(), std::numeric_limits::max()); - EXPECT_EQ(region->GetFixLine(), std::numeric_limits::max()); } HWTEST_F_L0(RegionSpaceTest, AllocPinnedRegion_PhaseEnum) { - ASSERT_NE(mutator_, nullptr); - mutator_->SetMutatorPhase(GCPhase::GC_PHASE_ENUM); + auto* mutator = common::Mutator::GetMutator(); + mutator->SetMutatorPhase(GCPhase::GC_PHASE_ENUM); RegionSpace& theAllocator = reinterpret_cast(Heap::GetHeap().GetAllocator()); uintptr_t addr = theAllocator.AllocPinnedRegion(); ASSERT_NE(addr, 0); RegionDesc* region = RegionDesc::GetAliveRegionDescAt(addr); EXPECT_EQ(region->GetTraceLine(), region->GetRegionStart()); EXPECT_EQ(region->GetCopyLine(), std::numeric_limits::max()); - EXPECT_EQ(region->GetFixLine(), std::numeric_limits::max()); } HWTEST_F_L0(RegionSpaceTest, AllocPinnedRegion_PhaseMark) { - ASSERT_NE(mutator_, nullptr); - mutator_->SetMutatorPhase(GCPhase::GC_PHASE_MARK); + auto* mutator = common::Mutator::GetMutator(); + mutator->SetMutatorPhase(GCPhase::GC_PHASE_MARK); RegionSpace& theAllocator = reinterpret_cast(Heap::GetHeap().GetAllocator()); uintptr_t addr = theAllocator.AllocPinnedRegion(); ASSERT_NE(addr, 0); RegionDesc* region = RegionDesc::GetAliveRegionDescAt(addr); EXPECT_EQ(region->GetTraceLine(), region->GetRegionStart()); EXPECT_EQ(region->GetCopyLine(), std::numeric_limits::max()); - EXPECT_EQ(region->GetFixLine(), std::numeric_limits::max()); } HWTEST_F_L0(RegionSpaceTest, AllocPinnedRegion_PhaseRemarkStab) { - ASSERT_NE(mutator_, nullptr); - mutator_->SetMutatorPhase(GCPhase::GC_PHASE_REMARK_SATB); + auto* mutator = common::Mutator::GetMutator(); + mutator->SetMutatorPhase(GCPhase::GC_PHASE_REMARK_SATB); RegionSpace& theAllocator = reinterpret_cast(Heap::GetHeap().GetAllocator()); uintptr_t addr = theAllocator.AllocPinnedRegion(); ASSERT_NE(addr, 0); RegionDesc* region = RegionDesc::GetAliveRegionDescAt(addr); EXPECT_EQ(region->GetTraceLine(), region->GetRegionStart()); EXPECT_EQ(region->GetCopyLine(), std::numeric_limits::max()); - EXPECT_EQ(region->GetFixLine(), std::numeric_limits::max()); } HWTEST_F_L0(RegionSpaceTest, AllocPinnedRegion_PhasePostMark) { - ASSERT_NE(mutator_, nullptr); - mutator_->SetMutatorPhase(GCPhase::GC_PHASE_POST_MARK); + auto* mutator = common::Mutator::GetMutator(); + mutator->SetMutatorPhase(GCPhase::GC_PHASE_POST_MARK); RegionSpace& theAllocator = reinterpret_cast(Heap::GetHeap().GetAllocator()); uintptr_t addr = theAllocator.AllocPinnedRegion(); ASSERT_NE(addr, 0); RegionDesc* region = RegionDesc::GetAliveRegionDescAt(addr); EXPECT_EQ(region->GetTraceLine(), region->GetRegionStart()); EXPECT_EQ(region->GetCopyLine(), std::numeric_limits::max()); - EXPECT_EQ(region->GetFixLine(), std::numeric_limits::max()); } HWTEST_F_L0(RegionSpaceTest, AllocPinnedRegion_PhasePrecopy) @@ -297,7 +246,6 @@ HWTEST_F_L0(RegionSpaceTest, AllocPinnedRegion_PhaseFix) ASSERT_NE(addr, 0); RegionDesc* region = RegionDesc::GetAliveRegionDescAt(addr); EXPECT_EQ(region->GetCopyLine(), region->GetRegionStart()); - EXPECT_EQ(region->GetFixLine(), region->GetRegionStart()); } HWTEST_F_L0(RegionSpaceTest, AllocPinnedRegion_PhaseUndef) @@ -309,7 +257,6 @@ HWTEST_F_L0(RegionSpaceTest, AllocPinnedRegion_PhaseUndef) ASSERT_NE(addr, 0); RegionDesc* region = RegionDesc::GetAliveRegionDescAt(addr); EXPECT_EQ(region->GetCopyLine(), std::numeric_limits::max()); - EXPECT_EQ(region->GetFixLine(), std::numeric_limits::max()); } HWTEST_F_L0(RegionSpaceTest, AllocateThreadLocalRegion2) @@ -318,9 +265,8 @@ HWTEST_F_L0(RegionSpaceTest, AllocateThreadLocalRegion2) mutator->SetMutatorPhase(GCPhase::GC_PHASE_FIX); ThreadLocal::SetThreadType(ThreadType::ARK_PROCESSOR); RegionSpace& theAllocator = reinterpret_cast(Heap::GetHeap().GetAllocator()); - RegionDesc* region = theAllocator.AllocateThreadLocalRegion(false); + RegionDesc* region = theAllocator.AllocateThreadLocalRegion(false); EXPECT_EQ(region->GetCopyLine(), region->GetRegionStart()); - EXPECT_EQ(region->GetFixLine(), region->GetRegionStart()); } HWTEST_F_L0(RegionSpaceTest, AllocateThreadLocalRegion3) @@ -329,13 +275,11 @@ HWTEST_F_L0(RegionSpaceTest, AllocateThreadLocalRegion3) mutator->SetMutatorPhase(GCPhase::GC_PHASE_COPY); RegionSpace& theAllocator = reinterpret_cast(Heap::GetHeap().GetAllocator()); ThreadLocal::SetThreadType(ThreadType::ARK_PROCESSOR); - RegionDesc* region = theAllocator.AllocateThreadLocalRegion(false); + RegionDesc* region = theAllocator.AllocateThreadLocalRegion(false); EXPECT_EQ(region->GetCopyLine(), region->GetRegionStart()); - EXPECT_EQ(region->GetFixLine(), std::numeric_limits::max()); mutator->SetMutatorPhase(GCPhase::GC_PHASE_PRECOPY); - RegionDesc* region1 = theAllocator.AllocateThreadLocalRegion(false); + RegionDesc* region1 = theAllocator.AllocateThreadLocalRegion(false); EXPECT_EQ(region1->GetCopyLine(), region1->GetRegionStart()); - EXPECT_EQ(region1->GetFixLine(), std::numeric_limits::max()); } HWTEST_F_L0(RegionSpaceTest, AllocateThreadLocalRegion4) @@ -344,42 +288,141 @@ HWTEST_F_L0(RegionSpaceTest, AllocateThreadLocalRegion4) mutator->SetMutatorPhase(GCPhase::GC_PHASE_ENUM); RegionSpace& theAllocator = reinterpret_cast(Heap::GetHeap().GetAllocator()); ThreadLocal::SetThreadType(ThreadType::ARK_PROCESSOR); - RegionDesc* region = theAllocator.AllocateThreadLocalRegion(false); + RegionDesc* region = theAllocator.AllocateThreadLocalRegion(false); EXPECT_EQ(region->GetTraceLine(), region->GetRegionStart()); EXPECT_EQ(region->GetCopyLine(), std::numeric_limits::max()); - EXPECT_EQ(region->GetFixLine(), std::numeric_limits::max()); mutator->SetMutatorPhase(GCPhase::GC_PHASE_MARK); - RegionDesc* region2 = theAllocator.AllocateThreadLocalRegion(false); + RegionDesc* region2 = theAllocator.AllocateThreadLocalRegion(false); EXPECT_EQ(region2->GetTraceLine(), region2->GetRegionStart()); EXPECT_EQ(region2->GetCopyLine(), std::numeric_limits::max()); - EXPECT_EQ(region2->GetFixLine(), std::numeric_limits::max()); mutator->SetMutatorPhase(GCPhase::GC_PHASE_REMARK_SATB); - RegionDesc* region3 = theAllocator.AllocateThreadLocalRegion(false); + RegionDesc* region3 = theAllocator.AllocateThreadLocalRegion(false); EXPECT_EQ(region3->GetTraceLine(), region3->GetRegionStart()); EXPECT_EQ(region3->GetCopyLine(), std::numeric_limits::max()); - EXPECT_EQ(region3->GetFixLine(), std::numeric_limits::max()); mutator->SetMutatorPhase(GCPhase::GC_PHASE_POST_MARK); - RegionDesc* region4 = theAllocator.AllocateThreadLocalRegion(false); + RegionDesc* region4 = theAllocator.AllocateThreadLocalRegion(false); EXPECT_EQ(region4->GetTraceLine(), region4->GetRegionStart()); EXPECT_EQ(region4->GetCopyLine(), std::numeric_limits::max()); - EXPECT_EQ(region4->GetFixLine(), std::numeric_limits::max()); } -HWTEST_F_L0(RegionSpaceTest, CopyRegion1) +HWTEST_F_L0(RegionSpaceTest, CopyRegion) { auto* mutator = common::Mutator::GetMutator(); - mutator_->SetMutatorPhase(GCPhase::GC_PHASE_ENUM); + mutator->SetMutatorPhase(GCPhase::GC_PHASE_ENUM); RegionSpace& theAllocator = reinterpret_cast(Heap::GetHeap().GetAllocator()); - theAllocator.AssembleSmallGarbageCandidates(); - RegionDesc* region = theAllocator.GetRegionManager().TakeRegion( - 16, RegionDesc::UnitRole::SMALL_SIZED_UNITS, true, false); + uintptr_t addr = theAllocator.AllocOldRegion(); + ASSERT_NE(addr, 0); + RegionDesc* region = RegionDesc::GetRegionDescAt(addr); region->SetRegionType(RegionDesc::RegionType::FROM_REGION); ASSERT(region->IsFromRegion()); - region->AddLiveByteCount(1); theAllocator.CopyRegion(region); - EXPECT_NE(theAllocator.FromSpaceSize(), 0); + EXPECT_EQ(theAllocator.FromSpaceSize(), 0); +} + +HWTEST_F_L0(RegionSpaceTest, AllocateThreadLocalRegion1_NotGcThread_EntersElseBranch) +{ + auto& heapAllocator = Heap::GetHeap().GetAllocator(); + RegionSpace& regionSpace = reinterpret_cast(heapAllocator); + + Mutator::GetMutator()->SetMutatorPhase(GCPhase::GC_PHASE_ENUM); + + auto* region = regionSpace.AllocateThreadLocalRegion(false); + EXPECT_NE(region, nullptr); +} + +HWTEST_F_L0(RegionSpaceTest, AllocateThreadLocalRegion2_NotGcThread_EntersElseBranch) +{ + auto& heapAllocator = Heap::GetHeap().GetAllocator(); + RegionSpace& regionSpace = reinterpret_cast(heapAllocator); + + Mutator::GetMutator()->SetMutatorPhase(GCPhase::GC_PHASE_PRECOPY); + + auto* region = regionSpace.AllocateThreadLocalRegion(false); + EXPECT_NE(region, nullptr); +} + +HWTEST_F_L0(RegionSpaceTest, AllocateThreadLocalRegion3_NotGcThread_EntersElseBranch) +{ + auto& heapAllocator = Heap::GetHeap().GetAllocator(); + RegionSpace& regionSpace = reinterpret_cast(heapAllocator); + + Mutator::GetMutator()->SetMutatorPhase(GCPhase::GC_PHASE_FIX); + + auto* region = regionSpace.AllocateThreadLocalRegion(false); + EXPECT_NE(region, nullptr); +} + +HWTEST_F_L0(RegionSpaceTest, Allocate_ValidSize_ReturnsNonNull) +{ + RegionSpace& theAllocator = reinterpret_cast(Heap::GetHeap().GetAllocator()); + uintptr_t addr = theAllocator.AllocOldRegion(); + ASSERT_NE(addr, 0); + + RegionDesc* region = RegionDesc::GetRegionDescAt(addr); + region->InitFreeUnits(); + region->SetRegionType(RegionDesc::RegionType::THREAD_LOCAL_REGION); + Mutator::GetMutator()->SetMutatorPhase(GCPhase::GC_PHASE_UNDEF); + Heap::GetHeap().EnableGC(true); + Heap::GetHeap().GetCollectorResources().SetGcStarted(false); + + uintptr_t result = theAllocator.Allocate(16, AllocType::PINNED_OBJECT); + EXPECT_NE(result, 0u); +} + +HWTEST_F_L0(RegionSpaceTest, FeedHungryBuffers_ShouldProvideValidRegions) +{ + RegionSpace& theAllocator = reinterpret_cast(Heap::GetHeap().GetAllocator()); + uintptr_t addr = theAllocator.AllocOldRegion(); + ASSERT_NE(addr, 0); + + AllocationBuffer* buffer1 = new (std::nothrow) AllocationBuffer(); + AllocationBuffer* buffer2 = new (std::nothrow) AllocationBuffer(); + ASSERT_NE(buffer1, nullptr); + ASSERT_NE(buffer2, nullptr); + + RegionDesc* region = RegionDesc::GetRegionDescAt(addr); + ASSERT_NE(region, nullptr); + region->InitFreeUnits(); + region->SetRegionType(RegionDesc::RegionType::THREAD_LOCAL_REGION); + + buffer1->SetPreparedRegion(region); + buffer2->SetPreparedRegion(region); + Heap::GetHeap().GetAllocator().AddHungryBuffer(*buffer1); + Heap::GetHeap().GetAllocator().AddHungryBuffer(*buffer2); + + Mutator::GetMutator()->SetMutatorPhase(GCPhase::GC_PHASE_FIX); + + Heap::GetHeap().GetAllocator().FeedHungryBuffers(); + + EXPECT_NE(buffer2->GetPreparedRegion(), nullptr); + delete buffer1; + delete buffer2; +} + +HWTEST_F_L0(RegionSpaceTest, AllocationBuffer_AllocateRawPointerObject_ValidSize_ReturnsNonNull) +{ + RegionSpace& theAllocator = reinterpret_cast(Heap::GetHeap().GetAllocator()); + uintptr_t addr = theAllocator.AllocOldRegion(); + ASSERT_NE(addr, 0); + + RegionDesc* region = RegionDesc::GetRegionDescAt(addr); + ASSERT_NE(region, nullptr); + region->InitFreeUnits(); + region->SetRegionType(RegionDesc::RegionType::THREAD_LOCAL_REGION); + + AllocationBuffer* buffer = new (std::nothrow) AllocationBuffer(); + ASSERT_NE(buffer, nullptr); + buffer->SetPreparedRegion(region); + + Mutator::GetMutator()->SetMutatorPhase(GCPhase::GC_PHASE_UNDEF); + Heap::GetHeap().EnableGC(true); + Heap::GetHeap().GetCollectorResources().SetGcStarted(false); + + uintptr_t result = theAllocator.Allocate(16, AllocType::PINNED_OBJECT); + EXPECT_NE(result, 0u); + delete buffer; } } diff --git a/common_components/heap/barrier/tests/barrier_test.cpp b/common_components/heap/barrier/tests/barrier_test.cpp index 391784f10342a87f703c4fdeb77063a35d40528f..f5f361144535d0724322d91bcb465f7180c6dc9f 100644 --- a/common_components/heap/barrier/tests/barrier_test.cpp +++ b/common_components/heap/barrier/tests/barrier_test.cpp @@ -248,4 +248,20 @@ HWTEST_F_L0(BarrierTest, ReadStruct_ReadsCorrectly) { EXPECT_EQ(result->b, initValue->b); delete initValue; +} + +HWTEST_F_L0(BarrierTest, AtomicWriteStaticRef_NonConcurrent) +{ + DummyObject* targetObj = new DummyObject(); + DummyObject* initialObj = new DummyObject(); + + RefField field(reinterpret_cast(0x1)); + field.SetTargetObject(initialObj); + + MockCollector collector; + Barrier barrier(collector); + + barrier.AtomicWriteRefField(nullptr, field, targetObj, std::memory_order_relaxed); + + EXPECT_EQ(field.GetTargetObject(std::memory_order_relaxed), targetObj); } \ No newline at end of file diff --git a/common_components/heap/collector/collector_proxy.h b/common_components/heap/collector/collector_proxy.h index 27a9fea1964b381715d50372eb75bd1f147bc9cd..d65c16846219061307dff33cdb538fcaf2925c18 100755 --- a/common_components/heap/collector/collector_proxy.h +++ b/common_components/heap/collector/collector_proxy.h @@ -25,7 +25,7 @@ namespace common { // collector. However, it actually manages a set of collectors implemented yet, and delegate garbage-collecting to // one of these collectors. // CollectorProxy should inherit collector interfaces, but no datas -class CollectorProxy final : public Collector { +class CollectorProxy : public Collector { public: explicit CollectorProxy(Allocator& allocator, CollectorResources& resources) : wCollector_(allocator, resources) diff --git a/common_components/heap/collector/finalizer_processor.cpp b/common_components/heap/collector/finalizer_processor.cpp index 73ec6abdb23b64a21fa2496ca7e2f834330d33e5..d464623d537c52ff63e57effebb1180d9b24e989 100755 --- a/common_components/heap/collector/finalizer_processor.cpp +++ b/common_components/heap/collector/finalizer_processor.cpp @@ -252,7 +252,7 @@ void FinalizerProcessor::LogAfterProcess() void FinalizerProcessor::RegisterFinalizer(BaseObject* obj) { RefField<> tmpField(nullptr); - Heap::GetHeap().GetBarrier().WriteStaticRef(tmpField, obj); + Heap::GetHeap().GetBarrier().WriteRefField(obj, tmpField, obj); std::lock_guard l(listLock_); finalizers_.push_back(reinterpret_cast(tmpField.GetFieldValue())); } diff --git a/common_components/heap/collector/tests/BUILD.gn b/common_components/heap/collector/tests/BUILD.gn index 20a34d4289709824629fe2663dcf71b8349d9011..729d58249df8b15664dfe39cec2bf3c58b9da2c0 100755 --- a/common_components/heap/collector/tests/BUILD.gn +++ b/common_components/heap/collector/tests/BUILD.gn @@ -21,7 +21,7 @@ host_unittest_action("Collector_Test") { sources = [ # test file "collector_resources_test.cpp", - # "finalizer_processor_test.cpp", + "finalizer_processor_test.cpp", ] configs = [ @@ -33,12 +33,59 @@ host_unittest_action("Collector_Test") { # hiviewdfx libraries external_deps = [ + "bounds_checking_function:libsec_shared", "icu:shared_icui18n", "icu:shared_icuuc", "zlib:libz", ] } +host_unittest_action("Heuristic_Gc_Policy_Test") { + module_out_path = module_output_path + + sources = [ + # test file + "heuristic_gc_policy_test.cpp", + ] + + configs = [ + "//arkcompiler/ets_runtime/common_components:common_components_test_config", + "//arkcompiler/ets_runtime:icu_path_test_config", + ] + + deps = [ "//arkcompiler/ets_runtime/common_components:libark_common_components_test" ] + + # hiviewdfx libraries + external_deps = [ + "icu:shared_icui18n", + "icu:shared_icuuc", + "runtime_core:libarkassembler_static", + ] +} + +host_unittest_action("Collector_Proxy_Test") { + module_out_path = module_output_path + + sources = [ + # test file + "collector_proxy_test.cpp", + ] + + configs = [ + "//arkcompiler/ets_runtime/common_components:common_components_test_config", + "//arkcompiler/ets_runtime:icu_path_test_config", + ] + + deps = [ "//arkcompiler/ets_runtime/common_components:libark_common_components_test" ] + + # hiviewdfx libraries + external_deps = [ + "icu:shared_icui18n", + "icu:shared_icuuc", + "runtime_core:libarkassembler_static", + ] +} + host_unittest_action("Trace_Collector_Test") { module_out_path = module_output_path @@ -114,6 +161,8 @@ group("unittest") { # deps file deps = [ ":Collector_Test", + ":Heuristic_Gc_Policy_Test", + ":Collector_Proxy_Test", ":Trace_Collector_Test", ":Task_Queue_Test", ":Gc_Request_Test", @@ -126,6 +175,8 @@ group("host_unittest") { # deps file deps = [ ":Collector_TestAction", + ":Heuristic_Gc_Policy_TestAction", + ":Collector_Proxy_TestAction", ":Trace_Collector_TestAction", ":Task_Queue_TestAction", ":Gc_Request_TestAction", diff --git a/common_components/heap/collector/tests/collector_proxy_test.cpp b/common_components/heap/collector/tests/collector_proxy_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2baca36eb1519c6ea39bd6eb5f2cbff4e4b2fac8 --- /dev/null +++ b/common_components/heap/collector/tests/collector_proxy_test.cpp @@ -0,0 +1,44 @@ +/* +* Copyright (c) 2025 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 "common_components/heap/collector/collector_proxy.h" +#include "common_components/tests/test_helper.h" + +using namespace common; +namespace common::test { +class CollectorProxyTest : public common::test::BaseTestWithScope { +protected: + static void SetUpTestCase() + { + BaseRuntime::GetInstance()->Init(); + } + + static void TearDownTestCase() + { + BaseRuntime::GetInstance()->Fini(); + } + + void SetUp() override {} + void TearDown() override {} +}; + +HWTEST_F_L0(CollectorProxyTest, RunGarbageCollection) +{ + CollectorProxy collectorProxy(Heap::GetHeap().GetAllocator(), Heap::GetHeap().GetCollectorResources()); + Heap::GetHeap().SetGCReason(GCReason::GC_REASON_OOM); + collectorProxy.RunGarbageCollection(0, GCReason::GC_REASON_OOM, GCType::GC_TYPE_BEGIN); + ASSERT_TRUE(Heap::GetHeap().GetGCReason() == GCReason::GC_REASON_OOM); +} +} // namespace common::test \ No newline at end of file diff --git a/common_components/heap/collector/tests/collector_resources_test.cpp b/common_components/heap/collector/tests/collector_resources_test.cpp index e5c41750fcb1344b801a23067148d3fb5d8e0aba..490c776ecbbf5b1081494940d105238e4acba5bd 100755 --- a/common_components/heap/collector/tests/collector_resources_test.cpp +++ b/common_components/heap/collector/tests/collector_resources_test.cpp @@ -14,6 +14,7 @@ */ #include "common_components/heap/collector/collector_resources.h" +#include "common_components/heap/collector/gc_request.h" #include "common_components/mutator/mutator_manager.h" #include "common_components/tests/test_helper.h" #include "common_interfaces/base_runtime.h" @@ -55,7 +56,7 @@ HWTEST_F_L0(CollectorResourcesTest, RequestGC) { Heap::GetHeap().EnableGC(false); EXPECT_TRUE(!Heap::GetHeap().GetCollectorResources().IsGCActive()); GCReason reason = gcRequests.reason; - Heap::GetHeap().GetCollectorResources().RequestGC(reason, true); + Heap::GetHeap().GetCollectorResources().RequestGC(reason, true, common::GC_TYPE_FULL); } HWTEST_F_L0(CollectorResourcesTest, RequestGCAndWaitTest) { @@ -63,29 +64,12 @@ HWTEST_F_L0(CollectorResourcesTest, RequestGCAndWaitTest) { GCReason reason = gcRequests.reason; Heap::GetHeap().EnableGC(true); EXPECT_TRUE(Heap::GetHeap().GetCollectorResources().IsGCActive()); - Heap::GetHeap().GetCollectorResources().RequestGC(reason, false); + Heap::GetHeap().GetCollectorResources().RequestGC(reason, false, common::GC_TYPE_FULL); EXPECT_TRUE(!gcRequests.IsSyncGC()); } -HWTEST_F_L0(CollectorResourcesTest, GetGCThreadCountTest0) { +HWTEST_F_L0(CollectorResourcesTest, GetGCThreadCountTest) { uint32_t res = Heap::GetHeap().GetCollectorResources().GetGCThreadCount(false); EXPECT_EQ(res, 2u); } - -HWTEST_F_L0(CollectorResourcesTest, GetGCThreadCountTest1) { - Heap::GetHeap().GetCollectorResources().Fini(); - uint32_t res = Heap::GetHeap().GetCollectorResources().GetGCThreadCount(false); - EXPECT_EQ(res, 1u); -} - -HWTEST_F_L0(CollectorResourcesTest, StartRuntimeThreadsTest) { - Heap::GetHeap().GetCollectorResources().Fini(); - Heap::GetHeap().GetCollectorResources().StartRuntimeThreads(); - EXPECT_TRUE(Heap::GetHeap().GetCollectorResources().GetFinalizerProcessor().IsRunning()); -} - -HWTEST_F_L0(CollectorResourcesTest, StopRuntimeThreadsTest) { - Heap::GetHeap().GetCollectorResources().StopRuntimeThreads(); - EXPECT_FALSE(Heap::GetHeap().GetCollectorResources().GetFinalizerProcessor().IsRunning()); -} } // namespace common::test \ No newline at end of file diff --git a/common_components/heap/collector/tests/finalizer_processor_test.cpp b/common_components/heap/collector/tests/finalizer_processor_test.cpp index 746a5744ae4fe2cfb6b8f5160e775b5d902a56df..a9f4a7fa06af1343177f2e35663a6032557e9baf 100755 --- a/common_components/heap/collector/tests/finalizer_processor_test.cpp +++ b/common_components/heap/collector/tests/finalizer_processor_test.cpp @@ -35,12 +35,12 @@ protected: void SetUp() override { - MutatorManager::Instance().CreateRuntimeMutator(ThreadType::GC_THREAD); + MutatorManager::Instance().CreateRuntimeMutator(ThreadType::ARK_PROCESSOR); } void TearDown() override { - MutatorManager::Instance().DestroyRuntimeMutator(ThreadType::GC_THREAD); + MutatorManager::Instance().DestroyRuntimeMutator(ThreadType::ARK_PROCESSOR); } }; @@ -123,12 +123,10 @@ HWTEST_F_L0(FinalizerProcessorTest, Run_TEST1) HeapAddress addr = common::HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); BaseObject *obj = reinterpret_cast(addr); new (obj) BaseObject(); - AllocationBuffer* buffer1 = new (std::nothrow) AllocationBuffer(); - AllocationBuffer* buffer2 = new (std::nothrow) AllocationBuffer(); - RegionDesc* Region = RegionDesc::InitRegion(0, 1, RegionDesc::UnitRole::SMALL_SIZED_UNITS); - buffer1->SetPreparedRegion(Region); - Heap::GetHeap().GetAllocator().AddHungryBuffer(*buffer1); - Heap::GetHeap().GetAllocator().AddHungryBuffer(*buffer2); + AllocationBuffer* buffer = new (std::nothrow) AllocationBuffer(); + RegionDesc* region = RegionDesc::GetRegionDescAt(addr); + buffer->SetPreparedRegion(region); + Heap::GetHeap().GetAllocator().AddHungryBuffer(*buffer); finalizerProcessor.RegisterFinalizer(obj); finalizerProcessor.Start(); std::thread notifier([&]() { @@ -140,6 +138,7 @@ HWTEST_F_L0(FinalizerProcessorTest, Run_TEST1) notifier.join(); std::this_thread::sleep_for(std::chrono::seconds(TWO_SECONDS)); finalizerProcessor.Stop(); - EXPECT_NE(buffer2->GetPreparedRegion(), nullptr); + EXPECT_NE(buffer->GetPreparedRegion(), nullptr); + delete buffer; } -} // namespace common::test \ No newline at end of file +} // namespace common::test diff --git a/common_components/heap/collector/tests/heuristic_gc_policy_test.cpp b/common_components/heap/collector/tests/heuristic_gc_policy_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8275022c1a85706bd8b51f815af49360c3dd8258 --- /dev/null +++ b/common_components/heap/collector/tests/heuristic_gc_policy_test.cpp @@ -0,0 +1,130 @@ +/* +* Copyright (c) 2025 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 "common_components/heap/allocator/allocator.h" +#include "common_components/heap/collector/heuristic_gc_policy.h" +#include "common_components/heap/heap.h" +#include "common_components/tests/test_helper.h" + +using namespace common; +namespace common::test { +class HeuristicGCPolicyTest : public common::test::BaseTestWithScope { +protected: + static void SetUpTestCase() + { + BaseRuntime::GetInstance()->Init(); + } + + static void TearDownTestCase() + { + BaseRuntime::GetInstance()->Fini(); + } + + void SetUp() override {} + void TearDown() override {} +}; + +HWTEST_F_L0(HeuristicGCPolicyTest, NotifyNativeAllocation) +{ + HeuristicGCPolicy gcPolicy; + size_t initialNotified = gcPolicy.GetNotifiedNativeSize(); + size_t initialObjects = gcPolicy.GetNativeHeapThreshold(); + + gcPolicy.NotifyNativeAllocation(NATIVE_IMMEDIATE_THRESHOLD / 2); + + EXPECT_EQ(gcPolicy.GetNotifiedNativeSize(), initialNotified + NATIVE_IMMEDIATE_THRESHOLD / 2); + EXPECT_NE(gcPolicy.GetNativeHeapThreshold(), initialObjects + 1); +} + +HWTEST_F_L0(HeuristicGCPolicyTest, NotifyNativeAllocation_TriggerByBytes) +{ + HeuristicGCPolicy gcPolicy; + size_t initialNotified = gcPolicy.GetNotifiedNativeSize(); + size_t initialObjects = gcPolicy.GetNativeHeapThreshold(); + + gcPolicy.NotifyNativeAllocation(NATIVE_IMMEDIATE_THRESHOLD + 1); + + EXPECT_EQ(gcPolicy.GetNotifiedNativeSize(), initialNotified + NATIVE_IMMEDIATE_THRESHOLD + 1); + EXPECT_NE(gcPolicy.GetNativeHeapThreshold(), initialObjects + 1); +} + +HWTEST_F_L0(HeuristicGCPolicyTest, TryHeuristicGC) +{ + HeuristicGCPolicy gcPolicy; + StartupStatusManager::SetStartupStatus(StartupStatus::COLD_STARTUP_FINISH); + Heap::GetHeap().GetCollector().GetGCStats().heapThreshold = 0; + gcPolicy.TryHeuristicGC(); + Heap::GetHeap().GetCollector().GetGCStats().shouldRequestYoung = true; + gcPolicy.TryHeuristicGC(); + EXPECT_EQ(Heap::GetHeap().GetAllocator().GetAllocatedBytes(), + Heap::GetHeap().GetCollector().GetGCStats().GetThreshold()); +} + +HWTEST_F_L0(HeuristicGCPolicyTest, ChangeGCParams) +{ + HeuristicGCPolicy gcPolicy; + gcPolicy.RecordAliveSizeAfterLastGC(1); + gcPolicy.ChangeGCParams(true); + EXPECT_EQ(Heap::GetHeap().GetAllocator().GetAllocatedBytes(), 0); +} + +HWTEST_F_L0(HeuristicGCPolicyTest, CheckAndTriggerHintGC) +{ + HeuristicGCPolicy gcPolicy; + StartupStatusManager::SetStartupStatus(StartupStatus::COLD_STARTUP); + bool result = gcPolicy.CheckAndTriggerHintGC(MemoryReduceDegree::HIGH); + ASSERT_FALSE(result); + + StartupStatusManager::SetStartupStatus(StartupStatus::COLD_STARTUP_FINISH); + result = gcPolicy.CheckAndTriggerHintGC(MemoryReduceDegree::HIGH); + ASSERT_FALSE(result); + + gcPolicy.RecordAliveSizeAfterLastGC(1); + result = gcPolicy.CheckAndTriggerHintGC(MemoryReduceDegree::HIGH); + ASSERT_FALSE(result); + + result = gcPolicy.CheckAndTriggerHintGC(MemoryReduceDegree::LOW); + ASSERT_FALSE(result); +} + +HWTEST_F_L0(HeuristicGCPolicyTest, ShouldRestrainGCOnStartup) +{ + HeuristicGCPolicy gcPolicy; + StartupStatusManager::SetStartupStatus(StartupStatus::COLD_STARTUP); + EXPECT_TRUE(gcPolicy.ShouldRestrainGCOnStartupOrSensitive()); + gcPolicy.TryHeuristicGC(); + + StartupStatusManager::SetStartupStatus(StartupStatus::COLD_STARTUP_FINISH); + EXPECT_FALSE(gcPolicy.ShouldRestrainGCOnStartupOrSensitive()); + + gcPolicy.Init(); + EXPECT_FALSE(gcPolicy.ShouldRestrainGCOnStartupOrSensitive()); + StartupStatusManager::SetStartupStatus(StartupStatus::COLD_STARTUP_PARTIALLY_FINISH); + EXPECT_TRUE(gcPolicy.ShouldRestrainGCOnStartupOrSensitive()); +} + +HWTEST_F_L0(HeuristicGCPolicyTest, NotifyNativeAllocation_TriggerByBytes1) +{ + HeuristicGCPolicy gcPolicy; + size_t initialNotified = gcPolicy.GetNotifiedNativeSize(); + size_t initialObjects = gcPolicy.GetNativeHeapThreshold(); + + gcPolicy.SetNativeHeapThreshold(1); + gcPolicy.NotifyNativeAllocation(NATIVE_IMMEDIATE_THRESHOLD + 1); + + EXPECT_EQ(gcPolicy.GetNotifiedNativeSize(), initialNotified + NATIVE_IMMEDIATE_THRESHOLD + 1); + EXPECT_NE(gcPolicy.GetNativeHeapThreshold(), initialObjects + 1); +} +} // namespace common::test \ No newline at end of file diff --git a/common_components/heap/collector/tests/task_queue_test.cpp b/common_components/heap/collector/tests/task_queue_test.cpp index aacc1a958952ef94f3fddc00b28bfe50559d7f81..f11f30e1a543b554f229e117d522bbdd70ef1c42 100644 --- a/common_components/heap/collector/tests/task_queue_test.cpp +++ b/common_components/heap/collector/tests/task_queue_test.cpp @@ -37,6 +37,7 @@ public: bool IsHeapObject(HeapAddress) const override { return false; } #endif void FeedHungryBuffers() override {} + size_t GetSurvivedSize() const override { return 0; } }; class StubCollectorProxy : public CollectorProxy { diff --git a/common_components/heap/collector/tests/trace_collector_test.cpp b/common_components/heap/collector/tests/trace_collector_test.cpp index 5b579b4ff2eeda1a74ce2debc4d0a29c4837d92d..0c40c5dd80434793c101ddf979cab5ecc4dd0348 100755 --- a/common_components/heap/collector/tests/trace_collector_test.cpp +++ b/common_components/heap/collector/tests/trace_collector_test.cpp @@ -23,11 +23,6 @@ using namespace common; namespace common::test { -class TestWCollector : public WCollector { -public: - using WCollector::WCollector; -}; - class TraceCollectorTest : public common::test::BaseTestWithScope { protected: static void SetUpTestCase() @@ -39,6 +34,16 @@ protected: { BaseRuntime::GetInstance()->Fini(); } + void SetUp() override + { + MutatorManager::Instance().CreateRuntimeMutator(ThreadType::ARK_PROCESSOR); + } + + void TearDown() override + { + MutatorManager::Instance().DestroyRuntimeMutator(ThreadType::ARK_PROCESSOR); + } + StaticRootTable rootTable_; bool ContainsRoot(StaticRootTable& table, const StaticRootTable::StaticRootArray* array, uint32_t size) { @@ -54,13 +59,98 @@ protected: table.VisitRoots(visitor); return found; } + class TableTraceCollctor : public TraceCollector { + public: + using TraceCollector::SetGCReason; + using TraceCollector::TraceRoots; + using TraceCollector::PushRootToWorkStack; + using TraceCollector::UpdateNativeThreshold; + }; }; -std::unique_ptr GetWCollector() +HWTEST_F_L0(TraceCollectorTest, RunGarbageCollection) { - CollectorResources& resources = Heap::GetHeap().GetCollectorResources(); - Allocator& allocator = Heap::GetHeap().GetAllocator(); - return std::make_unique(allocator, resources); + TraceCollector& collector = reinterpret_cast(Heap::GetHeap().GetCollector()); + Heap::GetHeap().SetGCReason(GCReason::GC_REASON_YOUNG); + collector.RunGarbageCollection(0, GCReason::GC_REASON_USER, common::GC_TYPE_FULL); + ASSERT_FALSE(Heap::GetHeap().GetCollector().GetGCStats().isYoungGC()); + + Heap::GetHeap().SetGCReason(GCReason::GC_REASON_BACKUP); + collector.RunGarbageCollection(0, GCReason::GC_REASON_OOM, common::GC_TYPE_FULL); + ASSERT_FALSE(Heap::GetHeap().GetCollector().GetGCStats().isYoungGC()); } +HWTEST_F_L0(TraceCollectorTest, RunGarbageCollectionTest2) +{ + TraceCollector& collector = reinterpret_cast(Heap::GetHeap().GetCollector()); + Heap::GetHeap().SetGCReason(GCReason::GC_REASON_YOUNG); + collector.RunGarbageCollection(0, GCReason::GC_REASON_YOUNG, common::GC_TYPE_FULL); + ASSERT_TRUE(Heap::GetHeap().GetCollector().GetGCStats().isYoungGC()); +} + +HWTEST_F_L0(TraceCollectorTest, UpdateNativeThresholdTest) +{ + TableTraceCollctor& collector = reinterpret_cast(Heap::GetHeap().GetCollector()); + GCParam gcParam; + gcParam.minGrowBytes = 1024; + Heap::GetHeap().SetNativeHeapThreshold(512); + auto oldThreshold = Heap::GetHeap().GetNativeHeapThreshold(); + collector.UpdateNativeThreshold(gcParam); + auto newThreshold = Heap::GetHeap().GetNativeHeapThreshold(); + EXPECT_NE(newThreshold, oldThreshold); +} + +HWTEST_F_L0(TraceCollectorTest, UpdateNativeThresholdTest2) +{ + TableTraceCollctor& collector = reinterpret_cast(Heap::GetHeap().GetCollector()); + Heap::GetHeap().NotifyNativeAllocation(1100 * MB); + + GCParam param; + collector.UpdateNativeThreshold(param); + ASSERT_TRUE(Heap::GetHeap().GetNotifiedNativeSize() > MAX_NATIVE_SIZE_INC); +} + +HWTEST_F_L0(TraceCollectorTest, TraceRootsTest) +{ + TableTraceCollctor& collector = reinterpret_cast(Heap::GetHeap().GetCollector()); + CArrayList roots; + RegionSpace& theAllocator = reinterpret_cast(Heap::GetHeap().GetAllocator()); + uintptr_t addr = theAllocator.AllocOldRegion(); + ASSERT_NE(addr, 0); + BaseObject* obj = reinterpret_cast(addr); + RegionDesc* region = RegionDesc::GetRegionDescAt(addr); + region->SetRegionType(RegionDesc::RegionType::OLD_REGION); + Heap::GetHeap().SetGCReason(GC_REASON_YOUNG); + collector.SetGCReason(GC_REASON_YOUNG); + + roots.push_back(obj); + collector.TraceRoots(roots); + ASSERT_TRUE(region->IsInOldSpace()); +} + +HWTEST_F_L0(TraceCollectorTest, PushRootToWorkStackTest) +{ + TableTraceCollctor& collector = reinterpret_cast(Heap::GetHeap().GetCollector()); + RegionSpace& theAllocator = reinterpret_cast(Heap::GetHeap().GetAllocator()); + uintptr_t addr = theAllocator.AllocOldRegion(); + ASSERT_NE(addr, 0); + BaseObject* obj = reinterpret_cast(addr); + RootSet roots; + RegionDesc* region = RegionDesc::GetRegionDescAt(addr); + region->SetRegionType(RegionDesc::RegionType::RECENT_LARGE_REGION); + collector.SetGCReason(GC_REASON_NATIVE); + region->MarkObject(obj); + bool result = collector.PushRootToWorkStack(&roots, obj); + ASSERT_FALSE(result); + + region->SetRegionType(RegionDesc::RegionType::RECENT_LARGE_REGION); + collector.SetGCReason(GC_REASON_YOUNG); + result = collector.PushRootToWorkStack(&roots, obj); + ASSERT_FALSE(result); + + region->SetRegionType(RegionDesc::RegionType::OLD_REGION); + collector.SetGCReason(GC_REASON_NATIVE); + result = collector.PushRootToWorkStack(&roots, obj); + ASSERT_FALSE(result); +} } \ No newline at end of file diff --git a/common_components/heap/space/tests/BUILD.gn b/common_components/heap/space/tests/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..deaaa4e3bae817a50547f578c59367b1bd787afc --- /dev/null +++ b/common_components/heap/space/tests/BUILD.gn @@ -0,0 +1,58 @@ +# Copyright (c) 2025 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. + +import("//arkcompiler/ets_runtime/common_components/tests/test_helper.gni") + +module_output_path = "ets_runtime" + +host_unittest_action("From_Space_Test") { + module_out_path = module_output_path + + sources = [ + # test file + "from_space_test.cpp", + ] + + configs = [ + "//arkcompiler/ets_runtime/common_components:common_components_test_config", + "//arkcompiler/ets_runtime:icu_path_test_config", + ] + + deps = [ "//arkcompiler/ets_runtime/common_components:libark_common_components_test" ] + + # hiviewdfx libraries + external_deps = [ + "bounds_checking_function:libsec_shared", + "icu:shared_icui18n", + "icu:shared_icuuc", + "zlib:libz", + ] +} + +group("unittest") { + testonly = true + + # deps file + deps = [ + ":From_Space_Test", + ] +} + +group("host_unittest") { + testonly = true + + # deps file + deps = [ + ":From_Space_TestAction", + ] +} \ No newline at end of file diff --git a/common_components/heap/space/tests/from_space_test.cpp b/common_components/heap/space/tests/from_space_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..177670045345011d78a191487f56ee66cb72d659 --- /dev/null +++ b/common_components/heap/space/tests/from_space_test.cpp @@ -0,0 +1,89 @@ +/* +* Copyright (c) 2025 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 "common_components/heap/allocator/region_space.h" +#include "common_components/heap/space/from_space.h" +#include "common_components/mutator/thread_local.h" +#include "common_components/tests/test_helper.h" + +using namespace common; +namespace common::test { +class FromSpaceTest : public common::test::BaseTestWithScope { +protected: + class TestRegionList : public RegionList { + public: + TestRegionList() : RegionList("TestList") {} + void setHeadRegion(RegionDesc* head) { listHead_ = head; } + }; + static void SetUpTestCase() + { + BaseRuntime::GetInstance()->Init(); + } + + static void TearDownTestCase() + { + BaseRuntime::GetInstance()->Fini(); + } + + void SetUp() override {} + void TearDown() override {} +}; + +HWTEST_F_L0(FromSpaceTest, CopyFromRegions) +{ + RegionManager regionManager; + RegionSpace heap; + FromSpace fromSpace(regionManager, heap); + ThreadLocal::SetAllocBuffer(nullptr); + fromSpace.CopyFromRegions(nullptr); + ASSERT_FALSE(fromSpace.GetFromRegionList().GetHeadRegion() != nullptr); +} + +HWTEST_F_L0(FromSpaceTest, CopyFromRegionsTest) +{ + size_t unitIdx = 0; + size_t nUnit = 4; + RegionDesc* region = RegionDesc::InitRegion(unitIdx, nUnit, RegionDesc::UnitRole::LARGE_SIZED_UNITS); + TestRegionList list; + list.setHeadRegion(region); + ASSERT_TRUE(list.GetHeadRegion() != nullptr); + + RegionSpace heap; + RegionManager manager; + FromSpace fromSpace(manager, heap); + fromSpace.AssembleGarbageCandidates(list); + + AllocationBuffer* buffer1 = new (std::nothrow) AllocationBuffer(); + ThreadLocal::SetAllocBuffer(buffer1); + fromSpace.CopyFromRegions(); + fromSpace.ExemptFromRegions(); + ASSERT_TRUE(AllocationBuffer::GetAllocBuffer() != nullptr); +} + +HWTEST_F_L0(FromSpaceTest, ParallelCopyFromRegions) +{ + RegionManager regionManager; + RegionSpace heap; + FromSpace fromSpace(regionManager, heap); + AllocationBuffer* buffer1 = new (std::nothrow) AllocationBuffer(); + ThreadLocal::SetAllocBuffer(buffer1); + fromSpace.ParallelCopyFromRegions(nullptr, 5); + ASSERT_TRUE(AllocationBuffer::GetAllocBuffer() != nullptr); + + ThreadLocal::SetAllocBuffer(nullptr); + fromSpace.ParallelCopyFromRegions(nullptr, 5); + ASSERT_FALSE(AllocationBuffer::GetAllocBuffer() != nullptr); +} +} // namespace common::test \ No newline at end of file diff --git a/common_components/heap/tests/BUILD.gn b/common_components/heap/tests/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..ead18f376182e924776fc3be6f0d69a3bca90bba --- /dev/null +++ b/common_components/heap/tests/BUILD.gn @@ -0,0 +1,85 @@ +# Copyright (c) 2025 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. + +import("//arkcompiler/ets_runtime/common_components/tests/test_helper.gni") + +module_output_path = "ets_runtime" + +host_unittest_action("Heap_Manager_Test") { + module_out_path = module_output_path + + sources = [ + # test file + "heap_manager_test.cpp", + ] + + configs = [ + "//arkcompiler/ets_runtime/common_components:common_components_test_config", + "//arkcompiler/ets_runtime:icu_path_test_config", + ] + + deps = [ "//arkcompiler/ets_runtime/common_components:libark_common_components_test" ] + + # hiviewdfx libraries + external_deps = [ + "icu:shared_icui18n", + "icu:shared_icuuc", + "zlib:libz", + ] +} + +host_unittest_action("Verification_Test") { + module_out_path = module_output_path + + sources = [ + # test file + "verification_test.cpp", + ] + + include_dirs = [ "//arkcompiler/ets_runtime/common_components/" ] + + configs = [ + "//arkcompiler/ets_runtime/common_components:common_components_test_config", + "//arkcompiler/ets_runtime:icu_path_test_config", + ] + + deps = [ "//arkcompiler/ets_runtime/common_components:libark_common_components_test" ] + + # hiviewdfx libraries + external_deps = [ + "bounds_checking_function:libsec_shared", + "icu:shared_icui18n", + "icu:shared_icuuc", + "zlib:libz", + ] +} + +group("unittest") { + testonly = true + + # deps file + deps = [ + ":Heap_Manager_Test", + ":Verification_Test", + ] +} + +group("host_unittest") { + testonly = true + + # deps file + deps = [ + ":Heap_Manager_TestAction", + ":Verification_TestAction", + ] +} \ No newline at end of file diff --git a/common_components/heap/tests/heap_manager_test.cpp b/common_components/heap/tests/heap_manager_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7721f429c268c8bdbdad2c1327c90e9c69ed5558 --- /dev/null +++ b/common_components/heap/tests/heap_manager_test.cpp @@ -0,0 +1,41 @@ +/* +* Copyright (c) 2025 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 "common_components/heap/heap.h" +#include "common_components/heap/heap_manager.h" +#include "common_components/tests/test_helper.h" + +using namespace common; +namespace common::test { +class HeapManagerTest : public common::test::BaseTestWithScope { +protected: + static void SetUpTestCase() + { + BaseRuntime::GetInstance()->Init(); + } +}; + +HWTEST_F_L0(HeapManagerTest, RequestGC) +{ + HeapManager manager; + Heap::GetHeap().EnableGC(false); + manager.RequestGC(GCReason::GC_REASON_USER, true, common::GC_TYPE_FULL); + ASSERT_FALSE(Heap::GetHeap().IsGCEnabled()); + + Heap::GetHeap().EnableGC(true); + manager.RequestGC(GCReason::GC_REASON_USER, true, common::GC_TYPE_FULL); + ASSERT_TRUE(Heap::GetHeap().IsGCEnabled()); +} +} // namespace common::test \ No newline at end of file diff --git a/common_components/heap/tests/verification_test.cpp b/common_components/heap/tests/verification_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..dd63f60c65ea7e3750b910a1a2d37fdc3aeda16f --- /dev/null +++ b/common_components/heap/tests/verification_test.cpp @@ -0,0 +1,286 @@ +/* +* Copyright (c) 2025 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 "common_components/heap/verification.cpp" +#include "common_components/heap/heap_manager.h" +#include "common_components/heap/w_collector/w_collector.h" +#include "common_components/tests/test_helper.h" +#include "common_interfaces/objects/base_object_operator.h" + +using namespace common; +namespace common::test { +class TestBaseObjectOperator : public common::BaseObjectOperatorInterfaces { +public: + bool IsValidObject([[maybe_unused]] const BaseObject *object) const override { return enbaleValidObject_; } + void ForEachRefField(const BaseObject *object, const common::RefFieldVisitor &visitor) const override {} + size_t GetSize(const BaseObject *object) const override{ return size_; } + BaseObject *GetForwardingPointer(const BaseObject *object) const override { return nullptr; } + void SetForwardingPointerAfterExclusive(BaseObject *object, BaseObject *fwdPtr) override {} + void SetValidObject(bool value) { enbaleValidObject_ = value; } + void SetSize(size_t size) { size_ = size; } +private: + bool enbaleValidObject_ = false; + size_t size_ = 0; +}; +class VerificationTest : public common::test::BaseTestWithScope { +protected: + static void SetUpTestCase() + { + BaseRuntime::GetInstance()->Init(); + } + + static void TearDownTestCase() + { + BaseRuntime::GetInstance()->Fini(); + } + + void SetUp() override + { + MutatorManager::Instance().CreateRuntimeMutator(ThreadType::GC_THREAD); + } + + void TearDown() override + { + MutatorManager::Instance().DestroyRuntimeMutator(ThreadType::GC_THREAD); + } +}; + +HWTEST_F_L0(VerificationTest, GetObjectInfoTest) +{ + BaseObject* obj = nullptr; + std::string result = GetObjectInfo(obj); + + EXPECT_NE(result.find("address: 0x0"), std::string::npos); + EXPECT_NE(result.find("Skip: nullptr"), std::string::npos); + EXPECT_NE(result.find("Skip: Object is not in heap range"), std::string::npos); +} + +HWTEST_F_L0(VerificationTest, GetObjectInfoTest2) +{ + BaseObject obj; + std::string result = GetObjectInfo(&obj); + EXPECT_NE(result.find("address: 0x"), std::string::npos); + EXPECT_NE(result.find("Skip: Object is not in heap range"), std::string::npos); +} + +HWTEST_F_L0(VerificationTest, GetRefInfoTest) +{ + BaseObject oldObj; + RefField oldField(&oldObj); + MAddress oldAddress = oldField.GetFieldValue(); + std::string result = GetRefInfo(oldField); + EXPECT_NE(result.find("address: 0x"), std::string::npos); + EXPECT_NE(result.find("Skip: Object is not in heap range"), std::string::npos); +} + +HWTEST_F_L0(VerificationTest, VerifyRefImplTest2) +{ + RegionSpace& theAllocator = reinterpret_cast(Heap::GetHeap().GetAllocator()); + uintptr_t addr = theAllocator.AllocOldRegion(); + ASSERT_NE(addr, 0U); + BaseObject* obj = reinterpret_cast(addr); + RegionDesc* region = RegionDesc::GetRegionDescAt(reinterpret_cast(obj)); + ASSERT_NE(region, nullptr); + region->SetRegionType(RegionDesc::RegionType::FROM_REGION); + RefField field(obj); + + auto refObj = field.GetTargetObject(); + + AfterForwardVisitor visitor; + visitor.VerifyRefImpl(obj, field); + ASSERT_FALSE(RegionSpace::IsMarkedObject(refObj)); + ASSERT_FALSE(RegionSpace::IsResurrectedObject(refObj)); +} + +HWTEST_F_L0(VerificationTest, VerifyRefImplTest3) +{ + RegionSpace& theAllocator = reinterpret_cast(Heap::GetHeap().GetAllocator()); + uintptr_t addr = theAllocator.AllocOldRegion(); + ASSERT_NE(addr, 0U); + BaseObject* obj = reinterpret_cast(addr); + RegionDesc* region = RegionDesc::GetRegionDescAt(reinterpret_cast(obj)); + ASSERT_NE(region, nullptr); + region->SetRegionType(RegionDesc::RegionType::FULL_PINNED_REGION); + RefField field(obj); + + auto refObj = field.GetTargetObject(); + + ReadBarrierSetter visitor; + visitor.VerifyRefImpl(nullptr, field); + visitor.VerifyRefImpl(obj, field); + EXPECT_EQ(RegionDesc::RegionType::FULL_PINNED_REGION, + RegionDesc::GetRegionDescAt(reinterpret_cast(field.GetTargetObject()))->GetRegionType()); + + region->SetRegionType(RegionDesc::RegionType::RECENT_PINNED_REGION); + visitor.VerifyRefImpl(obj, field); + EXPECT_EQ(RegionDesc::RegionType::RECENT_PINNED_REGION, + RegionDesc::GetRegionDescAt(reinterpret_cast(field.GetTargetObject()))->GetRegionType()); + + region->SetRegionType(RegionDesc::RegionType::FIXED_PINNED_REGION); + visitor.VerifyRefImpl(obj, field); + EXPECT_EQ(RegionDesc::RegionType::FIXED_PINNED_REGION, + RegionDesc::GetRegionDescAt(reinterpret_cast(field.GetTargetObject()))->GetRegionType()); + + region->SetRegionType(RegionDesc::RegionType::FULL_FIXED_PINNED_REGION); + visitor.VerifyRefImpl(obj, field); + EXPECT_EQ(RegionDesc::RegionType::FULL_FIXED_PINNED_REGION, + RegionDesc::GetRegionDescAt(reinterpret_cast(field.GetTargetObject()))->GetRegionType()); + + region->SetRegionType(RegionDesc::RegionType::READ_ONLY_REGION); + auto oldRefValue = field.GetFieldValue(); + visitor.VerifyRefImpl(obj, field); + auto newRefValue = field.GetFieldValue(); + EXPECT_NE(oldRefValue, newRefValue); +} + +std::unique_ptr GetWCollector() +{ + CollectorResources &resources = Heap::GetHeap().GetCollectorResources(); + Allocator &allocator = Heap::GetHeap().GetAllocator(); + + return std::make_unique(allocator, resources); +} + +HWTEST_F_L0(VerificationTest, VerifyAfterMarkTest1) +{ + Heap::GetHeap().SetGCPhase(GCPhase::GC_PHASE_POST_MARK); + std::unique_ptr wcollector = GetWCollector(); + ASSERT_TRUE(wcollector != nullptr); + WVerify verify; + verify.VerifyAfterMark(*wcollector); + ASSERT_FALSE(MutatorManager::Instance().WorldStopped()); +} + +HWTEST_F_L0(VerificationTest, VerifyAfterForwardTest1) +{ + Heap::GetHeap().SetGCPhase(GCPhase::GC_PHASE_COPY); + std::unique_ptr wcollector = GetWCollector(); + ASSERT_TRUE(wcollector != nullptr); + WVerify verify; + verify.VerifyAfterForward(*wcollector); + ASSERT_FALSE(MutatorManager::Instance().WorldStopped()); +} + +HWTEST_F_L0(VerificationTest, VerifyAfterFixTest1) +{ + Heap::GetHeap().SetGCPhase(GCPhase::GC_PHASE_FIX); + std::unique_ptr wcollector = GetWCollector(); + ASSERT_TRUE(wcollector != nullptr); + WVerify verify; + verify.VerifyAfterFix(*wcollector); + ASSERT_FALSE(MutatorManager::Instance().WorldStopped()); +} + +HWTEST_F_L0(VerificationTest, EnableReadBarrierDFXTest1) +{ + std::unique_ptr wcollector = GetWCollector(); + ASSERT_TRUE(wcollector != nullptr); + WVerify verify; + verify.EnableReadBarrierDFX(*wcollector); + ASSERT_FALSE(MutatorManager::Instance().WorldStopped()); +} + +HWTEST_F_L0(VerificationTest, DisableReadBarrierDFXTest1) +{ + std::unique_ptr wcollector = GetWCollector(); + ASSERT_TRUE(wcollector != nullptr); + WVerify verify; + verify.DisableReadBarrierDFX(*wcollector); + ASSERT_FALSE(MutatorManager::Instance().WorldStopped()); +} + +HWTEST_F_L0(VerificationTest, GetObjectInfoTest3) +{ + HeapAddress addr = HeapManager::Allocate(sizeof(BaseObject), AllocType::PINNED_OBJECT, true); + BaseObject *obj = reinterpret_cast(addr); + std::string result = GetObjectInfo(obj); + EXPECT_NE(result.find("address: 0x"), std::string::npos); + EXPECT_NE(result.find("Type: 0x"), std::string::npos); + EXPECT_NE(result.find("Base: 0x"), std::string::npos); + EXPECT_NE(result.find("Start: 0x"), std::string::npos); + EXPECT_NE(result.find("End: 0x"), std::string::npos); + EXPECT_NE(result.find("AllocPtr: 0x"), std::string::npos); + EXPECT_NE(result.find("TraceLine: 0x"), std::string::npos); + EXPECT_NE(result.find("CopyLine: 0x"), std::string::npos); +} + +HWTEST_F_L0(VerificationTest, GetRefInfoTest2) +{ + RefField field(nullptr); + uintptr_t taggedValue = 0x04; + field.SetFieldValue(static_cast(taggedValue)); + std::string result = GetRefInfo(field); + EXPECT_NE(result.find("> Raw memory:"), std::string::npos); + EXPECT_NE(result.find("Skip: primitive"), std::string::npos); +} + +HWTEST_F_L0(VerificationTest, VerifyRefImplTest) +{ + HeapAddress addr = HeapManager::Allocate(sizeof(BaseObject), AllocType::PINNED_OBJECT, true); + BaseObject *obj = reinterpret_cast(addr); + RefField oldField(obj); + TestBaseObjectOperator operatorImpl; + BaseObject::RegisterDynamic(&operatorImpl); + operatorImpl.SetValidObject(true); + Heap::GetHeap().SetGCReason(GCReason::GC_REASON_YOUNG); + operatorImpl.SetSize(BaseObject::BaseObjectSize()); + AfterMarkVisitor visitor; + visitor.VerifyRefImpl(nullptr, oldField); + ASSERT_TRUE(Heap::GetHeap().GetGCReason() == GCReason::GC_REASON_YOUNG); + ASSERT_TRUE(Heap::IsTaggedObject(oldField.GetFieldValue())); + + AfterMarkVisitor visitor1; + visitor1.VerifyRefImpl(nullptr, oldField); + ASSERT_TRUE(Heap::IsTaggedObject(oldField.GetFieldValue())); +} + +HWTEST_F_L0(VerificationTest, VerifyRefImplTest1) +{ + HeapAddress addr = HeapManager::Allocate(sizeof(BaseObject), AllocType::PINNED_OBJECT, true); + BaseObject *obj = reinterpret_cast(addr); + RefField oldField(obj); + TestBaseObjectOperator operatorImpl; + BaseObject::RegisterDynamic(&operatorImpl); + operatorImpl.SetValidObject(true); + Heap::GetHeap().SetGCReason(GCReason::GC_REASON_YOUNG); + operatorImpl.SetSize(BaseObject::BaseObjectSize()); + AfterMarkVisitor visitor; + visitor.VerifyRefImpl(obj, oldField); + ASSERT_TRUE(Heap::GetHeap().GetGCReason() == GCReason::GC_REASON_YOUNG); + ASSERT_TRUE(Heap::IsTaggedObject(oldField.GetFieldValue())); +} + +static BaseObject* testObj = nullptr; +static void CustomVisitRoot(const RefFieldVisitor& visitorFunc) +{ + RefField<> field(testObj); + visitorFunc(field); +} +HWTEST_F_L0(VerificationTest, IterateRetraced_VerifyAllRefs) +{ + RegionSpace regionSpace; + VerifyIterator verify(regionSpace); + AfterForwardVisitor visitor; + std::unordered_set markSet; + HeapAddress addr = HeapManager::Allocate(sizeof(BaseObject), AllocType::PINNED_OBJECT, true); + testObj = reinterpret_cast(addr); + markSet.insert(testObj); + + verify.IterateRetraced(visitor, markSet, true); + verify.IterateRetraced(visitor, markSet, false); + EXPECT_EQ(markSet.size(), 1); + EXPECT_TRUE(markSet.find(testObj) != markSet.end()); +} +} // namespace common::test diff --git a/common_components/heap/w_collector/tests/BUILD.gn b/common_components/heap/w_collector/tests/BUILD.gn index 31bcb39b94be7c2ee498e96b05b3ab053de8bc40..a5ba83c64be15ad0ab26f53ea1c28cacaae9d13f 100755 --- a/common_components/heap/w_collector/tests/BUILD.gn +++ b/common_components/heap/w_collector/tests/BUILD.gn @@ -192,6 +192,7 @@ host_unittest_action("W_Collector_Test") { # hiviewdfx libraries external_deps = [ + "bounds_checking_function:libsec_shared", "icu:shared_icui18n", "icu:shared_icuuc", "zlib:libz", diff --git a/common_components/heap/w_collector/tests/copy_barrier_test.cpp b/common_components/heap/w_collector/tests/copy_barrier_test.cpp index 178108f97715fde11b613e8593f94a22b3383ffc..b967734728a22cf2dd43c7f15f4b7839ed7f5a82 100755 --- a/common_components/heap/w_collector/tests/copy_barrier_test.cpp +++ b/common_components/heap/w_collector/tests/copy_barrier_test.cpp @@ -92,22 +92,21 @@ HWTEST_F_L0(CopyBarrierTest, ReadRefField_TEST3) HWTEST_F_L0(CopyBarrierTest, ReadRefField_TEST4) { - MockCollectorUnmovableTest collector; + MockCollectorForwardTest collector; auto copyBarrier = std::make_unique(collector); ASSERT_TRUE(copyBarrier != nullptr); HeapAddress addr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); BaseObject* obj = reinterpret_cast(addr); - RefField field(obj); + RefField field(nullptr); BaseObject* resultObj = copyBarrier->ReadRefField(obj, field); - ASSERT_TRUE(resultObj != nullptr); - EXPECT_EQ(resultObj, obj); + ASSERT_TRUE(resultObj == nullptr); } HWTEST_F_L0(CopyBarrierTest, ReadRefField_TEST5) { - MockCollectorUnmovableTest collector; + MockCollectorForwardTest collector; auto copyBarrier = std::make_unique(collector); ASSERT_TRUE(copyBarrier != nullptr); @@ -117,15 +116,11 @@ HWTEST_F_L0(CopyBarrierTest, ReadRefField_TEST5) BaseObject* resultObj = copyBarrier->ReadRefField(obj, field); ASSERT_TRUE(resultObj != nullptr); - constexpr uint64_t TAG_WEAK = 0x01ULL; - BaseObject* newObj = reinterpret_cast(reinterpret_cast(obj) | TAG_WEAK); - EXPECT_EQ(resultObj, newObj); } - -HWTEST_F_L0(CopyBarrierTest, ReadRefField_TEST6) +HWTEST_F_L0(CopyBarrierTest, ReadStaticRef_TEST1) { - MockCollectorForwardTest collector; + MockCollector collector; auto copyBarrier = std::make_unique(collector); ASSERT_TRUE(copyBarrier != nullptr); @@ -133,25 +128,41 @@ HWTEST_F_L0(CopyBarrierTest, ReadRefField_TEST6) BaseObject* obj = reinterpret_cast(addr); RefField field(obj); - BaseObject* resultObj = copyBarrier->ReadRefField(obj, field); + BaseObject* resultObj = copyBarrier->ReadStaticRef(field); ASSERT_TRUE(resultObj != nullptr); + EXPECT_EQ(resultObj, obj); } -HWTEST_F_L0(CopyBarrierTest, ReadRefField_TEST7) +HWTEST_F_L0(CopyBarrierTest, ReadStringTableStaticRef_TEST1) { - MockCollectorForwardTest collector; + MockCollector collector; + auto copyBarrier = std::make_unique(collector); + ASSERT_TRUE(copyBarrier != nullptr); + + RefField field(nullptr); + + BaseObject* resultObj = copyBarrier->ReadStringTableStaticRef(field); + ASSERT_TRUE(resultObj == nullptr); +} + +HWTEST_F_L0(CopyBarrierTest, ReadStringTableStaticRef_TEST2) +{ + MockCollector collector; auto copyBarrier = std::make_unique(collector); ASSERT_TRUE(copyBarrier != nullptr); HeapAddress addr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); BaseObject* obj = reinterpret_cast(addr); - RefField field(obj, true); + RegionDesc *regionInfo = RegionDesc::GetRegionDescAt(addr); + regionInfo->SetRegionAllocPtr(addr - 1); + regionInfo->SetTraceLine(); + RefField field(obj); - BaseObject* resultObj = copyBarrier->ReadRefField(obj, field); + BaseObject* resultObj = copyBarrier->ReadStringTableStaticRef(field); ASSERT_TRUE(resultObj != nullptr); } -HWTEST_F_L0(CopyBarrierTest, ReadStaticRef_TEST1) +HWTEST_F_L0(CopyBarrierTest, ReadStringTableStaticRef_TEST3) { MockCollector collector; auto copyBarrier = std::make_unique(collector); @@ -159,23 +170,27 @@ HWTEST_F_L0(CopyBarrierTest, ReadStaticRef_TEST1) HeapAddress addr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); BaseObject* obj = reinterpret_cast(addr); + RegionDesc *regionInfo = RegionDesc::GetRegionDescAt(addr); + regionInfo->SetRegionType(RegionDesc::RegionType::ALIVE_REGION_FIRST); RefField field(obj); - BaseObject* resultObj = copyBarrier->ReadStaticRef(field); - ASSERT_TRUE(resultObj != nullptr); - EXPECT_EQ(resultObj, obj); + BaseObject* resultObj = copyBarrier->ReadStringTableStaticRef(field); + ASSERT_TRUE(resultObj == nullptr); } -HWTEST_F_L0(CopyBarrierTest, ReadStringTableStaticRef_TEST1) +HWTEST_F_L0(CopyBarrierTest, ReadStringTableStaticRef_TEST4) { MockCollector collector; auto copyBarrier = std::make_unique(collector); ASSERT_TRUE(copyBarrier != nullptr); - RefField field(nullptr); + HeapAddress addr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); + BaseObject* obj = reinterpret_cast(addr); + RefField field(obj); + Heap::GetHeap().SetGCReason(GC_REASON_YOUNG); BaseObject* resultObj = copyBarrier->ReadStringTableStaticRef(field); - ASSERT_TRUE(resultObj == nullptr); + ASSERT_TRUE(resultObj != nullptr); } HWTEST_F_L0(CopyBarrierTest, ReadStruct_TEST1) @@ -186,15 +201,19 @@ HWTEST_F_L0(CopyBarrierTest, ReadStruct_TEST1) HeapAddress addr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); BaseObject* obj = reinterpret_cast(addr); - constexpr size_t size = 16; - uint8_t srcBuffer[size] = {}; + HeapAddress src = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); + BaseObject* srcObj = reinterpret_cast(src); + srcObj->SetForwardState(BaseStateWord::ForwardState::FORWARDING); + + constexpr size_t size = sizeof(BaseObject); uint8_t dstBuffer[size] = {}; - srcBuffer[0] = 1; - HeapAddress src = reinterpret_cast(srcBuffer); HeapAddress dst = reinterpret_cast(dstBuffer); + BaseObject* dstObj = reinterpret_cast(dst); + dstObj->SetForwardState(BaseStateWord::ForwardState::FORWARDED); + EXPECT_NE(dstObj->IsForwarding(), srcObj->IsForwarding()); + copyBarrier->ReadStruct(dst, obj, src, size); - EXPECT_EQ(dstBuffer[0], 1); - EXPECT_EQ(srcBuffer[0], dstBuffer[0]); + EXPECT_EQ(dstObj->IsForwarding(), srcObj->IsForwarding()); } HWTEST_F_L0(CopyBarrierTest, ReadStruct_TEST2) @@ -203,15 +222,19 @@ HWTEST_F_L0(CopyBarrierTest, ReadStruct_TEST2) auto copyBarrier = std::make_unique(collector); ASSERT_TRUE(copyBarrier != nullptr); - constexpr size_t size = 16; - uint8_t srcBuffer[size] = {}; + HeapAddress src = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); + BaseObject* srcObj = reinterpret_cast(src); + srcObj->SetForwardState(BaseStateWord::ForwardState::FORWARDING); + + constexpr size_t size = sizeof(BaseObject); uint8_t dstBuffer[size] = {}; - srcBuffer[0] = 1; - HeapAddress src = reinterpret_cast(srcBuffer); HeapAddress dst = reinterpret_cast(dstBuffer); + BaseObject* dstObj = reinterpret_cast(dst); + dstObj->SetForwardState(BaseStateWord::ForwardState::FORWARDED); + EXPECT_NE(dstObj->IsForwarding(), srcObj->IsForwarding()); + copyBarrier->ReadStruct(dst, nullptr, src, size); - EXPECT_EQ(dstBuffer[0], 1); - EXPECT_EQ(srcBuffer[0], dstBuffer[0]); + EXPECT_EQ(dstObj->IsForwarding(), srcObj->IsForwarding()); } HWTEST_F_L0(CopyBarrierTest, AtomicWriteRefField_TEST1) diff --git a/common_components/heap/w_collector/tests/enum_barrier_test.cpp b/common_components/heap/w_collector/tests/enum_barrier_test.cpp index 6044a2267940bd4e79c0b2229dbdf868b1155c4f..4a83549f06c0947ccb9b9787bd8804b35be7f40d 100755 --- a/common_components/heap/w_collector/tests/enum_barrier_test.cpp +++ b/common_components/heap/w_collector/tests/enum_barrier_test.cpp @@ -184,6 +184,28 @@ HWTEST_F_L0(EnumBarrierTest, WriteBarrier_TEST2) #endif } +HWTEST_F_L0(EnumBarrierTest, WriteBarrier_TEST3) +{ + MockCollector collector; + auto enumBarrier = std::make_unique(collector); + ASSERT_TRUE(enumBarrier != nullptr); + +#ifndef ARK_USE_SATB_BARRIER + constexpr uint64_t TAG_BITS_SHIFT = 48; + constexpr uint64_t TAG_MARK = 0xFFFFULL << TAG_BITS_SHIFT; + constexpr uint64_t TAG_SPECIAL = 0x02ULL; + constexpr uint64_t TAG_BOOLEAN = 0x04ULL; + constexpr uint64_t TAG_HEAP_OBJECT_MASK = TAG_MARK | TAG_SPECIAL | TAG_BOOLEAN; + + HeapAddress addr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); + BaseObject* obj = reinterpret_cast(addr); + RefField<> field(obj); + Heap::GetHeap().SetGCReason(GC_REASON_YOUNG); + enumBarrier->WriteBarrier(obj, field, obj); + EXPECT_TRUE(obj != nullptr); +#endif +} + HWTEST_F_L0(EnumBarrierTest, ReadStruct_TEST1) { MockCollector collector; @@ -192,15 +214,15 @@ HWTEST_F_L0(EnumBarrierTest, ReadStruct_TEST1) HeapAddress addr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); BaseObject* obj = reinterpret_cast(addr); - constexpr size_t size = 16; - uint8_t srcBuffer[size] = {}; - uint8_t dstBuffer[size] = {}; - srcBuffer[0] = 1; - HeapAddress src = reinterpret_cast(srcBuffer); - HeapAddress dst = reinterpret_cast(dstBuffer); - enumBarrier->ReadStruct(dst, obj, src, size); - EXPECT_EQ(dstBuffer[0], 1); - EXPECT_EQ(srcBuffer[0], dstBuffer[0]); + HeapAddress src = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); + BaseObject* srcObj = reinterpret_cast(src); + srcObj->SetForwardState(BaseStateWord::ForwardState::FORWARDING); + HeapAddress dst = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); + BaseObject* dstObj = reinterpret_cast(dst); + dstObj->SetForwardState(BaseStateWord::ForwardState::FORWARDED); + EXPECT_NE(dstObj->IsForwarding(), srcObj->IsForwarding()); + enumBarrier->ReadStruct(dst, obj, src, sizeof(BaseObject)); + EXPECT_EQ(dstObj->IsForwarding(), srcObj->IsForwarding()); } HWTEST_F_L0(EnumBarrierTest, WriteStruct_TEST1) @@ -209,16 +231,17 @@ HWTEST_F_L0(EnumBarrierTest, WriteStruct_TEST1) auto enumBarrier = std::make_unique(collector); ASSERT_TRUE(enumBarrier != nullptr); - auto objPtr = std::make_unique(); - constexpr size_t size = 16; - auto srcBuffer = std::make_unique(size); - auto dstBuffer = std::make_unique(size); - srcBuffer[0] = 1; - HeapAddress src = reinterpret_cast(srcBuffer.get()); - HeapAddress dst = reinterpret_cast(dstBuffer.get()); - enumBarrier->WriteStruct(objPtr.get(), dst, size, src, size); - EXPECT_EQ(dstBuffer[0], 1); - EXPECT_EQ(srcBuffer[0], dstBuffer[0]); + HeapAddress addr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); + BaseObject* obj = reinterpret_cast(addr); + HeapAddress src = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); + BaseObject* srcObj = reinterpret_cast(src); + srcObj->SetForwardState(BaseStateWord::ForwardState::FORWARDING); + HeapAddress dst = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); + BaseObject* dstObj = reinterpret_cast(dst); + dstObj->SetForwardState(BaseStateWord::ForwardState::FORWARDED); + EXPECT_NE(dstObj->IsForwarding(), srcObj->IsForwarding()); + enumBarrier->WriteStruct(obj, dst, sizeof(BaseObject), src, sizeof(BaseObject)); + EXPECT_EQ(dstObj->IsForwarding(), srcObj->IsForwarding()); } HWTEST_F_L0(EnumBarrierTest, WriteStruct_TEST2) @@ -227,15 +250,15 @@ HWTEST_F_L0(EnumBarrierTest, WriteStruct_TEST2) auto enumBarrier = std::make_unique(collector); ASSERT_TRUE(enumBarrier != nullptr); - constexpr size_t size = 16; - auto srcBuffer = std::make_unique(size); - auto dstBuffer = std::make_unique(size); - srcBuffer[0] = 1; - HeapAddress src = reinterpret_cast(srcBuffer.get()); - HeapAddress dst = reinterpret_cast(dstBuffer.get()); - enumBarrier->WriteStruct(nullptr, dst, size, src, size); - EXPECT_EQ(dstBuffer[0], 1); - EXPECT_EQ(srcBuffer[0], dstBuffer[0]); + HeapAddress src = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); + BaseObject* srcObj = reinterpret_cast(src); + srcObj->SetForwardState(BaseStateWord::ForwardState::FORWARDING); + HeapAddress dst = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); + BaseObject* dstObj = reinterpret_cast(dst); + dstObj->SetForwardState(BaseStateWord::ForwardState::FORWARDED); + EXPECT_NE(dstObj->IsForwarding(), srcObj->IsForwarding()); + enumBarrier->WriteStruct(nullptr, dst, sizeof(BaseObject), src, sizeof(BaseObject)); + EXPECT_EQ(dstObj->IsForwarding(), srcObj->IsForwarding()); } HWTEST_F_L0(EnumBarrierTest, AtomicReadRefField_TEST1) diff --git a/common_components/heap/w_collector/tests/idle_barrier_test.cpp b/common_components/heap/w_collector/tests/idle_barrier_test.cpp index 8097de5ca05bc83ae68ede25c946bd34d1e70f44..daac3a733dd2471208b98beac47e6ba40b19a033 100755 --- a/common_components/heap/w_collector/tests/idle_barrier_test.cpp +++ b/common_components/heap/w_collector/tests/idle_barrier_test.cpp @@ -51,15 +51,15 @@ HWTEST_F_L0(IdleBarrierTest, ReadStruct_TEST0) HeapAddress addr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); BaseObject* obj = reinterpret_cast(addr); - constexpr size_t size = 16; - uint8_t srcBuffer[size] = {}; - uint8_t dstBuffer[size] = {}; - srcBuffer[0] = 1; - HeapAddress src = reinterpret_cast(srcBuffer); - HeapAddress dst = reinterpret_cast(dstBuffer); - idleBarrier->ReadStruct(dst, obj, src, size); - EXPECT_EQ(dstBuffer[0], 1); - EXPECT_EQ(srcBuffer[0], dstBuffer[0]); + HeapAddress src = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); + BaseObject* srcObj = reinterpret_cast(src); + srcObj->SetForwardState(BaseStateWord::ForwardState::FORWARDING); + HeapAddress dst = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); + BaseObject* dstObj = reinterpret_cast(dst); + dstObj->SetForwardState(BaseStateWord::ForwardState::FORWARDED); + EXPECT_NE(dstObj->IsForwarding(), srcObj->IsForwarding()); + idleBarrier->ReadStruct(dst, obj, src, sizeof(BaseObject)); + EXPECT_EQ(dstObj->IsForwarding(), srcObj->IsForwarding()); } HWTEST_F_L0(IdleBarrierTest, AtomicWriteRefField_TEST0) @@ -217,7 +217,43 @@ HWTEST_F_L0(IdleBarrierTest, WriteRefField_TEST0) EXPECT_EQ(oldField.GetFieldValue(), neWAddress); } -HWTEST_F_L0(IdleBarrierTest, WriteStruct_TEST0) +HWTEST_F_L0(IdleBarrierTest, WriteRefField_TEST1) +{ + MockCollector collector; + auto idleBarrier = std::make_unique(collector); + ASSERT_TRUE(idleBarrier != nullptr); + + constexpr uint64_t TAG_BITS_SHIFT = 48; + constexpr uint64_t TAG_MARK = 0xFFFFULL << TAG_BITS_SHIFT; + constexpr uint64_t TAG_SPECIAL = 0x02ULL; + constexpr uint64_t TAG_BOOLEAN = 0x04ULL; + constexpr uint64_t TAG_HEAP_OBJECT_MASK = TAG_MARK | TAG_SPECIAL | TAG_BOOLEAN; + + RefField<> field(MAddress(0)); + BaseObject *obj = reinterpret_cast(TAG_HEAP_OBJECT_MASK); + idleBarrier->WriteRefField(obj, field, obj); + EXPECT_TRUE(obj != nullptr); +} + +HWTEST_F_L0(IdleBarrierTest, WriteBarrier_TEST1) +{ + MockCollector collector; + auto idleBarrier = std::make_unique(collector); + ASSERT_TRUE(idleBarrier != nullptr); + + constexpr uint64_t TAG_BITS_SHIFT = 48; + constexpr uint64_t TAG_MARK = 0xFFFFULL << TAG_BITS_SHIFT; + constexpr uint64_t TAG_SPECIAL = 0x02ULL; + constexpr uint64_t TAG_BOOLEAN = 0x04ULL; + constexpr uint64_t TAG_HEAP_OBJECT_MASK = TAG_MARK | TAG_SPECIAL | TAG_BOOLEAN; + + RefField<> field(MAddress(0)); + BaseObject *obj = reinterpret_cast(TAG_HEAP_OBJECT_MASK); + idleBarrier->WriteBarrier(obj, field, obj); + EXPECT_TRUE(obj != nullptr); +} + +HWTEST_F_L0(IdleBarrierTest, WriteBarrier_TEST2) { MockCollector collector; auto idleBarrier = std::make_unique(collector); @@ -225,45 +261,46 @@ HWTEST_F_L0(IdleBarrierTest, WriteStruct_TEST0) HeapAddress addr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); BaseObject* obj = reinterpret_cast(addr); - constexpr size_t size = 16; - uint8_t srcBuffer[size] = {}; - uint8_t dstBuffer[size] = {}; - srcBuffer[0] = 1; - HeapAddress src = reinterpret_cast(srcBuffer); - HeapAddress dst = reinterpret_cast(dstBuffer); - - idleBarrier->WriteStruct(obj, dst, size, src, size); - EXPECT_EQ(dstBuffer[0], 1); - EXPECT_EQ(srcBuffer[0], dstBuffer[0]); + RefField<> field(obj); + idleBarrier->WriteBarrier(obj, field, obj); + EXPECT_TRUE(obj != nullptr); } -HWTEST_F_L0(IdleBarrierTest, CopyStructArray_TEST0) +HWTEST_F_L0(IdleBarrierTest, WriteStruct_TEST0) { MockCollector collector; auto idleBarrier = std::make_unique(collector); ASSERT_TRUE(idleBarrier != nullptr); - HeapAddress oldAddr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); - BaseObject* oldObj = reinterpret_cast(oldAddr); - constexpr size_t oldSize = 100; - oldObj->SetSizeForwarded(oldSize); - EXPECT_EQ(oldObj->GetSizeForwarded(), oldSize); - - HeapAddress newAddr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); - BaseObject* newObj = reinterpret_cast(newAddr); - constexpr size_t newSize = 200; - newObj->SetSizeForwarded(newSize); - EXPECT_EQ(newObj->GetSizeForwarded(), newSize); + HeapAddress addr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); + BaseObject* obj = reinterpret_cast(addr); + HeapAddress src = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); + BaseObject* srcObj = reinterpret_cast(src); + srcObj->SetForwardState(BaseStateWord::ForwardState::FORWARDING); + HeapAddress dst = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); + BaseObject* dstObj = reinterpret_cast(dst); + dstObj->SetForwardState(BaseStateWord::ForwardState::FORWARDED); + EXPECT_NE(dstObj->IsForwarding(), srcObj->IsForwarding()); + idleBarrier->WriteStruct(obj, dst, sizeof(BaseObject), src, sizeof(BaseObject)); + EXPECT_EQ(dstObj->IsForwarding(), srcObj->IsForwarding()); +} - constexpr size_t size = 16; - uint8_t srcBuffer[size] = {}; - uint8_t dstBuffer[size] = {}; - srcBuffer[0] = 1; - HeapAddress src = reinterpret_cast(srcBuffer); - HeapAddress dst = reinterpret_cast(dstBuffer); +HWTEST_F_L0(IdleBarrierTest, CopyStructArray_TEST0) +{ + MockCollector collector; + auto idleBarrier = std::make_unique(collector); + ASSERT_TRUE(idleBarrier != nullptr); - idleBarrier->CopyStructArray(oldObj, dst, size, newObj, src, size); - EXPECT_EQ(dstBuffer[0], 1); - EXPECT_EQ(srcBuffer[0], dstBuffer[0]); + HeapAddress addr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); + BaseObject* obj = reinterpret_cast(addr); + HeapAddress src = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); + BaseObject* srcObj = reinterpret_cast(src); + srcObj->SetForwardState(BaseStateWord::ForwardState::FORWARDING); + HeapAddress dst = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); + BaseObject* dstObj = reinterpret_cast(dst); + dstObj->SetForwardState(BaseStateWord::ForwardState::FORWARDED); + EXPECT_NE(dstObj->IsForwarding(), srcObj->IsForwarding()); + idleBarrier->CopyStructArray(obj, dst, sizeof(BaseObject), obj, src, sizeof(BaseObject)); + EXPECT_EQ(dstObj->IsForwarding(), srcObj->IsForwarding()); } } // namespace common::test diff --git a/common_components/heap/w_collector/tests/mock_barrier_collector.h b/common_components/heap/w_collector/tests/mock_barrier_collector.h index b5cfbfd44806e284712dd52277090db37c431aa0..1465518624739194a3071e32bdb6c5b3a1b4b801 100755 --- a/common_components/heap/w_collector/tests/mock_barrier_collector.h +++ b/common_components/heap/w_collector/tests/mock_barrier_collector.h @@ -74,18 +74,6 @@ public: void RemoveRawPointerObject(BaseObject*) override {} }; -class MockCollectorUnmovableTest : public MockCollector { -public: - bool IsFromObject(BaseObject*) const override - { - return true; - } - bool IsUnmovableFromObject(BaseObject*) const override - { - return true; - } -}; - class MockCollectorForwardTest : public MockCollector { public: bool IsFromObject(BaseObject*) const override @@ -94,6 +82,12 @@ public: } bool TryForwardRefField(BaseObject*, RefField<>&, BaseObject*&) const override { + static bool isForward = false; + if (!isForward) { + isForward = true; + return false; + } + return true; } }; diff --git a/common_components/heap/w_collector/tests/post_trace_barrier_test.cpp b/common_components/heap/w_collector/tests/post_trace_barrier_test.cpp index 2811fc77706aa5996ca4a4c568ae3533922b23c3..a450d45bc29c5598acb9c5ca23dec8e6fa6f724c 100755 --- a/common_components/heap/w_collector/tests/post_trace_barrier_test.cpp +++ b/common_components/heap/w_collector/tests/post_trace_barrier_test.cpp @@ -100,6 +100,54 @@ HWTEST_F_L0(PostTraceBarrierTest, ReadStringTableStaticRef_TEST1) ASSERT_TRUE(resultObj == nullptr); } +HWTEST_F_L0(PostTraceBarrierTest, ReadStringTableStaticRef_TEST2) +{ + MockCollector collector; + auto postTraceBarrier = std::make_unique(collector); + ASSERT_TRUE(postTraceBarrier != nullptr); + + HeapAddress addr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); + BaseObject* obj = reinterpret_cast(addr); + RegionDesc *regionInfo = RegionDesc::GetRegionDescAt(addr); + regionInfo->SetRegionAllocPtr(addr - 1); + regionInfo->SetTraceLine(); + RefField field(obj); + + BaseObject* resultObj = postTraceBarrier->ReadStringTableStaticRef(field); + ASSERT_TRUE(resultObj != nullptr); +} + +HWTEST_F_L0(PostTraceBarrierTest, ReadStringTableStaticRef_TEST3) +{ + MockCollector collector; + auto postTraceBarrier = std::make_unique(collector); + ASSERT_TRUE(postTraceBarrier != nullptr); + + HeapAddress addr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); + BaseObject* obj = reinterpret_cast(addr); + RegionDesc *regionInfo = RegionDesc::GetRegionDescAt(addr); + regionInfo->SetRegionType(RegionDesc::RegionType::ALIVE_REGION_FIRST); + RefField field(obj); + + BaseObject* resultObj = postTraceBarrier->ReadStringTableStaticRef(field); + ASSERT_TRUE(resultObj == nullptr); +} + +HWTEST_F_L0(PostTraceBarrierTest, ReadStringTableStaticRef_TEST4) +{ + MockCollector collector; + auto postTraceBarrier = std::make_unique(collector); + ASSERT_TRUE(postTraceBarrier != nullptr); + + HeapAddress addr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); + BaseObject* obj = reinterpret_cast(addr); + RefField field(obj); + + Heap::GetHeap().SetGCReason(GC_REASON_YOUNG); + BaseObject* resultObj = postTraceBarrier->ReadStringTableStaticRef(field); + ASSERT_TRUE(resultObj != nullptr); +} + HWTEST_F_L0(PostTraceBarrierTest, WriteRefField_TEST1) { MockCollector collector; @@ -120,6 +168,33 @@ HWTEST_F_L0(PostTraceBarrierTest, WriteRefField_TEST1) EXPECT_EQ(newAddr, reinterpret_cast(newObj)); } +HWTEST_F_L0(PostTraceBarrierTest, WriteBarrier_TEST1) +{ + MockCollector collector; + auto postTraceBarrier = std::make_unique(collector); + ASSERT_TRUE(postTraceBarrier != nullptr); + + HeapAddress addr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); + BaseObject* obj = reinterpret_cast(addr); + RefField<> field(obj); + postTraceBarrier->WriteBarrier(obj, field, obj); + EXPECT_TRUE(obj != nullptr); +} + +HWTEST_F_L0(PostTraceBarrierTest, WriteBarrier_TEST2) +{ + MockCollector collector; + auto postTraceBarrier = std::make_unique(collector); + ASSERT_TRUE(postTraceBarrier != nullptr); + + HeapAddress addr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); + BaseObject* obj = reinterpret_cast(addr); + RefField<> field(obj); + Heap::GetHeap().SetGCReason(GC_REASON_YOUNG); + postTraceBarrier->WriteBarrier(obj, field, obj); + EXPECT_TRUE(obj != nullptr); +} + HWTEST_F_L0(PostTraceBarrierTest, ReadStruct_TEST1) { MockCollector collector; @@ -128,15 +203,15 @@ HWTEST_F_L0(PostTraceBarrierTest, ReadStruct_TEST1) HeapAddress addr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); BaseObject* obj = reinterpret_cast(addr); - constexpr size_t size = 16; - uint8_t srcBuffer[size] = {}; - uint8_t dstBuffer[size] = {}; - srcBuffer[0] = 1; - HeapAddress src = reinterpret_cast(srcBuffer); - HeapAddress dst = reinterpret_cast(dstBuffer); - postTraceBarrier->ReadStruct(dst, obj, src, size); - EXPECT_EQ(dstBuffer[0], 1); - EXPECT_EQ(srcBuffer[0], dstBuffer[0]); + HeapAddress src = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); + BaseObject* srcObj = reinterpret_cast(src); + srcObj->SetForwardState(BaseStateWord::ForwardState::FORWARDING); + HeapAddress dst = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); + BaseObject* dstObj = reinterpret_cast(dst); + dstObj->SetForwardState(BaseStateWord::ForwardState::FORWARDED); + EXPECT_NE(dstObj->IsForwarding(), srcObj->IsForwarding()); + postTraceBarrier->ReadStruct(dst, obj, src, sizeof(BaseObject)); + EXPECT_EQ(dstObj->IsForwarding(), srcObj->IsForwarding()); } HWTEST_F_L0(PostTraceBarrierTest, WriteStruct_TEST1) @@ -147,15 +222,15 @@ HWTEST_F_L0(PostTraceBarrierTest, WriteStruct_TEST1) HeapAddress addr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); BaseObject* obj = reinterpret_cast(addr); - constexpr size_t size = 16; - uint8_t srcBuffer[size] = {}; - uint8_t dstBuffer[size] = {}; - srcBuffer[0] = 1; - HeapAddress src = reinterpret_cast(srcBuffer); - HeapAddress dst = reinterpret_cast(dstBuffer); - postTraceBarrier->WriteStruct(obj, dst, size, src, size); - EXPECT_EQ(dstBuffer[0], 1); - EXPECT_EQ(srcBuffer[0], dstBuffer[0]); + HeapAddress src = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); + BaseObject* srcObj = reinterpret_cast(src); + srcObj->SetForwardState(BaseStateWord::ForwardState::FORWARDING); + HeapAddress dst = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); + BaseObject* dstObj = reinterpret_cast(dst); + dstObj->SetForwardState(BaseStateWord::ForwardState::FORWARDED); + EXPECT_NE(dstObj->IsForwarding(), srcObj->IsForwarding()); + postTraceBarrier->WriteStruct(obj, dst, sizeof(BaseObject), src, sizeof(BaseObject)); + EXPECT_EQ(dstObj->IsForwarding(), srcObj->IsForwarding()); } HWTEST_F_L0(PostTraceBarrierTest, AtomicReadRefField_TEST1) @@ -325,27 +400,16 @@ HWTEST_F_L0(PostTraceBarrierTest, CopyStructArray_TEST1) auto postTraceBarrier = std::make_unique(collector); ASSERT_TRUE(postTraceBarrier != nullptr); - HeapAddress oldAddr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); - BaseObject* oldObj = reinterpret_cast(oldAddr); - constexpr size_t oldSize = 100; - oldObj->SetSizeForwarded(oldSize); - EXPECT_EQ(oldObj->GetSizeForwarded(), oldSize); - - HeapAddress newAddr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); - BaseObject* newObj = reinterpret_cast(newAddr); - constexpr size_t newSize = 200; - newObj->SetSizeForwarded(newSize); - EXPECT_EQ(newObj->GetSizeForwarded(), newSize); - - constexpr size_t size = 16; - uint8_t srcBuffer[size] = {}; - uint8_t dstBuffer[size] = {}; - srcBuffer[0] = 1; - HeapAddress src = reinterpret_cast(srcBuffer); - HeapAddress dst = reinterpret_cast(dstBuffer); - - postTraceBarrier->CopyStructArray(oldObj, dst, size, newObj, src, size); - EXPECT_EQ(dstBuffer[0], 1); - EXPECT_EQ(srcBuffer[0], dstBuffer[0]); + HeapAddress addr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); + BaseObject* obj = reinterpret_cast(addr); + HeapAddress src = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); + BaseObject* srcObj = reinterpret_cast(src); + srcObj->SetForwardState(BaseStateWord::ForwardState::FORWARDING); + HeapAddress dst = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); + BaseObject* dstObj = reinterpret_cast(dst); + dstObj->SetForwardState(BaseStateWord::ForwardState::FORWARDED); + EXPECT_NE(dstObj->IsForwarding(), srcObj->IsForwarding()); + postTraceBarrier->CopyStructArray(obj, dst, sizeof(BaseObject), obj, src, sizeof(BaseObject)); + EXPECT_EQ(dstObj->IsForwarding(), srcObj->IsForwarding()); } } // namespace common::test diff --git a/common_components/heap/w_collector/tests/preforward_barrier_test.cpp b/common_components/heap/w_collector/tests/preforward_barrier_test.cpp index 559e5938223d4cf059f23aec3b179d8832fc4a85..38f1d76bdc717fc3178556a2533034707688e0b0 100755 --- a/common_components/heap/w_collector/tests/preforward_barrier_test.cpp +++ b/common_components/heap/w_collector/tests/preforward_barrier_test.cpp @@ -92,22 +92,21 @@ HWTEST_F_L0(PreforwardBarrierTest, ReadRefField_TEST3) HWTEST_F_L0(PreforwardBarrierTest, ReadRefField_TEST4) { - MockCollectorUnmovableTest collector; + MockCollectorForwardTest collector; auto preforwardBarrier = std::make_unique(collector); ASSERT_TRUE(preforwardBarrier != nullptr); HeapAddress addr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); BaseObject* obj = reinterpret_cast(addr); - RefField field(obj); + RefField field(nullptr); BaseObject* resultObj = preforwardBarrier->ReadRefField(obj, field); - ASSERT_TRUE(resultObj != nullptr); - EXPECT_EQ(resultObj, obj); + ASSERT_TRUE(resultObj == nullptr); } HWTEST_F_L0(PreforwardBarrierTest, ReadRefField_TEST5) { - MockCollectorUnmovableTest collector; + MockCollectorForwardTest collector; auto preforwardBarrier = std::make_unique(collector); ASSERT_TRUE(preforwardBarrier != nullptr); @@ -117,15 +116,11 @@ HWTEST_F_L0(PreforwardBarrierTest, ReadRefField_TEST5) BaseObject* resultObj = preforwardBarrier->ReadRefField(obj, field); ASSERT_TRUE(resultObj != nullptr); - constexpr uint64_t TAG_WEAK = 0x01ULL; - BaseObject* newObj = reinterpret_cast(reinterpret_cast(obj) | TAG_WEAK); - EXPECT_EQ(resultObj, newObj); } - -HWTEST_F_L0(PreforwardBarrierTest, ReadRefField_TEST6) +HWTEST_F_L0(PreforwardBarrierTest, ReadStaticRef_TEST1) { - MockCollectorForwardTest collector; + MockCollector collector; auto preforwardBarrier = std::make_unique(collector); ASSERT_TRUE(preforwardBarrier != nullptr); @@ -133,25 +128,41 @@ HWTEST_F_L0(PreforwardBarrierTest, ReadRefField_TEST6) BaseObject* obj = reinterpret_cast(addr); RefField field(obj); - BaseObject* resultObj = preforwardBarrier->ReadRefField(obj, field); + BaseObject* resultObj = preforwardBarrier->ReadStaticRef(field); ASSERT_TRUE(resultObj != nullptr); + EXPECT_EQ(resultObj, obj); } -HWTEST_F_L0(PreforwardBarrierTest, ReadRefField_TEST7) +HWTEST_F_L0(PreforwardBarrierTest, ReadStringTableStaticRef_TEST1) { - MockCollectorForwardTest collector; + MockCollector collector; + auto preforwardBarrier = std::make_unique(collector); + ASSERT_TRUE(preforwardBarrier != nullptr); + + RefField field(nullptr); + + BaseObject* resultObj = preforwardBarrier->ReadStringTableStaticRef(field); + ASSERT_TRUE(resultObj == nullptr); +} + +HWTEST_F_L0(PreforwardBarrierTest, ReadStringTableStaticRef_TEST2) +{ + MockCollector collector; auto preforwardBarrier = std::make_unique(collector); ASSERT_TRUE(preforwardBarrier != nullptr); HeapAddress addr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); BaseObject* obj = reinterpret_cast(addr); - RefField field(obj, true); + RegionDesc *regionInfo = RegionDesc::GetRegionDescAt(addr); + regionInfo->SetRegionAllocPtr(addr - 1); + regionInfo->SetTraceLine(); + RefField field(obj); - BaseObject* resultObj = preforwardBarrier->ReadRefField(obj, field); + BaseObject* resultObj = preforwardBarrier->ReadStringTableStaticRef(field); ASSERT_TRUE(resultObj != nullptr); } -HWTEST_F_L0(PreforwardBarrierTest, ReadStaticRef_TEST1) +HWTEST_F_L0(PreforwardBarrierTest, ReadStringTableStaticRef_TEST3) { MockCollector collector; auto preforwardBarrier = std::make_unique(collector); @@ -159,23 +170,27 @@ HWTEST_F_L0(PreforwardBarrierTest, ReadStaticRef_TEST1) HeapAddress addr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); BaseObject* obj = reinterpret_cast(addr); + RegionDesc *regionInfo = RegionDesc::GetRegionDescAt(addr); + regionInfo->SetRegionType(RegionDesc::RegionType::ALIVE_REGION_FIRST); RefField field(obj); - BaseObject* resultObj = preforwardBarrier->ReadStaticRef(field); - ASSERT_TRUE(resultObj != nullptr); - EXPECT_EQ(resultObj, obj); + BaseObject* resultObj = preforwardBarrier->ReadStringTableStaticRef(field); + ASSERT_TRUE(resultObj == nullptr); } -HWTEST_F_L0(PreforwardBarrierTest, ReadStringTableStaticRef_TEST1) +HWTEST_F_L0(PreforwardBarrierTest, ReadStringTableStaticRef_TEST4) { MockCollector collector; auto preforwardBarrier = std::make_unique(collector); ASSERT_TRUE(preforwardBarrier != nullptr); - RefField field(nullptr); + HeapAddress addr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); + BaseObject* obj = reinterpret_cast(addr); + RefField field(obj); + Heap::GetHeap().SetGCReason(GC_REASON_YOUNG); BaseObject* resultObj = preforwardBarrier->ReadStringTableStaticRef(field); - ASSERT_TRUE(resultObj == nullptr); + ASSERT_TRUE(resultObj != nullptr); } HWTEST_F_L0(PreforwardBarrierTest, ReadStruct_TEST1) @@ -186,15 +201,15 @@ HWTEST_F_L0(PreforwardBarrierTest, ReadStruct_TEST1) HeapAddress addr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); BaseObject* obj = reinterpret_cast(addr); - constexpr size_t size = 16; - uint8_t srcBuffer[size] = {}; - uint8_t dstBuffer[size] = {}; - srcBuffer[0] = 1; - HeapAddress src = reinterpret_cast(srcBuffer); - HeapAddress dst = reinterpret_cast(dstBuffer); - preforwardBarrier->ReadStruct(dst, obj, src, size); - EXPECT_EQ(dstBuffer[0], 1); - EXPECT_EQ(srcBuffer[0], dstBuffer[0]); + HeapAddress src = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); + BaseObject* srcObj = reinterpret_cast(src); + srcObj->SetForwardState(BaseStateWord::ForwardState::FORWARDING); + HeapAddress dst = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); + BaseObject* dstObj = reinterpret_cast(dst); + dstObj->SetForwardState(BaseStateWord::ForwardState::FORWARDED); + EXPECT_NE(dstObj->IsForwarding(), srcObj->IsForwarding()); + preforwardBarrier->ReadStruct(dst, obj, src, sizeof(BaseObject)); + EXPECT_EQ(dstObj->IsForwarding(), srcObj->IsForwarding()); } HWTEST_F_L0(PreforwardBarrierTest, ReadStruct_TEST2) @@ -203,15 +218,15 @@ HWTEST_F_L0(PreforwardBarrierTest, ReadStruct_TEST2) auto preforwardBarrier = std::make_unique(collector); ASSERT_TRUE(preforwardBarrier != nullptr); - constexpr size_t size = 16; - uint8_t srcBuffer[size] = {}; - uint8_t dstBuffer[size] = {}; - srcBuffer[0] = 1; - HeapAddress src = reinterpret_cast(srcBuffer); - HeapAddress dst = reinterpret_cast(dstBuffer); - preforwardBarrier->ReadStruct(dst, nullptr, src, size); - EXPECT_EQ(dstBuffer[0], 1); - EXPECT_EQ(srcBuffer[0], dstBuffer[0]); + HeapAddress src = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); + BaseObject* srcObj = reinterpret_cast(src); + srcObj->SetForwardState(BaseStateWord::ForwardState::FORWARDING); + HeapAddress dst = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); + BaseObject* dstObj = reinterpret_cast(dst); + dstObj->SetForwardState(BaseStateWord::ForwardState::FORWARDED); + EXPECT_NE(dstObj->IsForwarding(), srcObj->IsForwarding()); + preforwardBarrier->ReadStruct(dst, nullptr, src, sizeof(BaseObject)); + EXPECT_EQ(dstObj->IsForwarding(), srcObj->IsForwarding()); } HWTEST_F_L0(PreforwardBarrierTest, AtomicReadRefField_TEST1) diff --git a/common_components/heap/w_collector/tests/remark_barrier_test.cpp b/common_components/heap/w_collector/tests/remark_barrier_test.cpp index e161a377570443a73aa85279b30e0d989ef00fae..41f61ec1f103886153e0929061b6ec139f6280db 100755 --- a/common_components/heap/w_collector/tests/remark_barrier_test.cpp +++ b/common_components/heap/w_collector/tests/remark_barrier_test.cpp @@ -97,6 +97,54 @@ HWTEST_F_L0(RemarkBarrierTest, ReadStringTableStaticRef_TEST1) ASSERT_TRUE(resultObj == nullptr); } +HWTEST_F_L0(RemarkBarrierTest, ReadStringTableStaticRef_TEST2) +{ + MockCollector collector; + auto remarkBarrier = std::make_unique(collector); + ASSERT_TRUE(remarkBarrier != nullptr); + + HeapAddress addr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); + BaseObject* obj = reinterpret_cast(addr); + RegionDesc *regionInfo = RegionDesc::GetRegionDescAt(addr); + regionInfo->SetRegionAllocPtr(addr - 1); + regionInfo->SetTraceLine(); + RefField field(obj); + + BaseObject* resultObj = remarkBarrier->ReadStringTableStaticRef(field); + ASSERT_TRUE(resultObj != nullptr); +} + +HWTEST_F_L0(RemarkBarrierTest, ReadStringTableStaticRef_TEST3) +{ + MockCollector collector; + auto remarkBarrier = std::make_unique(collector); + ASSERT_TRUE(remarkBarrier != nullptr); + + HeapAddress addr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); + BaseObject* obj = reinterpret_cast(addr); + RegionDesc *regionInfo = RegionDesc::GetRegionDescAt(addr); + regionInfo->SetRegionType(RegionDesc::RegionType::ALIVE_REGION_FIRST); + RefField field(obj); + + BaseObject* resultObj = remarkBarrier->ReadStringTableStaticRef(field); + ASSERT_TRUE(resultObj == nullptr); +} + +HWTEST_F_L0(RemarkBarrierTest, ReadStringTableStaticRef_TEST4) +{ + MockCollector collector; + auto remarkBarrier = std::make_unique(collector); + ASSERT_TRUE(remarkBarrier != nullptr); + + HeapAddress addr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); + BaseObject* obj = reinterpret_cast(addr); + RefField field(obj); + + Heap::GetHeap().SetGCReason(GC_REASON_YOUNG); + BaseObject* resultObj = remarkBarrier->ReadStringTableStaticRef(field); + ASSERT_TRUE(resultObj != nullptr); +} + HWTEST_F_L0(RemarkBarrierTest, ReadStruct_TEST1) { MockCollector collector; @@ -105,15 +153,15 @@ HWTEST_F_L0(RemarkBarrierTest, ReadStruct_TEST1) HeapAddress addr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); BaseObject* obj = reinterpret_cast(addr); - constexpr size_t size = 16; - uint8_t srcBuffer[size] = {}; - uint8_t dstBuffer[size] = {}; - srcBuffer[0] = 1; - HeapAddress src = reinterpret_cast(srcBuffer); - HeapAddress dst = reinterpret_cast(dstBuffer); - remarkBarrier->ReadStruct(dst, obj, src, size); - EXPECT_EQ(dstBuffer[0], 1); - EXPECT_EQ(srcBuffer[0], dstBuffer[0]); + HeapAddress src = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); + BaseObject* srcObj = reinterpret_cast(src); + srcObj->SetForwardState(BaseStateWord::ForwardState::FORWARDING); + HeapAddress dst = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); + BaseObject* dstObj = reinterpret_cast(dst); + dstObj->SetForwardState(BaseStateWord::ForwardState::FORWARDED); + EXPECT_NE(dstObj->IsForwarding(), srcObj->IsForwarding()); + remarkBarrier->ReadStruct(dst, obj, src, sizeof(BaseObject)); + EXPECT_EQ(dstObj->IsForwarding(), srcObj->IsForwarding()); } HWTEST_F_L0(RemarkBarrierTest, WriteRefField_TEST1) @@ -221,22 +269,61 @@ HWTEST_F_L0(RemarkBarrierTest, WriteBarrier_TEST2) #endif } +HWTEST_F_L0(RemarkBarrierTest, WriteBarrier_TEST3) +{ + MockCollector collector; + auto remarkBarrier = std::make_unique(collector); + ASSERT_TRUE(remarkBarrier != nullptr); + +#ifndef ARK_USE_SATB_BARRIER + HeapAddress addr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); + BaseObject* obj = reinterpret_cast(addr); + RefField<> field(obj); + remarkBarrier->WriteBarrier(obj, field, obj); + EXPECT_TRUE(obj != nullptr); +#endif +} + HWTEST_F_L0(RemarkBarrierTest, WriteStruct_TEST1) { MockCollector collector; auto remarkBarrier = std::make_unique(collector); ASSERT_TRUE(remarkBarrier != nullptr); - auto objPtr = std::make_unique(); - constexpr size_t size = 16; - auto srcBuffer = std::make_unique(size); - auto dstBuffer = std::make_unique(size); - srcBuffer[0] = 1; - HeapAddress src = reinterpret_cast(srcBuffer.get()); - HeapAddress dst = reinterpret_cast(dstBuffer.get()); - remarkBarrier->WriteStruct(objPtr.get(), dst, size, src, size); - EXPECT_EQ(dstBuffer[0], 1); - EXPECT_EQ(srcBuffer[0], dstBuffer[0]); + HeapAddress addr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); + BaseObject* obj = reinterpret_cast(addr); + HeapAddress src = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); + BaseObject* srcObj = reinterpret_cast(src); + srcObj->SetForwardState(BaseStateWord::ForwardState::FORWARDING); + HeapAddress dst = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); + BaseObject* dstObj = reinterpret_cast(dst); + dstObj->SetForwardState(BaseStateWord::ForwardState::FORWARDED); + EXPECT_NE(dstObj->IsForwarding(), srcObj->IsForwarding()); + remarkBarrier->WriteStruct(obj, dst, sizeof(BaseObject), src, sizeof(BaseObject)); + EXPECT_EQ(dstObj->IsForwarding(), srcObj->IsForwarding()); +} + +HWTEST_F_L0(RemarkBarrierTest, WriteStruct_TEST2) +{ + MockCollector collector; + auto remarkBarrier = std::make_unique(collector); + ASSERT_TRUE(remarkBarrier != nullptr); + + HeapAddress addr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); + BaseObject* obj = reinterpret_cast(addr); + HeapAddress src = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); + BaseObject* srcObj = reinterpret_cast(src); + srcObj->SetForwardState(BaseStateWord::ForwardState::FORWARDING); + HeapAddress dst = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); + BaseObject* dstObj = reinterpret_cast(dst); + dstObj->SetForwardState(BaseStateWord::ForwardState::FORWARDED); + EXPECT_NE(dstObj->IsForwarding(), srcObj->IsForwarding()); + + auto mutator = ThreadLocal::GetMutator(); + ThreadLocal::SetMutator(nullptr); + remarkBarrier->WriteStruct(obj, dst, sizeof(BaseObject), src, sizeof(BaseObject)); + ThreadLocal::SetMutator(mutator); + EXPECT_EQ(dstObj->IsForwarding(), srcObj->IsForwarding()); } HWTEST_F_L0(RemarkBarrierTest, AtomicReadRefField_TEST1) diff --git a/common_components/heap/w_collector/tests/trace_barrier_test.cpp b/common_components/heap/w_collector/tests/trace_barrier_test.cpp index 3037915f7303c810971cb41d31c86fbebd51e264..8a57038242f5e2bbe30b76ca56eb6ad238855bd8 100755 --- a/common_components/heap/w_collector/tests/trace_barrier_test.cpp +++ b/common_components/heap/w_collector/tests/trace_barrier_test.cpp @@ -93,15 +93,15 @@ HWTEST_F_L0(TraceBarrierTest, ReadStruct_TEST1) HeapAddress addr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); BaseObject* obj = reinterpret_cast(addr); - constexpr size_t size = 16; - uint8_t srcBuffer[size] = {}; - uint8_t dstBuffer[size] = {}; - srcBuffer[0] = 1; - HeapAddress src = reinterpret_cast(srcBuffer); - HeapAddress dst = reinterpret_cast(dstBuffer); - traceBarrier->ReadStruct(dst, obj, src, size); - EXPECT_EQ(dstBuffer[0], 1); - EXPECT_EQ(srcBuffer[0], dstBuffer[0]); + HeapAddress src = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); + BaseObject* srcObj = reinterpret_cast(src); + srcObj->SetForwardState(BaseStateWord::ForwardState::FORWARDING); + HeapAddress dst = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); + BaseObject* dstObj = reinterpret_cast(dst); + dstObj->SetForwardState(BaseStateWord::ForwardState::FORWARDED); + EXPECT_NE(dstObj->IsForwarding(), srcObj->IsForwarding()); + traceBarrier->ReadStruct(dst, obj, src, sizeof(BaseObject)); + EXPECT_EQ(dstObj->IsForwarding(), srcObj->IsForwarding()); } HWTEST_F_L0(TraceBarrierTest, WriteRefField_TEST1) @@ -208,6 +208,64 @@ HWTEST_F_L0(TraceBarrierTest, WriteBarrier_TEST2) #endif } +HWTEST_F_L0(TraceBarrierTest, WriteBarrier_TEST3) +{ + MockCollector collector; + auto traceBarrier = std::make_unique(collector); + ASSERT_TRUE(traceBarrier != nullptr); + +#ifndef ARK_USE_SATB_BARRIER + HeapAddress addr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); + BaseObject* obj = reinterpret_cast(addr); + RefField<> field(obj); + Heap::GetHeap().SetGCReason(GC_REASON_YOUNG); + traceBarrier->WriteBarrier(obj, field, obj); + EXPECT_TRUE(obj != nullptr); +#endif +} + +HWTEST_F_L0(TraceBarrierTest, WriteStruct_TEST1) +{ + MockCollector collector; + auto traceBarrier = std::make_unique(collector); + ASSERT_TRUE(traceBarrier != nullptr); + + HeapAddress addr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); + BaseObject* obj = reinterpret_cast(addr); + HeapAddress src = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); + BaseObject* srcObj = reinterpret_cast(src); + srcObj->SetForwardState(BaseStateWord::ForwardState::FORWARDING); + HeapAddress dst = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); + BaseObject* dstObj = reinterpret_cast(dst); + dstObj->SetForwardState(BaseStateWord::ForwardState::FORWARDED); + EXPECT_NE(dstObj->IsForwarding(), srcObj->IsForwarding()); + traceBarrier->WriteStruct(obj, dst, sizeof(BaseObject), src, sizeof(BaseObject)); + EXPECT_EQ(dstObj->IsForwarding(), srcObj->IsForwarding()); +} + +HWTEST_F_L0(TraceBarrierTest, WriteStruct_TEST2) +{ + MockCollector collector; + auto traceBarrier = std::make_unique(collector); + ASSERT_TRUE(traceBarrier != nullptr); + + HeapAddress addr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); + BaseObject* obj = reinterpret_cast(addr); + HeapAddress src = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); + BaseObject* srcObj = reinterpret_cast(src); + srcObj->SetForwardState(BaseStateWord::ForwardState::FORWARDING); + HeapAddress dst = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); + BaseObject* dstObj = reinterpret_cast(dst); + dstObj->SetForwardState(BaseStateWord::ForwardState::FORWARDED); + EXPECT_NE(dstObj->IsForwarding(), srcObj->IsForwarding()); + + auto mutator = ThreadLocal::GetMutator(); + ThreadLocal::SetMutator(nullptr); + traceBarrier->WriteStruct(obj, dst, sizeof(BaseObject), src, sizeof(BaseObject)); + ThreadLocal::SetMutator(mutator); + EXPECT_EQ(dstObj->IsForwarding(), srcObj->IsForwarding()); +} + HWTEST_F_L0(TraceBarrierTest, AtomicReadRefField_TEST1) { MockCollector collector; diff --git a/common_components/heap/w_collector/tests/w_collector_test.cpp b/common_components/heap/w_collector/tests/w_collector_test.cpp index 21025740899869cd6b2fa1293b1a9c55c33fb6b8..d32216f13e7bf38cbe28b7d72ef1e5ede4d486f1 100644 --- a/common_components/heap/w_collector/tests/w_collector_test.cpp +++ b/common_components/heap/w_collector/tests/w_collector_test.cpp @@ -16,6 +16,7 @@ #include "common_components/tests/test_helper.h" #include "common_components/heap/w_collector/w_collector.h" +#include "common_components/heap/w_collector/w_collector.cpp" #include "common_components/heap/collector/collector_proxy.h" #include "common_components/heap/heap_manager.h" #include "common_components/heap/allocator/region_desc.h" @@ -25,7 +26,7 @@ using namespace common; namespace common::test { using SuspensionType = MutatorBase::SuspensionType; -class WCollectorTest : public BaseTestWithScope { +class WCollectorTest : public common::test::BaseTestWithScope { protected: static void SetUpTestCase() { @@ -127,8 +128,9 @@ void FlipTest() EXPECT_FALSE(mutatorManager.WorldStopped()); EXPECT_TRUE(stwCallbackExecuted); }; - STWParam stwParam{"flip-test"}; - mutatorManager.FlipMutators(stwParam, stwTest, &mutatorTest); + STWParam param; + param.stwReason = "flip-test"; + mutatorManager.FlipMutators(param, stwTest, &mutatorTest); } HWTEST_F_L0(WCollectorTest, FlipTest) @@ -136,4 +138,388 @@ HWTEST_F_L0(WCollectorTest, FlipTest) std::thread t1(FlipTest); t1.join(); } + +HWTEST_F_L0(WCollectorTest, IsUnmovableFromObject_ReturnsFalseForNullptr) +{ + std::unique_ptr wcollector = GetWCollector(); + ASSERT_TRUE(wcollector != nullptr); + + BaseObject* obj = nullptr; + EXPECT_FALSE(wcollector->IsUnmovableFromObject(obj)); +} + +class TestableWCollector : public WCollector { +public: + using WCollector::ForwardObject; + + explicit TestableWCollector(Allocator& allocator, CollectorResources& resources) + : WCollector(allocator, resources), currentGCPhase_(GCPhase::GC_PHASE_COPY) {} + + void SetCurrentGCPhaseForTest(GCPhase phase) + { + currentGCPhase_ = phase; + } + + GCPhase GetCurrentGCPhaseForTest() const + { + return currentGCPhase_; + } + +private: + GCPhase currentGCPhase_; +}; + + +class DummyObject : public BaseObject { +public: + const common::TypeInfo* GetTypeInfo() const { return nullptr; } + size_t GetSize() const { return sizeof(DummyObject); } + + void SetClass(uintptr_t cls) + { + stateWord_.StoreStateWord(static_cast(cls)); + } + +private: + class BaseStateWord { + public: + using StateWordType = uint64_t; + + void StoreStateWord(StateWordType word) + { + stateWord_ = word; + } + + StateWordType LoadStateWord() const + { + return stateWord_; + } + + private: + StateWordType stateWord_{0}; + }; + + BaseStateWord stateWord_; +}; + +HWTEST_F_L0(WCollectorTest, ForwardObject_WithUnmovedObject_ReturnsSameAddress) +{ + std::unique_ptr wcollector = GetWCollector(); + ASSERT_TRUE(wcollector != nullptr); + + TestableWCollector* testableCollector = reinterpret_cast(wcollector.get()); + + testableCollector->SetCurrentGCPhaseForTest(GCPhase::GC_PHASE_COPY); + EXPECT_EQ(testableCollector->GetCurrentGCPhaseForTest(), GCPhase::GC_PHASE_COPY); +} + +HWTEST_F_L0(WCollectorTest, TraceRefField_TEST1) +{ + constexpr uint64_t TAG_BITS_SHIFT = 48; + constexpr uint64_t TAG_MARK = 0xFFFFULL << TAG_BITS_SHIFT; + constexpr uint64_t TAG_SPECIAL = 0x02ULL; + constexpr uint64_t TAG_BOOLEAN = 0x04ULL; + constexpr uint64_t TAG_HEAP_OBJECT_MASK = TAG_MARK | TAG_SPECIAL | TAG_BOOLEAN; + HeapAddress addr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); + BaseObject *obj = reinterpret_cast(addr | TAG_HEAP_OBJECT_MASK); + RefField<> field(obj); + + MarkStack workStack; + WeakStack weakStack; + TraceRefField(nullptr, field, workStack, weakStack, GCReason::GC_REASON_YOUNG); + EXPECT_FALSE(Heap::IsTaggedObject(field.GetFieldValue())); +} + +HWTEST_F_L0(WCollectorTest, TraceRefField_TEST2) +{ + HeapAddress addr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); + RegionDesc* region = RegionDesc::GetRegionDescAt(addr); + region->SetRegionType(RegionDesc::RegionType::ALIVE_REGION_FIRST); + BaseObject* obj = reinterpret_cast(addr); + RefField field(obj); + + MarkStack workStack; + WeakStack weakStack; + TraceRefField(nullptr, field, workStack, weakStack, GCReason::GC_REASON_APPSPAWN); + EXPECT_FALSE(region->IsInOldSpace()); + workStack.pop_back(); +} + +HWTEST_F_L0(WCollectorTest, TraceRefField_TEST3) +{ + HeapAddress addr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); + RegionDesc* region = RegionDesc::GetRegionDescAt(addr); + region->SetRegionType(RegionDesc::RegionType::OLD_REGION); + BaseObject* obj = reinterpret_cast(addr); + RefField field(obj); + + MarkStack workStack; + WeakStack weakStack; + TraceRefField(nullptr, field, workStack, weakStack, GCReason::GC_REASON_APPSPAWN); + EXPECT_TRUE(region->IsInOldSpace()); + workStack.pop_back(); +} + +HWTEST_F_L0(WCollectorTest, TraceRefField_TEST4) +{ + HeapAddress addr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); + RegionDesc* region = RegionDesc::GetRegionDescAt(addr); + region->SetRegionType(RegionDesc::RegionType::ALIVE_REGION_FIRST); + BaseObject* obj = reinterpret_cast(addr); + RefField field(obj); + + MarkStack workStack; + WeakStack weakStack; + TraceRefField(nullptr, field, workStack, weakStack, GCReason::GC_REASON_YOUNG); + EXPECT_FALSE(region->IsInOldSpace()); + workStack.pop_back(); +} + +HWTEST_F_L0(WCollectorTest, TraceRefField_TEST5) +{ + HeapAddress addr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); + RegionDesc* region = RegionDesc::GetRegionDescAt(addr); + region->SetRegionType(RegionDesc::RegionType::OLD_REGION); + BaseObject* obj = reinterpret_cast(addr); + RefField field(obj); + + MarkStack workStack; + WeakStack weakStack; + TraceRefField(nullptr, field, workStack, weakStack, GCReason::GC_REASON_YOUNG); + EXPECT_TRUE(region->IsInOldSpace()); +} + +HWTEST_F_L0(WCollectorTest, TraceRefField_TEST6) +{ + HeapAddress addr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); + RegionDesc* region = RegionDesc::GetRegionDescAt(addr); + region->SetRegionAllocPtr(addr - 1); + region->SetTraceLine(); + BaseObject* obj = reinterpret_cast(addr); + RefField field(obj); + + MarkStack workStack; + TraceRefField(obj, obj, field, workStack, region); + EXPECT_TRUE(region->IsNewObjectSinceTrace(obj)); +} + +class TestCreateTraceWCollector : public TraceCollector { +public: + using TraceCollector::SetGCReason; + explicit TestCreateTraceWCollector(Allocator& allocator, CollectorResources& resources) + : TraceCollector(allocator, resources) {} + BaseObject* ForwardObject(BaseObject*) override { return nullptr; } + bool IsFromObject(BaseObject*) const override { return false; } + bool IsUnmovableFromObject(BaseObject*) const override { return false; } + BaseObject* FindToVersion(BaseObject* obj) const override { return nullptr; } + bool TryUpdateRefField(BaseObject*, RefField<>&, BaseObject*&) const override { return false; } + bool TryForwardRefField(BaseObject*, RefField<>&, BaseObject*&) const override { return false; } + bool TryUntagRefField(BaseObject*, RefField<>&, BaseObject*&) const override { return false; } + RefField<> GetAndTryTagRefField(BaseObject*) const override { return RefField<>(nullptr); } + bool IsOldPointer(RefField<>&) const override { return false; } + void AddRawPointerObject(BaseObject*) override {} + void RemoveRawPointerObject(BaseObject*) override {} + bool MarkObject(BaseObject* obj) const override { return false; } + void TraceObjectRefFields(BaseObject *obj, TraceRefFieldVisitor *data) override {} + BaseObject* CopyObjectAfterExclusive(BaseObject* obj) override { return nullptr; } + void DoGarbageCollection() override {} + bool IsCurrentPointer(RefField<>&) const override { return false; } + TraceRefFieldVisitor CreateTraceObjectRefFieldsVisitor(WorkStack *workStack, WeakStack *weakStack) override + { + return TraceRefFieldVisitor(); + } +}; + +HWTEST_F_L0(WCollectorTest, CreateTraceObjectRefFieldsVisitor_TEST1) +{ + std::unique_ptr wcollector = GetWCollector(); + ASSERT_TRUE(wcollector != nullptr); + + MarkStack workStack; + WeakStack weakStack; + TestCreateTraceWCollector* collector = reinterpret_cast(wcollector.get()); + collector->SetGCReason(GCReason::GC_REASON_YOUNG); + auto visitor = wcollector->CreateTraceObjectRefFieldsVisitor(&workStack, &weakStack); + EXPECT_TRUE(visitor.GetRefFieldVisitor() != nullptr); +} + +HWTEST_F_L0(WCollectorTest, FixRefField_TEST1) +{ + std::unique_ptr wcollector = GetWCollector(); + ASSERT_TRUE(wcollector != nullptr); + + constexpr uint64_t TAG_BITS_SHIFT = 48; + constexpr uint64_t TAG_MARK = 0xFFFFULL << TAG_BITS_SHIFT; + constexpr uint64_t TAG_SPECIAL = 0x02ULL; + constexpr uint64_t TAG_BOOLEAN = 0x04ULL; + constexpr uint64_t TAG_HEAP_OBJECT_MASK = TAG_MARK | TAG_SPECIAL | TAG_BOOLEAN; + HeapAddress addr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); + BaseObject *obj = reinterpret_cast(addr | TAG_HEAP_OBJECT_MASK); + RefField<> field(obj); + wcollector->FixRefField(obj, field); + EXPECT_FALSE(Heap::IsTaggedObject(field.GetFieldValue())); +} + +HWTEST_F_L0(WCollectorTest, FixRefField_TEST2) +{ + std::unique_ptr wcollector = GetWCollector(); + ASSERT_TRUE(wcollector != nullptr); + + BaseObject* obj = reinterpret_cast(0); + RefField<> field(obj); + wcollector->FixRefField(obj, field); + EXPECT_FALSE(Heap::IsHeapAddress(obj)); +} + +class TestStaticObject : public BaseObjectOperatorInterfaces { +public: + size_t GetSize(const BaseObject *object) const override { return 0; } + bool IsValidObject(const BaseObject *object) const override { return false; } + void ForEachRefField(const BaseObject *object, const RefFieldVisitor &visitor) const override {} + void SetForwardingPointerAfterExclusive(BaseObject *object, BaseObject *fwdPtr) override {} + BaseObject *GetForwardingPointer(const BaseObject *object) const override + { + return const_cast(object); + } +}; + +HWTEST_F_L0(WCollectorTest, ForwardUpdateRawRef_TEST1) +{ + std::unique_ptr wcollector = GetWCollector(); + ASSERT_TRUE(wcollector != nullptr); + + HeapAddress addr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); + RegionDesc* region = RegionDesc::GetRegionDescAt(addr); + region->SetRegionType(RegionDesc::RegionType::FROM_REGION); + Mutator::GetMutator()->SetMutatorPhase(GCPhase::GC_PHASE_PRECOPY); + BaseObject* obj = reinterpret_cast(addr); + EXPECT_FALSE(obj->IsForwarded()); + obj->SetForwardState(BaseStateWord::ForwardState::FORWARDED); + obj->SetLanguageType(LanguageType::STATIC); + EXPECT_TRUE(obj->IsForwarded()); + TestStaticObject staticObject; + obj->RegisterStatic(&staticObject); + + ObjectRef root; + root.object = obj; + auto ret = wcollector->ForwardUpdateRawRef(root); + EXPECT_TRUE(wcollector->IsFromObject(obj)); + EXPECT_EQ(ret, obj); +} + +class TestForwardNullObject : public TestStaticObject { +public: + BaseObject *GetForwardingPointer(const BaseObject *object) const override { return nullptr; } +}; + +HWTEST_F_L0(WCollectorTest, ForwardObject_TEST1) +{ + std::unique_ptr wcollector = GetWCollector(); + ASSERT_TRUE(wcollector != nullptr); + + HeapAddress addr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); + RegionDesc* region = RegionDesc::GetRegionDescAt(addr); + region->SetRegionType(RegionDesc::RegionType::FROM_REGION); + Mutator::GetMutator()->SetMutatorPhase(GCPhase::GC_PHASE_PRECOPY); + BaseObject* obj = reinterpret_cast(addr); + EXPECT_FALSE(obj->IsForwarded()); + obj->SetForwardState(BaseStateWord::ForwardState::FORWARDED); + obj->SetLanguageType(LanguageType::STATIC); + EXPECT_TRUE(obj->IsForwarded()); + TestForwardNullObject staticObject; + obj->RegisterStatic(&staticObject); + + auto ret = wcollector->ForwardObject(obj); + EXPECT_EQ(ret, obj); +} + +HWTEST_F_L0(WCollectorTest, CopyObjectImpl_TEST1) +{ + std::unique_ptr wcollector = GetWCollector(); + ASSERT_TRUE(wcollector != nullptr); + + HeapAddress addr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); + RegionDesc* region = RegionDesc::GetRegionDescAt(addr); + region->SetRegionType(RegionDesc::RegionType::FROM_REGION); + Mutator::GetMutator()->SetMutatorPhase(GCPhase::GC_PHASE_PRECOPY); + BaseObject* obj = reinterpret_cast(addr); + EXPECT_FALSE(obj->IsForwarded()); + obj->SetForwardState(BaseStateWord::ForwardState::FORWARDED); + obj->SetLanguageType(LanguageType::STATIC); + EXPECT_TRUE(obj->IsForwarded()); + TestForwardNullObject staticObject; + obj->RegisterStatic(&staticObject); + + auto ret = wcollector->CopyObjectImpl(obj); + EXPECT_TRUE(ret == nullptr); +} + +HWTEST_F_L0(WCollectorTest, TryUpdateRefFieldImpl_TEST1) +{ + std::unique_ptr wcollector = GetWCollector(); + ASSERT_TRUE(wcollector != nullptr); + + RefField<> field(nullptr); + BaseObject* obj = nullptr; + bool ret = wcollector->TryUpdateRefField(nullptr, field, obj); + EXPECT_FALSE(ret); +} + +HWTEST_F_L0(WCollectorTest, TryUpdateRefFieldImpl_TEST2) +{ + std::unique_ptr wcollector = GetWCollector(); + ASSERT_TRUE(wcollector != nullptr); + + HeapAddress addr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); + RegionDesc* region = RegionDesc::GetRegionDescAt(addr); + region->SetRegionType(RegionDesc::RegionType::FROM_REGION); + BaseObject* obj = reinterpret_cast(addr); + RefField field(obj); + bool ret = wcollector->TryUpdateRefField(nullptr, field, obj); + EXPECT_FALSE(ret); +} + +HWTEST_F_L0(WCollectorTest, TryUpdateRefFieldImpl_TEST3) +{ + std::unique_ptr wcollector = GetWCollector(); + ASSERT_TRUE(wcollector != nullptr); + + HeapAddress addr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); + RegionDesc* region = RegionDesc::GetRegionDescAt(addr); + region->SetRegionType(RegionDesc::RegionType::FROM_REGION); + Mutator::GetMutator()->SetMutatorPhase(GCPhase::GC_PHASE_PRECOPY); + BaseObject* obj = reinterpret_cast(addr); + EXPECT_FALSE(obj->IsForwarded()); + obj->SetForwardState(BaseStateWord::ForwardState::FORWARDED); + obj->SetLanguageType(LanguageType::STATIC); + EXPECT_TRUE(obj->IsForwarded()); + TestForwardNullObject staticObject; + obj->RegisterStatic(&staticObject); + + RefField field(obj); + bool ret = wcollector->TryForwardRefField(nullptr, field, obj); + EXPECT_FALSE(ret); +} + +HWTEST_F_L0(WCollectorTest, TryUpdateRefFieldImpl_TEST4) +{ + std::unique_ptr wcollector = GetWCollector(); + ASSERT_TRUE(wcollector != nullptr); + + HeapAddress addr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); + RegionDesc* region = RegionDesc::GetRegionDescAt(addr); + region->SetRegionType(RegionDesc::RegionType::FROM_REGION); + Mutator::GetMutator()->SetMutatorPhase(GCPhase::GC_PHASE_PRECOPY); + BaseObject* obj = reinterpret_cast(addr); + EXPECT_FALSE(obj->IsForwarded()); + obj->SetForwardState(BaseStateWord::ForwardState::FORWARDED); + obj->SetLanguageType(LanguageType::STATIC); + EXPECT_TRUE(obj->IsForwarded()); + TestStaticObject staticObject; + obj->RegisterStatic(&staticObject); + + RefField field(obj); + bool ret = wcollector->TryForwardRefField(nullptr, field, obj); + EXPECT_TRUE(ret); +} } // namespace common::test diff --git a/common_components/heap/w_collector/w_collector.h b/common_components/heap/w_collector/w_collector.h index c2727f87756ad2c61a905187406105a476fc2ccd..9613a4eb3a7c8e58584e16835d17efff5764b0ec 100755 --- a/common_components/heap/w_collector/w_collector.h +++ b/common_components/heap/w_collector/w_collector.h @@ -49,7 +49,7 @@ enum class GCMode: uint8_t { STW = 2 }; -class WCollector final : public TraceCollector { +class WCollector : public TraceCollector { public: explicit WCollector(Allocator& allocator, CollectorResources& resources) : TraceCollector(allocator, resources), fwdTable_(reinterpret_cast(allocator)) diff --git a/common_components/log/tests/log_test.cpp b/common_components/log/tests/log_test.cpp index e41af1f5b83c3bd9835e8f400704bbf209fcdc0d..269e1fe2e1a65d5a788b9550e3f2005a2c49bbb6 100644 --- a/common_components/log/tests/log_test.cpp +++ b/common_components/log/tests/log_test.cpp @@ -55,6 +55,11 @@ HWTEST_F_L0(LogTest, ConvertFromRuntime_Default_ReturnsDebug) { Level result = Log::ConvertFromRuntime(static_cast(999)); EXPECT_EQ(result, Level::DEBUG); } + +HWTEST_F_L0(LogTest, PrettyOrderMathNano) { + std::string result = PrettyOrderMathNano(1000000000000, "s"); + EXPECT_EQ(result, "1000s"); +} } namespace common { diff --git a/common_components/mutator/tests/BUILD.gn b/common_components/mutator/tests/BUILD.gn index 442f3c15abc184ea51473ab9318871c1cf0c895c..af57be74e8f378cd085cd35255b40b9c42ecb5b5 100755 --- a/common_components/mutator/tests/BUILD.gn +++ b/common_components/mutator/tests/BUILD.gn @@ -38,6 +38,29 @@ host_unittest_action("Mutator_Manager_Test") { ] } +host_unittest_action("Mutator_Test") { + module_out_path = module_output_path + + sources = [ + # test file + "mutator_test.cpp", + ] + + configs = [ + "//arkcompiler/ets_runtime/common_components:common_components_test_config", + "//arkcompiler/ets_runtime:icu_path_test_config", + ] + + deps = [ "//arkcompiler/ets_runtime/common_components:libark_common_components_test" ] + + # hiviewdfx libraries + external_deps = [ + "icu:shared_icui18n", + "icu:shared_icuuc", + "runtime_core:libarkassembler_static", + ] +} + host_unittest_action("Satb_Buffer_Test") { module_out_path = module_output_path @@ -61,12 +84,38 @@ host_unittest_action("Satb_Buffer_Test") { ] } +host_unittest_action("Thread_Local_Test") { + module_out_path = module_output_path + + sources = [ + # test file + "thread_local_test.cpp", + ] + + configs = [ + "//arkcompiler/ets_runtime/common_components:common_components_test_config", + "//arkcompiler/ets_runtime:icu_path_test_config", + ] + + deps = [ "//arkcompiler/ets_runtime/common_components:libark_common_components_test" ] + + # hiviewdfx libraries + external_deps = [ + "icu:shared_icui18n", + "icu:shared_icuuc", + "zlib:libz", + ] +} + group("unittest") { testonly = true # deps file deps = [ ":Mutator_Manager_Test", + ":Mutator_Test", + ":Satb_Buffer_Test", + ":Thread_Local_Test", ] } @@ -76,5 +125,8 @@ group("host_unittest") { # deps file deps = [ ":Mutator_Manager_TestAction", + ":Mutator_TestAction", + ":Satb_Buffer_TestAction", + ":Thread_Local_TestAction", ] } diff --git a/common_components/mutator/tests/mutator_manager_test.cpp b/common_components/mutator/tests/mutator_manager_test.cpp index 87a1649f9575c53c2b573045f68f429f363db7a6..7b5ebc0712226d86ce8cdfc09f3b17a49ddc8fd3 100755 --- a/common_components/mutator/tests/mutator_manager_test.cpp +++ b/common_components/mutator/tests/mutator_manager_test.cpp @@ -27,6 +27,16 @@ protected: void TearDown() override {} }; +HWTEST_F_L0(MutatorManagerTest, BindMutatorOnly_Test1) +{ + MutatorManager *managerPtr = new MutatorManager(); + Mutator mutator; + managerPtr->UnbindMutatorOnly(); + bool res = managerPtr->BindMutatorOnly(&mutator); + ASSERT_TRUE(res); + delete managerPtr; +} + HWTEST_F_L0(MutatorManagerTest, IsRuntimeThread_Test1) { ThreadLocalData* localData = ThreadLocal::GetThreadLocalData(); @@ -78,17 +88,6 @@ HWTEST_F_L0(MutatorManagerTest, CreateMutator_Test1) delete localData->mutator; } -HWTEST_F_L0(MutatorManagerTest, TransitMutatorToExit_Test1) -{ - ThreadLocalData* localData = ThreadLocal::GetThreadLocalData(); - localData->mutator = new Mutator(); - MutatorManager *managerPtr = new MutatorManager(); - localData->mutator->SetInSaferegion(MutatorBase::SaferegionState::SAFE_REGION_FALSE); - managerPtr->TransitMutatorToExit(); - delete managerPtr; - delete localData->mutator; -} - HWTEST_F_L0(MutatorManagerTest, CreateRuntimeMutato_Test1) { ThreadType threadType = ThreadType::FP_THREAD; @@ -100,14 +99,6 @@ HWTEST_F_L0(MutatorManagerTest, CreateRuntimeMutato_Test1) EXPECT_TRUE(ptr != nullptr); } -HWTEST_F_L0(MutatorManagerTest, DumpMutators_Test1) -{ - MutatorManager *managerPtr = new MutatorManager(); - uint32_t timeoutTimes = 1; - managerPtr->DumpMutators(timeoutTimes); - delete managerPtr; -} - HWTEST_F_L0(MutatorManagerTest, DestroyRuntimeMutator_Test1) { ThreadType threadType = ThreadType::GC_THREAD; @@ -143,7 +134,7 @@ HWTEST_F_L0(MutatorManagerTest, AcquireMutatorManagementWLockForCpuProfile_Test1 MutatorManager::Instance().AcquireMutatorManagementWLockForCpuProfile(); }); while (!threadStarted) {} - std::this_thread::sleep_for(std::chrono::milliseconds(1)); + std::this_thread::sleep_for(std::chrono::milliseconds(3)); MutatorManager::Instance().MutatorManagementWUnlock(); testthread.join(); EXPECT_FALSE(MutatorManager::Instance().TryAcquireMutatorManagementRLock()); @@ -179,7 +170,7 @@ HWTEST_F_L0(MutatorManagerTest, EnsureCpuProfileFinish_Test3) ThreadType threadType = ThreadType::GC_THREAD; Mutator* ptr = MutatorManager::Instance().CreateRuntimeMutator(threadType); std::thread testthread([&]() { - std::this_thread::sleep_for(std::chrono::milliseconds(1)); + std::this_thread::sleep_for(std::chrono::milliseconds(3)); ptr->SetCpuProfileState(MutatorBase::CpuProfileState::NO_CPUPROFILE); }); ptr->SetCpuProfileState(MutatorBase::CpuProfileState::IN_CPUPROFILING); @@ -196,7 +187,7 @@ HWTEST_F_L0(MutatorManagerTest, EnsureCpuProfileFinish_Test4) ThreadType threadType = ThreadType::GC_THREAD; Mutator* ptr = MutatorManager::Instance().CreateRuntimeMutator(threadType); std::thread testthread([&]() { - std::this_thread::sleep_for(std::chrono::milliseconds(1)); + std::this_thread::sleep_for(std::chrono::milliseconds(3)); ptr->SetInSaferegion(MutatorBase::SaferegionState::SAFE_REGION_TRUE); ptr->SetCpuProfileState(MutatorBase::CpuProfileState::NO_CPUPROFILE); }); @@ -214,7 +205,7 @@ HWTEST_F_L0(MutatorManagerTest, EnsureCpuProfileFinish_Test5) ThreadType threadType = ThreadType::GC_THREAD; Mutator* ptr = MutatorManager::Instance().CreateRuntimeMutator(threadType); std::thread testthread([&]() { - std::this_thread::sleep_for(std::chrono::milliseconds(1)); + std::this_thread::sleep_for(std::chrono::milliseconds(3)); ptr->SetInSaferegion(MutatorBase::SaferegionState::SAFE_REGION_TRUE); }); diff --git a/common_components/mutator/tests/mutator_test.cpp b/common_components/mutator/tests/mutator_test.cpp new file mode 100755 index 0000000000000000000000000000000000000000..3a4aa66ea6a9dfe7a210d054aa732e51da3a20bd --- /dev/null +++ b/common_components/mutator/tests/mutator_test.cpp @@ -0,0 +1,256 @@ +/* + * Copyright (c) 2025 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 "common_components/heap/heap_manager.h" +#include "common_components/mutator/mutator.h" +#include "common_components/mutator/mutator_manager.h" +#include "common_components/tests/test_helper.h" +#include "common_interfaces/base_runtime.h" +#include "common_interfaces/objects/base_object.h" + +using namespace common; + +namespace common::test { +class TestMutator : public Mutator { +public: + using Mutator::VisitRawObjects; +}; +class MutatorTest : public BaseTestWithScope { +protected: + static void SetUpTestCase() + { + BaseRuntime::GetInstance()->Init(); + } + static void TearDownTestCase() {} +}; + +HWTEST_F_L0(MutatorTest, GetThreadLocalData_Test1) +{ + ThreadLocalData *ret = GetThreadLocalData(); + ASSERT_TRUE(ret != nullptr); +} + +HWTEST_F_L0(MutatorTest, TransitionGCPhase_Test1) +{ + MutatorBase mutatorBase; + mutatorBase.Init(); + bool ret = mutatorBase.TransitionGCPhase(false); + EXPECT_TRUE(ret == true); + + MutatorBase::SuspensionType flag = MutatorBase::SuspensionType::SUSPENSION_FOR_GC_PHASE; + mutatorBase.SetSuspensionFlag(flag); + + ret = mutatorBase.TransitionGCPhase(false); + EXPECT_TRUE(ret == true); + + ret = mutatorBase.TransitionGCPhase(true); + EXPECT_TRUE(ret == true); + ret = mutatorBase.TransitionGCPhase(false); + EXPECT_TRUE(ret == true); +} + +HWTEST_F_L0(MutatorTest, HandleSuspensionRequest_Test0) +{ + MutatorBase mutatorBase; + mutatorBase.Init(); + + MutatorBase::SuspensionType flag = MutatorBase::SuspensionType::SUSPENSION_FOR_STW; + mutatorBase.SetSuspensionFlag(flag); + + mutatorBase.HandleSuspensionRequest(); + EXPECT_TRUE(mutatorBase.InSaferegion() == false); + + flag = MutatorBase::SuspensionType::SUSPENSION_FOR_GC_PHASE; + mutatorBase.SetSuspensionFlag(flag); + mutatorBase.HandleSuspensionRequest(); + EXPECT_TRUE(mutatorBase.InSaferegion() == false); +} + +HWTEST_F_L0(MutatorTest, SuspendForStw_Test0) +{ + MutatorBase mutatorBase; + mutatorBase.Init(); + + mutatorBase.SuspendForStw(); + EXPECT_TRUE(mutatorBase.InSaferegion() == false); +} + +HWTEST_F_L0(MutatorTest, VisitRawObjects_Nullptr_NoCall) +{ + TestMutator mutator; + mutator.Init(); + mutator.PushRawObject(nullptr); + + bool called = false; + RootVisitor func = [&called](const ObjectRef& obj) { + called = true; + }; + mutator.VisitRawObjects(func); + EXPECT_FALSE(called); +} + +HWTEST_F_L0(MutatorTest, VisitRawObjects_NonNull_Call) +{ + TestMutator mutator; + mutator.Init(); + BaseObject mockObj; + mutator.PushRawObject(&mockObj); + + bool called = false; + RootVisitor func = [&called, &mockObj](const ObjectRef& obj) { + called = true; + EXPECT_EQ(obj.object, &mockObj); + }; + + mutator.VisitRawObjects(func); + EXPECT_TRUE(called); +} + +HWTEST_F_L0(MutatorTest, HandleSuspensionRequest_Test1) +{ + MutatorBase mutatorBase; + mutatorBase.Init(); + MutatorBase::SuspensionType flag = MutatorBase::SuspensionType::SUSPENSION_FOR_STW; + mutatorBase.SetSuspensionFlag(flag); + flag = MutatorBase::SuspensionType::SUSPENSION_FOR_GC_PHASE; + mutatorBase.SetSuspensionFlag(flag); + mutatorBase.HandleSuspensionRequest(); + EXPECT_FALSE(mutatorBase.InSaferegion()); + EXPECT_TRUE(mutatorBase.FinishedTransition()); +} + +HWTEST_F_L0(MutatorTest, HandleSuspensionRequest_Test2) +{ + MutatorBase mutatorBase; + mutatorBase.Init(); + MutatorBase::SuspensionType flag = MutatorBase::SuspensionType::SUSPENSION_FOR_CPU_PROFILE; + mutatorBase.SetSuspensionFlag(flag); + mutatorBase.SetCpuProfileState(MutatorBase::CpuProfileState::FINISH_CPUPROFILE); + std::thread t([&]() { + std::this_thread::sleep_for(std::chrono::nanoseconds(1)); + mutatorBase.ClearSuspensionFlag(MutatorBase::SUSPENSION_FOR_CPU_PROFILE); + }); + mutatorBase.HandleSuspensionRequest(); + t.join(); + EXPECT_FALSE(mutatorBase.InSaferegion()); + EXPECT_TRUE(mutatorBase.FinishedCpuProfile()); +} + +HWTEST_F_L0(MutatorTest, HandleSuspensionRequest_Test3) +{ + MutatorBase mutatorBase; + mutatorBase.Init(); + mutatorBase.SetSuspensionFlag(MutatorBase::SUSPENSION_FOR_STW); + mutatorBase.SetSuspensionFlag(MutatorBase::SUSPENSION_FOR_CPU_PROFILE); + mutatorBase.SetCpuProfileState(MutatorBase::CpuProfileState::FINISH_CPUPROFILE); + std::thread t([&]() { + std::this_thread::sleep_for(std::chrono::nanoseconds(1)); + mutatorBase.ClearSuspensionFlag(MutatorBase::SUSPENSION_FOR_CPU_PROFILE); + }); + mutatorBase.HandleSuspensionRequest(); + t.join(); + EXPECT_FALSE(mutatorBase.InSaferegion()); + EXPECT_TRUE(mutatorBase.FinishedCpuProfile()); +} + +HWTEST_F_L0(MutatorTest, HandleGCPhase_SatbNodeNotNull) +{ + Mutator* mutator = MutatorManager::Instance().CreateRuntimeMutator(ThreadType::ARK_PROCESSOR); + HeapAddress addr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); + BaseObject *mockObj = reinterpret_cast(addr); + new (mockObj) BaseObject(); + mutator->RememberObjectInSatbBuffer(mockObj); + EXPECT_NE(mutator->GetSatbBufferNode(), nullptr); + MutatorBase* base = static_cast(mutator->GetMutatorBasePtr()); + base->TransitionToGCPhaseExclusive(GCPhase::GC_PHASE_REMARK_SATB); + EXPECT_EQ(mutator->GetSatbBufferNode(), nullptr); + MutatorManager::Instance().DestroyRuntimeMutator(ThreadType::ARK_PROCESSOR); +} + +HWTEST_F_L0(MutatorTest, HandleSuspensionRequest_LeaveSaferegion1) +{ + MutatorBase mutatorBase; + mutatorBase.Init(); + mutatorBase.IncObserver(); + std::thread t([&]() { + std::this_thread::sleep_for(std::chrono::nanoseconds(1)); + mutatorBase.DecObserver(); + }); + mutatorBase.HandleSuspensionRequest(); + t.join(); + EXPECT_FALSE(mutatorBase.InSaferegion()); +} + +HWTEST_F_L0(MutatorTest, HandleSuspensionRequest_LeaveSaferegion2) +{ + MutatorBase mutatorBase; + mutatorBase.Init(); + MutatorBase::SuspensionType flag = MutatorBase::SuspensionType::SUSPENSION_FOR_CPU_PROFILE; + mutatorBase.SetSuspensionFlag(flag); + mutatorBase.SetCpuProfileState(MutatorBase::CpuProfileState::FINISH_CPUPROFILE); + mutatorBase.IncObserver(); + std::thread t([&]() { + std::this_thread::sleep_for(std::chrono::nanoseconds(1)); + mutatorBase.ClearSuspensionFlag(MutatorBase::SUSPENSION_FOR_CPU_PROFILE); + mutatorBase.DecObserver(); + }); + mutatorBase.HandleSuspensionRequest(); + t.join(); + EXPECT_FALSE(mutatorBase.InSaferegion()); +} + +HWTEST_F_L0(MutatorTest, HandleSuspensionRequest_Test4) +{ + MutatorBase mutatorBase; + mutatorBase.Init(); + mutatorBase.SetSuspensionFlag(MutatorBase::SUSPENSION_FOR_STW); + EXPECT_NO_FATAL_FAILURE(mutatorBase.HandleSuspensionRequest()); +} + +HWTEST_F_L0(MutatorTest, HandleSuspensionRequest_Test5) +{ + MutatorBase mutatorBase; + mutatorBase.Init(); + mutatorBase.SetSuspensionFlag(MutatorBase::SUSPENSION_FOR_GC_PHASE); + EXPECT_NO_FATAL_FAILURE(mutatorBase.HandleSuspensionRequest()); +} + +HWTEST_F_L0(MutatorTest, TransitionToGCPhaseExclusive_TestEnum) +{ + MutatorBase mutatorBase; + mutatorBase.Init(); + + GCPhase phase = GCPhase::GC_PHASE_ENUM; + EXPECT_NO_FATAL_FAILURE(mutatorBase.TransitionToGCPhaseExclusive(phase)); +} + +HWTEST_F_L0(MutatorTest, TransitionToGCPhaseExclusive_TestPrecopy) +{ + MutatorBase mutatorBase; + mutatorBase.Init(); + + GCPhase phase = GCPhase::GC_PHASE_PRECOPY; + EXPECT_NO_FATAL_FAILURE(mutatorBase.TransitionToGCPhaseExclusive(phase)); +} + +HWTEST_F_L0(MutatorTest, TransitionToGCPhaseExclusive_TestIdle) +{ + MutatorBase mutatorBase; + mutatorBase.Init(); + + GCPhase phase = GCPhase::GC_PHASE_IDLE; + EXPECT_NO_FATAL_FAILURE(mutatorBase.TransitionToGCPhaseExclusive(phase)); +} +} // namespace common::test diff --git a/common_components/mutator/tests/satb_buffer_test.cpp b/common_components/mutator/tests/satb_buffer_test.cpp index 41d209d5b72d7ed1e6faeee2a26cdcf40cea7d79..feec5b10277ecfe6fe68dde373f8a329cdd06025 100755 --- a/common_components/mutator/tests/satb_buffer_test.cpp +++ b/common_components/mutator/tests/satb_buffer_test.cpp @@ -13,79 +13,51 @@ * limitations under the License. */ -#include "common_components/common_runtime/base_runtime_param.h" #include "common_components/heap/allocator/region_desc.h" #include "common_components/heap/allocator/region_space.h" #include "common_components/mutator/satb_buffer.h" #include "common_components/tests/test_helper.h" -#include +#include "common_interfaces/base_runtime.h" using namespace common; namespace common::test { class SatbBufferTest : public BaseTestWithScope { -protected: - void* regionMemory_; - size_t totalUnits_ = 1024; - size_t heapSize_; - Mutator* mutator_ = nullptr; - - static void SetUpTestCase() - { - BaseRuntime::GetInstance()->Init(); - } - - static void TearDownTestCase() - { - BaseRuntime::GetInstance()->Fini(); - } - void SetUp() override { - heapSize_ = totalUnits_ * RegionDesc::UNIT_SIZE; - size_t allocSize = heapSize_ + totalUnits_ * sizeof(RegionDesc); - regionMemory_ = malloc(allocSize); - ASSERT_NE(regionMemory_, nullptr); - uintptr_t unitInfoStart = reinterpret_cast(regionMemory_); - RegionSpace& theAllocator = reinterpret_cast(Heap::GetHeap().GetAllocator()); - RegionManager& manager = theAllocator.GetRegionManager(); - manager.Initialize(totalUnits_, reinterpret_cast(regionMemory_)); - size_t metadataSize = totalUnits_ * sizeof(RegionDesc); - uintptr_t heapStartAddress = unitInfoStart + metadataSize; - RegionDesc::Initialize(totalUnits_, unitInfoStart, heapStartAddress); - mutator_ = Mutator::NewMutator(); - ASSERT_NE(mutator_, nullptr); - mutator_->InitTid(); - ThreadLocal::GetThreadLocalData()->mutator = mutator_; + BaseRuntime::GetInstance()->Init(); + holder_ = ThreadHolder::CreateAndRegisterNewThreadHolder(nullptr); + scope_ = new ThreadHolder::TryBindMutatorScope(holder_); } void TearDown() override { - if (mutator_) { - delete mutator_; - mutator_ = nullptr; - } - if (regionMemory_) { - free(regionMemory_); - regionMemory_ = nullptr; + if (scope_ != nullptr) { + delete scope_; + scope_ = nullptr; } + + BaseRuntime::GetInstance()->Fini(); } + + ThreadHolder *holder_ {nullptr}; + ThreadHolder::TryBindMutatorScope *scope_ {nullptr}; }; -HWTEST_F_L0(SatbBufferTest, NullptrReturnsFalse)\ +HWTEST_F_L0(SatbBufferTest, NullptrReturnsFalse) { EXPECT_FALSE(SatbBuffer::Instance().ShouldEnqueue(nullptr)); } HWTEST_F_L0(SatbBufferTest, IsYoungSpaceObject1) { - ASSERT_NE(mutator_, nullptr); - mutator_->SetMutatorPhase(GCPhase::GC_PHASE_ENUM); + auto* mutator = common::Mutator::GetMutator(); + mutator->SetMutatorPhase(GCPhase::GC_PHASE_ENUM); RegionSpace& theAllocator = reinterpret_cast(Heap::GetHeap().GetAllocator()); uintptr_t addr = theAllocator.AllocOldRegion(); ASSERT_NE(addr, 0); RegionDesc* region = RegionDesc::GetRegionDescAt(addr); - region->SetRegionType(RegionDesc::RegionType::FREE_REGION); + region->SetRegionType(RegionDesc::RegionType::ALIVE_REGION_FIRST); Heap::GetHeap().SetGCReason(GC_REASON_YOUNG); BaseObject* obj = reinterpret_cast(addr); @@ -94,8 +66,8 @@ HWTEST_F_L0(SatbBufferTest, IsYoungSpaceObject1) HWTEST_F_L0(SatbBufferTest, IsYoungSpaceObject2) { - ASSERT_NE(mutator_, nullptr); - mutator_->SetMutatorPhase(GCPhase::GC_PHASE_ENUM); + auto* mutator = common::Mutator::GetMutator(); + mutator->SetMutatorPhase(GCPhase::GC_PHASE_ENUM); RegionSpace& theAllocator = reinterpret_cast(Heap::GetHeap().GetAllocator()); uintptr_t addr = theAllocator.AllocOldRegion(); ASSERT_NE(addr, 0); @@ -109,8 +81,8 @@ HWTEST_F_L0(SatbBufferTest, IsYoungSpaceObject2) HWTEST_F_L0(SatbBufferTest, IsYoungSpaceObject3) { - ASSERT_NE(mutator_, nullptr); - mutator_->SetMutatorPhase(GCPhase::GC_PHASE_ENUM); + auto* mutator = common::Mutator::GetMutator(); + mutator->SetMutatorPhase(GCPhase::GC_PHASE_ENUM); RegionSpace& theAllocator = reinterpret_cast(Heap::GetHeap().GetAllocator()); uintptr_t addr = theAllocator.AllocOldRegion(); ASSERT_NE(addr, 0); @@ -124,15 +96,84 @@ HWTEST_F_L0(SatbBufferTest, IsYoungSpaceObject3) HWTEST_F_L0(SatbBufferTest, IsYoungSpaceObject4) { - ASSERT_NE(mutator_, nullptr); - mutator_->SetMutatorPhase(GCPhase::GC_PHASE_ENUM); + auto* mutator = common::Mutator::GetMutator(); + mutator->SetMutatorPhase(GCPhase::GC_PHASE_ENUM); RegionSpace& theAllocator = reinterpret_cast(Heap::GetHeap().GetAllocator()); uintptr_t addr = theAllocator.AllocOldRegion(); ASSERT_NE(addr, 0); RegionDesc* region = RegionDesc::GetRegionDescAt(addr); - region->SetRegionType(RegionDesc::RegionType::FREE_REGION); + region->SetRegionType(RegionDesc::RegionType::ALIVE_REGION_FIRST); Heap::GetHeap().SetGCReason(GC_REASON_HEU); BaseObject* obj = reinterpret_cast(addr); EXPECT_FALSE(SatbBuffer::Instance().ShouldEnqueue(obj)); } + +HWTEST_F_L0(SatbBufferTest, IsMarkedObject) +{ + RegionSpace& theAllocator = reinterpret_cast(Heap::GetHeap().GetAllocator()); + uintptr_t addr = theAllocator.AllocOldRegion(); + ASSERT_NE(addr, 0U); + BaseObject* obj = reinterpret_cast(addr); + Heap::GetHeap().SetGCReason(GC_REASON_HEU); + + RegionDesc* region = RegionDesc::GetRegionDescAt(reinterpret_cast(obj)); + region->SetMarkedRegionFlag(1); + + size_t offset = region->GetAddressOffset(reinterpret_cast(obj)); + RegionBitmap* markBitmap = region->GetOrAllocMarkBitmap(); + markBitmap->MarkBits(offset); + + bool result = SatbBuffer::Instance().ShouldEnqueue(obj); + EXPECT_FALSE(result); +} + +void ClearMarkBit(RegionBitmap* bitmap, size_t offset) +{ + uintptr_t* bits = *reinterpret_cast(bitmap); + + size_t wordIndex = offset / (sizeof(uintptr_t) * 8); + size_t bitIndex = offset % (sizeof(uintptr_t) * 8); + + uintptr_t mask = ~(static_cast(1) << bitIndex); + + uintptr_t* addr = const_cast(bits + wordIndex); + uintptr_t oldVal; + uintptr_t newVal; + + do { + oldVal = __atomic_load_n(addr, __ATOMIC_ACQUIRE); + newVal = oldVal & mask; + if (oldVal == newVal) { + return; + } + } while (!__atomic_compare_exchange_n(addr, &oldVal, newVal, false, __ATOMIC_ACQ_REL, __ATOMIC_ACQUIRE)); +} + +HWTEST_F_L0(SatbBufferTest, EnqueueObject) +{ + RegionSpace& theAllocator = reinterpret_cast(Heap::GetHeap().GetAllocator()); + uintptr_t addr = theAllocator.AllocOldRegion(); + ASSERT_NE(addr, 0U); + + uintptr_t objAddress = addr + 0x100; + BaseObject* obj = reinterpret_cast(objAddress); + Heap::GetHeap().SetGCReason(GC_REASON_HEU); + + RegionDesc* region = RegionDesc::GetRegionDescAt(reinterpret_cast(obj)); + region->SetRegionType(RegionDesc::RegionType::FROM_REGION); + region->SetTraceLine(); + region->SetMarkedRegionFlag(0); + RegionBitmap* markBitmap = region->GetMarkBitmap(); + size_t offset = region->GetAddressOffset(reinterpret_cast(obj)); + if (markBitmap != nullptr) { + ClearMarkBit(markBitmap, offset); + } + + region->SetEnqueuedRegionFlag(1); + RegionBitmap* enqueueBitmap = region->GetOrAllocEnqueueBitmap(); + enqueueBitmap->MarkBits(offset); + + bool result = SatbBuffer::Instance().ShouldEnqueue(obj); + EXPECT_FALSE(result); +} } // namespace common::test diff --git a/common_components/mutator/tests/thread_local_test.cpp b/common_components/mutator/tests/thread_local_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8ee8f5cbf99655b60e50f1742febd376fd28d4a1 --- /dev/null +++ b/common_components/mutator/tests/thread_local_test.cpp @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2025 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 "common_components/mutator/thread_local.h" +#include "common_components/tests/test_helper.h" + +namespace common { + +class ThreadLocalTest : public common::test::BaseTestWithScope { +protected: + void SetUp() override {} + void TearDown() override {} +}; + +HWTEST_F_L0(ThreadLocalTest, GetThreadLocalData_ReturnsNonNull) { + ThreadLocalData* data = ThreadLocal::GetThreadLocalData(); + EXPECT_NE(data, nullptr); +} +} \ No newline at end of file diff --git a/common_components/objects/tests/BUILD.gn b/common_components/objects/tests/BUILD.gn index e6d55ad7b48d80040124371fc808a3d69a2713c7..f6d6aef286200b053228b029438d395273870142 100755 --- a/common_components/objects/tests/BUILD.gn +++ b/common_components/objects/tests/BUILD.gn @@ -40,12 +40,64 @@ host_unittest_action("Base_String_Test") { ] } +host_unittest_action("Base_String_Table_Test") { + module_out_path = module_output_path + + sources = [ + # test file + "base_string_table_test.cpp", + ] + + configs = [ + "//arkcompiler/ets_runtime/common_components:common_components_test_config", + "//arkcompiler/ets_runtime:icu_path_test_config", + ] + + deps = [ "//arkcompiler/ets_runtime/common_components:libark_common_components_test" ] + + # hiviewdfx libraries + external_deps = [ + "icu:shared_icui18n", + "icu:shared_icuuc", + "zlib:libz", + ] +} + +host_unittest_action("Composite_Base_Class_Test") { + module_out_path = module_output_path + + sources = [ + # test file + "composite_base_class_test.cpp", + "//arkcompiler/ets_runtime/common_components/objects/base_string.cpp", + "//arkcompiler/ets_runtime/common_components/base/utf_helper.cpp", + "base_string_table_test.cpp", + ] + + configs = [ + "//arkcompiler/ets_runtime/common_components:common_components_test_config", + "//arkcompiler/ets_runtime:icu_path_test_config", + ] + + deps = [ "//arkcompiler/ets_runtime/common_components:libark_common_components_test" ] + + # hiviewdfx libraries + external_deps = [ + "icu:shared_icui18n", + "icu:shared_icuuc", + "zlib:libz", + ] +} + + group("unittest") { testonly = true # deps file deps = [ ":Base_String_Test", + ":Base_String_Table_Test", + ":Composite_Base_Class_Test", ] } @@ -55,5 +107,7 @@ group("host_unittest") { # deps file deps = [ ":Base_String_TestAction", + ":Base_String_Table_TestAction", + ":Composite_Base_Class_TestAction", ] } diff --git a/common_components/objects/tests/base_string_table_test.cpp b/common_components/objects/tests/base_string_table_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..aa165055f1b83685b0faa961d924c2bb8705d48a --- /dev/null +++ b/common_components/objects/tests/base_string_table_test.cpp @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2025 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 "common_components/tests/test_helper.h" +#include "common_interfaces/objects/base_string_table.h" +#include "common_components/objects/string_table_internal.h" +#include "common_interfaces/thread/mutator_base.h" +#include "common_interfaces/objects/base_string.h" +#include "common_interfaces/thread/thread_holder.h" +#include "common_interfaces/base_runtime.h" +#include "common_interfaces/heap/heap_allocator.h" +#include "common_interfaces/objects/string/base_string-inl2.h" + + +namespace common { + +struct DummyMutator : public MutatorBase { + explicit DummyMutator(LanguageType lang) : lang_(lang) {} + LanguageType lang_; +}; + +class BaseStringTableTest : public common::test::BaseTestWithScope { +protected: + using TableType = BaseStringTableInternal; + BaseRuntime* runtime_; + std::unique_ptr mutator_; + std::unique_ptr table_; + ThreadHolder* threadHolder_; + + void SetUp() override + { + mutator_ = std::make_unique(LanguageType::DYNAMIC); + threadHolder_ = new ThreadHolder(mutator_.get()); + + runtime_ = BaseRuntime::GetInstance(); + ASSERT_TRUE(runtime_ != nullptr); + + runtime_->Init(); + + table_ = std::make_unique(); + } + + void TearDown() override + { + table_.reset(); + + if (runtime_) { + runtime_->Fini(); + } + + mutator_.reset(); + threadHolder_ = nullptr; + } + + BaseString* CreateUtf8String(const char* utf8Data, uint32_t length, bool canBeCompress) + { + auto allocator = [](size_t size, CommonType type) -> BaseString* { + void* mem = reinterpret_cast(HeapAllocator::AllocateInOldOrHuge(size, LanguageType::DYNAMIC)); + if (mem == nullptr) { + return nullptr; + } + return reinterpret_cast(mem); + }; + + BaseString* str = BaseString::CreateFromUtf8(allocator, + reinterpret_cast(utf8Data), length, canBeCompress); + + if (str == nullptr) { + return nullptr; + } + return str; + } + + static ReadOnlyHandle MockHandleCreator(ThreadHolder* holder, BaseString* str) + { + uintptr_t handleValue = reinterpret_cast(str); + return ReadOnlyHandle(handleValue); + } +}; + +HWTEST_F_L0(BaseStringTableTest, SweepWeakRef) +{ + WeakRefFieldVisitor mockVisitor = [](RefField& field) { + return true; + }; + + table_->GetHashTrieMap().StartSweeping(); + table_->SweepWeakRef(mockVisitor); + table_->GetHashTrieMap().FinishSweeping(); + + EXPECT_TRUE(true); +} + +HWTEST_F_L0(BaseStringTableTest, CleanUp) +{ + table_->GetHashTrieMap().Clear(); + EXPECT_TRUE(true); +} + +} \ No newline at end of file diff --git a/common_components/objects/tests/base_string_test.cpp b/common_components/objects/tests/base_string_test.cpp index ae004c97c0017e4b38137c093070a14ab71618d5..495a30af2373d5ca1364719403757f43fced9725 100755 --- a/common_components/objects/tests/base_string_test.cpp +++ b/common_components/objects/tests/base_string_test.cpp @@ -14,6 +14,7 @@ */ #include "common_interfaces/objects/base_string.h" +#include "common_components/platform/string_hash.h" #include "common_components/tests/test_helper.h" using namespace common; @@ -22,6 +23,286 @@ namespace common::test { class BaseStringTest : public common::test::BaseTestWithScope { }; +HWTEST_F_L0(BaseStringTest, ComputeHashForData_TEST0) +{ + const uint8_t data[] = {'a', 'b', 'c'}; + size_t size = sizeof(data) / sizeof(data[0]); + uint32_t hashSeed = 0; + uint32_t expectedHash = hashSeed; + for (uint32_t i = 0; i < size; ++i) { + expectedHash = (expectedHash << static_cast(StringHash::HASH_SHIFT)) - expectedHash + data[i]; + } + + EXPECT_EQ(BaseString::ComputeHashForData(data, size, hashSeed), expectedHash); +} + +HWTEST_F_L0(BaseStringTest, ComputeHashForData_TEST1) +{ + std::vector largeData(1000, 'x'); + size_t size = largeData.size(); + uint32_t hashSeed = 0; + + uint32_t result = BaseString::ComputeHashForData(largeData.data(), size, hashSeed); + EXPECT_NE(result, 0); +} + +HWTEST_F_L0(BaseStringTest, ComputeHashcodeUtf8_TEST0) +{ + const uint8_t utf8Data[] = u8"hello"; + size_t utf8Len = sizeof(utf8Data) / sizeof(utf8Data[0]) - 1; + + uint32_t expectedHash = 0; + for (uint32_t i = 0; i < utf8Len; ++i) { + expectedHash = (expectedHash << static_cast(StringHash::HASH_SHIFT)) - expectedHash + utf8Data[i]; + } + + EXPECT_EQ(BaseString::ComputeHashcodeUtf8(utf8Data, utf8Len, true), expectedHash); +} + +HWTEST_F_L0(BaseStringTest, ComputeHashcodeUtf8_TEST1) +{ + const uint8_t utf8Data[] = u8"hello"; + size_t utf8Len = sizeof(utf8Data) / sizeof(utf8Data[0]) - 1; + + uint32_t expectedHash = 0; + for (uint32_t i = 0; i < utf8Len; ++i) { + expectedHash = (expectedHash << static_cast(StringHash::HASH_SHIFT)) - expectedHash + utf8Data[i]; + } + + EXPECT_EQ(BaseString::ComputeHashcodeUtf8(utf8Data, utf8Len, false), expectedHash); +} + +HWTEST_F_L0(BaseStringTest, IsASCIICharacter_TEST0) +{ + const uint16_t num = 0; + bool result = BaseString::IsASCIICharacter(num); + ASSERT_FALSE(result); +} + +HWTEST_F_L0(BaseStringTest, IsASCIICharacter_TEST1) +{ + const uint16_t num = 0x7f; + bool result = BaseString::IsASCIICharacter(num); + ASSERT_TRUE(result); +} + +HWTEST_F_L0(BaseStringTest, CanBeCompressed_TEST0) +{ + uint8_t data[] = {}; + EXPECT_TRUE(BaseString::CanBeCompressed(data, 0)); + + uint8_t data1[] = {1, 1, 1, 1, 0}; + ASSERT_FALSE(BaseString::CanBeCompressed(data1, 5)); + ASSERT_TRUE(BaseString::CanBeCompressed(data1, 2)); + + uint8_t data2[] = {'a', 'b', 'c', 'd'}; + ASSERT_TRUE(BaseString::CanBeCompressed(data2, 4)); + + uint8_t data3[] = {'a', '\0', 'c', 'd'}; + ASSERT_FALSE(BaseString::CanBeCompressed(data3, 4)); +} + +HWTEST_F_L0(BaseStringTest, CanBeCompressed_TEST1) +{ + uint16_t data[] = {}; + EXPECT_TRUE(BaseString::CanBeCompressed(data, 0)); + + uint16_t data1[] = {1, 1, 1, 1, 0}; + ASSERT_FALSE(BaseString::CanBeCompressed(data1, 5)); + ASSERT_TRUE(BaseString::CanBeCompressed(data1, 2)); + + uint16_t data2[] = {'a', 'b', 'c', 'd'}; + ASSERT_TRUE(BaseString::CanBeCompressed(data2, 4)); + + uint16_t data3[] = {'a', '\0', 'c', 'd'}; + ASSERT_FALSE(BaseString::CanBeCompressed(data3, 4)); +} + +HWTEST_F_L0(BaseStringTest, IndexOf_TEST0) +{ + const uint8_t lhs[] = {'a', 'b', 'c', 'd', 'e'}; + const uint8_t rhs[] = {'a', 'b', 'c'}; + Span lhsSp(lhs, 5); + Span rhsSp(rhs, 3); + + EXPECT_EQ(BaseString::IndexOf(lhsSp, rhsSp, 0, 4), 0); +} + +HWTEST_F_L0(BaseStringTest, IndexOf_TEST1) +{ + const uint8_t lhs[] = {'a', 'b', 'c', 'd', 'e'}; + const uint8_t rhs[] = {'c', 'd'}; + Span lhsSp(lhs, 5); + Span rhsSp(rhs, 2); + + EXPECT_EQ(BaseString::IndexOf(lhsSp, rhsSp, 0, 4), 2); +} + +HWTEST_F_L0(BaseStringTest, IndexOf_TEST2) +{ + const uint8_t lhs[] = {'a', 'b', 'c', 'd', 'e'}; + const uint8_t rhs[] = {'x', 'y', 'z'}; + Span lhsSp(lhs, 5); + Span rhsSp(rhs, 3); + + EXPECT_EQ(BaseString::IndexOf(lhsSp, rhsSp, 0, 4), -1); +} + +HWTEST_F_L0(BaseStringTest, IndexOf_TEST3) +{ + const uint8_t lhs[] = {'a', 'b', 'a', 'b', 'c'}; + const uint8_t rhs[] = {'a', 'b', 'c'}; + Span lhsSp(lhs, 5); + Span rhsSp(rhs, 3); + + EXPECT_EQ(BaseString::IndexOf(lhsSp, rhsSp, 0, 4), 2); +} + +HWTEST_F_L0(BaseStringTest, IndexOf_TEST4) +{ + const uint8_t lhs[] = {'a', 'b', 'c', 'd', 'e'}; + const uint8_t rhs[] = {'a', 'b', 'x'}; + Span lhsSp(lhs, 5); + Span rhsSp(rhs, 3); + + EXPECT_EQ(BaseString::IndexOf(lhsSp, rhsSp, 0, 4), -1); +} + +HWTEST_F_L0(BaseStringTest, CompareStringSpan_TEST0) +{ + const uint8_t lhs[] = {1, 2, 3}; + const uint8_t rhs[] = {1, 2, 3}; + Span lhsSp(lhs, 5); + Span rhsSp(rhs, 3); + EXPECT_EQ(CompareStringSpan(lhsSp, rhsSp, 3), 0); +} + +HWTEST_F_L0(BaseStringTest, CompareStringSpan_TEST1) +{ + const uint8_t lhs[] = {1, 2, 4}; + const uint8_t rhs[] = {1, 2, 3}; + Span lhsSp(lhs, 5); + Span rhsSp(rhs, 3); + EXPECT_EQ(CompareStringSpan(lhsSp, rhsSp, 3), 1); +} + +HWTEST_F_L0(BaseStringTest, IsSubStringAtSpan_TEST1) +{ + const uint8_t lhs[] = {'a', 'b', 'c'}; + const uint8_t rhs[] = {'x', 'y'}; + Span lhsSp(lhs, 3); + Span rhsSp(rhs, 2); + ASSERT_FALSE(IsSubStringAtSpan(lhsSp, rhsSp, 1)); +} + +HWTEST_F_L0(BaseStringTest, IsSubStringAtSpan_TEST2) +{ + const uint8_t lhs[] = {'a', 'b'}; + const uint8_t rhs[] = {'b'}; + Span lhsSp(lhs, 2); + Span rhsSp(rhs, 1); + ASSERT_TRUE(IsSubStringAtSpan(lhsSp, rhsSp, 1)); +} + +HWTEST_F_L0(BaseStringTest, IndexOf_TEST5) +{ + const uint8_t lhs[] = {'a', 'b', 'c', 'd', 'e'}; + const uint16_t rhs[] = {'a', 'b', 'c'}; + Span lhsSp(lhs, 5); + Span rhsSp(rhs, 3); + EXPECT_EQ(BaseString::IndexOf(lhsSp, rhsSp, 0, 4), 0); + + const uint8_t lhs1[] = {'a', 'b', 'c', 'd', 'e'}; + const uint16_t rhs1[] = {'c', 'd'}; + Span lhsSp1(lhs1, 5); + Span rhsSp1(rhs1, 2); + EXPECT_EQ(BaseString::IndexOf(lhsSp1, rhsSp1, 0, 4), 2); + + const uint8_t lhs2[] = {'a', 'b', 'c', 'd', 'e'}; + const uint16_t rhs2[] = {'x', 'y', 'z'}; + Span lhsSp2(lhs2, 5); + Span rhsSp2(rhs2, 3); + EXPECT_EQ(BaseString::IndexOf(lhsSp2, rhsSp2, 0, 4), -1); + + const uint8_t lhs3[] = {'a', 'b', 'a', 'b', 'c'}; + const uint16_t rhs3[] = {'a', 'b', 'c'}; + Span lhsSp3(lhs3, 5); + Span rhsSp3(rhs3, 3); + EXPECT_EQ(BaseString::IndexOf(lhsSp3, rhsSp3, 0, 4), 2); + + const uint8_t lhs4[] = {'a', 'b', 'c', 'd', 'e'}; + const uint16_t rhs4[] = {'a', 'b', 'x'}; + Span lhsSp4(lhs4, 5); + Span rhsSp4(rhs4, 3); + EXPECT_EQ(BaseString::IndexOf(lhsSp4, rhsSp4, 0, 4), -1); +} + +HWTEST_F_L0(BaseStringTest, IndexOf_TEST6) +{ + const uint16_t lhs[] = {'a', 'b', 'c', 'd', 'e'}; + const uint16_t rhs[] = {'a', 'b', 'c'}; + Span lhsSp(lhs, 5); + Span rhsSp(rhs, 3); + EXPECT_EQ(BaseString::IndexOf(lhsSp, rhsSp, 0, 4), 0); + + const uint16_t lhs1[] = {'a', 'b', 'c', 'd', 'e'}; + const uint16_t rhs1[] = {'c', 'd'}; + Span lhsSp1(lhs1, 5); + Span rhsSp1(rhs1, 2); + EXPECT_EQ(BaseString::IndexOf(lhsSp1, rhsSp1, 0, 4), 2); + + const uint16_t lhs2[] = {'a', 'b', 'c', 'd', 'e'}; + const uint16_t rhs2[] = {'x', 'y', 'z'}; + Span lhsSp2(lhs2, 5); + Span rhsSp2(rhs2, 3); + EXPECT_EQ(BaseString::IndexOf(lhsSp2, rhsSp2, 0, 4), -1); + + const uint16_t lhs3[] = {'a', 'b', 'a', 'b', 'c'}; + const uint16_t rhs3[] = {'a', 'b', 'c'}; + Span lhsSp3(lhs3, 5); + Span rhsSp3(rhs3, 3); + EXPECT_EQ(BaseString::IndexOf(lhsSp3, rhsSp3, 0, 4), 2); + + const uint16_t lhs4[] = {'a', 'b', 'c', 'd', 'e'}; + const uint16_t rhs4[] = {'a', 'b', 'x'}; + Span lhsSp4(lhs4, 5); + Span rhsSp4(rhs4, 3); + EXPECT_EQ(BaseString::IndexOf(lhsSp4, rhsSp4, 0, 4), -1); +} + +HWTEST_F_L0(BaseStringTest, IndexOf_TEST7) +{ + const uint16_t lhs[] = {'a', 'b', 'c', 'd', 'e'}; + const uint8_t rhs[] = {'a', 'b', 'c'}; + Span lhsSp(lhs, 5); + Span rhsSp(rhs, 3); + EXPECT_EQ(BaseString::IndexOf(lhsSp, rhsSp, 0, 4), 0); + + const uint16_t lhs1[] = {'a', 'b', 'c', 'd', 'e'}; + const uint8_t rhs1[] = {'c', 'd'}; + Span lhsSp1(lhs1, 5); + Span rhsSp1(rhs1, 2); + EXPECT_EQ(BaseString::IndexOf(lhsSp1, rhsSp1, 0, 4), 2); + + const uint16_t lhs2[] = {'a', 'b', 'c', 'd', 'e'}; + const uint8_t rhs2[] = {'x', 'y', 'z'}; + Span lhsSp2(lhs2, 5); + Span rhsSp2(rhs2, 3); + EXPECT_EQ(BaseString::IndexOf(lhsSp2, rhsSp2, 0, 4), -1); + + const uint16_t lhs3[] = {'a', 'b', 'a', 'b', 'c'}; + const uint8_t rhs3[] = {'a', 'b', 'c'}; + Span lhsSp3(lhs3, 5); + Span rhsSp3(rhs3, 3); + EXPECT_EQ(BaseString::IndexOf(lhsSp3, rhsSp3, 0, 4), 2); + + const uint16_t lhs4[] = {'a', 'b', 'c', 'd', 'e'}; + const uint8_t rhs4[] = {'a', 'b', 'x'}; + Span lhsSp4(lhs4, 5); + Span rhsSp4(rhs4, 3); + EXPECT_EQ(BaseString::IndexOf(lhsSp4, rhsSp4, 0, 4), -1); +} + HWTEST_F_L0(BaseStringTest, IsUtf8EqualsUtf16_TEST0) { const uint8_t utf8_01[] = {0xF0, 0xE0, 0xC0}; @@ -106,4 +387,148 @@ HWTEST_F_L0(BaseStringTest, LastIndexOf_TEST4) EXPECT_EQ(BaseString::LastIndexOf(lhsSp, rhsSp, 3), -1); } + +HWTEST_F_L0(BaseStringTest, IsSubStringAtSpan_TEST3) +{ + const uint8_t lhs[] = {'a', 'b', 'c'}; + const uint16_t rhs[] = {'x', 'y'}; + Span lhsSp(lhs, 3); + Span rhsSp(rhs, 2); + ASSERT_FALSE(IsSubStringAtSpan(lhsSp, rhsSp, 1)); + + const uint8_t lhs1[] = {'a', 'b'}; + const uint16_t rhs1[] = {'b'}; + Span lhsSp1(lhs1, 2); + Span rhsSp1(rhs1, 1); + ASSERT_TRUE(IsSubStringAtSpan(lhsSp1, rhsSp1, 1)); +} + +HWTEST_F_L0(BaseStringTest, IsSubStringAtSpan_TEST4) +{ + const uint16_t lhs[] = {'a', 'b', 'c'}; + const uint8_t rhs[] = {'x', 'y'}; + Span lhsSp(lhs, 3); + Span rhsSp(rhs, 2); + ASSERT_FALSE(IsSubStringAtSpan(lhsSp, rhsSp, 1)); + + const uint16_t lhs1[] = {'a', 'b'}; + const uint8_t rhs1[] = {'b'}; + Span lhsSp1(lhs1, 2); + Span rhsSp1(rhs1, 1); + ASSERT_TRUE(IsSubStringAtSpan(lhsSp1, rhsSp1, 1)); +} + +HWTEST_F_L0(BaseStringTest, IsSubStringAtSpan_TEST5) +{ + const uint16_t lhs[] = {'a', 'b', 'c'}; + const uint16_t rhs[] = {'x', 'y'}; + Span lhsSp(lhs, 3); + Span rhsSp(rhs, 2); + ASSERT_FALSE(IsSubStringAtSpan(lhsSp, rhsSp, 1)); + + const uint16_t lhs1[] = {'a', 'b'}; + const uint16_t rhs1[] = {'b'}; + Span lhsSp1(lhs1, 2); + Span rhsSp1(rhs1, 1); + ASSERT_TRUE(IsSubStringAtSpan(lhsSp1, rhsSp1, 1)); +} + +HWTEST_F_L0(BaseStringTest, LastIndexOf_TEST5) +{ + const uint8_t lhs[] = {'a', 'b', 'c', 'd', 'e'}; + const uint16_t rhs[] = {'c', 'd'}; + Span lhsSp(lhs, 5); + Span rhsSp(rhs, 2); + EXPECT_EQ(BaseString::LastIndexOf(lhsSp, rhsSp, 4), 2); + + const uint8_t lhs1[] = {'a', 'b', 'c', 'x', 'e'}; + const uint16_t rhs1[] = {'c', 'd'}; + Span lhsSp1(lhs1, 5); + Span rhsSp1(rhs1, 2); + EXPECT_EQ(BaseString::LastIndexOf(lhsSp1, rhsSp1, 4), -1); + + const uint8_t lhs2[] = {'a', 'b', 'c', 'd', 'e'}; + const uint16_t rhs2[] = {'c', 'x'}; + Span lhsSp2(lhs2, 5); + Span rhsSp2(rhs2, 2); + EXPECT_EQ(BaseString::LastIndexOf(lhsSp2, rhsSp2, 4), -1); + + const uint8_t lhs3[] = {'a', 'b', 'a', 'b', 'c'}; + const uint16_t rhs3[] = {'a', 'b'}; + Span lhsSp3(lhs3, 5); + Span rhsSp3(rhs3, 2); + EXPECT_EQ(BaseString::LastIndexOf(lhsSp3, rhsSp3, 4), 2); + + const uint8_t lhs4[] = {'a', 'b', 'c', 'd'}; + const uint16_t rhs4[] = {'x', 'y'}; + Span lhsSp4(lhs4, 4); + Span rhsSp4(rhs4, 2); + EXPECT_EQ(BaseString::LastIndexOf(lhsSp4, rhsSp4, 3), -1); +} + +HWTEST_F_L0(BaseStringTest, LastIndexOf_TEST6) +{ + const uint16_t lhs[] = {'a', 'b', 'c', 'd', 'e'}; + const uint16_t rhs[] = {'c', 'd'}; + Span lhsSp(lhs, 5); + Span rhsSp(rhs, 2); + EXPECT_EQ(BaseString::LastIndexOf(lhsSp, rhsSp, 4), 2); + + const uint16_t lhs1[] = {'a', 'b', 'c', 'x', 'e'}; + const uint16_t rhs1[] = {'c', 'd'}; + Span lhsSp1(lhs1, 5); + Span rhsSp1(rhs1, 2); + EXPECT_EQ(BaseString::LastIndexOf(lhsSp1, rhsSp1, 4), -1); + + const uint16_t lhs2[] = {'a', 'b', 'c', 'd', 'e'}; + const uint16_t rhs2[] = {'c', 'x'}; + Span lhsSp2(lhs2, 5); + Span rhsSp2(rhs2, 2); + EXPECT_EQ(BaseString::LastIndexOf(lhsSp2, rhsSp2, 4), -1); + + const uint16_t lhs3[] = {'a', 'b', 'a', 'b', 'c'}; + const uint16_t rhs3[] = {'a', 'b'}; + Span lhsSp3(lhs3, 5); + Span rhsSp3(rhs3, 2); + EXPECT_EQ(BaseString::LastIndexOf(lhsSp3, rhsSp3, 4), 2); + + const uint16_t lhs4[] = {'a', 'b', 'c', 'd'}; + const uint16_t rhs4[] = {'x', 'y'}; + Span lhsSp4(lhs4, 4); + Span rhsSp4(rhs4, 2); + EXPECT_EQ(BaseString::LastIndexOf(lhsSp4, rhsSp4, 3), -1); +} + +HWTEST_F_L0(BaseStringTest, LastIndexOf_TEST7) +{ + const uint16_t lhs[] = {'a', 'b', 'c', 'd', 'e'}; + const uint8_t rhs[] = {'c', 'd'}; + Span lhsSp(lhs, 5); + Span rhsSp(rhs, 2); + EXPECT_EQ(BaseString::LastIndexOf(lhsSp, rhsSp, 4), 2); + + const uint16_t lhs1[] = {'a', 'b', 'c', 'x', 'e'}; + const uint8_t rhs1[] = {'c', 'd'}; + Span lhsSp1(lhs1, 5); + Span rhsSp1(rhs1, 2); + EXPECT_EQ(BaseString::LastIndexOf(lhsSp1, rhsSp1, 4), -1); + + const uint16_t lhs2[] = {'a', 'b', 'c', 'd', 'e'}; + const uint8_t rhs2[] = {'c', 'x'}; + Span lhsSp2(lhs2, 5); + Span rhsSp2(rhs2, 2); + EXPECT_EQ(BaseString::LastIndexOf(lhsSp2, rhsSp2, 4), -1); + + const uint16_t lhs3[] = {'a', 'b', 'a', 'b', 'c'}; + const uint8_t rhs3[] = {'a', 'b'}; + Span lhsSp3(lhs3, 5); + Span rhsSp3(rhs3, 2); + EXPECT_EQ(BaseString::LastIndexOf(lhsSp3, rhsSp3, 4), 2); + + const uint16_t lhs4[] = {'a', 'b', 'c', 'd'}; + const uint8_t rhs4[] = {'x', 'y'}; + Span lhsSp4(lhs4, 4); + Span rhsSp4(rhs4, 2); + EXPECT_EQ(BaseString::LastIndexOf(lhsSp4, rhsSp4, 3), -1); +} } // namespace common::test diff --git a/common_components/objects/tests/composite_base_class_test.cpp b/common_components/objects/tests/composite_base_class_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d5a1c91b7f19b1f4c39b001150f8cdc4a4e6a2b7 --- /dev/null +++ b/common_components/objects/tests/composite_base_class_test.cpp @@ -0,0 +1,114 @@ +/* +* Copyright (c) 2025 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 "common_components/tests/test_helper.h" +#include "common_interfaces/objects/composite_base_class.h" +#include "common_interfaces/objects/base_object.h" + +#include +#include +#include + +namespace common { +class CompositeBaseClassTest : public test::BaseTestWithScope { +protected: + static CompositeBaseClass* MockAllocator() + { + void* memory = ::operator new(sizeof(uint64_t) * 16); + + auto* baseClass = reinterpret_cast(memory); + baseClass->SetObjectType(CommonType::LINE_STRING); + baseClass->ClearBitField(); + + return reinterpret_cast(baseClass); + } + + void SetUp() override + { + roots_ = std::make_unique(); + } + + void TearDown() override + { + roots_.reset(); + } + + std::unique_ptr roots_; +}; + +HWTEST_F_L0(CompositeBaseClassTest, InitializeOnce) +{ + auto allocator = []() -> CompositeBaseClass* { + return CompositeBaseClassTest::MockAllocator(); + }; + + roots_->InitializeCompositeBaseClass(allocator); + roots_->InitializeCompositeBaseClass(allocator); + + EXPECT_TRUE(true); +} + +HWTEST_F_L0(CompositeBaseClassTest, CreateAndGetType) +{ + auto allocator = []() -> CompositeBaseClass* { + return CompositeBaseClassTest::MockAllocator(); + }; + + roots_->InitializeCompositeBaseClass(allocator); + + auto* baseClass = roots_->GetBaseClass(CommonType::LINE_STRING); + ASSERT_NE(baseClass, nullptr); + EXPECT_EQ(baseClass->GetObjectType(), CommonType::LINE_STRING); +} + +HWTEST_F_L0(CompositeBaseClassTest, GetBaseClassReturnsCorrectType) +{ + auto allocator = []() -> CompositeBaseClass* { + return CompositeBaseClassTest::MockAllocator(); + }; + + roots_->InitializeCompositeBaseClass(allocator); + + auto* lineString = roots_->GetBaseClass(CommonType::LINE_STRING); + auto* slicedString = roots_->GetBaseClass(CommonType::SLICED_STRING); + auto* treeString = roots_->GetBaseClass(CommonType::TREE_STRING); + + ASSERT_NE(lineString, nullptr); + ASSERT_NE(slicedString, nullptr); + ASSERT_NE(treeString, nullptr); + + EXPECT_EQ(lineString->GetObjectType(), CommonType::LINE_STRING); + EXPECT_EQ(slicedString->GetObjectType(), CommonType::SLICED_STRING); + EXPECT_EQ(treeString->GetObjectType(), CommonType::TREE_STRING); +} + +HWTEST_F_L0(CompositeBaseClassTest, IterateCompositeBaseClass) +{ + auto allocator = []() -> CompositeBaseClass* { + return CompositeBaseClassTest::MockAllocator(); + }; + + roots_->InitializeCompositeBaseClass(allocator); + + std::vector visited; + + roots_->IterateCompositeBaseClass([&visited](RefField<>& field) { + auto* ptr = reinterpret_cast(const_cast(static_cast(&field))); + visited.push_back(ptr); + }); + + EXPECT_EQ(visited.size(), 3); +} +} \ No newline at end of file diff --git a/common_components/platform/unix/tests/BUILD.gn b/common_components/platform/unix/tests/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..645bc239e757bdcf47648a53405ed36f343d7c4d --- /dev/null +++ b/common_components/platform/unix/tests/BUILD.gn @@ -0,0 +1,57 @@ +# Copyright (c) 2025 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. + +import("//arkcompiler/ets_runtime/common_components/tests/test_helper.gni") + +module_output_path = "ets_runtime" + +host_unittest_action("Map_Test") { + module_out_path = module_output_path + + sources = [ + # test file + "map_test.cpp", + ] + + configs = [ + "//arkcompiler/ets_runtime/common_components:common_components_test_config", + "//arkcompiler/ets_runtime:icu_path_test_config", + ] + + deps = [ "//arkcompiler/ets_runtime/common_components:libark_common_components_test" ] + + # hiviewdfx libraries + external_deps = [ + "icu:shared_icui18n", + "icu:shared_icuuc", + "zlib:libz", + ] +} + +group("unittest") { + testonly = true + + # deps file + deps = [ + ":Map_Test", + ] +} + +group("host_unittest") { + testonly = true + + # deps file + deps = [ + ":Map_TestAction", + ] +} \ No newline at end of file diff --git a/common_components/platform/unix/tests/map_test.cpp b/common_components/platform/unix/tests/map_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4032e3a1862d42c446a7d20af79775776adced52 --- /dev/null +++ b/common_components/platform/unix/tests/map_test.cpp @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2025 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 "common_components/tests/test_helper.h" +#include "common_components/platform/map.h" + +#include +#include + +class PageProtectTest : public common::test::BaseTestWithScope { +protected: + void SetUp() override {} + void TearDown() override {} +}; + +HWTEST_F_L0(PageProtectTest, TestPageProtect) +{ + size_t pageSize = getpagesize(); + void* mem = mmap(nullptr, pageSize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + ASSERT_NE(mem, MAP_FAILED); + + bool success = common::PageProtect(mem, pageSize, PROT_READ); + EXPECT_TRUE(success); + + munmap(mem, pageSize); +} + +HWTEST_F_L0(PageProtectTest, TestNullptrMemory) +{ + bool success = common::PageProtect(nullptr, getpagesize(), PROT_READ); + EXPECT_FALSE(success); +} \ No newline at end of file diff --git a/common_components/profiler/tests/BUILD.gn b/common_components/profiler/tests/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..0dc10d69e6735fc82d8179e29c4650857ed99916 --- /dev/null +++ b/common_components/profiler/tests/BUILD.gn @@ -0,0 +1,57 @@ +# Copyright (c) 2025 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. + +import("//arkcompiler/ets_runtime/common_components/tests/test_helper.gni") + +module_output_path = "ets_runtime" + +host_unittest_action("Common_Profiler_Interface_Test") { + module_out_path = module_output_path + + sources = [ + # test file + "common_profiler_interface_test.cpp", + ] + + configs = [ + "//arkcompiler/ets_runtime/common_components:common_components_test_config", + "//arkcompiler/ets_runtime:icu_path_test_config", + ] + + deps = [ "//arkcompiler/ets_runtime/common_components:libark_common_components_test" ] + + # hiviewdfx libraries + external_deps = [ + "icu:shared_icui18n", + "icu:shared_icuuc", + "zlib:libz", + ] +} + +group("unittest") { + testonly = true + + # deps file + deps = [ + ":Common_Profiler_Interface_Test", + ] +} + +group("host_unittest") { + testonly = true + + # deps file + deps = [ + ":Common_Profiler_Interface_TestAction", + ] +} diff --git a/common_components/profiler/tests/common_profiler_interface_test.cpp b/common_components/profiler/tests/common_profiler_interface_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6f85a0e98156eee229b207b0c7b7325214ca97f8 --- /dev/null +++ b/common_components/profiler/tests/common_profiler_interface_test.cpp @@ -0,0 +1,96 @@ +/* +* Copyright (c) 2025 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 "common_components/profiler/common_profiler_interface.h" +#include "common_components/profiler/heap_profiler_listener.cpp" +#include "common_components/tests/test_helper.h" + +using namespace common; + +namespace common::test { +class MockCommonProfiler : public CommonHeapProfilerInterface { +public: + bool isSingleInstance = false; + void DumpHeapSnapshotForCMCOOM() override + { + isSingleInstance = true; + } +}; + +class CommonProfilerInterfaceTest : public common::test::BaseTestWithScope { +}; + +HWTEST_F_L0(CommonProfilerInterfaceTest, DumpHeapSnapshotBeforeOOM) +{ + MockCommonProfiler *instance = new MockCommonProfiler(); + ASSERT_NE(instance, nullptr); + CommonHeapProfilerInterface::SetSingleInstance(nullptr); + CommonHeapProfilerInterface::DumpHeapSnapshotBeforeOOM(); + CommonHeapProfilerInterface::SetSingleInstance(instance); + CommonHeapProfilerInterface::DumpHeapSnapshotBeforeOOM(); + ASSERT_TRUE(instance->isSingleInstance); + delete instance; +} +} // namespace common::test + +namespace common::test { +class HeapProfilerListenerTest : public common::test::BaseTestWithScope { +protected: + void SetUp() override + { + listener_ = &HeapProfilerListener::GetInstance(); + moveEventCallbackCalled = false; + callbackId = 0; + } + + void TearDown() override + { + if (callbackId != 0) { + listener_->UnRegisterMoveEventCb(callbackId); + } + } + + HeapProfilerListener* listener_; + bool moveEventCallbackCalled; + uint32_t callbackId; +}; + +uintptr_t capturedFromObj = 0; +uintptr_t capturedToObj = 0; +size_t capturedSize = 0; + +HWTEST_F_L0(HeapProfilerListenerTest, OnMoveEvent) +{ + std::function emptyCallback; + callbackId = listener_->RegisterMoveEventCb(emptyCallback); + listener_->OnMoveEvent(0x1000, 0x2000, 64); + uintptr_t fromObj = 0x12345678; + uintptr_t toObj = 0x87654321; + size_t size = 1024; + auto callback = [this](uintptr_t from, uintptr_t to, size_t sz) { + moveEventCallbackCalled = true; + capturedFromObj = from; + capturedToObj = to; + capturedSize = sz; + }; + + callbackId = listener_->RegisterMoveEventCb(callback); + listener_->OnMoveEvent(fromObj, toObj, size); + EXPECT_TRUE(moveEventCallbackCalled); + EXPECT_EQ(capturedFromObj, fromObj); + EXPECT_EQ(capturedToObj, toObj); + EXPECT_EQ(capturedSize, size); +} +} //namespace common::test diff --git a/common_components/serialize/tests/BUILD.gn b/common_components/serialize/tests/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..bfcdc438399f306cfb36395018127eaa5fa5208f --- /dev/null +++ b/common_components/serialize/tests/BUILD.gn @@ -0,0 +1,57 @@ +# Copyright (c) 2025 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. + +import("//arkcompiler/ets_runtime/common_components/tests/test_helper.gni") + +module_output_path = "ets_runtime" + +host_unittest_action("Serialize_Utils_Test") { + module_out_path = module_output_path + + sources = [ + # test file + "serialize_utils_test.cpp", + ] + + configs = [ + "//arkcompiler/ets_runtime/common_components:common_components_test_config", + "//arkcompiler/ets_runtime:icu_path_test_config", + ] + + deps = [ "//arkcompiler/ets_runtime/common_components:libark_common_components_test" ] + + # hiviewdfx libraries + external_deps = [ + "icu:shared_icui18n", + "icu:shared_icuuc", + "zlib:libz", + ] +} + +group("unittest") { + testonly = true + + # deps file + deps = [ + ":Serialize_Utils_Test", + ] +} + +group("host_unittest") { + testonly = true + + # deps file + deps = [ + ":Serialize_Utils_TestAction", + ] +} diff --git a/common_components/serialize/tests/serialize_utils_test.cpp b/common_components/serialize/tests/serialize_utils_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..680b592484112f9d08a8909295d45d8405235b8f --- /dev/null +++ b/common_components/serialize/tests/serialize_utils_test.cpp @@ -0,0 +1,57 @@ +/* +* Copyright (c) 2025 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 "common_components/heap/allocator/region_desc.h" +#include "common_components/heap/allocator/region_space.h" +#include "common_components/serialize/serialize_utils.h" +#include "common_components/serialize/serialize_utils.cpp" +#include "common_components/tests/test_helper.h" + +using namespace common; + +namespace common::test { +class SerializeUtilsTest : public common::test::BaseTestWithScope { +protected: + static void SetUpTestCase() + { + BaseRuntime::GetInstance()->Init(); + } + + static void TearDownTestCase() + { + BaseRuntime::GetInstance()->Fini(); + } + void SetUp() override + { + MutatorManager::Instance().CreateRuntimeMutator(ThreadType::GC_THREAD); + } + + void TearDown() override + { + MutatorManager::Instance().DestroyRuntimeMutator(ThreadType::GC_THREAD); + } +}; + +HWTEST_F_L0(SerializeUtilsTest, GetSerializeObjectSpace) +{ + RegionSpace& theAllocator = reinterpret_cast(Heap::GetHeap().GetAllocator()); + uintptr_t addr = theAllocator.AllocOldRegion(); + ASSERT_NE(addr, 0); + RegionDesc* region = RegionDesc::GetRegionDescAt(addr); + region->SetRegionType(RegionDesc::RegionType::END_OF_REGION_TYPE); + SerializedBaseObjectSpace spaceType = SerializeUtils::GetSerializeObjectSpace(addr); + EXPECT_EQ(spaceType, SerializedBaseObjectSpace::OTHER); +} +} // namespace common::test \ No newline at end of file diff --git a/common_components/taskpool/tests/BUILD.gn b/common_components/taskpool/tests/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..3c3a88f482efe1b5e3ab7b225a6934db3831d7f9 --- /dev/null +++ b/common_components/taskpool/tests/BUILD.gn @@ -0,0 +1,107 @@ +# Copyright (c) 2025 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. + +import("//arkcompiler/ets_runtime/common_components/tests/test_helper.gni") + +module_output_path = "ets_runtime" + +host_unittest_action("Runner_Test") { + module_out_path = module_output_path + + sources = [ + # test file + "runner_test.cpp", + ] + + configs = [ + "//arkcompiler/ets_runtime/common_components:common_components_test_config", + "//arkcompiler/ets_runtime:icu_path_test_config", + ] + + deps = [ "//arkcompiler/ets_runtime/common_components:libark_common_components_test" ] + + # hiviewdfx libraries + external_deps = [ + "icu:shared_icui18n", + "icu:shared_icuuc", + "zlib:libz", + ] +} + +host_unittest_action("Taskpool_Task_Queue_Test") { + module_out_path = module_output_path + + sources = [ + # test file + "task_queue_test.cpp", + ] + + configs = [ + "//arkcompiler/ets_runtime/common_components:common_components_test_config", + "//arkcompiler/ets_runtime:icu_path_test_config", + ] + + deps = [ "//arkcompiler/ets_runtime/common_components:libark_common_components_test" ] + + # hiviewdfx libraries + external_deps = [ + "icu:shared_icui18n", + "icu:shared_icuuc", + "zlib:libz", + ] +} + +host_unittest_action("Taskpool_Test") { + module_out_path = module_output_path + + sources = [ + # test file + "taskpool_test.cpp", + ] + + configs = [ + "//arkcompiler/ets_runtime/common_components:common_components_test_config", + "//arkcompiler/ets_runtime:icu_path_test_config", + ] + + deps = [ "//arkcompiler/ets_runtime/common_components:libark_common_components_test" ] + + # hiviewdfx libraries + external_deps = [ + "icu:shared_icui18n", + "icu:shared_icuuc", + "zlib:libz", + ] +} + +group("unittest") { + testonly = true + + # deps file + deps = [ + ":Runner_Test", + ":Taskpool_Task_Queue_Test", + ":Taskpool_Test", + ] +} + +group("host_unittest") { + testonly = true + + # deps file + deps = [ + ":Runner_TestAction", + ":Taskpool_Task_Queue_TestAction", + ":Taskpool_TestAction", + ] +} \ No newline at end of file diff --git a/common_components/taskpool/tests/runner_test.cpp b/common_components/taskpool/tests/runner_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4e005bdccb77c35977e50caa47511aa4166e141a --- /dev/null +++ b/common_components/taskpool/tests/runner_test.cpp @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2025 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 "common_components/tests/test_helper.h" +#include "common_components/taskpool/runner.h" + +#include +#include +#include +#include + +namespace common { +class RunnerTest : public common::test::BaseTestWithScope { +protected: + void SetUp() override {} + void TearDown() override {} + + static std::function CreateMockPrologueHook() + { + return [](native_handle_type handle) {}; + } + + static std::function CreateMockEpilogueHook() + { + return [](native_handle_type handle) {}; + } +}; + +class MockTask : public Task { +public: + explicit MockTask(int32_t id) + : Task(id), executed_(false) {} + + bool Run(uint32_t threadId) override + { + executed_ = true; + return true; + } + + bool IsExecuted() const { return executed_; } + +private: + std::atomic executed_; +}; + +HWTEST_F_L0(RunnerTest, InitializeRunnerWithThreads) { + constexpr uint32_t threadNum = 4; + Runner runner(threadNum, RunnerTest::CreateMockPrologueHook(), RunnerTest::CreateMockEpilogueHook()); + EXPECT_EQ(runner.GetTotalThreadNum(), threadNum); + + runner.TerminateThread(); +} +} \ No newline at end of file diff --git a/common_components/taskpool/tests/task_queue_test.cpp b/common_components/taskpool/tests/task_queue_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e9d39728913d82279ced0637ae88eb430ceda26c --- /dev/null +++ b/common_components/taskpool/tests/task_queue_test.cpp @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2025 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 "common_components/tests/test_helper.h" +#include "common_components/taskpool/task_queue.h" +#include "common_components/taskpool/task.h" + +#include +#include + +namespace common { + +class TaskQueueTest : public common::test::BaseTestWithScope { +protected: + void SetUp() override + { + queue_ = new TaskQueue(); + } + + void TearDown() override + { + delete queue_; + queue_ = nullptr; + } + + TaskQueue* queue_; +}; + +class MockTask : public Task { +public: + explicit MockTask(int id) : Task(id), executed_(false) {} + + bool Run(uint32_t threadId) override + { + executed_ = true; + return true; + } + + bool IsExecuted() const { return executed_; } + +private: + mutable bool executed_; +}; + + +HWTEST_F_L0(TaskQueueTest, PopTask_DelayedTaskExpired_CanBeExecuted) +{ + auto task = std::make_unique(2); + queue_->PostDelayedTask(std::move(task), 500); + + usleep(600 * 1000); + + auto poppedTask = queue_->PopTask(); + ASSERT_NE(poppedTask, nullptr); + + MockTask* mockTask = static_cast(poppedTask.get()); + EXPECT_FALSE(mockTask->IsExecuted()); + + (void)poppedTask->Run(0); + EXPECT_TRUE(mockTask->IsExecuted()); +} + +HWTEST_F_L0(TaskQueueTest, PopTask_MultipleDelayedTasks_ExecuteInOrder) +{ + auto task1 = std::make_unique(1); + auto task2 = std::make_unique(2); + auto task3 = std::make_unique(3); + + queue_->PostDelayedTask(std::move(task1), 800); + queue_->PostDelayedTask(std::move(task2), 500); + queue_->PostDelayedTask(std::move(task3), 1000); + + usleep(600 * 1000); + + auto poppedTask = queue_->PopTask(); + ASSERT_NE(poppedTask, nullptr); + EXPECT_EQ(poppedTask->GetId(), 2); + + poppedTask->Run(0); + MockTask* mockTask2 = static_cast(poppedTask.get()); + EXPECT_TRUE(mockTask2->IsExecuted()); + + usleep(300 * 1000); + + poppedTask = queue_->PopTask(); + ASSERT_NE(poppedTask, nullptr); + EXPECT_EQ(poppedTask->GetId(), 1); + + poppedTask->Run(0); + MockTask* mockTask1 = static_cast(poppedTask.get()); + EXPECT_TRUE(mockTask1->IsExecuted()); + + usleep(200 * 1000); + + poppedTask = queue_->PopTask(); + ASSERT_NE(poppedTask, nullptr); + EXPECT_EQ(poppedTask->GetId(), 3); + + poppedTask->Run(0); + MockTask* mockTask3 = static_cast(poppedTask.get()); + EXPECT_TRUE(mockTask3->IsExecuted()); +} +} \ No newline at end of file diff --git a/common_components/taskpool/tests/taskpool_test.cpp b/common_components/taskpool/tests/taskpool_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..11e0741a266a50345833a9e3027f231fc32b61cb --- /dev/null +++ b/common_components/taskpool/tests/taskpool_test.cpp @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2025 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 "common_components/tests/test_helper.h" +#include "common_components/taskpool/taskpool.h" +#include "common_components/taskpool/task.h" + +#include +#include +#include + +namespace common { + +class MockTask : public Task { +public: + explicit MockTask(int32_t id) + : Task(id), executed_(false), terminated_(false) {} + + bool Run(uint32_t threadId) override + { + executed_ = true; + return true; + } + + bool IsExecuted() const { return executed_; } + + bool IsTerminate() const + { + return terminated_; + } + + void Terminate() + { + terminated_ = true; + } + +private: + std::atomic executed_; + std::atomic terminated_; +}; + +class TaskpoolTest : public common::test::BaseTestWithScope { +protected: + void SetUp() override {} + void TearDown() override {} + + class ScopedTaskpool { + public: + explicit ScopedTaskpool(int threadNum = DEFAULT_TASKPOOL_THREAD_NUM) + : isInitialized_(false) + { + isInitialized_ = true; + pool_.Initialize(threadNum); + } + + Taskpool* Get() + { + return &pool_; + } + + private: + Taskpool pool_; + bool isInitialized_; + }; +}; + +HWTEST_F_L0(TaskpoolTest, InitializeAndDestroy) { + TaskpoolTest::ScopedTaskpool pool(2); + EXPECT_NE(pool.Get(), nullptr); + EXPECT_GT(pool.Get()->GetTotalThreadNum(), 0U); +} + +HWTEST_F_L0(TaskpoolTest, TerminateTask) { + TaskpoolTest::ScopedTaskpool pool(2); + Taskpool* taskpool = pool.Get(); + ASSERT_NE(taskpool, nullptr); + + auto task1 = std::make_unique(1); + auto task2 = std::make_unique(2); + taskpool->PostTask(std::move(task1)); + taskpool->PostTask(std::move(task2)); + + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + + taskpool->TerminateTask(1, TaskType::ALL); + + bool isTerminated = false; + taskpool->ForEachTask([&isTerminated](Task* task) { + if (task->GetId() == 1 && task->IsTerminate()) { + isTerminated = true; + } + }); + + EXPECT_FALSE(isTerminated); +} +} \ No newline at end of file diff --git a/common_components/tests/ohos_test.xml b/common_components/tests/ohos_test.xml index a9332b249edfadefb88244a85a60ce144a938823..58b48bedd902a8729b137a1802852c19049adb8f 100644 --- a/common_components/tests/ohos_test.xml +++ b/common_components/tests/ohos_test.xml @@ -38,11 +38,26 @@