diff --git a/BUILD.gn b/BUILD.gn index 7a00f3610d603f6fc8d0156a6d2a75cbb42d1f84..8c5f76c7185b9147b70f695e6e08ec5703145086 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -159,16 +159,19 @@ group("common_components_js_unittest") { deps += [ "common_components/base/tests:unittest", "common_components/base_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/thread/tests:unittest", "common_components/log/tests:unittest", + "common_components/platform/unix/tests:unittest", + "common_components/taskpool/tests:unittest", ] } } @@ -181,16 +184,19 @@ group("common_components_unittest") { deps += [ "common_components/base/tests:host_unittest", "common_components/base_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/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/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..b1543fbd8a79b903d35e3121df07428dcedff208 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,128 @@ 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"); +} + } \ 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..f01e8cafd3078726ddd03842561455906d8ddd10 --- /dev/null +++ b/common_components/base/tests/utf_helper_test.cpp @@ -0,0 +1,263 @@ +/* + * 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); +} +} // 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..742493056a4da98fd1ac1f9564ca66cfcb1a61cb 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", @@ -137,7 +138,7 @@ group("unittest") { # deps file deps = [ - ":Allocator_Test", + #":Allocator_Test", ":Treap_Test", ":Region_Space_Test", ":Heap_Allocator_Test", @@ -150,7 +151,7 @@ group("host_unittest") { # deps file deps = [ - ":Allocator_TestAction", + #":Allocator_TestAction", ":Treap_TestAction", ":Region_Space_TestAction", ":Heap_Allocator_TestAction", diff --git a/common_components/heap/allocator/tests/allocator_test.cpp b/common_components/heap/allocator/tests/allocator_test.cpp index 58820668fc412f0c90fe2b225f6a2104e32c26eb..c7d02c39d752c53cdf0d61621814a7e6561ca954 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 { }; diff --git a/common_components/heap/allocator/tests/heap_allocator_test.cpp b/common_components/heap/allocator/tests/heap_allocator_test.cpp index 7f8c1372b245f9548dbb020a6d50287fa3e91d7a..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/base_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 07b15d7c6d6174ba979a0b44576822d17487d392..33794b16347ee995075e29b7b65016b45b41df44 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); } @@ -345,11 +343,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 +355,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 +367,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 +379,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 +391,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 +403,6 @@ 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()); } } diff --git a/common_components/heap/allocator/tests/region_space_test.cpp b/common_components/heap/allocator/tests/region_space_test.cpp index f2db5516d6128e8087cbe86d4abd2f8b119cff1d..62c6ff0e7ec422097ef94a7259f5717836a68585 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/base_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::GetRegionDescAt(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::GetRegionDescAt(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::GetRegionDescAt(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::GetRegionDescAt(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::GetRegionDescAt(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::GetRegionDescAt(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::GetRegionDescAt(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::GetRegionDescAt(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::GetRegionDescAt(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::GetRegionDescAt(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::GetRegionDescAt(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::GetRegionDescAt(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/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/tests/BUILD.gn b/common_components/heap/collector/tests/BUILD.gn index 20a34d4289709824629fe2663dcf71b8349d9011..612929d1c754438da26c4507befcec94a6f45ebf 100755 --- a/common_components/heap/collector/tests/BUILD.gn +++ b/common_components/heap/collector/tests/BUILD.gn @@ -33,12 +33,36 @@ 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("Trace_Collector_Test") { module_out_path = module_output_path @@ -114,6 +138,7 @@ group("unittest") { # deps file deps = [ ":Collector_Test", + ":Heuristic_Gc_Policy_Test", ":Trace_Collector_Test", ":Task_Queue_Test", ":Gc_Request_Test", @@ -126,6 +151,7 @@ group("host_unittest") { # deps file deps = [ ":Collector_TestAction", + ":Heuristic_Gc_Policy_TestAction", ":Trace_Collector_TestAction", ":Task_Queue_TestAction", ":Gc_Request_TestAction", diff --git a/common_components/heap/collector/tests/collector_resources_test.cpp b/common_components/heap/collector/tests/collector_resources_test.cpp index e5c41750fcb1344b801a23067148d3fb5d8e0aba..058891056e96012cce31b8baf7d11ed20e9f2373 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,7 +64,7 @@ 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()); } @@ -88,4 +89,28 @@ HWTEST_F_L0(CollectorResourcesTest, StopRuntimeThreadsTest) { Heap::GetHeap().GetCollectorResources().StopRuntimeThreads(); EXPECT_FALSE(Heap::GetHeap().GetCollectorResources().GetFinalizerProcessor().IsRunning()); } + +HWTEST_F_L0(CollectorResourcesTest, RequestGC_TriggerPostIgnoredGcRequest_WithHighFrequency) +{ + auto& collectorResources = Heap::GetHeap().GetCollectorResources(); + + uint64_t now = TimeUtil::NanoSeconds(); + GCRequest req = { + GC_REASON_NATIVE, + "FrequentObject", + false, + false, + 100, + now + }; + + for (int i = 0; i < 5; ++i) + { + req.prevRequestTime = now; + now += 50; + req.minIntervelNs = 100; + + collectorResources.RequestGC(req.reason, false, common::GC_TYPE_FULL); + } +} } // 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..0281724f8e4362aacb27adcee05191f4f085cf33 --- /dev/null +++ b/common_components/heap/collector/tests/heuristic_gc_policy_test.cpp @@ -0,0 +1,62 @@ +/* +* 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/heuristic_gc_policy.h" +#include "common_components/tests/test_helper.h" + +using namespace common; +namespace common::test { +class HeuristicGCPolicyTest : public common::test::BaseTestWithScope { +}; + +HWTEST_F_L0(HeuristicGCPolicyTest, ShouldRestrainGCOnStartup) +{ + HeuristicGCPolicy gcPolicy; + StartupStatusManager::SetStartupStatus(StartupStatus::COLD_STARTUP); + EXPECT_TRUE(gcPolicy.ShouldRestrainGCOnStartup()); + gcPolicy.TryHeuristicGC(); + + StartupStatusManager::SetStartupStatus(StartupStatus::COLD_STARTUP_FINISH); + EXPECT_FALSE(gcPolicy.ShouldRestrainGCOnStartup()); + + gcPolicy.Init(); + EXPECT_FALSE(gcPolicy.ShouldRestrainGCOnStartup()); + StartupStatusManager::SetStartupStatus(StartupStatus::COLD_STARTUP_PARTIALLY_FINISH); + EXPECT_FALSE(gcPolicy.ShouldRestrainGCOnStartup()); +} + +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); +} +} // 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..63ebbd25218a466904d3cf1cedd8134fa575bfbb 100755 --- a/common_components/heap/collector/tests/trace_collector_test.cpp +++ b/common_components/heap/collector/tests/trace_collector_test.cpp @@ -63,4 +63,15 @@ std::unique_ptr GetWCollector() return std::make_unique(allocator, resources); } +HWTEST_F_L0(TraceCollectorTest, RunGarbageCollection) +{ + 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()); +} } \ 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..150821d3248eadfbdee8b5a014c596bd92893778 --- /dev/null +++ b/common_components/heap/space/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("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 = [ + "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..0cd023fa811f0a676d4957feb354e2d9f35c512b --- /dev/null +++ b/common_components/heap/space/tests/from_space_test.cpp @@ -0,0 +1,35 @@ +/* +* 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 { +}; + +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); +} +} // 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..fa9f1087e6343a00182cf0ebac2987712b8e43d1 --- /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 = [ + "icu:shared_icui18n", + "icu:shared_icuuc", + "zlib:libz", + "bounds_checking_function:libsec_shared", + ] +} + +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..88bb08b1d5335507d3442c615677443b591e886d --- /dev/null +++ b/common_components/heap/tests/verification_test.cpp @@ -0,0 +1,187 @@ +/* +* 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" + +using namespace common; +namespace common::test { +class VerificationTest : public common::test::BaseTestWithScope { +protected: + static void SetUpTestCase() + { + BaseRuntime::GetInstance()->Init(); + } + + static void TearDownTestCase() + {} + + 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()); +} +} // namespace common::test 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..8358728dbdd24821b12f86586c5ff5fcc7fcf0fa 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::FREE_REGION); 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) 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..7ebcbd0d4b11e3c89316801a476dea041c80dd97 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; 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..7f0acf2606c86e8eab64352686169270fda3c846 100755 --- a/common_components/heap/w_collector/tests/idle_barrier_test.cpp +++ b/common_components/heap/w_collector/tests/idle_barrier_test.cpp @@ -217,6 +217,55 @@ HWTEST_F_L0(IdleBarrierTest, WriteRefField_TEST0) EXPECT_EQ(oldField.GetFieldValue(), neWAddress); } +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); + ASSERT_TRUE(idleBarrier != nullptr); + + HeapAddress addr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); + BaseObject* obj = reinterpret_cast(addr); + RefField<> field(obj); + idleBarrier->WriteBarrier(obj, field, obj); + EXPECT_TRUE(obj != nullptr); +} + HWTEST_F_L0(IdleBarrierTest, WriteStruct_TEST0) { MockCollector collector; 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..4f661ce6621a86e0abc38797d84479ce11500fc9 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::FREE_REGION); + 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; 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..eefeea3d1b1cdb1f8e00114fa67cb727893ad652 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::FREE_REGION); 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) 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..30c9ff6a0ddacda06c7cb7504668abce5387c80b 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::FREE_REGION); + 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; @@ -221,6 +269,21 @@ 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; @@ -239,6 +302,27 @@ HWTEST_F_L0(RemarkBarrierTest, WriteStruct_TEST1) EXPECT_EQ(srcBuffer[0], dstBuffer[0]); } +HWTEST_F_L0(RemarkBarrierTest, WriteStruct_TEST2) +{ + 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()); + auto mutator = ThreadLocal::GetMutator(); + ThreadLocal::SetMutator(nullptr); + remarkBarrier->WriteStruct(objPtr.get(), dst, size, src, size); + ThreadLocal::SetMutator(mutator); + EXPECT_EQ(dstBuffer[0], 1); + EXPECT_EQ(srcBuffer[0], dstBuffer[0]); +} + HWTEST_F_L0(RemarkBarrierTest, AtomicReadRefField_TEST1) { MockCollector collector; 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..e515a43ebedc6685f4e9fa9183312e070347730f 100755 --- a/common_components/heap/w_collector/tests/trace_barrier_test.cpp +++ b/common_components/heap/w_collector/tests/trace_barrier_test.cpp @@ -208,6 +208,61 @@ 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); + + 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()); + traceBarrier->WriteStruct(objPtr.get(), dst, size, src, size); + EXPECT_EQ(dstBuffer[0], 1); + EXPECT_EQ(srcBuffer[0], dstBuffer[0]); +} + +HWTEST_F_L0(TraceBarrierTest, WriteStruct_TEST2) +{ + MockCollector collector; + auto traceBarrier = std::make_unique(collector); + ASSERT_TRUE(traceBarrier != 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()); + auto mutator = ThreadLocal::GetMutator(); + ThreadLocal::SetMutator(nullptr); + traceBarrier->WriteStruct(objPtr.get(), dst, size, src, size); + ThreadLocal::SetMutator(mutator); + EXPECT_EQ(dstBuffer[0], 1); + EXPECT_EQ(srcBuffer[0], dstBuffer[0]); +} + 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 25185f35efb6ba4272481a6713a6a63c7fca5d8b..8875284dcb5617a783a287b76d5b9a2978315753 100644 --- a/common_components/heap/w_collector/tests/w_collector_test.cpp +++ b/common_components/heap/w_collector/tests/w_collector_test.cpp @@ -25,7 +25,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 +127,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 +137,79 @@ 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); +} + } // namespace common::test diff --git a/common_components/heap/w_collector/w_collector.h b/common_components/heap/w_collector/w_collector.h index 627a9d71c825fa18c4c66fc0c1fed8b4c10f6508..597cb13afca3ac1d19afee7124c5c2cda10d310f 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/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 d6a6f79fc2f0f753a093559f256b085ff2ab88c4..7704ebdf8218a8a798c6a40bfd5c55c0c570767d 100755 --- a/common_components/mutator/tests/mutator_manager_test.cpp +++ b/common_components/mutator/tests/mutator_manager_test.cpp @@ -78,17 +78,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 +89,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; diff --git a/common_components/mutator/tests/mutator_test.cpp b/common_components/mutator/tests/mutator_test.cpp new file mode 100755 index 0000000000000000000000000000000000000000..197a14069351a761b8115f79dcff1496952bff69 --- /dev/null +++ b/common_components/mutator/tests/mutator_test.cpp @@ -0,0 +1,243 @@ +/* + * 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); + mutatorBase.SetSuspensionFlag(MutatorBase::SUSPENSION_FOR_GC_PHASE); + EXPECT_NO_FATAL_FAILURE(mutatorBase.HandleSuspensionRequest()); +} + +HWTEST_F_L0(MutatorTest, HandleSuspensionRequest_Test5) +{ + MutatorBase mutatorBase; + mutatorBase.Init(); + mutatorBase.SetSuspensionFlag(MutatorBase::SUSPENSION_FOR_FINALIZE); + EXPECT_NO_FATAL_FAILURE(mutatorBase.HandleSuspensionRequest()); +} + +HWTEST_F_L0(MutatorTest, TransitionToGCPhaseExclusive_TestAllBranches) +{ + MutatorBase mutatorBase; + mutatorBase.Init(); + + GCPhase phase = GCPhase::GC_PHASE_ENUM; + EXPECT_NO_FATAL_FAILURE(mutatorBase.TransitionToGCPhaseExclusive(phase)); + phase = GCPhase::GC_PHASE_PRECOPY; + EXPECT_NO_FATAL_FAILURE(mutatorBase.TransitionToGCPhaseExclusive(phase)); + 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 1236bb44fd7afa260dc2a7cd9552a39c40ff069c..e22bda58fad5640eebc7185c73c4837cedb3f192 100755 --- a/common_components/mutator/tests/satb_buffer_test.cpp +++ b/common_components/mutator/tests/satb_buffer_test.cpp @@ -13,74 +13,46 @@ * limitations under the License. */ -#include "common_components/base_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); @@ -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,8 +96,8 @@ 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); @@ -135,4 +107,73 @@ HWTEST_F_L0(SatbBufferTest, IsYoungSpaceObject4) 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..232e8a1111a4573125d84d37af8745f04a3559f2 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,187 @@ 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, IsUtf8EqualsUtf16_TEST0) { const uint8_t utf8_01[] = {0xF0, 0xE0, 0xC0}; 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/taskpool/tests/BUILD.gn b/common_components/taskpool/tests/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..1e71ec4e59c6292d48c7ecd7bce98bf8f8255c58 --- /dev/null +++ b/common_components/taskpool/tests/BUILD.gn @@ -0,0 +1,82 @@ +# 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_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_Test", + ] +} + +group("host_unittest") { + testonly = true + + # deps file + deps = [ + ":Runner_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/taskpool_test.cpp b/common_components/taskpool/tests/taskpool_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5e22daf35ca5fd008ed0fa8790af9d2b405a2dbc --- /dev/null +++ b/common_components/taskpool/tests/taskpool_test.cpp @@ -0,0 +1,92 @@ +/* + * 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) {} + + bool Run(uint32_t threadId) override + { + executed_ = true; + return true; + } + + bool IsExecuted() const { return executed_; } + +private: + std::atomic executed_; +}; + +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, SetQosPriority) { + TaskpoolTest::ScopedTaskpool pool(1); + pool.Get()->SetThreadPriority(PriorityMode::BACKGROUND); +} + +HWTEST_F_L0(TaskpoolTest, ForEachTask) { + TaskpoolTest::ScopedTaskpool pool(1); + + auto task = std::make_unique(1); + pool.Get()->PostTask(std::move(task)); + + std::atomic count(0); + pool.Get()->ForEachTask([&count](Task* t) { + count++; + }); + + EXPECT_EQ(count.load(), 1); +} +} \ No newline at end of file diff --git a/common_components/tests/ohos_test.xml b/common_components/tests/ohos_test.xml index a9332b249edfadefb88244a85a60ce144a938823..972245bcf7873b60b39b819a93280e1dd5273f54 100644 --- a/common_components/tests/ohos_test.xml +++ b/common_components/tests/ohos_test.xml @@ -43,6 +43,11 @@