From cdd70557e4bba1e93740642f342ca19409b1c785 Mon Sep 17 00:00:00 2001 From: yp9522 Date: Wed, 16 Jul 2025 16:53:39 +0800 Subject: [PATCH] add common_components tdd MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Issue: [新需求]: https://gitee.com/openharmony/arkcompiler_ets_runtime/issues/ICM6AY Change-Id: I90bd0938d08cef29b12995803e60b7c1934abd2d Signed-off-by: yp9522 --- BUILD.gn | 26 +- common_components/base/tests/BUILD.gn | 50 +++ .../base/tests/c_string_test.cpp | 134 +++++- .../base/tests/utf_helper_test.cpp | 329 ++++++++++++++ .../heap/allocator/tests/allocator_test.cpp | 1 + .../allocator/tests/heap_allocator_test.cpp | 16 +- .../allocator/tests/region_manager_test.cpp | 129 ++++-- .../allocator/tests/region_space_test.cpp | 265 ++++++----- .../heap/barrier/tests/barrier_test.cpp | 16 + .../heap/collector/tests/BUILD.gn | 53 ++- .../collector/tests/collector_proxy_test.cpp | 44 ++ .../collector/tests/trace_collector_test.cpp | 35 ++ .../heap/space/tests/from_space_test.cpp | 89 ++++ common_components/heap/tests/BUILD.gn | 85 ++++ .../heap/tests/verification_test.cpp | 286 ++++++++++++ .../w_collector/tests/w_collector_test.cpp | 398 +++++++++++++++- common_components/log/tests/log_test.cpp | 5 + .../mutator/tests/mutator_manager_test.cpp | 29 +- .../objects/tests/base_string_test.cpp | 425 ++++++++++++++++++ common_components/profiler/tests/BUILD.gn | 57 +++ .../tests/common_profiler_interface_test.cpp | 96 ++++ common_components/serialize/tests/BUILD.gn | 57 +++ .../serialize/tests/serialize_utils_test.cpp | 57 +++ common_components/taskpool/tests/BUILD.gn | 107 +++++ .../taskpool/tests/task_queue_test.cpp | 115 +++++ .../taskpool/tests/taskpool_test.cpp | 127 ++++++ common_components/tests/ohos_test.xml | 105 +++++ 27 files changed, 2954 insertions(+), 182 deletions(-) create mode 100644 common_components/base/tests/utf_helper_test.cpp create mode 100644 common_components/heap/collector/tests/collector_proxy_test.cpp create mode 100644 common_components/heap/space/tests/from_space_test.cpp create mode 100644 common_components/heap/tests/BUILD.gn create mode 100644 common_components/heap/tests/verification_test.cpp create mode 100644 common_components/profiler/tests/BUILD.gn create mode 100644 common_components/profiler/tests/common_profiler_interface_test.cpp create mode 100644 common_components/serialize/tests/BUILD.gn create mode 100644 common_components/serialize/tests/serialize_utils_test.cpp create mode 100644 common_components/taskpool/tests/BUILD.gn create mode 100644 common_components/taskpool/tests/task_queue_test.cpp create mode 100644 common_components/taskpool/tests/taskpool_test.cpp diff --git a/BUILD.gn b/BUILD.gn index 55d9cf0cad..931fbff1d4 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -159,16 +159,21 @@ group("common_components_js_unittest") { deps += [ "common_components/base/tests:unittest", "common_components/common_runtime/tests:unittest", - - #"common_components/heap/allocator/tests:unittest", + "common_components/common/tests:unittest", + "common_components/heap/allocator/tests:unittest", "common_components/heap/barrier/tests:unittest", - - #"common_components/heap/collector/tests:unittest", + "common_components/heap/collector/tests:unittest", + "common_components/heap/space/tests:unittest", "common_components/heap/w_collector/tests:unittest", + "common_components/heap/tests:unittest", "common_components/mutator/tests:unittest", "common_components/objects/tests:unittest", + "common_components/profiler/tests:unittest", + "common_components/serialize/tests:unittest", "common_components/thread/tests:unittest", "common_components/log/tests:unittest", + "common_components/platform/unix/tests:unittest", + "common_components/taskpool/tests:unittest", ] } } @@ -181,16 +186,21 @@ group("common_components_unittest") { deps += [ "common_components/base/tests:host_unittest", "common_components/common_runtime/tests:host_unittest", - - #"common_components/heap/allocator/tests:host_unittest", + "common_components/common/tests:host_unittest", + "common_components/heap/allocator/tests:host_unittest", "common_components/heap/barrier/tests:host_unittest", - - #"common_components/heap/collector/tests:host_unittest", + "common_components/heap/collector/tests:host_unittest", + "common_components/heap/space/tests:host_unittest", "common_components/heap/w_collector/tests:host_unittest", + "common_components/heap/tests:host_unittest", "common_components/mutator/tests:host_unittest", "common_components/objects/tests:host_unittest", + "common_components/profiler/tests:host_unittest", + "common_components/serialize/tests:host_unittest", "common_components/thread/tests:host_unittest", "common_components/log/tests:host_unittest", + "common_components/platform/unix/tests:host_unittest", + "common_components/taskpool/tests:host_unittest", ] } } diff --git a/common_components/base/tests/BUILD.gn b/common_components/base/tests/BUILD.gn index 39e86f58d2..b539cdb7f8 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 56b0436ac5..704e27c728 100755 --- a/common_components/base/tests/c_string_test.cpp +++ b/common_components/base/tests/c_string_test.cpp @@ -15,7 +15,6 @@ #include "common_components/base/c_string.h" #include "common_components/tests/test_helper.h" -#include using namespace common; namespace common::test { @@ -274,4 +273,137 @@ HWTEST_F_L0(CStringTest, ConstructTest) EXPECT_EQ(nonEmptyStr.Length(), static_cast(0)); EXPECT_EQ(nonEmptyStr.Str()[0], '\0'); } + +HWTEST_F_L0(CStringTest, FormatStringBasicTest) +{ + CString result = CString::FormatString("Hello, %s!", "World"); + EXPECT_STREQ(result.Str(), "Hello, World!"); +} + +HWTEST_F_L0(CStringTest, FormatString_InvalidArguments_ReturnsError) +{ + CString result = CString::FormatString("%n", nullptr); + EXPECT_STREQ(result.Str(), "invalid arguments for FormatString"); +} + +HWTEST_F_L0(CStringTest, InsertMiddle_Success) +{ + CString str("helloworld"); + EXPECT_STREQ(str.Insert(5, ", ").Str(), "hello, world"); +} + +HWTEST_F_L0(CStringTest, TruncateValidIndex_Success) +{ + CString str("hello world"); + EXPECT_STREQ(str.Truncate(5).Str(), "hello"); + EXPECT_EQ(str.Length(), static_cast(5)); +} + +HWTEST_F_L0(CStringTest, GetStr_NonEmptyString_ReturnsCorrect) +{ + CString str("test string"); + EXPECT_STREQ(str.GetStr(), "test string"); +} + +HWTEST_F_L0(CStringTest, CombineWithEmptyString_ReturnsOriginal) +{ + CString str("original"); + CString emptyStr; + CString combined = str.Combine(emptyStr); + EXPECT_STREQ(combined.Str(), "original"); + EXPECT_EQ(combined.Length(), str.Length()); +} + +HWTEST_F_L0(CStringTest, CombineWithEmptyCStr_ReturnsOriginal) +{ + CString str("original"); + const char* emptyCStr = ""; + CString combined = str.Combine(emptyCStr); + EXPECT_STREQ(combined.Str(), "original"); + EXPECT_EQ(combined.Length(), str.Length()); +} + +HWTEST_F_L0(CStringTest, AppendNullptr_NoChange) +{ + CString str("original"); + str.Append(nullptr, 5); + EXPECT_STREQ(str.Str(), "original"); + EXPECT_EQ(str.Length(), strlen("original")); +} + +HWTEST_F_L0(CStringTest, AppendZeroLength_NoChange) +{ + CString str("test"); + CString emptyStr; + + str.Append(emptyStr, 0); + + EXPECT_STREQ(str.Str(), "test"); + EXPECT_EQ(str.Length(), strlen("test")); +} + +HWTEST_F_L0(CStringTest, AppendSelf_ValidResult) +{ + CString str("abc"); + str.Append(str.Str(), str.Length()); + EXPECT_STREQ(str.Str(), "abcabc"); + EXPECT_EQ(str.Length(), strlen("abcabc")); +} + +HWTEST_F_L0(CStringTest, AppendEmptyCString_NoChange) +{ + CString str("original"); + CString emptyStr; + str.Append(emptyStr); + EXPECT_STREQ(str.Str(), "original"); + EXPECT_EQ(str.Length(), strlen("original")); +} + +HWTEST_F_L0(CStringTest, AppendEmptyCStringZeroLength_NoChange) +{ + CString str("test"); + CString emptyStr; + + str.Append(emptyStr, 0); + + EXPECT_STREQ(str.Str(), "test"); + EXPECT_EQ(str.Length(), strlen("test")); +} + +HWTEST_F_L0(CStringTest, AppendValidCString_CorrectResult) +{ + CString str("hello"); + CString addStr(" world!"); + str.Append(addStr, strlen(addStr.Str())); + EXPECT_STREQ(str.Str(), "hello world!"); + EXPECT_EQ(str.Length(), strlen("hello world!")); +} + +HWTEST_F_L0(CStringTest, EnsureMultipleCalls_CapacityGrowsCorrectly) +{ + CString str("initial"); + char* firstPtr = str.GetStr(); + + str.EnsureSpace(16); + char* secondPtr = str.GetStr(); + + EXPECT_NE(firstPtr, secondPtr); + + str.EnsureSpace(100); + char* thirdPtr = str.GetStr(); + + EXPECT_NE(secondPtr, thirdPtr); + EXPECT_EQ(str.Length(), strlen("initial")); + EXPECT_STREQ(str.Str(), "initial"); +} + +HWTEST_F_L0(CStringTest, CStringSubscriptOperatorTest) +{ + const CString constStr("hello world"); + EXPECT_EQ(constStr[0], 'h'); + + CString mutableStr("mutable"); + mutableStr[0] = 'M'; + EXPECT_EQ(mutableStr[0], 'M'); +} } \ No newline at end of file diff --git a/common_components/base/tests/utf_helper_test.cpp b/common_components/base/tests/utf_helper_test.cpp new file mode 100644 index 0000000000..a6bd777ea9 --- /dev/null +++ b/common_components/base/tests/utf_helper_test.cpp @@ -0,0 +1,329 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "common_components/base/utf_helper.h" +#include "common_components/tests/test_helper.h" + +using namespace common; +namespace common::test { +class UtfHelperTest : public common::test::BaseTestWithScope { +}; + +HWTEST_F_L0(UtfHelperTest, DecodeUTF16Test1) +{ + uint16_t utf16[] = {0xD7FF}; + size_t index = 0; + size_t len = 1; + uint32_t result = utf_helper::DecodeUTF16(utf16, len, &index, false); + EXPECT_EQ(result, 0xD7FF); + + uint16_t utf16In[] = {0xDC00}; + result = utf_helper::DecodeUTF16(utf16In, len, &index, false); + EXPECT_EQ(result, 0xDC00); + + uint16_t utf16In1[] = {0xD800}; + result = utf_helper::DecodeUTF16(utf16In1, len, &index, false); + EXPECT_EQ(result, 0xD800); + + uint16_t utf16In2[] = {0xD7FF}; + len = 2; + result = utf_helper::DecodeUTF16(utf16In2, len, &index, false); + EXPECT_EQ(result, 0xD7FF); + + len = 1; + result = utf_helper::DecodeUTF16(utf16In2, len, &index, false); + EXPECT_EQ(result, 0xD7FF); + + result = utf_helper::DecodeUTF16(utf16In, len, &index, false); + EXPECT_EQ(result, 0xDC00); +} + +HWTEST_F_L0(UtfHelperTest, DecodeUTF16Test2) +{ + size_t index = 0; + uint16_t utf16[] = {0xD800, 0xDC00}; + size_t len = 2; + utf16[1] = 0xFFFF; + uint32_t result = utf_helper::DecodeUTF16(utf16, len, &index, false); + EXPECT_EQ(result, 0xD800); +} + +HWTEST_F_L0(UtfHelperTest, DecodeUTF16Test3) +{ + size_t index = 0; + uint16_t utf16[] = {0xD800, 0xDC00}; + size_t len = 2; + uint32_t result = utf_helper::DecodeUTF16(utf16, len, &index, true); + EXPECT_EQ(result, 0xD800); + + uint16_t utf16In[] = {0xD800, 0x0041}; + result = utf_helper::DecodeUTF16(utf16In, len, &index, false); + EXPECT_EQ(result, 0xD800); +} + +HWTEST_F_L0(UtfHelperTest, HandleAndDecodeInvalidUTF16Test1) +{ + uint16_t input[] = {0xDC00}; + size_t index = 0; + size_t len = sizeof(input) / sizeof(input[0]); + uint32_t result = utf_helper::HandleAndDecodeInvalidUTF16(input, len, &index); + EXPECT_EQ(result, utf_helper::UTF16_REPLACEMENT_CHARACTER); +} + +HWTEST_F_L0(UtfHelperTest, HandleAndDecodeInvalidUTF16Test2) +{ + uint16_t input[] = {0xD800}; + size_t index = 0; + size_t len = sizeof(input) / sizeof(input[0]); + uint32_t result = utf_helper::HandleAndDecodeInvalidUTF16(input, len, &index); + EXPECT_EQ(result, utf_helper::UTF16_REPLACEMENT_CHARACTER); + + uint16_t input1[] = {0xD800, 0xD800}; + size_t len1 = sizeof(input1) / sizeof(input1[0]); + result = utf_helper::HandleAndDecodeInvalidUTF16(input1, len1, &index); + EXPECT_EQ(result, utf_helper::UTF16_REPLACEMENT_CHARACTER); + + uint16_t input2[] = {'A'}; + size_t len2 = sizeof(input2) / sizeof(input2[0]); + result = utf_helper::HandleAndDecodeInvalidUTF16(input2, len2, &index); + EXPECT_EQ(result, 'A'); + + uint16_t input3[] = {0xD800 ^ 0x01}; + size_t len3 = sizeof(input3) / sizeof(input3[0]); + result = utf_helper::HandleAndDecodeInvalidUTF16(input3, len3, &index); + EXPECT_EQ(result, utf_helper::UTF16_REPLACEMENT_CHARACTER); +} + +HWTEST_F_L0(UtfHelperTest, HandleAndDecodeInvalidUTF16Test3) +{ + uint16_t input[] = {0xDBFF, 0xDFFF}; + size_t index = 0; + size_t len = sizeof(input) / sizeof(input[0]); + uint32_t expected = ((0xDBFF - utf_helper::DECODE_LEAD_LOW) << utf_helper::UTF16_OFFSET) + + (0xDFFF - utf_helper::DECODE_TRAIL_LOW) + utf_helper::DECODE_SECOND_FACTOR; + uint32_t result = utf_helper::HandleAndDecodeInvalidUTF16(input, len, &index); + EXPECT_EQ(result, expected); +} + +HWTEST_F_L0(UtfHelperTest, HandleAndDecodeInvalidUTF16Test4) +{ + uint16_t input[] = {0xD800, 0xDC00}; + size_t index = 0; + size_t len = sizeof(input) / sizeof(input[0]); + uint32_t expected = ((0xD800 - utf_helper::DECODE_LEAD_LOW) << utf_helper::UTF16_OFFSET) + + (0xDC00 - utf_helper::DECODE_TRAIL_LOW) + utf_helper::DECODE_SECOND_FACTOR; + uint32_t result = utf_helper::HandleAndDecodeInvalidUTF16(input, len, &index); + EXPECT_EQ(result, expected); + EXPECT_EQ(index, 1); +} + +HWTEST_F_L0(UtfHelperTest, IsValidUTF8Test1) +{ + std::vector data = {0xED, 0xA0, 0x80}; + EXPECT_FALSE(utf_helper::IsValidUTF8(data)); + + std::vector data1 = {0xED, 0x90, 0x80}; + EXPECT_TRUE(utf_helper::IsValidUTF8(data1)); + + std::vector data2 = {0xED, 0xC0, 0x80}; + EXPECT_FALSE(utf_helper::IsValidUTF8(data2)); + + std::vector data3 = {0xED, 0x80, 0x80}; + EXPECT_TRUE(utf_helper::IsValidUTF8(data3)); + + std::vector data4 = {0xE0, 0xA0, 0x80}; + EXPECT_TRUE(utf_helper::IsValidUTF8(data4)); +} + +HWTEST_F_L0(UtfHelperTest, IsValidUTF8Test2) +{ + std::vector data = {0xF4, 0x90, 0x80, 0x80}; + EXPECT_FALSE(utf_helper::IsValidUTF8(data)); + + std::vector data1 = {0xF5, 0x80, 0x80, 0x80}; + EXPECT_FALSE(utf_helper::IsValidUTF8(data1)); + + std::vector data2 = {0xF0, 0x90, 0x80, 0x80}; + EXPECT_TRUE(utf_helper::IsValidUTF8(data2)); + + std::vector data3 = {0xF1, 0x80, 0x80, 0x80}; + EXPECT_TRUE(utf_helper::IsValidUTF8(data3)); + + std::vector data4 = {0xF4, 0x80, 0x80, 0x80}; + EXPECT_TRUE(utf_helper::IsValidUTF8(data4)); +} + +HWTEST_F_L0(UtfHelperTest, ConvertRegionUtf16ToUtf8Test3) +{ + uint8_t utf8Out[10]; + size_t result = utf_helper::ConvertRegionUtf16ToUtf8(nullptr, utf8Out, 5, 10, 0, false, false, false); + EXPECT_EQ(result, 0); + + uint16_t utf16In[] = {0x0041}; + result = utf_helper::ConvertRegionUtf16ToUtf8(utf16In, nullptr, 1, sizeof(utf16In), 0, false, false, false); + EXPECT_EQ(result, 0); + + result = utf_helper::ConvertRegionUtf16ToUtf8(utf16In, utf8Out, 1, 0, 0, false, false, false); + EXPECT_EQ(result, 0); + + result = utf_helper::ConvertRegionUtf16ToUtf8(nullptr, utf8Out, 1, 0, 0, false, false, false); + EXPECT_EQ(result, 0); + + result = utf_helper::ConvertRegionUtf16ToUtf8(utf16In, nullptr, 1, 0, 0, false, false, false); + EXPECT_EQ(result, 0); + + result = utf_helper::ConvertRegionUtf16ToUtf8(nullptr, nullptr, 1, sizeof(utf8Out), 0, false, false, false); + EXPECT_EQ(result, 0); + + result = utf_helper::ConvertRegionUtf16ToUtf8(nullptr, nullptr, 1, 0, 0, false, false, false); + EXPECT_EQ(result, 0); + + result = utf_helper::ConvertRegionUtf16ToUtf8(utf16In, utf8Out, 1, sizeof(utf8Out), 0, false, false, false); + EXPECT_EQ(result, 1); +} + +HWTEST_F_L0(UtfHelperTest, ConvertRegionUtf16ToLatin1Test) +{ + uint8_t utf8Out[10]; + size_t result = utf_helper::ConvertRegionUtf16ToLatin1(nullptr, utf8Out, 5, 10); + EXPECT_EQ(result, 0); + + uint16_t utf16In[] = {0x0041}; + result = utf_helper::ConvertRegionUtf16ToLatin1(utf16In, nullptr, 1, sizeof(utf16In)); + EXPECT_EQ(result, 0); + + result = utf_helper::ConvertRegionUtf16ToLatin1(utf16In, utf8Out, 1, 0); + EXPECT_EQ(result, 0); + + result = utf_helper::ConvertRegionUtf16ToLatin1(nullptr, utf8Out, 1, 0); + EXPECT_EQ(result, 0); + + result = utf_helper::ConvertRegionUtf16ToLatin1(utf16In, nullptr, 1, 0); + EXPECT_EQ(result, 0); + + result = utf_helper::ConvertRegionUtf16ToLatin1(nullptr, nullptr, 1, sizeof(utf8Out)); + EXPECT_EQ(result, 0); + + result = utf_helper::ConvertRegionUtf16ToLatin1(nullptr, nullptr, 1, 0); + EXPECT_EQ(result, 0); + + result = utf_helper::ConvertRegionUtf16ToLatin1(utf16In, utf8Out, 1, sizeof(utf8Out)); + EXPECT_EQ(result, 1); + + const uint16_t input[] = {0x0041, 0x0042, 0x0043}; + uint8_t output[2] = {0}; + result = utf_helper::ConvertRegionUtf16ToLatin1(input, output, 3, 2); + EXPECT_EQ(result, 2); +} + +HWTEST_F_L0(UtfHelperTest, DebuggerConvertRegionUtf16ToUtf8Test) +{ + uint8_t utf8Out[10]; + size_t result = utf_helper::DebuggerConvertRegionUtf16ToUtf8(nullptr, utf8Out, 5, sizeof(utf8Out), 0, false, false); + EXPECT_EQ(result, 0); + + uint16_t utf16In[] = {0x0041}; + result = utf_helper::DebuggerConvertRegionUtf16ToUtf8(utf16In, nullptr, 1, sizeof(utf16In), 0, false, false); + EXPECT_EQ(result, 0); + + result = utf_helper::DebuggerConvertRegionUtf16ToUtf8(nullptr, nullptr, 1, sizeof(utf8Out), 0, false, false); + EXPECT_EQ(result, 0); + + result = utf_helper::DebuggerConvertRegionUtf16ToUtf8(nullptr, utf8Out, 1, 0, 0, false, false); + EXPECT_EQ(result, 0); + + result = utf_helper::DebuggerConvertRegionUtf16ToUtf8(nullptr, utf8Out, 1, 0, 0, false, false); + EXPECT_EQ(result, 0); + + result = utf_helper::DebuggerConvertRegionUtf16ToUtf8(nullptr, nullptr, 1, 0, 0, false, false); + EXPECT_EQ(result, 0); + + result = utf_helper::DebuggerConvertRegionUtf16ToUtf8(utf16In, utf8Out, 1, 0, 0, false, false); + EXPECT_EQ(result, 0); + + result = utf_helper::DebuggerConvertRegionUtf16ToUtf8(utf16In, utf8Out, 1, sizeof(utf8Out), 0, false, false); + EXPECT_EQ(result, 1); + + uint16_t utf16In1[] = {0x0041, 0x0042, 0x0043}; + result = utf_helper::DebuggerConvertRegionUtf16ToUtf8(utf16In1, nullptr, 3, 0, 0, false, false); + EXPECT_EQ(result, 0); +} + +HWTEST_F_L0(UtfHelperTest, DecodeUTF16Test4) +{ + uint16_t utf16[] = {0xD800, 0xDC00}; + size_t index = 0; + size_t len = sizeof(utf16) / sizeof(utf16[0]); + + uint32_t result = utf_helper::DecodeUTF16(utf16, len, &index, false); + EXPECT_EQ(result, 0x10000); + EXPECT_EQ(index, 1); +} + +HWTEST_F_L0(UtfHelperTest, Utf8ToUtf16Size_LastByteIsTwoByteStart_TrimLastByte) +{ + const uint8_t utf8[] = {0xC0}; + size_t utf8Len = sizeof(utf8); + + size_t result = utf_helper::Utf8ToUtf16Size(utf8, utf8Len); + EXPECT_EQ(result, 1); +} + +HWTEST_F_L0(UtfHelperTest, Utf8ToUtf16Size_LastTwoBytesStartWithThreeByteHeader_TrimTwoBytes) +{ + const uint8_t utf8[] = {0xE2, 0x82}; + size_t utf8Len = sizeof(utf8); + + size_t result = utf_helper::Utf8ToUtf16Size(utf8, utf8Len); + EXPECT_EQ(result, 2); +} + +HWTEST_F_L0(UtfHelperTest, Utf8ToUtf16Size_IncompleteSequenceAtEnd_ReturnsSizeWithoutInvalid) +{ + const uint8_t utf8[] = {0xF0, 0x90, 0x8D}; + size_t result = utf_helper::Utf8ToUtf16Size(utf8, 3); + EXPECT_EQ(result, 3); +} + +HWTEST_F_L0(UtfHelperTest, DebuggerConvertRegionUtf16ToUtf8_ZeroCodepoint_WriteNulChar) +{ + uint16_t utf16In[] = {0x0000}; + uint8_t utf8Out[10] = {0}; + size_t utf16Len = 1; + size_t utf8Len = sizeof(utf8Out); + size_t start = 0; + bool modify = false; + bool isWriteBuffer = true; + + size_t result = utf_helper::DebuggerConvertRegionUtf16ToUtf8( + utf16In, utf8Out, utf16Len, utf8Len, start, modify, isWriteBuffer); + + EXPECT_EQ(result, 1); + EXPECT_EQ(utf8Out[0], 0x00U); +} + +HWTEST_F_L0(UtfHelperTest, ConvertUtf16ToUtf8_NulChar_WriteBufferMode_ReturnsZeroByte) +{ + uint16_t d0 = 0x0000; + uint16_t d1 = 0; + bool modify = false; + bool isWriteBuffer = true; + + utf_helper::Utf8Char result = utf_helper::ConvertUtf16ToUtf8(d0, d1, modify, isWriteBuffer); + + EXPECT_EQ(result.n, 1); + EXPECT_EQ(result.ch[0], 0x00U); +} +} // namespace common::test \ No newline at end of file diff --git a/common_components/heap/allocator/tests/allocator_test.cpp b/common_components/heap/allocator/tests/allocator_test.cpp index 58820668fc..c7d02c39d7 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 f23fb161ee..be2b6faa6f 100644 --- a/common_components/heap/allocator/tests/heap_allocator_test.cpp +++ b/common_components/heap/allocator/tests/heap_allocator_test.cpp @@ -13,15 +13,11 @@ * limitations under the License. */ -#include - #include "common_interfaces/heap/heap_allocator.h" +#include "common_components/heap/allocator/region_desc.h" #include "common_components/heap/allocator/region_space.h" -#include "common_components/heap/collector/trace_collector.h" -#include "common_components/heap/heap.cpp" -#include "common_components/common_runtime/base_runtime_param.h" -#include "common_components/heap/heap_manager.h" #include "common_components/tests/test_helper.h" +#include "common_interfaces/base_runtime.h" using namespace common; @@ -36,7 +32,11 @@ class HeapAllocatorTest : public BaseTestWithScope { void TearDown() override { - delete scope_; + if (scope_ != nullptr) { + delete scope_; + scope_ = nullptr; + } + BaseRuntime::GetInstance()->Fini(); } @@ -46,7 +46,7 @@ class HeapAllocatorTest : public BaseTestWithScope { HWTEST_F_L0(HeapAllocatorTest, AllocLargeObject) { - uintptr_t addr = common::HeapAllocator::Allocate(Heap::NORMAL_UNIT_SIZE, common::LanguageType::DYNAMIC); + uintptr_t addr = common::HeapAllocator::AllocateInHuge(Heap::NORMAL_UNIT_SIZE, common::LanguageType::DYNAMIC); ASSERT(addr > 0); RegionDesc* region = RegionDesc::GetAliveRegionDescAt(addr); ASSERT(region->IsLargeRegion()); diff --git a/common_components/heap/allocator/tests/region_manager_test.cpp b/common_components/heap/allocator/tests/region_manager_test.cpp index 8fe0bece36..03fe4628b8 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,96 @@ HWTEST_F_L0(RegionManagerTest, AllocReadOnly7) manager.ClearAllGCInfo(); ThreadLocal::SetThreadType(ThreadType::ARK_PROCESSOR); uintptr_t ret = manager.AllocReadOnly(sizeof(RegionDesc), false); - RegionDesc* region = RegionDesc::GetRegionDescAt(ret); EXPECT_NE(ret, 0); - EXPECT_EQ(region->GetTraceLine(), std::numeric_limits::max()); - EXPECT_EQ(region->GetCopyLine(), std::numeric_limits::max()); - EXPECT_EQ(region->GetFixLine(), std::numeric_limits::max()); +} + +HWTEST_F_L0(RegionManagerTest, VisitRememberSetTest) +{ + size_t totalUnits = 1024; + size_t heapSize = totalUnits * RegionDesc::UNIT_SIZE; + + void* regionMemory = malloc(heapSize + 4096); + ASSERT_NE(regionMemory, nullptr); + + uintptr_t heapStartAddress = reinterpret_cast(regionMemory); + uintptr_t regionInfoAddr = heapStartAddress + 4096; + + RegionManager manager; + manager.Initialize(totalUnits, regionInfoAddr); + + size_t unitIdx = 0; + size_t nUnit = 4; + RegionDesc* region = RegionDesc::InitRegion(unitIdx, nUnit, RegionDesc::UnitRole::LARGE_SIZED_UNITS); + ASSERT_NE(region, nullptr); + + manager.MarkRememberSet([&](BaseObject* obj) {}); + + int callbackCount = 0; + region->VisitRememberSet([&](BaseObject* obj) { + callbackCount++; + }); + + EXPECT_GE(callbackCount, 0); + free(regionMemory); +} + +HWTEST_F_L0(RegionManagerTest, VisitRememberSetBeforeCopyTest) +{ + size_t totalUnits = 1024; + size_t heapSize = totalUnits * RegionDesc::UNIT_SIZE; + + void* regionMemory = malloc(heapSize + 4096); + ASSERT_NE(regionMemory, nullptr); + + uintptr_t heapStartAddress = reinterpret_cast(regionMemory); + uintptr_t regionInfoAddr = heapStartAddress + 4096; + + RegionManager manager; + manager.Initialize(totalUnits, regionInfoAddr); + + size_t unitIdx = 0; + size_t nUnit = 4; + RegionDesc* region = RegionDesc::InitRegion(unitIdx, nUnit, RegionDesc::UnitRole::LARGE_SIZED_UNITS); + ASSERT_NE(region, nullptr); + + manager.MarkRememberSet([&](BaseObject* obj) {}); + + int callbackCount = 0; + region->VisitRememberSetBeforeCopy([&](BaseObject* obj) { + callbackCount++; + }); + + EXPECT_GE(callbackCount, 0); + free(regionMemory); +} + +HWTEST_F_L0(RegionManagerTest, VisitRememberSetBeforeTraceTest) +{ + size_t totalUnits = 1024; + size_t heapSize = totalUnits * RegionDesc::UNIT_SIZE; + + void* regionMemory = malloc(heapSize + 4096); + ASSERT_NE(regionMemory, nullptr); + + uintptr_t heapStartAddress = reinterpret_cast(regionMemory); + uintptr_t regionInfoAddr = heapStartAddress + 4096; + + RegionManager manager; + manager.Initialize(totalUnits, regionInfoAddr); + + size_t unitIdx = 0; + size_t nUnit = 4; + RegionDesc* region = RegionDesc::InitRegion(unitIdx, nUnit, RegionDesc::UnitRole::LARGE_SIZED_UNITS); + ASSERT_NE(region, nullptr); + + manager.MarkRememberSet([&](BaseObject* obj) {}); + + int callbackCount = 0; + region->VisitRememberSetBeforeTrace([&](BaseObject* obj) { + callbackCount++; + }); + + EXPECT_GE(callbackCount, 0); + free(regionMemory); } } diff --git a/common_components/heap/allocator/tests/region_space_test.cpp b/common_components/heap/allocator/tests/region_space_test.cpp index f7ccc043a5..11b0bbef35 100755 --- a/common_components/heap/allocator/tests/region_space_test.cpp +++ b/common_components/heap/allocator/tests/region_space_test.cpp @@ -13,96 +13,56 @@ * limitations under the License. */ -#include "common_interfaces/heap/heap_allocator.h" +#include "common_components/heap/allocator/region_desc.h" #include "common_components/heap/allocator/region_space.h" -#include "common_components/heap/collector/trace_collector.h" -#include "common_components/heap/heap.cpp" -#include "common_components/common_runtime/base_runtime_param.h" -#include "common_components/heap/heap_manager.h" +#include "common_components/heap/allocator/region_space.cpp" +#include "common_components/heap/collector/collector_resources.h" #include "common_components/tests/test_helper.h" -#include +#include "common_interfaces/base_runtime.h" using namespace common; namespace common::test { class RegionSpaceTest : public common::test::BaseTestWithScope { -protected: - void* regionMemory_; - size_t totalUnits_ = 1024; - size_t heapSize_; - Mutator* mutator_ = nullptr; - - static void SetUpTestCase() - { - BaseRuntime::GetInstance()->Init(); - } - - static void TearDownTestCase() - { - BaseRuntime::GetInstance()->Fini(); - } - void SetUp() override { - heapSize_ = totalUnits_ * RegionDesc::UNIT_SIZE; - size_t allocSize = heapSize_ + totalUnits_ * sizeof(RegionDesc); - regionMemory_ = malloc(allocSize); - ASSERT_NE(regionMemory_, nullptr); - uintptr_t unitInfoStart = reinterpret_cast(regionMemory_); - size_t metadataSize = totalUnits_ * sizeof(RegionDesc); - uintptr_t heapStartAddress = unitInfoStart + metadataSize; - RegionDesc::Initialize(totalUnits_, unitInfoStart, heapStartAddress); - mutator_ = Mutator::NewMutator(); - ASSERT_NE(mutator_, nullptr); - mutator_->InitTid(); - ThreadLocal::GetThreadLocalData()->mutator = mutator_; - BaseRuntime::GetInstance()->GetHeapParam().regionSize = 64; // 64:region size - RegionSpace& theAllocator = reinterpret_cast(Heap::GetHeap().GetAllocator()); - RegionManager& regionManager = theAllocator.GetRegionManager(); - regionManager.SetMaxUnitCountForRegion(); + BaseRuntime::GetInstance()->Init(); + holder_ = ThreadHolder::CreateAndRegisterNewThreadHolder(nullptr); + scope_ = new ThreadHolder::TryBindMutatorScope(holder_); } void TearDown() override { - if (mutator_) { - delete mutator_; - mutator_ = nullptr; - } - if (regionMemory_) { - free(regionMemory_); - regionMemory_ = nullptr; + if (scope_ != nullptr) { + delete scope_; + scope_ = nullptr; } + + BaseRuntime::GetInstance()->Fini(); } -}; -HWTEST_F_L0(RegionSpaceTest, ShouldRetryAllocation) -{ - auto* mutator = common::Mutator::GetMutator(); - mutator->SetMutatorPhase(GCPhase::GC_PHASE_UNDEF); - ThreadLocal::SetThreadType(ThreadType::GC_THREAD); - Heap::GetHeap().EnableGC(false); - Heap::GetHeap().GetCollectorResources().SetGcStarted(true); - Allocator *regionSpace = RegionSpace::CreateAllocator(); - EXPECT_EQ(regionSpace->Allocate(16, AllocType::MOVEABLE_OBJECT), 0); -} + ThreadHolder *holder_ {nullptr}; + ThreadHolder::TryBindMutatorScope *scope_ {nullptr}; +}; HWTEST_F_L0(RegionSpaceTest, FeedHungryBuffers2) { auto* mutator = common::Mutator::GetMutator(); mutator->SetMutatorPhase(GCPhase::GC_PHASE_FIX); - RegionSpace& theAllocator = reinterpret_cast(Heap::GetHeap().GetAllocator()); - RegionManager& manager = theAllocator.GetRegionManager(); ThreadLocal::SetThreadType(ThreadType::ARK_PROCESSOR); - manager.Initialize(1024, reinterpret_cast(regionMemory_)); AllocationBuffer* buffer1 = new (std::nothrow) AllocationBuffer(); AllocationBuffer* buffer2 = new (std::nothrow) AllocationBuffer(); - RegionDesc* Region = RegionDesc::InitRegion(0, 1, RegionDesc::UnitRole::SMALL_SIZED_UNITS); - buffer1->SetPreparedRegion(Region); + RegionDesc* region = RegionDesc::InitRegion(0, 1, RegionDesc::UnitRole::LARGE_SIZED_UNITS); + region->InitFreeUnits(); + buffer1->SetPreparedRegion(region); + buffer2->SetPreparedRegion(region); Heap::GetHeap().GetAllocator().AddHungryBuffer(*buffer1); Heap::GetHeap().GetAllocator().AddHungryBuffer(*buffer2); Heap::GetHeap().GetAllocator().FeedHungryBuffers(); EXPECT_NE(buffer2->GetPreparedRegion(), nullptr); + delete buffer1; + delete buffer2; } HWTEST_F_L0(RegionSpaceTest, FeedHungryBuffers3) @@ -115,57 +75,52 @@ HWTEST_F_L0(RegionSpaceTest, FeedHungryBuffers3) EXPECT_EQ(hungryBuffers.size(), 0); } - HWTEST_F_L0(RegionSpaceTest, AllocRegion_PhaseEnum) { - ASSERT_NE(mutator_, nullptr); - mutator_->SetMutatorPhase(GCPhase::GC_PHASE_ENUM); + auto* mutator = common::Mutator::GetMutator(); + mutator->SetMutatorPhase(GCPhase::GC_PHASE_ENUM); RegionSpace& theAllocator = reinterpret_cast(Heap::GetHeap().GetAllocator()); uintptr_t addr = theAllocator.AllocOldRegion(); ASSERT_NE(addr, 0); RegionDesc* region = RegionDesc::GetAliveRegionDescAt(addr); EXPECT_EQ(region->GetTraceLine(), region->GetRegionStart()); EXPECT_EQ(region->GetCopyLine(), std::numeric_limits::max()); - EXPECT_EQ(region->GetFixLine(), std::numeric_limits::max()); } HWTEST_F_L0(RegionSpaceTest, AllocRegion_PhaseMark) { - ASSERT_NE(mutator_, nullptr); - mutator_->SetMutatorPhase(GCPhase::GC_PHASE_MARK); + auto* mutator = common::Mutator::GetMutator(); + mutator->SetMutatorPhase(GCPhase::GC_PHASE_MARK); RegionSpace& theAllocator = reinterpret_cast(Heap::GetHeap().GetAllocator()); uintptr_t addr = theAllocator.AllocOldRegion(); ASSERT_NE(addr, 0); RegionDesc* region = RegionDesc::GetAliveRegionDescAt(addr); EXPECT_EQ(region->GetTraceLine(), region->GetRegionStart()); EXPECT_EQ(region->GetCopyLine(), std::numeric_limits::max()); - EXPECT_EQ(region->GetFixLine(), std::numeric_limits::max()); } HWTEST_F_L0(RegionSpaceTest, AllocRegion_PhaseRemarkStab) { - ASSERT_NE(mutator_, nullptr); - mutator_->SetMutatorPhase(GCPhase::GC_PHASE_REMARK_SATB); + auto* mutator = common::Mutator::GetMutator(); + mutator->SetMutatorPhase(GCPhase::GC_PHASE_REMARK_SATB); RegionSpace& theAllocator = reinterpret_cast(Heap::GetHeap().GetAllocator()); uintptr_t addr = theAllocator.AllocOldRegion(); ASSERT_NE(addr, 0); RegionDesc* region = RegionDesc::GetAliveRegionDescAt(addr); EXPECT_EQ(region->GetTraceLine(), region->GetRegionStart()); EXPECT_EQ(region->GetCopyLine(), std::numeric_limits::max()); - EXPECT_EQ(region->GetFixLine(), std::numeric_limits::max()); } HWTEST_F_L0(RegionSpaceTest, AllocRegion_PhasePostMark) { - ASSERT_NE(mutator_, nullptr); - mutator_->SetMutatorPhase(GCPhase::GC_PHASE_POST_MARK); + auto* mutator = common::Mutator::GetMutator(); + mutator->SetMutatorPhase(GCPhase::GC_PHASE_POST_MARK); RegionSpace& theAllocator = reinterpret_cast(Heap::GetHeap().GetAllocator()); uintptr_t addr = theAllocator.AllocOldRegion(); ASSERT_NE(addr, 0); RegionDesc* region = RegionDesc::GetAliveRegionDescAt(addr); EXPECT_EQ(region->GetTraceLine(), region->GetRegionStart()); EXPECT_EQ(region->GetCopyLine(), std::numeric_limits::max()); - EXPECT_EQ(region->GetFixLine(), std::numeric_limits::max()); } HWTEST_F_L0(RegionSpaceTest, AllocRegion_PhasePrecopy) @@ -199,7 +154,6 @@ HWTEST_F_L0(RegionSpaceTest, AllocRegion_PhaseFix) ASSERT_NE(addr, 0); RegionDesc* region = RegionDesc::GetAliveRegionDescAt(addr); EXPECT_EQ(region->GetCopyLine(), region->GetRegionStart()); - EXPECT_EQ(region->GetFixLine(), region->GetRegionStart()); } HWTEST_F_L0(RegionSpaceTest, AllocRegion_PhaseUndef) @@ -211,59 +165,54 @@ HWTEST_F_L0(RegionSpaceTest, AllocRegion_PhaseUndef) ASSERT_NE(addr, 0); RegionDesc* region = RegionDesc::GetAliveRegionDescAt(addr); EXPECT_EQ(region->GetCopyLine(), std::numeric_limits::max()); - EXPECT_EQ(region->GetFixLine(), std::numeric_limits::max()); } HWTEST_F_L0(RegionSpaceTest, AllocPinnedRegion_PhaseEnum) { - ASSERT_NE(mutator_, nullptr); - mutator_->SetMutatorPhase(GCPhase::GC_PHASE_ENUM); + auto* mutator = common::Mutator::GetMutator(); + mutator->SetMutatorPhase(GCPhase::GC_PHASE_ENUM); RegionSpace& theAllocator = reinterpret_cast(Heap::GetHeap().GetAllocator()); uintptr_t addr = theAllocator.AllocPinnedRegion(); ASSERT_NE(addr, 0); RegionDesc* region = RegionDesc::GetAliveRegionDescAt(addr); EXPECT_EQ(region->GetTraceLine(), region->GetRegionStart()); EXPECT_EQ(region->GetCopyLine(), std::numeric_limits::max()); - EXPECT_EQ(region->GetFixLine(), std::numeric_limits::max()); } HWTEST_F_L0(RegionSpaceTest, AllocPinnedRegion_PhaseMark) { - ASSERT_NE(mutator_, nullptr); - mutator_->SetMutatorPhase(GCPhase::GC_PHASE_MARK); + auto* mutator = common::Mutator::GetMutator(); + mutator->SetMutatorPhase(GCPhase::GC_PHASE_MARK); RegionSpace& theAllocator = reinterpret_cast(Heap::GetHeap().GetAllocator()); uintptr_t addr = theAllocator.AllocPinnedRegion(); ASSERT_NE(addr, 0); RegionDesc* region = RegionDesc::GetAliveRegionDescAt(addr); EXPECT_EQ(region->GetTraceLine(), region->GetRegionStart()); EXPECT_EQ(region->GetCopyLine(), std::numeric_limits::max()); - EXPECT_EQ(region->GetFixLine(), std::numeric_limits::max()); } HWTEST_F_L0(RegionSpaceTest, AllocPinnedRegion_PhaseRemarkStab) { - ASSERT_NE(mutator_, nullptr); - mutator_->SetMutatorPhase(GCPhase::GC_PHASE_REMARK_SATB); + auto* mutator = common::Mutator::GetMutator(); + mutator->SetMutatorPhase(GCPhase::GC_PHASE_REMARK_SATB); RegionSpace& theAllocator = reinterpret_cast(Heap::GetHeap().GetAllocator()); uintptr_t addr = theAllocator.AllocPinnedRegion(); ASSERT_NE(addr, 0); RegionDesc* region = RegionDesc::GetAliveRegionDescAt(addr); EXPECT_EQ(region->GetTraceLine(), region->GetRegionStart()); EXPECT_EQ(region->GetCopyLine(), std::numeric_limits::max()); - EXPECT_EQ(region->GetFixLine(), std::numeric_limits::max()); } HWTEST_F_L0(RegionSpaceTest, AllocPinnedRegion_PhasePostMark) { - ASSERT_NE(mutator_, nullptr); - mutator_->SetMutatorPhase(GCPhase::GC_PHASE_POST_MARK); + auto* mutator = common::Mutator::GetMutator(); + mutator->SetMutatorPhase(GCPhase::GC_PHASE_POST_MARK); RegionSpace& theAllocator = reinterpret_cast(Heap::GetHeap().GetAllocator()); uintptr_t addr = theAllocator.AllocPinnedRegion(); ASSERT_NE(addr, 0); RegionDesc* region = RegionDesc::GetAliveRegionDescAt(addr); EXPECT_EQ(region->GetTraceLine(), region->GetRegionStart()); EXPECT_EQ(region->GetCopyLine(), std::numeric_limits::max()); - EXPECT_EQ(region->GetFixLine(), std::numeric_limits::max()); } HWTEST_F_L0(RegionSpaceTest, AllocPinnedRegion_PhasePrecopy) @@ -297,7 +246,6 @@ HWTEST_F_L0(RegionSpaceTest, AllocPinnedRegion_PhaseFix) ASSERT_NE(addr, 0); RegionDesc* region = RegionDesc::GetAliveRegionDescAt(addr); EXPECT_EQ(region->GetCopyLine(), region->GetRegionStart()); - EXPECT_EQ(region->GetFixLine(), region->GetRegionStart()); } HWTEST_F_L0(RegionSpaceTest, AllocPinnedRegion_PhaseUndef) @@ -309,7 +257,6 @@ HWTEST_F_L0(RegionSpaceTest, AllocPinnedRegion_PhaseUndef) ASSERT_NE(addr, 0); RegionDesc* region = RegionDesc::GetAliveRegionDescAt(addr); EXPECT_EQ(region->GetCopyLine(), std::numeric_limits::max()); - EXPECT_EQ(region->GetFixLine(), std::numeric_limits::max()); } HWTEST_F_L0(RegionSpaceTest, AllocateThreadLocalRegion2) @@ -318,9 +265,8 @@ HWTEST_F_L0(RegionSpaceTest, AllocateThreadLocalRegion2) mutator->SetMutatorPhase(GCPhase::GC_PHASE_FIX); ThreadLocal::SetThreadType(ThreadType::ARK_PROCESSOR); RegionSpace& theAllocator = reinterpret_cast(Heap::GetHeap().GetAllocator()); - RegionDesc* region = theAllocator.AllocateThreadLocalRegion(false); + RegionDesc* region = theAllocator.AllocateThreadLocalRegion(false); EXPECT_EQ(region->GetCopyLine(), region->GetRegionStart()); - EXPECT_EQ(region->GetFixLine(), region->GetRegionStart()); } HWTEST_F_L0(RegionSpaceTest, AllocateThreadLocalRegion3) @@ -329,13 +275,11 @@ HWTEST_F_L0(RegionSpaceTest, AllocateThreadLocalRegion3) mutator->SetMutatorPhase(GCPhase::GC_PHASE_COPY); RegionSpace& theAllocator = reinterpret_cast(Heap::GetHeap().GetAllocator()); ThreadLocal::SetThreadType(ThreadType::ARK_PROCESSOR); - RegionDesc* region = theAllocator.AllocateThreadLocalRegion(false); + RegionDesc* region = theAllocator.AllocateThreadLocalRegion(false); EXPECT_EQ(region->GetCopyLine(), region->GetRegionStart()); - EXPECT_EQ(region->GetFixLine(), std::numeric_limits::max()); mutator->SetMutatorPhase(GCPhase::GC_PHASE_PRECOPY); - RegionDesc* region1 = theAllocator.AllocateThreadLocalRegion(false); + RegionDesc* region1 = theAllocator.AllocateThreadLocalRegion(false); EXPECT_EQ(region1->GetCopyLine(), region1->GetRegionStart()); - EXPECT_EQ(region1->GetFixLine(), std::numeric_limits::max()); } HWTEST_F_L0(RegionSpaceTest, AllocateThreadLocalRegion4) @@ -344,42 +288,141 @@ HWTEST_F_L0(RegionSpaceTest, AllocateThreadLocalRegion4) mutator->SetMutatorPhase(GCPhase::GC_PHASE_ENUM); RegionSpace& theAllocator = reinterpret_cast(Heap::GetHeap().GetAllocator()); ThreadLocal::SetThreadType(ThreadType::ARK_PROCESSOR); - RegionDesc* region = theAllocator.AllocateThreadLocalRegion(false); + RegionDesc* region = theAllocator.AllocateThreadLocalRegion(false); EXPECT_EQ(region->GetTraceLine(), region->GetRegionStart()); EXPECT_EQ(region->GetCopyLine(), std::numeric_limits::max()); - EXPECT_EQ(region->GetFixLine(), std::numeric_limits::max()); mutator->SetMutatorPhase(GCPhase::GC_PHASE_MARK); - RegionDesc* region2 = theAllocator.AllocateThreadLocalRegion(false); + RegionDesc* region2 = theAllocator.AllocateThreadLocalRegion(false); EXPECT_EQ(region2->GetTraceLine(), region2->GetRegionStart()); EXPECT_EQ(region2->GetCopyLine(), std::numeric_limits::max()); - EXPECT_EQ(region2->GetFixLine(), std::numeric_limits::max()); mutator->SetMutatorPhase(GCPhase::GC_PHASE_REMARK_SATB); - RegionDesc* region3 = theAllocator.AllocateThreadLocalRegion(false); + RegionDesc* region3 = theAllocator.AllocateThreadLocalRegion(false); EXPECT_EQ(region3->GetTraceLine(), region3->GetRegionStart()); EXPECT_EQ(region3->GetCopyLine(), std::numeric_limits::max()); - EXPECT_EQ(region3->GetFixLine(), std::numeric_limits::max()); mutator->SetMutatorPhase(GCPhase::GC_PHASE_POST_MARK); - RegionDesc* region4 = theAllocator.AllocateThreadLocalRegion(false); + RegionDesc* region4 = theAllocator.AllocateThreadLocalRegion(false); EXPECT_EQ(region4->GetTraceLine(), region4->GetRegionStart()); EXPECT_EQ(region4->GetCopyLine(), std::numeric_limits::max()); - EXPECT_EQ(region4->GetFixLine(), std::numeric_limits::max()); } -HWTEST_F_L0(RegionSpaceTest, CopyRegion1) +HWTEST_F_L0(RegionSpaceTest, CopyRegion) { auto* mutator = common::Mutator::GetMutator(); - mutator_->SetMutatorPhase(GCPhase::GC_PHASE_ENUM); + mutator->SetMutatorPhase(GCPhase::GC_PHASE_ENUM); RegionSpace& theAllocator = reinterpret_cast(Heap::GetHeap().GetAllocator()); - theAllocator.AssembleSmallGarbageCandidates(); - RegionDesc* region = theAllocator.GetRegionManager().TakeRegion( - 16, RegionDesc::UnitRole::SMALL_SIZED_UNITS, true, false); + uintptr_t addr = theAllocator.AllocOldRegion(); + ASSERT_NE(addr, 0); + RegionDesc* region = RegionDesc::GetRegionDescAt(addr); region->SetRegionType(RegionDesc::RegionType::FROM_REGION); ASSERT(region->IsFromRegion()); - region->AddLiveByteCount(1); theAllocator.CopyRegion(region); - EXPECT_NE(theAllocator.FromSpaceSize(), 0); + EXPECT_EQ(theAllocator.FromSpaceSize(), 0); +} + +HWTEST_F_L0(RegionSpaceTest, AllocateThreadLocalRegion1_NotGcThread_EntersElseBranch) +{ + auto& heapAllocator = Heap::GetHeap().GetAllocator(); + RegionSpace& regionSpace = reinterpret_cast(heapAllocator); + + Mutator::GetMutator()->SetMutatorPhase(GCPhase::GC_PHASE_ENUM); + + auto* region = regionSpace.AllocateThreadLocalRegion(false); + EXPECT_NE(region, nullptr); +} + +HWTEST_F_L0(RegionSpaceTest, AllocateThreadLocalRegion2_NotGcThread_EntersElseBranch) +{ + auto& heapAllocator = Heap::GetHeap().GetAllocator(); + RegionSpace& regionSpace = reinterpret_cast(heapAllocator); + + Mutator::GetMutator()->SetMutatorPhase(GCPhase::GC_PHASE_PRECOPY); + + auto* region = regionSpace.AllocateThreadLocalRegion(false); + EXPECT_NE(region, nullptr); +} + +HWTEST_F_L0(RegionSpaceTest, AllocateThreadLocalRegion3_NotGcThread_EntersElseBranch) +{ + auto& heapAllocator = Heap::GetHeap().GetAllocator(); + RegionSpace& regionSpace = reinterpret_cast(heapAllocator); + + Mutator::GetMutator()->SetMutatorPhase(GCPhase::GC_PHASE_FIX); + + auto* region = regionSpace.AllocateThreadLocalRegion(false); + EXPECT_NE(region, nullptr); +} + +HWTEST_F_L0(RegionSpaceTest, Allocate_ValidSize_ReturnsNonNull) +{ + RegionSpace& theAllocator = reinterpret_cast(Heap::GetHeap().GetAllocator()); + uintptr_t addr = theAllocator.AllocOldRegion(); + ASSERT_NE(addr, 0); + + RegionDesc* region = RegionDesc::GetRegionDescAt(addr); + region->InitFreeUnits(); + region->SetRegionType(RegionDesc::RegionType::THREAD_LOCAL_REGION); + Mutator::GetMutator()->SetMutatorPhase(GCPhase::GC_PHASE_UNDEF); + Heap::GetHeap().EnableGC(true); + Heap::GetHeap().GetCollectorResources().SetGcStarted(false); + + uintptr_t result = theAllocator.Allocate(16, AllocType::PINNED_OBJECT); + EXPECT_NE(result, 0u); +} + +HWTEST_F_L0(RegionSpaceTest, FeedHungryBuffers_ShouldProvideValidRegions) +{ + RegionSpace& theAllocator = reinterpret_cast(Heap::GetHeap().GetAllocator()); + uintptr_t addr = theAllocator.AllocOldRegion(); + ASSERT_NE(addr, 0); + + AllocationBuffer* buffer1 = new (std::nothrow) AllocationBuffer(); + AllocationBuffer* buffer2 = new (std::nothrow) AllocationBuffer(); + ASSERT_NE(buffer1, nullptr); + ASSERT_NE(buffer2, nullptr); + + RegionDesc* region = RegionDesc::GetRegionDescAt(addr); + ASSERT_NE(region, nullptr); + region->InitFreeUnits(); + region->SetRegionType(RegionDesc::RegionType::THREAD_LOCAL_REGION); + + buffer1->SetPreparedRegion(region); + buffer2->SetPreparedRegion(region); + Heap::GetHeap().GetAllocator().AddHungryBuffer(*buffer1); + Heap::GetHeap().GetAllocator().AddHungryBuffer(*buffer2); + + Mutator::GetMutator()->SetMutatorPhase(GCPhase::GC_PHASE_FIX); + + Heap::GetHeap().GetAllocator().FeedHungryBuffers(); + + EXPECT_NE(buffer2->GetPreparedRegion(), nullptr); + delete buffer1; + delete buffer2; +} + +HWTEST_F_L0(RegionSpaceTest, AllocationBuffer_AllocateRawPointerObject_ValidSize_ReturnsNonNull) +{ + RegionSpace& theAllocator = reinterpret_cast(Heap::GetHeap().GetAllocator()); + uintptr_t addr = theAllocator.AllocOldRegion(); + ASSERT_NE(addr, 0); + + RegionDesc* region = RegionDesc::GetRegionDescAt(addr); + ASSERT_NE(region, nullptr); + region->InitFreeUnits(); + region->SetRegionType(RegionDesc::RegionType::THREAD_LOCAL_REGION); + + AllocationBuffer* buffer = new (std::nothrow) AllocationBuffer(); + ASSERT_NE(buffer, nullptr); + buffer->SetPreparedRegion(region); + + Mutator::GetMutator()->SetMutatorPhase(GCPhase::GC_PHASE_UNDEF); + Heap::GetHeap().EnableGC(true); + Heap::GetHeap().GetCollectorResources().SetGcStarted(false); + + uintptr_t result = theAllocator.Allocate(16, AllocType::PINNED_OBJECT); + EXPECT_NE(result, 0u); + delete buffer; } } diff --git a/common_components/heap/barrier/tests/barrier_test.cpp b/common_components/heap/barrier/tests/barrier_test.cpp index 391784f103..f5f3611445 100644 --- a/common_components/heap/barrier/tests/barrier_test.cpp +++ b/common_components/heap/barrier/tests/barrier_test.cpp @@ -248,4 +248,20 @@ HWTEST_F_L0(BarrierTest, ReadStruct_ReadsCorrectly) { EXPECT_EQ(result->b, initValue->b); delete initValue; +} + +HWTEST_F_L0(BarrierTest, AtomicWriteStaticRef_NonConcurrent) +{ + DummyObject* targetObj = new DummyObject(); + DummyObject* initialObj = new DummyObject(); + + RefField field(reinterpret_cast(0x1)); + field.SetTargetObject(initialObj); + + MockCollector collector; + Barrier barrier(collector); + + barrier.AtomicWriteRefField(nullptr, field, targetObj, std::memory_order_relaxed); + + EXPECT_EQ(field.GetTargetObject(std::memory_order_relaxed), targetObj); } \ No newline at end of file diff --git a/common_components/heap/collector/tests/BUILD.gn b/common_components/heap/collector/tests/BUILD.gn index 20a34d4289..729d58249d 100755 --- a/common_components/heap/collector/tests/BUILD.gn +++ b/common_components/heap/collector/tests/BUILD.gn @@ -21,7 +21,7 @@ host_unittest_action("Collector_Test") { sources = [ # test file "collector_resources_test.cpp", - # "finalizer_processor_test.cpp", + "finalizer_processor_test.cpp", ] configs = [ @@ -33,12 +33,59 @@ host_unittest_action("Collector_Test") { # hiviewdfx libraries external_deps = [ + "bounds_checking_function:libsec_shared", "icu:shared_icui18n", "icu:shared_icuuc", "zlib:libz", ] } +host_unittest_action("Heuristic_Gc_Policy_Test") { + module_out_path = module_output_path + + sources = [ + # test file + "heuristic_gc_policy_test.cpp", + ] + + configs = [ + "//arkcompiler/ets_runtime/common_components:common_components_test_config", + "//arkcompiler/ets_runtime:icu_path_test_config", + ] + + deps = [ "//arkcompiler/ets_runtime/common_components:libark_common_components_test" ] + + # hiviewdfx libraries + external_deps = [ + "icu:shared_icui18n", + "icu:shared_icuuc", + "runtime_core:libarkassembler_static", + ] +} + +host_unittest_action("Collector_Proxy_Test") { + module_out_path = module_output_path + + sources = [ + # test file + "collector_proxy_test.cpp", + ] + + configs = [ + "//arkcompiler/ets_runtime/common_components:common_components_test_config", + "//arkcompiler/ets_runtime:icu_path_test_config", + ] + + deps = [ "//arkcompiler/ets_runtime/common_components:libark_common_components_test" ] + + # hiviewdfx libraries + external_deps = [ + "icu:shared_icui18n", + "icu:shared_icuuc", + "runtime_core:libarkassembler_static", + ] +} + host_unittest_action("Trace_Collector_Test") { module_out_path = module_output_path @@ -114,6 +161,8 @@ group("unittest") { # deps file deps = [ ":Collector_Test", + ":Heuristic_Gc_Policy_Test", + ":Collector_Proxy_Test", ":Trace_Collector_Test", ":Task_Queue_Test", ":Gc_Request_Test", @@ -126,6 +175,8 @@ group("host_unittest") { # deps file deps = [ ":Collector_TestAction", + ":Heuristic_Gc_Policy_TestAction", + ":Collector_Proxy_TestAction", ":Trace_Collector_TestAction", ":Task_Queue_TestAction", ":Gc_Request_TestAction", diff --git a/common_components/heap/collector/tests/collector_proxy_test.cpp b/common_components/heap/collector/tests/collector_proxy_test.cpp new file mode 100644 index 0000000000..2baca36eb1 --- /dev/null +++ b/common_components/heap/collector/tests/collector_proxy_test.cpp @@ -0,0 +1,44 @@ +/* +* Copyright (c) 2025 Huawei Device Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include "common_components/heap/collector/collector_proxy.h" +#include "common_components/tests/test_helper.h" + +using namespace common; +namespace common::test { +class CollectorProxyTest : public common::test::BaseTestWithScope { +protected: + static void SetUpTestCase() + { + BaseRuntime::GetInstance()->Init(); + } + + static void TearDownTestCase() + { + BaseRuntime::GetInstance()->Fini(); + } + + void SetUp() override {} + void TearDown() override {} +}; + +HWTEST_F_L0(CollectorProxyTest, RunGarbageCollection) +{ + CollectorProxy collectorProxy(Heap::GetHeap().GetAllocator(), Heap::GetHeap().GetCollectorResources()); + Heap::GetHeap().SetGCReason(GCReason::GC_REASON_OOM); + collectorProxy.RunGarbageCollection(0, GCReason::GC_REASON_OOM, GCType::GC_TYPE_BEGIN); + ASSERT_TRUE(Heap::GetHeap().GetGCReason() == GCReason::GC_REASON_OOM); +} +} // namespace common::test \ No newline at end of file diff --git a/common_components/heap/collector/tests/trace_collector_test.cpp b/common_components/heap/collector/tests/trace_collector_test.cpp index 5b579b4ff2..71111e4e5b 100755 --- a/common_components/heap/collector/tests/trace_collector_test.cpp +++ b/common_components/heap/collector/tests/trace_collector_test.cpp @@ -54,6 +54,10 @@ protected: table.VisitRoots(visitor); return found; } + class TableTraceCollctor : public TraceCollector { + public: + using TraceCollector::UpdateNativeThreshold; + }; }; std::unique_ptr GetWCollector() @@ -63,4 +67,35 @@ 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()); +} + +HWTEST_F_L0(TraceCollectorTest, RunGarbageCollectionTest2) +{ + TraceCollector& collector = reinterpret_cast(Heap::GetHeap().GetCollector()); + Heap::GetHeap().SetGCReason(GCReason::GC_REASON_YOUNG); + collector.RunGarbageCollection(0, GCReason::GC_REASON_YOUNG, common::GC_TYPE_FULL); + ASSERT_TRUE(Heap::GetHeap().GetCollector().GetGCStats().isYoungGC()); +} + +HWTEST_F_L0(TraceCollectorTest, UpdateNativeThresholdTest) +{ + TableTraceCollctor& collector = reinterpret_cast(Heap::GetHeap().GetCollector()); + GCParam gcParam; + gcParam.minGrowBytes = 1024; + Heap::GetHeap().SetNativeHeapThreshold(512); + auto oldThreshold = Heap::GetHeap().GetNativeHeapThreshold(); + collector.UpdateNativeThreshold(gcParam); + auto newThreshold = Heap::GetHeap().GetNativeHeapThreshold(); + EXPECT_NE(newThreshold, oldThreshold); +} } \ 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 0000000000..1776700453 --- /dev/null +++ b/common_components/heap/space/tests/from_space_test.cpp @@ -0,0 +1,89 @@ +/* +* Copyright (c) 2025 Huawei Device Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include "common_components/heap/allocator/region_space.h" +#include "common_components/heap/space/from_space.h" +#include "common_components/mutator/thread_local.h" +#include "common_components/tests/test_helper.h" + +using namespace common; +namespace common::test { +class FromSpaceTest : public common::test::BaseTestWithScope { +protected: + class TestRegionList : public RegionList { + public: + TestRegionList() : RegionList("TestList") {} + void setHeadRegion(RegionDesc* head) { listHead_ = head; } + }; + static void SetUpTestCase() + { + BaseRuntime::GetInstance()->Init(); + } + + static void TearDownTestCase() + { + BaseRuntime::GetInstance()->Fini(); + } + + void SetUp() override {} + void TearDown() override {} +}; + +HWTEST_F_L0(FromSpaceTest, CopyFromRegions) +{ + RegionManager regionManager; + RegionSpace heap; + FromSpace fromSpace(regionManager, heap); + ThreadLocal::SetAllocBuffer(nullptr); + fromSpace.CopyFromRegions(nullptr); + ASSERT_FALSE(fromSpace.GetFromRegionList().GetHeadRegion() != nullptr); +} + +HWTEST_F_L0(FromSpaceTest, CopyFromRegionsTest) +{ + size_t unitIdx = 0; + size_t nUnit = 4; + RegionDesc* region = RegionDesc::InitRegion(unitIdx, nUnit, RegionDesc::UnitRole::LARGE_SIZED_UNITS); + TestRegionList list; + list.setHeadRegion(region); + ASSERT_TRUE(list.GetHeadRegion() != nullptr); + + RegionSpace heap; + RegionManager manager; + FromSpace fromSpace(manager, heap); + fromSpace.AssembleGarbageCandidates(list); + + AllocationBuffer* buffer1 = new (std::nothrow) AllocationBuffer(); + ThreadLocal::SetAllocBuffer(buffer1); + fromSpace.CopyFromRegions(); + fromSpace.ExemptFromRegions(); + ASSERT_TRUE(AllocationBuffer::GetAllocBuffer() != nullptr); +} + +HWTEST_F_L0(FromSpaceTest, ParallelCopyFromRegions) +{ + RegionManager regionManager; + RegionSpace heap; + FromSpace fromSpace(regionManager, heap); + AllocationBuffer* buffer1 = new (std::nothrow) AllocationBuffer(); + ThreadLocal::SetAllocBuffer(buffer1); + fromSpace.ParallelCopyFromRegions(nullptr, 5); + ASSERT_TRUE(AllocationBuffer::GetAllocBuffer() != nullptr); + + ThreadLocal::SetAllocBuffer(nullptr); + fromSpace.ParallelCopyFromRegions(nullptr, 5); + ASSERT_FALSE(AllocationBuffer::GetAllocBuffer() != nullptr); +} +} // namespace common::test \ No newline at end of file diff --git a/common_components/heap/tests/BUILD.gn b/common_components/heap/tests/BUILD.gn new file mode 100644 index 0000000000..ead18f3761 --- /dev/null +++ b/common_components/heap/tests/BUILD.gn @@ -0,0 +1,85 @@ +# Copyright (c) 2025 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//arkcompiler/ets_runtime/common_components/tests/test_helper.gni") + +module_output_path = "ets_runtime" + +host_unittest_action("Heap_Manager_Test") { + module_out_path = module_output_path + + sources = [ + # test file + "heap_manager_test.cpp", + ] + + configs = [ + "//arkcompiler/ets_runtime/common_components:common_components_test_config", + "//arkcompiler/ets_runtime:icu_path_test_config", + ] + + deps = [ "//arkcompiler/ets_runtime/common_components:libark_common_components_test" ] + + # hiviewdfx libraries + external_deps = [ + "icu:shared_icui18n", + "icu:shared_icuuc", + "zlib:libz", + ] +} + +host_unittest_action("Verification_Test") { + module_out_path = module_output_path + + sources = [ + # test file + "verification_test.cpp", + ] + + include_dirs = [ "//arkcompiler/ets_runtime/common_components/" ] + + configs = [ + "//arkcompiler/ets_runtime/common_components:common_components_test_config", + "//arkcompiler/ets_runtime:icu_path_test_config", + ] + + deps = [ "//arkcompiler/ets_runtime/common_components:libark_common_components_test" ] + + # hiviewdfx libraries + external_deps = [ + "bounds_checking_function:libsec_shared", + "icu:shared_icui18n", + "icu:shared_icuuc", + "zlib:libz", + ] +} + +group("unittest") { + testonly = true + + # deps file + deps = [ + ":Heap_Manager_Test", + ":Verification_Test", + ] +} + +group("host_unittest") { + testonly = true + + # deps file + deps = [ + ":Heap_Manager_TestAction", + ":Verification_TestAction", + ] +} \ No newline at end of file diff --git a/common_components/heap/tests/verification_test.cpp b/common_components/heap/tests/verification_test.cpp new file mode 100644 index 0000000000..dd63f60c65 --- /dev/null +++ b/common_components/heap/tests/verification_test.cpp @@ -0,0 +1,286 @@ +/* +* Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "common_components/heap/verification.cpp" +#include "common_components/heap/heap_manager.h" +#include "common_components/heap/w_collector/w_collector.h" +#include "common_components/tests/test_helper.h" +#include "common_interfaces/objects/base_object_operator.h" + +using namespace common; +namespace common::test { +class TestBaseObjectOperator : public common::BaseObjectOperatorInterfaces { +public: + bool IsValidObject([[maybe_unused]] const BaseObject *object) const override { return enbaleValidObject_; } + void ForEachRefField(const BaseObject *object, const common::RefFieldVisitor &visitor) const override {} + size_t GetSize(const BaseObject *object) const override{ return size_; } + BaseObject *GetForwardingPointer(const BaseObject *object) const override { return nullptr; } + void SetForwardingPointerAfterExclusive(BaseObject *object, BaseObject *fwdPtr) override {} + void SetValidObject(bool value) { enbaleValidObject_ = value; } + void SetSize(size_t size) { size_ = size; } +private: + bool enbaleValidObject_ = false; + size_t size_ = 0; +}; +class VerificationTest : public common::test::BaseTestWithScope { +protected: + static void SetUpTestCase() + { + BaseRuntime::GetInstance()->Init(); + } + + static void TearDownTestCase() + { + BaseRuntime::GetInstance()->Fini(); + } + + void SetUp() override + { + MutatorManager::Instance().CreateRuntimeMutator(ThreadType::GC_THREAD); + } + + void TearDown() override + { + MutatorManager::Instance().DestroyRuntimeMutator(ThreadType::GC_THREAD); + } +}; + +HWTEST_F_L0(VerificationTest, GetObjectInfoTest) +{ + BaseObject* obj = nullptr; + std::string result = GetObjectInfo(obj); + + EXPECT_NE(result.find("address: 0x0"), std::string::npos); + EXPECT_NE(result.find("Skip: nullptr"), std::string::npos); + EXPECT_NE(result.find("Skip: Object is not in heap range"), std::string::npos); +} + +HWTEST_F_L0(VerificationTest, GetObjectInfoTest2) +{ + BaseObject obj; + std::string result = GetObjectInfo(&obj); + EXPECT_NE(result.find("address: 0x"), std::string::npos); + EXPECT_NE(result.find("Skip: Object is not in heap range"), std::string::npos); +} + +HWTEST_F_L0(VerificationTest, GetRefInfoTest) +{ + BaseObject oldObj; + RefField oldField(&oldObj); + MAddress oldAddress = oldField.GetFieldValue(); + std::string result = GetRefInfo(oldField); + EXPECT_NE(result.find("address: 0x"), std::string::npos); + EXPECT_NE(result.find("Skip: Object is not in heap range"), std::string::npos); +} + +HWTEST_F_L0(VerificationTest, VerifyRefImplTest2) +{ + RegionSpace& theAllocator = reinterpret_cast(Heap::GetHeap().GetAllocator()); + uintptr_t addr = theAllocator.AllocOldRegion(); + ASSERT_NE(addr, 0U); + BaseObject* obj = reinterpret_cast(addr); + RegionDesc* region = RegionDesc::GetRegionDescAt(reinterpret_cast(obj)); + ASSERT_NE(region, nullptr); + region->SetRegionType(RegionDesc::RegionType::FROM_REGION); + RefField field(obj); + + auto refObj = field.GetTargetObject(); + + AfterForwardVisitor visitor; + visitor.VerifyRefImpl(obj, field); + ASSERT_FALSE(RegionSpace::IsMarkedObject(refObj)); + ASSERT_FALSE(RegionSpace::IsResurrectedObject(refObj)); +} + +HWTEST_F_L0(VerificationTest, VerifyRefImplTest3) +{ + RegionSpace& theAllocator = reinterpret_cast(Heap::GetHeap().GetAllocator()); + uintptr_t addr = theAllocator.AllocOldRegion(); + ASSERT_NE(addr, 0U); + BaseObject* obj = reinterpret_cast(addr); + RegionDesc* region = RegionDesc::GetRegionDescAt(reinterpret_cast(obj)); + ASSERT_NE(region, nullptr); + region->SetRegionType(RegionDesc::RegionType::FULL_PINNED_REGION); + RefField field(obj); + + auto refObj = field.GetTargetObject(); + + ReadBarrierSetter visitor; + visitor.VerifyRefImpl(nullptr, field); + visitor.VerifyRefImpl(obj, field); + EXPECT_EQ(RegionDesc::RegionType::FULL_PINNED_REGION, + RegionDesc::GetRegionDescAt(reinterpret_cast(field.GetTargetObject()))->GetRegionType()); + + region->SetRegionType(RegionDesc::RegionType::RECENT_PINNED_REGION); + visitor.VerifyRefImpl(obj, field); + EXPECT_EQ(RegionDesc::RegionType::RECENT_PINNED_REGION, + RegionDesc::GetRegionDescAt(reinterpret_cast(field.GetTargetObject()))->GetRegionType()); + + region->SetRegionType(RegionDesc::RegionType::FIXED_PINNED_REGION); + visitor.VerifyRefImpl(obj, field); + EXPECT_EQ(RegionDesc::RegionType::FIXED_PINNED_REGION, + RegionDesc::GetRegionDescAt(reinterpret_cast(field.GetTargetObject()))->GetRegionType()); + + region->SetRegionType(RegionDesc::RegionType::FULL_FIXED_PINNED_REGION); + visitor.VerifyRefImpl(obj, field); + EXPECT_EQ(RegionDesc::RegionType::FULL_FIXED_PINNED_REGION, + RegionDesc::GetRegionDescAt(reinterpret_cast(field.GetTargetObject()))->GetRegionType()); + + region->SetRegionType(RegionDesc::RegionType::READ_ONLY_REGION); + auto oldRefValue = field.GetFieldValue(); + visitor.VerifyRefImpl(obj, field); + auto newRefValue = field.GetFieldValue(); + EXPECT_NE(oldRefValue, newRefValue); +} + +std::unique_ptr GetWCollector() +{ + CollectorResources &resources = Heap::GetHeap().GetCollectorResources(); + Allocator &allocator = Heap::GetHeap().GetAllocator(); + + return std::make_unique(allocator, resources); +} + +HWTEST_F_L0(VerificationTest, VerifyAfterMarkTest1) +{ + Heap::GetHeap().SetGCPhase(GCPhase::GC_PHASE_POST_MARK); + std::unique_ptr wcollector = GetWCollector(); + ASSERT_TRUE(wcollector != nullptr); + WVerify verify; + verify.VerifyAfterMark(*wcollector); + ASSERT_FALSE(MutatorManager::Instance().WorldStopped()); +} + +HWTEST_F_L0(VerificationTest, VerifyAfterForwardTest1) +{ + Heap::GetHeap().SetGCPhase(GCPhase::GC_PHASE_COPY); + std::unique_ptr wcollector = GetWCollector(); + ASSERT_TRUE(wcollector != nullptr); + WVerify verify; + verify.VerifyAfterForward(*wcollector); + ASSERT_FALSE(MutatorManager::Instance().WorldStopped()); +} + +HWTEST_F_L0(VerificationTest, VerifyAfterFixTest1) +{ + Heap::GetHeap().SetGCPhase(GCPhase::GC_PHASE_FIX); + std::unique_ptr wcollector = GetWCollector(); + ASSERT_TRUE(wcollector != nullptr); + WVerify verify; + verify.VerifyAfterFix(*wcollector); + ASSERT_FALSE(MutatorManager::Instance().WorldStopped()); +} + +HWTEST_F_L0(VerificationTest, EnableReadBarrierDFXTest1) +{ + std::unique_ptr wcollector = GetWCollector(); + ASSERT_TRUE(wcollector != nullptr); + WVerify verify; + verify.EnableReadBarrierDFX(*wcollector); + ASSERT_FALSE(MutatorManager::Instance().WorldStopped()); +} + +HWTEST_F_L0(VerificationTest, DisableReadBarrierDFXTest1) +{ + std::unique_ptr wcollector = GetWCollector(); + ASSERT_TRUE(wcollector != nullptr); + WVerify verify; + verify.DisableReadBarrierDFX(*wcollector); + ASSERT_FALSE(MutatorManager::Instance().WorldStopped()); +} + +HWTEST_F_L0(VerificationTest, GetObjectInfoTest3) +{ + HeapAddress addr = HeapManager::Allocate(sizeof(BaseObject), AllocType::PINNED_OBJECT, true); + BaseObject *obj = reinterpret_cast(addr); + std::string result = GetObjectInfo(obj); + EXPECT_NE(result.find("address: 0x"), std::string::npos); + EXPECT_NE(result.find("Type: 0x"), std::string::npos); + EXPECT_NE(result.find("Base: 0x"), std::string::npos); + EXPECT_NE(result.find("Start: 0x"), std::string::npos); + EXPECT_NE(result.find("End: 0x"), std::string::npos); + EXPECT_NE(result.find("AllocPtr: 0x"), std::string::npos); + EXPECT_NE(result.find("TraceLine: 0x"), std::string::npos); + EXPECT_NE(result.find("CopyLine: 0x"), std::string::npos); +} + +HWTEST_F_L0(VerificationTest, GetRefInfoTest2) +{ + RefField field(nullptr); + uintptr_t taggedValue = 0x04; + field.SetFieldValue(static_cast(taggedValue)); + std::string result = GetRefInfo(field); + EXPECT_NE(result.find("> Raw memory:"), std::string::npos); + EXPECT_NE(result.find("Skip: primitive"), std::string::npos); +} + +HWTEST_F_L0(VerificationTest, VerifyRefImplTest) +{ + HeapAddress addr = HeapManager::Allocate(sizeof(BaseObject), AllocType::PINNED_OBJECT, true); + BaseObject *obj = reinterpret_cast(addr); + RefField oldField(obj); + TestBaseObjectOperator operatorImpl; + BaseObject::RegisterDynamic(&operatorImpl); + operatorImpl.SetValidObject(true); + Heap::GetHeap().SetGCReason(GCReason::GC_REASON_YOUNG); + operatorImpl.SetSize(BaseObject::BaseObjectSize()); + AfterMarkVisitor visitor; + visitor.VerifyRefImpl(nullptr, oldField); + ASSERT_TRUE(Heap::GetHeap().GetGCReason() == GCReason::GC_REASON_YOUNG); + ASSERT_TRUE(Heap::IsTaggedObject(oldField.GetFieldValue())); + + AfterMarkVisitor visitor1; + visitor1.VerifyRefImpl(nullptr, oldField); + ASSERT_TRUE(Heap::IsTaggedObject(oldField.GetFieldValue())); +} + +HWTEST_F_L0(VerificationTest, VerifyRefImplTest1) +{ + HeapAddress addr = HeapManager::Allocate(sizeof(BaseObject), AllocType::PINNED_OBJECT, true); + BaseObject *obj = reinterpret_cast(addr); + RefField oldField(obj); + TestBaseObjectOperator operatorImpl; + BaseObject::RegisterDynamic(&operatorImpl); + operatorImpl.SetValidObject(true); + Heap::GetHeap().SetGCReason(GCReason::GC_REASON_YOUNG); + operatorImpl.SetSize(BaseObject::BaseObjectSize()); + AfterMarkVisitor visitor; + visitor.VerifyRefImpl(obj, oldField); + ASSERT_TRUE(Heap::GetHeap().GetGCReason() == GCReason::GC_REASON_YOUNG); + ASSERT_TRUE(Heap::IsTaggedObject(oldField.GetFieldValue())); +} + +static BaseObject* testObj = nullptr; +static void CustomVisitRoot(const RefFieldVisitor& visitorFunc) +{ + RefField<> field(testObj); + visitorFunc(field); +} +HWTEST_F_L0(VerificationTest, IterateRetraced_VerifyAllRefs) +{ + RegionSpace regionSpace; + VerifyIterator verify(regionSpace); + AfterForwardVisitor visitor; + std::unordered_set markSet; + HeapAddress addr = HeapManager::Allocate(sizeof(BaseObject), AllocType::PINNED_OBJECT, true); + testObj = reinterpret_cast(addr); + markSet.insert(testObj); + + verify.IterateRetraced(visitor, markSet, true); + verify.IterateRetraced(visitor, markSet, false); + EXPECT_EQ(markSet.size(), 1); + EXPECT_TRUE(markSet.find(testObj) != markSet.end()); +} +} // namespace common::test diff --git a/common_components/heap/w_collector/tests/w_collector_test.cpp b/common_components/heap/w_collector/tests/w_collector_test.cpp index 2102574089..139e6571bb 100644 --- a/common_components/heap/w_collector/tests/w_collector_test.cpp +++ b/common_components/heap/w_collector/tests/w_collector_test.cpp @@ -16,6 +16,7 @@ #include "common_components/tests/test_helper.h" #include "common_components/heap/w_collector/w_collector.h" +#include "common_components/heap/w_collector/w_collector.cpp" #include "common_components/heap/collector/collector_proxy.h" #include "common_components/heap/heap_manager.h" #include "common_components/heap/allocator/region_desc.h" @@ -25,7 +26,7 @@ using namespace common; namespace common::test { using SuspensionType = MutatorBase::SuspensionType; -class WCollectorTest : public BaseTestWithScope { +class WCollectorTest : public common::test::BaseTestWithScope { protected: static void SetUpTestCase() { @@ -127,8 +128,9 @@ void FlipTest() EXPECT_FALSE(mutatorManager.WorldStopped()); EXPECT_TRUE(stwCallbackExecuted); }; - STWParam stwParam{"flip-test"}; - mutatorManager.FlipMutators(stwParam, stwTest, &mutatorTest); + STWParam param; + param.stwReason = "flip-test"; + mutatorManager.FlipMutators(param, stwTest, &mutatorTest); } HWTEST_F_L0(WCollectorTest, FlipTest) @@ -136,4 +138,394 @@ HWTEST_F_L0(WCollectorTest, FlipTest) std::thread t1(FlipTest); t1.join(); } + +HWTEST_F_L0(WCollectorTest, IsUnmovableFromObject_ReturnsFalseForNullptr) +{ + std::unique_ptr wcollector = GetWCollector(); + ASSERT_TRUE(wcollector != nullptr); + + BaseObject* obj = nullptr; + EXPECT_FALSE(wcollector->IsUnmovableFromObject(obj)); +} + +class TestableWCollector : public WCollector { +public: + using WCollector::ForwardObject; + + explicit TestableWCollector(Allocator& allocator, CollectorResources& resources) + : WCollector(allocator, resources), currentGCPhase_(GCPhase::GC_PHASE_COPY) {} + + void SetCurrentGCPhaseForTest(GCPhase phase) + { + currentGCPhase_ = phase; + } + + GCPhase GetCurrentGCPhaseForTest() const + { + return currentGCPhase_; + } + +private: + GCPhase currentGCPhase_; +}; + + +class DummyObject : public BaseObject { +public: + const common::TypeInfo* GetTypeInfo() const { return nullptr; } + size_t GetSize() const { return sizeof(DummyObject); } + + void SetClass(uintptr_t cls) + { + stateWord_.StoreStateWord(static_cast(cls)); + } + +private: + class BaseStateWord { + public: + using StateWordType = uint64_t; + + void StoreStateWord(StateWordType word) + { + stateWord_ = word; + } + + StateWordType LoadStateWord() const + { + return stateWord_; + } + + private: + StateWordType stateWord_{0}; + }; + + BaseStateWord stateWord_; +}; + +HWTEST_F_L0(WCollectorTest, ForwardObject_WithUnmovedObject_ReturnsSameAddress) +{ + std::unique_ptr wcollector = GetWCollector(); + ASSERT_TRUE(wcollector != nullptr); + + TestableWCollector* testableCollector = reinterpret_cast(wcollector.get()); + + testableCollector->SetCurrentGCPhaseForTest(GCPhase::GC_PHASE_COPY); + EXPECT_EQ(testableCollector->GetCurrentGCPhaseForTest(), GCPhase::GC_PHASE_COPY); +} + +HWTEST_F_L0(WCollectorTest, TraceRefField_TEST1) +{ + constexpr uint64_t TAG_BITS_SHIFT = 48; + constexpr uint64_t TAG_MARK = 0xFFFFULL << TAG_BITS_SHIFT; + constexpr uint64_t TAG_SPECIAL = 0x02ULL; + constexpr uint64_t TAG_BOOLEAN = 0x04ULL; + constexpr uint64_t TAG_HEAP_OBJECT_MASK = TAG_MARK | TAG_SPECIAL | TAG_BOOLEAN; + HeapAddress addr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); + BaseObject *obj = reinterpret_cast(addr | TAG_HEAP_OBJECT_MASK); + RefField<> field(obj); + + MarkStack workStack; + MarkStack*> weakStack; + TraceRefField(nullptr, field, workStack, weakStack, GCReason::GC_REASON_YOUNG); + EXPECT_FALSE(Heap::IsTaggedObject(field.GetFieldValue())); +} + +HWTEST_F_L0(WCollectorTest, TraceRefField_TEST2) +{ + HeapAddress addr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); + RegionDesc* region = RegionDesc::GetRegionDescAt(addr); + region->SetRegionType(RegionDesc::RegionType::ALIVE_REGION_FIRST); + BaseObject* obj = reinterpret_cast(addr); + RefField field(obj); + + MarkStack workStack; + MarkStack*> weakStack; + weakStack.push_back(&field); + TraceRefField(nullptr, field, workStack, weakStack, GCReason::GC_REASON_APPSPAWN); + EXPECT_FALSE(region->IsInOldSpace()); + workStack.pop_back(); + weakStack.pop_back(); +} + +HWTEST_F_L0(WCollectorTest, TraceRefField_TEST3) +{ + HeapAddress addr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); + RegionDesc* region = RegionDesc::GetRegionDescAt(addr); + region->SetRegionType(RegionDesc::RegionType::OLD_REGION); + BaseObject* obj = reinterpret_cast(addr); + RefField field(obj); + + MarkStack workStack; + MarkStack*> weakStack; + weakStack.push_back(&field); + TraceRefField(nullptr, field, workStack, weakStack, GCReason::GC_REASON_APPSPAWN); + EXPECT_TRUE(region->IsInOldSpace()); + workStack.pop_back(); + weakStack.pop_back(); +} + +HWTEST_F_L0(WCollectorTest, TraceRefField_TEST4) +{ + HeapAddress addr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); + RegionDesc* region = RegionDesc::GetRegionDescAt(addr); + region->SetRegionType(RegionDesc::RegionType::ALIVE_REGION_FIRST); + BaseObject* obj = reinterpret_cast(addr); + RefField field(obj); + + MarkStack workStack; + MarkStack*> weakStack; + weakStack.push_back(&field); + TraceRefField(nullptr, field, workStack, weakStack, GCReason::GC_REASON_YOUNG); + EXPECT_FALSE(region->IsInOldSpace()); + workStack.pop_back(); + weakStack.pop_back(); +} + +HWTEST_F_L0(WCollectorTest, TraceRefField_TEST5) +{ + HeapAddress addr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); + RegionDesc* region = RegionDesc::GetRegionDescAt(addr); + region->SetRegionType(RegionDesc::RegionType::OLD_REGION); + BaseObject* obj = reinterpret_cast(addr); + RefField field(obj); + + MarkStack workStack; + MarkStack*> weakStack; + TraceRefField(nullptr, field, workStack, weakStack, GCReason::GC_REASON_YOUNG); + EXPECT_TRUE(region->IsInOldSpace()); +} + +HWTEST_F_L0(WCollectorTest, TraceRefField_TEST6) +{ + HeapAddress addr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); + RegionDesc* region = RegionDesc::GetRegionDescAt(addr); + region->SetRegionAllocPtr(addr - 1); + region->SetTraceLine(); + BaseObject* obj = reinterpret_cast(addr); + RefField field(obj); + + MarkStack workStack; + TraceRefField(obj, obj, field, workStack, region); + EXPECT_TRUE(region->IsNewObjectSinceTrace(obj)); +} + +class TestCreateTraceWCollector : public TraceCollector { +public: + using TraceCollector::SetGCReason; + explicit TestCreateTraceWCollector(Allocator& allocator, CollectorResources& resources) + : TraceCollector(allocator, resources) {} + BaseObject* ForwardObject(BaseObject*) override { return nullptr; } + bool IsFromObject(BaseObject*) const override { return false; } + bool IsUnmovableFromObject(BaseObject*) const override { return false; } + BaseObject* FindToVersion(BaseObject* obj) const override { return nullptr; } + bool TryUpdateRefField(BaseObject*, RefField<>&, BaseObject*&) const override { return false; } + bool TryForwardRefField(BaseObject*, RefField<>&, BaseObject*&) const override { return false; } + bool TryUntagRefField(BaseObject*, RefField<>&, BaseObject*&) const override { return false; } + RefField<> GetAndTryTagRefField(BaseObject*) const override { return RefField<>(nullptr); } + bool IsOldPointer(RefField<>&) const override { return false; } + void AddRawPointerObject(BaseObject*) override {} + void RemoveRawPointerObject(BaseObject*) override {} + bool MarkObject(BaseObject* obj, size_t cellCount = 0) const override { return false; } + void TraceObjectRefFields(BaseObject *obj, TraceRefFieldVisitor *data) override {} + BaseObject* CopyObjectAfterExclusive(BaseObject* obj) override { return nullptr; } + void DoGarbageCollection() override {} + bool IsCurrentPointer(RefField<>&) const override { return false; } + TraceRefFieldVisitor CreateTraceObjectRefFieldsVisitor(WorkStack *workStack, WeakStack *weakStack) override + { + return TraceRefFieldVisitor(); + } +}; + +HWTEST_F_L0(WCollectorTest, CreateTraceObjectRefFieldsVisitor_TEST1) +{ + std::unique_ptr wcollector = GetWCollector(); + ASSERT_TRUE(wcollector != nullptr); + + MarkStack workStack; + MarkStack*> weakStack; + TestCreateTraceWCollector* collector = reinterpret_cast(wcollector.get()); + collector->SetGCReason(GCReason::GC_REASON_YOUNG); + auto visitor = wcollector->CreateTraceObjectRefFieldsVisitor(&workStack, &weakStack); + EXPECT_TRUE(visitor.GetRefFieldVisitor() != nullptr); +} + +HWTEST_F_L0(WCollectorTest, FixRefField_TEST1) +{ + std::unique_ptr wcollector = GetWCollector(); + ASSERT_TRUE(wcollector != nullptr); + + constexpr uint64_t TAG_BITS_SHIFT = 48; + constexpr uint64_t TAG_MARK = 0xFFFFULL << TAG_BITS_SHIFT; + constexpr uint64_t TAG_SPECIAL = 0x02ULL; + constexpr uint64_t TAG_BOOLEAN = 0x04ULL; + constexpr uint64_t TAG_HEAP_OBJECT_MASK = TAG_MARK | TAG_SPECIAL | TAG_BOOLEAN; + HeapAddress addr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); + BaseObject *obj = reinterpret_cast(addr | TAG_HEAP_OBJECT_MASK); + RefField<> field(obj); + wcollector->FixRefField(obj, field); + EXPECT_FALSE(Heap::IsTaggedObject(field.GetFieldValue())); +} + +HWTEST_F_L0(WCollectorTest, FixRefField_TEST2) +{ + std::unique_ptr wcollector = GetWCollector(); + ASSERT_TRUE(wcollector != nullptr); + + BaseObject* obj = reinterpret_cast(0); + RefField<> field(obj); + wcollector->FixRefField(obj, field); + EXPECT_FALSE(Heap::IsHeapAddress(obj)); +} + +class TestStaticObject : public BaseObjectOperatorInterfaces { +public: + size_t GetSize(const BaseObject *object) const override { return 0; } + bool IsValidObject(const BaseObject *object) const override { return false; } + void ForEachRefField(const BaseObject *object, const RefFieldVisitor &visitor) const override {} + void SetForwardingPointerAfterExclusive(BaseObject *object, BaseObject *fwdPtr) override {} + BaseObject *GetForwardingPointer(const BaseObject *object) const override + { + return const_cast(object); + } +}; + +HWTEST_F_L0(WCollectorTest, ForwardUpdateRawRef_TEST1) +{ + std::unique_ptr wcollector = GetWCollector(); + ASSERT_TRUE(wcollector != nullptr); + + HeapAddress addr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); + RegionDesc* region = RegionDesc::GetRegionDescAt(addr); + region->SetRegionType(RegionDesc::RegionType::FROM_REGION); + Mutator::GetMutator()->SetMutatorPhase(GCPhase::GC_PHASE_PRECOPY); + BaseObject* obj = reinterpret_cast(addr); + EXPECT_FALSE(obj->IsForwarded()); + obj->SetForwardState(BaseStateWord::ForwardState::FORWARDED); + obj->SetLanguageType(LanguageType::STATIC); + EXPECT_TRUE(obj->IsForwarded()); + TestStaticObject staticObject; + obj->RegisterStatic(&staticObject); + + ObjectRef root; + root.object = obj; + auto ret = wcollector->ForwardUpdateRawRef(root); + EXPECT_TRUE(wcollector->IsFromObject(obj)); + EXPECT_EQ(ret, obj); +} + +class TestForwardNullObject : public TestStaticObject { +public: + BaseObject *GetForwardingPointer(const BaseObject *object) const override { return nullptr; } +}; + +HWTEST_F_L0(WCollectorTest, ForwardObject_TEST1) +{ + std::unique_ptr wcollector = GetWCollector(); + ASSERT_TRUE(wcollector != nullptr); + + HeapAddress addr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); + RegionDesc* region = RegionDesc::GetRegionDescAt(addr); + region->SetRegionType(RegionDesc::RegionType::FROM_REGION); + Mutator::GetMutator()->SetMutatorPhase(GCPhase::GC_PHASE_PRECOPY); + BaseObject* obj = reinterpret_cast(addr); + EXPECT_FALSE(obj->IsForwarded()); + obj->SetForwardState(BaseStateWord::ForwardState::FORWARDED); + obj->SetLanguageType(LanguageType::STATIC); + EXPECT_TRUE(obj->IsForwarded()); + TestForwardNullObject staticObject; + obj->RegisterStatic(&staticObject); + + auto ret = wcollector->ForwardObject(obj); + EXPECT_EQ(ret, obj); +} + +HWTEST_F_L0(WCollectorTest, CopyObjectImpl_TEST1) +{ + std::unique_ptr wcollector = GetWCollector(); + ASSERT_TRUE(wcollector != nullptr); + + HeapAddress addr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); + RegionDesc* region = RegionDesc::GetRegionDescAt(addr); + region->SetRegionType(RegionDesc::RegionType::FROM_REGION); + Mutator::GetMutator()->SetMutatorPhase(GCPhase::GC_PHASE_PRECOPY); + BaseObject* obj = reinterpret_cast(addr); + EXPECT_FALSE(obj->IsForwarded()); + obj->SetForwardState(BaseStateWord::ForwardState::FORWARDED); + obj->SetLanguageType(LanguageType::STATIC); + EXPECT_TRUE(obj->IsForwarded()); + TestForwardNullObject staticObject; + obj->RegisterStatic(&staticObject); + + auto ret = wcollector->CopyObjectImpl(obj); + EXPECT_TRUE(ret == nullptr); +} + +HWTEST_F_L0(WCollectorTest, TryUpdateRefFieldImpl_TEST1) +{ + std::unique_ptr wcollector = GetWCollector(); + ASSERT_TRUE(wcollector != nullptr); + + RefField<> field(nullptr); + BaseObject* obj = nullptr; + bool ret = wcollector->TryUpdateRefField(nullptr, field, obj); + EXPECT_FALSE(ret); +} + +HWTEST_F_L0(WCollectorTest, TryUpdateRefFieldImpl_TEST2) +{ + std::unique_ptr wcollector = GetWCollector(); + ASSERT_TRUE(wcollector != nullptr); + + HeapAddress addr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); + RegionDesc* region = RegionDesc::GetRegionDescAt(addr); + region->SetRegionType(RegionDesc::RegionType::FROM_REGION); + BaseObject* obj = reinterpret_cast(addr); + RefField field(obj); + bool ret = wcollector->TryUpdateRefField(nullptr, field, obj); + EXPECT_FALSE(ret); +} + +HWTEST_F_L0(WCollectorTest, TryUpdateRefFieldImpl_TEST3) +{ + std::unique_ptr wcollector = GetWCollector(); + ASSERT_TRUE(wcollector != nullptr); + + HeapAddress addr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); + RegionDesc* region = RegionDesc::GetRegionDescAt(addr); + region->SetRegionType(RegionDesc::RegionType::FROM_REGION); + Mutator::GetMutator()->SetMutatorPhase(GCPhase::GC_PHASE_PRECOPY); + BaseObject* obj = reinterpret_cast(addr); + EXPECT_FALSE(obj->IsForwarded()); + obj->SetForwardState(BaseStateWord::ForwardState::FORWARDED); + obj->SetLanguageType(LanguageType::STATIC); + EXPECT_TRUE(obj->IsForwarded()); + TestForwardNullObject staticObject; + obj->RegisterStatic(&staticObject); + + RefField field(obj); + bool ret = wcollector->TryForwardRefField(nullptr, field, obj); + EXPECT_FALSE(ret); +} + +HWTEST_F_L0(WCollectorTest, TryUpdateRefFieldImpl_TEST4) +{ + std::unique_ptr wcollector = GetWCollector(); + ASSERT_TRUE(wcollector != nullptr); + + HeapAddress addr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); + RegionDesc* region = RegionDesc::GetRegionDescAt(addr); + region->SetRegionType(RegionDesc::RegionType::FROM_REGION); + Mutator::GetMutator()->SetMutatorPhase(GCPhase::GC_PHASE_PRECOPY); + BaseObject* obj = reinterpret_cast(addr); + EXPECT_FALSE(obj->IsForwarded()); + obj->SetForwardState(BaseStateWord::ForwardState::FORWARDED); + obj->SetLanguageType(LanguageType::STATIC); + EXPECT_TRUE(obj->IsForwarded()); + TestStaticObject staticObject; + obj->RegisterStatic(&staticObject); + + RefField field(obj); + bool ret = wcollector->TryForwardRefField(nullptr, field, obj); + EXPECT_TRUE(ret); +} } // namespace common::test diff --git a/common_components/log/tests/log_test.cpp b/common_components/log/tests/log_test.cpp index e41af1f5b8..269e1fe2e1 100644 --- a/common_components/log/tests/log_test.cpp +++ b/common_components/log/tests/log_test.cpp @@ -55,6 +55,11 @@ HWTEST_F_L0(LogTest, ConvertFromRuntime_Default_ReturnsDebug) { Level result = Log::ConvertFromRuntime(static_cast(999)); EXPECT_EQ(result, Level::DEBUG); } + +HWTEST_F_L0(LogTest, PrettyOrderMathNano) { + std::string result = PrettyOrderMathNano(1000000000000, "s"); + EXPECT_EQ(result, "1000s"); +} } namespace common { diff --git a/common_components/mutator/tests/mutator_manager_test.cpp b/common_components/mutator/tests/mutator_manager_test.cpp index 87a1649f95..0c71a15d6d 100755 --- a/common_components/mutator/tests/mutator_manager_test.cpp +++ b/common_components/mutator/tests/mutator_manager_test.cpp @@ -27,6 +27,16 @@ protected: void TearDown() override {} }; +HWTEST_F_L0(MutatorManagerTest, BindMutatorOnly_Test1) +{ + MutatorManager *managerPtr = new MutatorManager(); + Mutator mutator; + managerPtr->UnbindMutatorOnly(); + bool res = managerPtr->BindMutatorOnly(&mutator); + ASSERT_TRUE(res); + delete managerPtr; +} + HWTEST_F_L0(MutatorManagerTest, IsRuntimeThread_Test1) { ThreadLocalData* localData = ThreadLocal::GetThreadLocalData(); @@ -78,17 +88,6 @@ HWTEST_F_L0(MutatorManagerTest, CreateMutator_Test1) delete localData->mutator; } -HWTEST_F_L0(MutatorManagerTest, TransitMutatorToExit_Test1) -{ - ThreadLocalData* localData = ThreadLocal::GetThreadLocalData(); - localData->mutator = new Mutator(); - MutatorManager *managerPtr = new MutatorManager(); - localData->mutator->SetInSaferegion(MutatorBase::SaferegionState::SAFE_REGION_FALSE); - managerPtr->TransitMutatorToExit(); - delete managerPtr; - delete localData->mutator; -} - HWTEST_F_L0(MutatorManagerTest, CreateRuntimeMutato_Test1) { ThreadType threadType = ThreadType::FP_THREAD; @@ -100,14 +99,6 @@ HWTEST_F_L0(MutatorManagerTest, CreateRuntimeMutato_Test1) EXPECT_TRUE(ptr != nullptr); } -HWTEST_F_L0(MutatorManagerTest, DumpMutators_Test1) -{ - MutatorManager *managerPtr = new MutatorManager(); - uint32_t timeoutTimes = 1; - managerPtr->DumpMutators(timeoutTimes); - delete managerPtr; -} - HWTEST_F_L0(MutatorManagerTest, DestroyRuntimeMutator_Test1) { ThreadType threadType = ThreadType::GC_THREAD; diff --git a/common_components/objects/tests/base_string_test.cpp b/common_components/objects/tests/base_string_test.cpp index ae004c97c0..495a30af23 100755 --- a/common_components/objects/tests/base_string_test.cpp +++ b/common_components/objects/tests/base_string_test.cpp @@ -14,6 +14,7 @@ */ #include "common_interfaces/objects/base_string.h" +#include "common_components/platform/string_hash.h" #include "common_components/tests/test_helper.h" using namespace common; @@ -22,6 +23,286 @@ namespace common::test { class BaseStringTest : public common::test::BaseTestWithScope { }; +HWTEST_F_L0(BaseStringTest, ComputeHashForData_TEST0) +{ + const uint8_t data[] = {'a', 'b', 'c'}; + size_t size = sizeof(data) / sizeof(data[0]); + uint32_t hashSeed = 0; + uint32_t expectedHash = hashSeed; + for (uint32_t i = 0; i < size; ++i) { + expectedHash = (expectedHash << static_cast(StringHash::HASH_SHIFT)) - expectedHash + data[i]; + } + + EXPECT_EQ(BaseString::ComputeHashForData(data, size, hashSeed), expectedHash); +} + +HWTEST_F_L0(BaseStringTest, ComputeHashForData_TEST1) +{ + std::vector largeData(1000, 'x'); + size_t size = largeData.size(); + uint32_t hashSeed = 0; + + uint32_t result = BaseString::ComputeHashForData(largeData.data(), size, hashSeed); + EXPECT_NE(result, 0); +} + +HWTEST_F_L0(BaseStringTest, ComputeHashcodeUtf8_TEST0) +{ + const uint8_t utf8Data[] = u8"hello"; + size_t utf8Len = sizeof(utf8Data) / sizeof(utf8Data[0]) - 1; + + uint32_t expectedHash = 0; + for (uint32_t i = 0; i < utf8Len; ++i) { + expectedHash = (expectedHash << static_cast(StringHash::HASH_SHIFT)) - expectedHash + utf8Data[i]; + } + + EXPECT_EQ(BaseString::ComputeHashcodeUtf8(utf8Data, utf8Len, true), expectedHash); +} + +HWTEST_F_L0(BaseStringTest, ComputeHashcodeUtf8_TEST1) +{ + const uint8_t utf8Data[] = u8"hello"; + size_t utf8Len = sizeof(utf8Data) / sizeof(utf8Data[0]) - 1; + + uint32_t expectedHash = 0; + for (uint32_t i = 0; i < utf8Len; ++i) { + expectedHash = (expectedHash << static_cast(StringHash::HASH_SHIFT)) - expectedHash + utf8Data[i]; + } + + EXPECT_EQ(BaseString::ComputeHashcodeUtf8(utf8Data, utf8Len, false), expectedHash); +} + +HWTEST_F_L0(BaseStringTest, IsASCIICharacter_TEST0) +{ + const uint16_t num = 0; + bool result = BaseString::IsASCIICharacter(num); + ASSERT_FALSE(result); +} + +HWTEST_F_L0(BaseStringTest, IsASCIICharacter_TEST1) +{ + const uint16_t num = 0x7f; + bool result = BaseString::IsASCIICharacter(num); + ASSERT_TRUE(result); +} + +HWTEST_F_L0(BaseStringTest, CanBeCompressed_TEST0) +{ + uint8_t data[] = {}; + EXPECT_TRUE(BaseString::CanBeCompressed(data, 0)); + + uint8_t data1[] = {1, 1, 1, 1, 0}; + ASSERT_FALSE(BaseString::CanBeCompressed(data1, 5)); + ASSERT_TRUE(BaseString::CanBeCompressed(data1, 2)); + + uint8_t data2[] = {'a', 'b', 'c', 'd'}; + ASSERT_TRUE(BaseString::CanBeCompressed(data2, 4)); + + uint8_t data3[] = {'a', '\0', 'c', 'd'}; + ASSERT_FALSE(BaseString::CanBeCompressed(data3, 4)); +} + +HWTEST_F_L0(BaseStringTest, CanBeCompressed_TEST1) +{ + uint16_t data[] = {}; + EXPECT_TRUE(BaseString::CanBeCompressed(data, 0)); + + uint16_t data1[] = {1, 1, 1, 1, 0}; + ASSERT_FALSE(BaseString::CanBeCompressed(data1, 5)); + ASSERT_TRUE(BaseString::CanBeCompressed(data1, 2)); + + uint16_t data2[] = {'a', 'b', 'c', 'd'}; + ASSERT_TRUE(BaseString::CanBeCompressed(data2, 4)); + + uint16_t data3[] = {'a', '\0', 'c', 'd'}; + ASSERT_FALSE(BaseString::CanBeCompressed(data3, 4)); +} + +HWTEST_F_L0(BaseStringTest, IndexOf_TEST0) +{ + const uint8_t lhs[] = {'a', 'b', 'c', 'd', 'e'}; + const uint8_t rhs[] = {'a', 'b', 'c'}; + Span lhsSp(lhs, 5); + Span rhsSp(rhs, 3); + + EXPECT_EQ(BaseString::IndexOf(lhsSp, rhsSp, 0, 4), 0); +} + +HWTEST_F_L0(BaseStringTest, IndexOf_TEST1) +{ + const uint8_t lhs[] = {'a', 'b', 'c', 'd', 'e'}; + const uint8_t rhs[] = {'c', 'd'}; + Span lhsSp(lhs, 5); + Span rhsSp(rhs, 2); + + EXPECT_EQ(BaseString::IndexOf(lhsSp, rhsSp, 0, 4), 2); +} + +HWTEST_F_L0(BaseStringTest, IndexOf_TEST2) +{ + const uint8_t lhs[] = {'a', 'b', 'c', 'd', 'e'}; + const uint8_t rhs[] = {'x', 'y', 'z'}; + Span lhsSp(lhs, 5); + Span rhsSp(rhs, 3); + + EXPECT_EQ(BaseString::IndexOf(lhsSp, rhsSp, 0, 4), -1); +} + +HWTEST_F_L0(BaseStringTest, IndexOf_TEST3) +{ + const uint8_t lhs[] = {'a', 'b', 'a', 'b', 'c'}; + const uint8_t rhs[] = {'a', 'b', 'c'}; + Span lhsSp(lhs, 5); + Span rhsSp(rhs, 3); + + EXPECT_EQ(BaseString::IndexOf(lhsSp, rhsSp, 0, 4), 2); +} + +HWTEST_F_L0(BaseStringTest, IndexOf_TEST4) +{ + const uint8_t lhs[] = {'a', 'b', 'c', 'd', 'e'}; + const uint8_t rhs[] = {'a', 'b', 'x'}; + Span lhsSp(lhs, 5); + Span rhsSp(rhs, 3); + + EXPECT_EQ(BaseString::IndexOf(lhsSp, rhsSp, 0, 4), -1); +} + +HWTEST_F_L0(BaseStringTest, CompareStringSpan_TEST0) +{ + const uint8_t lhs[] = {1, 2, 3}; + const uint8_t rhs[] = {1, 2, 3}; + Span lhsSp(lhs, 5); + Span rhsSp(rhs, 3); + EXPECT_EQ(CompareStringSpan(lhsSp, rhsSp, 3), 0); +} + +HWTEST_F_L0(BaseStringTest, CompareStringSpan_TEST1) +{ + const uint8_t lhs[] = {1, 2, 4}; + const uint8_t rhs[] = {1, 2, 3}; + Span lhsSp(lhs, 5); + Span rhsSp(rhs, 3); + EXPECT_EQ(CompareStringSpan(lhsSp, rhsSp, 3), 1); +} + +HWTEST_F_L0(BaseStringTest, IsSubStringAtSpan_TEST1) +{ + const uint8_t lhs[] = {'a', 'b', 'c'}; + const uint8_t rhs[] = {'x', 'y'}; + Span lhsSp(lhs, 3); + Span rhsSp(rhs, 2); + ASSERT_FALSE(IsSubStringAtSpan(lhsSp, rhsSp, 1)); +} + +HWTEST_F_L0(BaseStringTest, IsSubStringAtSpan_TEST2) +{ + const uint8_t lhs[] = {'a', 'b'}; + const uint8_t rhs[] = {'b'}; + Span lhsSp(lhs, 2); + Span rhsSp(rhs, 1); + ASSERT_TRUE(IsSubStringAtSpan(lhsSp, rhsSp, 1)); +} + +HWTEST_F_L0(BaseStringTest, IndexOf_TEST5) +{ + const uint8_t lhs[] = {'a', 'b', 'c', 'd', 'e'}; + const uint16_t rhs[] = {'a', 'b', 'c'}; + Span lhsSp(lhs, 5); + Span rhsSp(rhs, 3); + EXPECT_EQ(BaseString::IndexOf(lhsSp, rhsSp, 0, 4), 0); + + const uint8_t lhs1[] = {'a', 'b', 'c', 'd', 'e'}; + const uint16_t rhs1[] = {'c', 'd'}; + Span lhsSp1(lhs1, 5); + Span rhsSp1(rhs1, 2); + EXPECT_EQ(BaseString::IndexOf(lhsSp1, rhsSp1, 0, 4), 2); + + const uint8_t lhs2[] = {'a', 'b', 'c', 'd', 'e'}; + const uint16_t rhs2[] = {'x', 'y', 'z'}; + Span lhsSp2(lhs2, 5); + Span rhsSp2(rhs2, 3); + EXPECT_EQ(BaseString::IndexOf(lhsSp2, rhsSp2, 0, 4), -1); + + const uint8_t lhs3[] = {'a', 'b', 'a', 'b', 'c'}; + const uint16_t rhs3[] = {'a', 'b', 'c'}; + Span lhsSp3(lhs3, 5); + Span rhsSp3(rhs3, 3); + EXPECT_EQ(BaseString::IndexOf(lhsSp3, rhsSp3, 0, 4), 2); + + const uint8_t lhs4[] = {'a', 'b', 'c', 'd', 'e'}; + const uint16_t rhs4[] = {'a', 'b', 'x'}; + Span lhsSp4(lhs4, 5); + Span rhsSp4(rhs4, 3); + EXPECT_EQ(BaseString::IndexOf(lhsSp4, rhsSp4, 0, 4), -1); +} + +HWTEST_F_L0(BaseStringTest, IndexOf_TEST6) +{ + const uint16_t lhs[] = {'a', 'b', 'c', 'd', 'e'}; + const uint16_t rhs[] = {'a', 'b', 'c'}; + Span lhsSp(lhs, 5); + Span rhsSp(rhs, 3); + EXPECT_EQ(BaseString::IndexOf(lhsSp, rhsSp, 0, 4), 0); + + const uint16_t lhs1[] = {'a', 'b', 'c', 'd', 'e'}; + const uint16_t rhs1[] = {'c', 'd'}; + Span lhsSp1(lhs1, 5); + Span rhsSp1(rhs1, 2); + EXPECT_EQ(BaseString::IndexOf(lhsSp1, rhsSp1, 0, 4), 2); + + const uint16_t lhs2[] = {'a', 'b', 'c', 'd', 'e'}; + const uint16_t rhs2[] = {'x', 'y', 'z'}; + Span lhsSp2(lhs2, 5); + Span rhsSp2(rhs2, 3); + EXPECT_EQ(BaseString::IndexOf(lhsSp2, rhsSp2, 0, 4), -1); + + const uint16_t lhs3[] = {'a', 'b', 'a', 'b', 'c'}; + const uint16_t rhs3[] = {'a', 'b', 'c'}; + Span lhsSp3(lhs3, 5); + Span rhsSp3(rhs3, 3); + EXPECT_EQ(BaseString::IndexOf(lhsSp3, rhsSp3, 0, 4), 2); + + const uint16_t lhs4[] = {'a', 'b', 'c', 'd', 'e'}; + const uint16_t rhs4[] = {'a', 'b', 'x'}; + Span lhsSp4(lhs4, 5); + Span rhsSp4(rhs4, 3); + EXPECT_EQ(BaseString::IndexOf(lhsSp4, rhsSp4, 0, 4), -1); +} + +HWTEST_F_L0(BaseStringTest, IndexOf_TEST7) +{ + const uint16_t lhs[] = {'a', 'b', 'c', 'd', 'e'}; + const uint8_t rhs[] = {'a', 'b', 'c'}; + Span lhsSp(lhs, 5); + Span rhsSp(rhs, 3); + EXPECT_EQ(BaseString::IndexOf(lhsSp, rhsSp, 0, 4), 0); + + const uint16_t lhs1[] = {'a', 'b', 'c', 'd', 'e'}; + const uint8_t rhs1[] = {'c', 'd'}; + Span lhsSp1(lhs1, 5); + Span rhsSp1(rhs1, 2); + EXPECT_EQ(BaseString::IndexOf(lhsSp1, rhsSp1, 0, 4), 2); + + const uint16_t lhs2[] = {'a', 'b', 'c', 'd', 'e'}; + const uint8_t rhs2[] = {'x', 'y', 'z'}; + Span lhsSp2(lhs2, 5); + Span rhsSp2(rhs2, 3); + EXPECT_EQ(BaseString::IndexOf(lhsSp2, rhsSp2, 0, 4), -1); + + const uint16_t lhs3[] = {'a', 'b', 'a', 'b', 'c'}; + const uint8_t rhs3[] = {'a', 'b', 'c'}; + Span lhsSp3(lhs3, 5); + Span rhsSp3(rhs3, 3); + EXPECT_EQ(BaseString::IndexOf(lhsSp3, rhsSp3, 0, 4), 2); + + const uint16_t lhs4[] = {'a', 'b', 'c', 'd', 'e'}; + const uint8_t rhs4[] = {'a', 'b', 'x'}; + Span lhsSp4(lhs4, 5); + Span rhsSp4(rhs4, 3); + EXPECT_EQ(BaseString::IndexOf(lhsSp4, rhsSp4, 0, 4), -1); +} + HWTEST_F_L0(BaseStringTest, IsUtf8EqualsUtf16_TEST0) { const uint8_t utf8_01[] = {0xF0, 0xE0, 0xC0}; @@ -106,4 +387,148 @@ HWTEST_F_L0(BaseStringTest, LastIndexOf_TEST4) EXPECT_EQ(BaseString::LastIndexOf(lhsSp, rhsSp, 3), -1); } + +HWTEST_F_L0(BaseStringTest, IsSubStringAtSpan_TEST3) +{ + const uint8_t lhs[] = {'a', 'b', 'c'}; + const uint16_t rhs[] = {'x', 'y'}; + Span lhsSp(lhs, 3); + Span rhsSp(rhs, 2); + ASSERT_FALSE(IsSubStringAtSpan(lhsSp, rhsSp, 1)); + + const uint8_t lhs1[] = {'a', 'b'}; + const uint16_t rhs1[] = {'b'}; + Span lhsSp1(lhs1, 2); + Span rhsSp1(rhs1, 1); + ASSERT_TRUE(IsSubStringAtSpan(lhsSp1, rhsSp1, 1)); +} + +HWTEST_F_L0(BaseStringTest, IsSubStringAtSpan_TEST4) +{ + const uint16_t lhs[] = {'a', 'b', 'c'}; + const uint8_t rhs[] = {'x', 'y'}; + Span lhsSp(lhs, 3); + Span rhsSp(rhs, 2); + ASSERT_FALSE(IsSubStringAtSpan(lhsSp, rhsSp, 1)); + + const uint16_t lhs1[] = {'a', 'b'}; + const uint8_t rhs1[] = {'b'}; + Span lhsSp1(lhs1, 2); + Span rhsSp1(rhs1, 1); + ASSERT_TRUE(IsSubStringAtSpan(lhsSp1, rhsSp1, 1)); +} + +HWTEST_F_L0(BaseStringTest, IsSubStringAtSpan_TEST5) +{ + const uint16_t lhs[] = {'a', 'b', 'c'}; + const uint16_t rhs[] = {'x', 'y'}; + Span lhsSp(lhs, 3); + Span rhsSp(rhs, 2); + ASSERT_FALSE(IsSubStringAtSpan(lhsSp, rhsSp, 1)); + + const uint16_t lhs1[] = {'a', 'b'}; + const uint16_t rhs1[] = {'b'}; + Span lhsSp1(lhs1, 2); + Span rhsSp1(rhs1, 1); + ASSERT_TRUE(IsSubStringAtSpan(lhsSp1, rhsSp1, 1)); +} + +HWTEST_F_L0(BaseStringTest, LastIndexOf_TEST5) +{ + const uint8_t lhs[] = {'a', 'b', 'c', 'd', 'e'}; + const uint16_t rhs[] = {'c', 'd'}; + Span lhsSp(lhs, 5); + Span rhsSp(rhs, 2); + EXPECT_EQ(BaseString::LastIndexOf(lhsSp, rhsSp, 4), 2); + + const uint8_t lhs1[] = {'a', 'b', 'c', 'x', 'e'}; + const uint16_t rhs1[] = {'c', 'd'}; + Span lhsSp1(lhs1, 5); + Span rhsSp1(rhs1, 2); + EXPECT_EQ(BaseString::LastIndexOf(lhsSp1, rhsSp1, 4), -1); + + const uint8_t lhs2[] = {'a', 'b', 'c', 'd', 'e'}; + const uint16_t rhs2[] = {'c', 'x'}; + Span lhsSp2(lhs2, 5); + Span rhsSp2(rhs2, 2); + EXPECT_EQ(BaseString::LastIndexOf(lhsSp2, rhsSp2, 4), -1); + + const uint8_t lhs3[] = {'a', 'b', 'a', 'b', 'c'}; + const uint16_t rhs3[] = {'a', 'b'}; + Span lhsSp3(lhs3, 5); + Span rhsSp3(rhs3, 2); + EXPECT_EQ(BaseString::LastIndexOf(lhsSp3, rhsSp3, 4), 2); + + const uint8_t lhs4[] = {'a', 'b', 'c', 'd'}; + const uint16_t rhs4[] = {'x', 'y'}; + Span lhsSp4(lhs4, 4); + Span rhsSp4(rhs4, 2); + EXPECT_EQ(BaseString::LastIndexOf(lhsSp4, rhsSp4, 3), -1); +} + +HWTEST_F_L0(BaseStringTest, LastIndexOf_TEST6) +{ + const uint16_t lhs[] = {'a', 'b', 'c', 'd', 'e'}; + const uint16_t rhs[] = {'c', 'd'}; + Span lhsSp(lhs, 5); + Span rhsSp(rhs, 2); + EXPECT_EQ(BaseString::LastIndexOf(lhsSp, rhsSp, 4), 2); + + const uint16_t lhs1[] = {'a', 'b', 'c', 'x', 'e'}; + const uint16_t rhs1[] = {'c', 'd'}; + Span lhsSp1(lhs1, 5); + Span rhsSp1(rhs1, 2); + EXPECT_EQ(BaseString::LastIndexOf(lhsSp1, rhsSp1, 4), -1); + + const uint16_t lhs2[] = {'a', 'b', 'c', 'd', 'e'}; + const uint16_t rhs2[] = {'c', 'x'}; + Span lhsSp2(lhs2, 5); + Span rhsSp2(rhs2, 2); + EXPECT_EQ(BaseString::LastIndexOf(lhsSp2, rhsSp2, 4), -1); + + const uint16_t lhs3[] = {'a', 'b', 'a', 'b', 'c'}; + const uint16_t rhs3[] = {'a', 'b'}; + Span lhsSp3(lhs3, 5); + Span rhsSp3(rhs3, 2); + EXPECT_EQ(BaseString::LastIndexOf(lhsSp3, rhsSp3, 4), 2); + + const uint16_t lhs4[] = {'a', 'b', 'c', 'd'}; + const uint16_t rhs4[] = {'x', 'y'}; + Span lhsSp4(lhs4, 4); + Span rhsSp4(rhs4, 2); + EXPECT_EQ(BaseString::LastIndexOf(lhsSp4, rhsSp4, 3), -1); +} + +HWTEST_F_L0(BaseStringTest, LastIndexOf_TEST7) +{ + const uint16_t lhs[] = {'a', 'b', 'c', 'd', 'e'}; + const uint8_t rhs[] = {'c', 'd'}; + Span lhsSp(lhs, 5); + Span rhsSp(rhs, 2); + EXPECT_EQ(BaseString::LastIndexOf(lhsSp, rhsSp, 4), 2); + + const uint16_t lhs1[] = {'a', 'b', 'c', 'x', 'e'}; + const uint8_t rhs1[] = {'c', 'd'}; + Span lhsSp1(lhs1, 5); + Span rhsSp1(rhs1, 2); + EXPECT_EQ(BaseString::LastIndexOf(lhsSp1, rhsSp1, 4), -1); + + const uint16_t lhs2[] = {'a', 'b', 'c', 'd', 'e'}; + const uint8_t rhs2[] = {'c', 'x'}; + Span lhsSp2(lhs2, 5); + Span rhsSp2(rhs2, 2); + EXPECT_EQ(BaseString::LastIndexOf(lhsSp2, rhsSp2, 4), -1); + + const uint16_t lhs3[] = {'a', 'b', 'a', 'b', 'c'}; + const uint8_t rhs3[] = {'a', 'b'}; + Span lhsSp3(lhs3, 5); + Span rhsSp3(rhs3, 2); + EXPECT_EQ(BaseString::LastIndexOf(lhsSp3, rhsSp3, 4), 2); + + const uint16_t lhs4[] = {'a', 'b', 'c', 'd'}; + const uint8_t rhs4[] = {'x', 'y'}; + Span lhsSp4(lhs4, 4); + Span rhsSp4(rhs4, 2); + EXPECT_EQ(BaseString::LastIndexOf(lhsSp4, rhsSp4, 3), -1); +} } // namespace common::test diff --git a/common_components/profiler/tests/BUILD.gn b/common_components/profiler/tests/BUILD.gn new file mode 100644 index 0000000000..0dc10d69e6 --- /dev/null +++ b/common_components/profiler/tests/BUILD.gn @@ -0,0 +1,57 @@ +# Copyright (c) 2025 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//arkcompiler/ets_runtime/common_components/tests/test_helper.gni") + +module_output_path = "ets_runtime" + +host_unittest_action("Common_Profiler_Interface_Test") { + module_out_path = module_output_path + + sources = [ + # test file + "common_profiler_interface_test.cpp", + ] + + configs = [ + "//arkcompiler/ets_runtime/common_components:common_components_test_config", + "//arkcompiler/ets_runtime:icu_path_test_config", + ] + + deps = [ "//arkcompiler/ets_runtime/common_components:libark_common_components_test" ] + + # hiviewdfx libraries + external_deps = [ + "icu:shared_icui18n", + "icu:shared_icuuc", + "zlib:libz", + ] +} + +group("unittest") { + testonly = true + + # deps file + deps = [ + ":Common_Profiler_Interface_Test", + ] +} + +group("host_unittest") { + testonly = true + + # deps file + deps = [ + ":Common_Profiler_Interface_TestAction", + ] +} diff --git a/common_components/profiler/tests/common_profiler_interface_test.cpp b/common_components/profiler/tests/common_profiler_interface_test.cpp new file mode 100644 index 0000000000..6f85a0e981 --- /dev/null +++ b/common_components/profiler/tests/common_profiler_interface_test.cpp @@ -0,0 +1,96 @@ +/* +* Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "common_components/profiler/common_profiler_interface.h" +#include "common_components/profiler/heap_profiler_listener.cpp" +#include "common_components/tests/test_helper.h" + +using namespace common; + +namespace common::test { +class MockCommonProfiler : public CommonHeapProfilerInterface { +public: + bool isSingleInstance = false; + void DumpHeapSnapshotForCMCOOM() override + { + isSingleInstance = true; + } +}; + +class CommonProfilerInterfaceTest : public common::test::BaseTestWithScope { +}; + +HWTEST_F_L0(CommonProfilerInterfaceTest, DumpHeapSnapshotBeforeOOM) +{ + MockCommonProfiler *instance = new MockCommonProfiler(); + ASSERT_NE(instance, nullptr); + CommonHeapProfilerInterface::SetSingleInstance(nullptr); + CommonHeapProfilerInterface::DumpHeapSnapshotBeforeOOM(); + CommonHeapProfilerInterface::SetSingleInstance(instance); + CommonHeapProfilerInterface::DumpHeapSnapshotBeforeOOM(); + ASSERT_TRUE(instance->isSingleInstance); + delete instance; +} +} // namespace common::test + +namespace common::test { +class HeapProfilerListenerTest : public common::test::BaseTestWithScope { +protected: + void SetUp() override + { + listener_ = &HeapProfilerListener::GetInstance(); + moveEventCallbackCalled = false; + callbackId = 0; + } + + void TearDown() override + { + if (callbackId != 0) { + listener_->UnRegisterMoveEventCb(callbackId); + } + } + + HeapProfilerListener* listener_; + bool moveEventCallbackCalled; + uint32_t callbackId; +}; + +uintptr_t capturedFromObj = 0; +uintptr_t capturedToObj = 0; +size_t capturedSize = 0; + +HWTEST_F_L0(HeapProfilerListenerTest, OnMoveEvent) +{ + std::function emptyCallback; + callbackId = listener_->RegisterMoveEventCb(emptyCallback); + listener_->OnMoveEvent(0x1000, 0x2000, 64); + uintptr_t fromObj = 0x12345678; + uintptr_t toObj = 0x87654321; + size_t size = 1024; + auto callback = [this](uintptr_t from, uintptr_t to, size_t sz) { + moveEventCallbackCalled = true; + capturedFromObj = from; + capturedToObj = to; + capturedSize = sz; + }; + + callbackId = listener_->RegisterMoveEventCb(callback); + listener_->OnMoveEvent(fromObj, toObj, size); + EXPECT_TRUE(moveEventCallbackCalled); + EXPECT_EQ(capturedFromObj, fromObj); + EXPECT_EQ(capturedToObj, toObj); + EXPECT_EQ(capturedSize, size); +} +} //namespace common::test diff --git a/common_components/serialize/tests/BUILD.gn b/common_components/serialize/tests/BUILD.gn new file mode 100644 index 0000000000..bfcdc43839 --- /dev/null +++ b/common_components/serialize/tests/BUILD.gn @@ -0,0 +1,57 @@ +# Copyright (c) 2025 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//arkcompiler/ets_runtime/common_components/tests/test_helper.gni") + +module_output_path = "ets_runtime" + +host_unittest_action("Serialize_Utils_Test") { + module_out_path = module_output_path + + sources = [ + # test file + "serialize_utils_test.cpp", + ] + + configs = [ + "//arkcompiler/ets_runtime/common_components:common_components_test_config", + "//arkcompiler/ets_runtime:icu_path_test_config", + ] + + deps = [ "//arkcompiler/ets_runtime/common_components:libark_common_components_test" ] + + # hiviewdfx libraries + external_deps = [ + "icu:shared_icui18n", + "icu:shared_icuuc", + "zlib:libz", + ] +} + +group("unittest") { + testonly = true + + # deps file + deps = [ + ":Serialize_Utils_Test", + ] +} + +group("host_unittest") { + testonly = true + + # deps file + deps = [ + ":Serialize_Utils_TestAction", + ] +} diff --git a/common_components/serialize/tests/serialize_utils_test.cpp b/common_components/serialize/tests/serialize_utils_test.cpp new file mode 100644 index 0000000000..680b592484 --- /dev/null +++ b/common_components/serialize/tests/serialize_utils_test.cpp @@ -0,0 +1,57 @@ +/* +* Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "common_components/heap/allocator/region_desc.h" +#include "common_components/heap/allocator/region_space.h" +#include "common_components/serialize/serialize_utils.h" +#include "common_components/serialize/serialize_utils.cpp" +#include "common_components/tests/test_helper.h" + +using namespace common; + +namespace common::test { +class SerializeUtilsTest : public common::test::BaseTestWithScope { +protected: + static void SetUpTestCase() + { + BaseRuntime::GetInstance()->Init(); + } + + static void TearDownTestCase() + { + BaseRuntime::GetInstance()->Fini(); + } + void SetUp() override + { + MutatorManager::Instance().CreateRuntimeMutator(ThreadType::GC_THREAD); + } + + void TearDown() override + { + MutatorManager::Instance().DestroyRuntimeMutator(ThreadType::GC_THREAD); + } +}; + +HWTEST_F_L0(SerializeUtilsTest, GetSerializeObjectSpace) +{ + RegionSpace& theAllocator = reinterpret_cast(Heap::GetHeap().GetAllocator()); + uintptr_t addr = theAllocator.AllocOldRegion(); + ASSERT_NE(addr, 0); + RegionDesc* region = RegionDesc::GetRegionDescAt(addr); + region->SetRegionType(RegionDesc::RegionType::END_OF_REGION_TYPE); + SerializedBaseObjectSpace spaceType = SerializeUtils::GetSerializeObjectSpace(addr); + EXPECT_EQ(spaceType, SerializedBaseObjectSpace::OTHER); +} +} // namespace common::test \ No newline at end of file diff --git a/common_components/taskpool/tests/BUILD.gn b/common_components/taskpool/tests/BUILD.gn new file mode 100644 index 0000000000..3c3a88f482 --- /dev/null +++ b/common_components/taskpool/tests/BUILD.gn @@ -0,0 +1,107 @@ +# Copyright (c) 2025 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//arkcompiler/ets_runtime/common_components/tests/test_helper.gni") + +module_output_path = "ets_runtime" + +host_unittest_action("Runner_Test") { + module_out_path = module_output_path + + sources = [ + # test file + "runner_test.cpp", + ] + + configs = [ + "//arkcompiler/ets_runtime/common_components:common_components_test_config", + "//arkcompiler/ets_runtime:icu_path_test_config", + ] + + deps = [ "//arkcompiler/ets_runtime/common_components:libark_common_components_test" ] + + # hiviewdfx libraries + external_deps = [ + "icu:shared_icui18n", + "icu:shared_icuuc", + "zlib:libz", + ] +} + +host_unittest_action("Taskpool_Task_Queue_Test") { + module_out_path = module_output_path + + sources = [ + # test file + "task_queue_test.cpp", + ] + + configs = [ + "//arkcompiler/ets_runtime/common_components:common_components_test_config", + "//arkcompiler/ets_runtime:icu_path_test_config", + ] + + deps = [ "//arkcompiler/ets_runtime/common_components:libark_common_components_test" ] + + # hiviewdfx libraries + external_deps = [ + "icu:shared_icui18n", + "icu:shared_icuuc", + "zlib:libz", + ] +} + +host_unittest_action("Taskpool_Test") { + module_out_path = module_output_path + + sources = [ + # test file + "taskpool_test.cpp", + ] + + configs = [ + "//arkcompiler/ets_runtime/common_components:common_components_test_config", + "//arkcompiler/ets_runtime:icu_path_test_config", + ] + + deps = [ "//arkcompiler/ets_runtime/common_components:libark_common_components_test" ] + + # hiviewdfx libraries + external_deps = [ + "icu:shared_icui18n", + "icu:shared_icuuc", + "zlib:libz", + ] +} + +group("unittest") { + testonly = true + + # deps file + deps = [ + ":Runner_Test", + ":Taskpool_Task_Queue_Test", + ":Taskpool_Test", + ] +} + +group("host_unittest") { + testonly = true + + # deps file + deps = [ + ":Runner_TestAction", + ":Taskpool_Task_Queue_TestAction", + ":Taskpool_TestAction", + ] +} \ No newline at end of file diff --git a/common_components/taskpool/tests/task_queue_test.cpp b/common_components/taskpool/tests/task_queue_test.cpp new file mode 100644 index 0000000000..e9d3972891 --- /dev/null +++ b/common_components/taskpool/tests/task_queue_test.cpp @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "common_components/tests/test_helper.h" +#include "common_components/taskpool/task_queue.h" +#include "common_components/taskpool/task.h" + +#include +#include + +namespace common { + +class TaskQueueTest : public common::test::BaseTestWithScope { +protected: + void SetUp() override + { + queue_ = new TaskQueue(); + } + + void TearDown() override + { + delete queue_; + queue_ = nullptr; + } + + TaskQueue* queue_; +}; + +class MockTask : public Task { +public: + explicit MockTask(int id) : Task(id), executed_(false) {} + + bool Run(uint32_t threadId) override + { + executed_ = true; + return true; + } + + bool IsExecuted() const { return executed_; } + +private: + mutable bool executed_; +}; + + +HWTEST_F_L0(TaskQueueTest, PopTask_DelayedTaskExpired_CanBeExecuted) +{ + auto task = std::make_unique(2); + queue_->PostDelayedTask(std::move(task), 500); + + usleep(600 * 1000); + + auto poppedTask = queue_->PopTask(); + ASSERT_NE(poppedTask, nullptr); + + MockTask* mockTask = static_cast(poppedTask.get()); + EXPECT_FALSE(mockTask->IsExecuted()); + + (void)poppedTask->Run(0); + EXPECT_TRUE(mockTask->IsExecuted()); +} + +HWTEST_F_L0(TaskQueueTest, PopTask_MultipleDelayedTasks_ExecuteInOrder) +{ + auto task1 = std::make_unique(1); + auto task2 = std::make_unique(2); + auto task3 = std::make_unique(3); + + queue_->PostDelayedTask(std::move(task1), 800); + queue_->PostDelayedTask(std::move(task2), 500); + queue_->PostDelayedTask(std::move(task3), 1000); + + usleep(600 * 1000); + + auto poppedTask = queue_->PopTask(); + ASSERT_NE(poppedTask, nullptr); + EXPECT_EQ(poppedTask->GetId(), 2); + + poppedTask->Run(0); + MockTask* mockTask2 = static_cast(poppedTask.get()); + EXPECT_TRUE(mockTask2->IsExecuted()); + + usleep(300 * 1000); + + poppedTask = queue_->PopTask(); + ASSERT_NE(poppedTask, nullptr); + EXPECT_EQ(poppedTask->GetId(), 1); + + poppedTask->Run(0); + MockTask* mockTask1 = static_cast(poppedTask.get()); + EXPECT_TRUE(mockTask1->IsExecuted()); + + usleep(200 * 1000); + + poppedTask = queue_->PopTask(); + ASSERT_NE(poppedTask, nullptr); + EXPECT_EQ(poppedTask->GetId(), 3); + + poppedTask->Run(0); + MockTask* mockTask3 = static_cast(poppedTask.get()); + EXPECT_TRUE(mockTask3->IsExecuted()); +} +} \ No newline at end of file diff --git a/common_components/taskpool/tests/taskpool_test.cpp b/common_components/taskpool/tests/taskpool_test.cpp new file mode 100644 index 0000000000..bd3873f44d --- /dev/null +++ b/common_components/taskpool/tests/taskpool_test.cpp @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "common_components/tests/test_helper.h" +#include "common_components/taskpool/taskpool.h" +#include "common_components/taskpool/task.h" + +#include +#include +#include + +namespace common { + +class MockTask : public Task { +public: + explicit MockTask(int32_t id) + : Task(id), executed_(false), terminated_(false) {} + + bool Run(uint32_t threadId) override + { + executed_ = true; + return true; + } + + bool IsExecuted() const { return executed_; } + + bool IsTerminate() const + { + return terminated_; + } + + void Terminate() + { + terminated_ = true; + } + +private: + std::atomic executed_; + std::atomic terminated_; +}; + +class TaskpoolTest : public common::test::BaseTestWithScope { +protected: + void SetUp() override {} + void TearDown() override {} + + class ScopedTaskpool { + public: + explicit ScopedTaskpool(int threadNum = DEFAULT_TASKPOOL_THREAD_NUM) + : isInitialized_(false) + { + isInitialized_ = true; + pool_.Initialize(threadNum); + } + + Taskpool* Get() + { + return &pool_; + } + + private: + Taskpool pool_; + bool isInitialized_; + }; +}; + +HWTEST_F_L0(TaskpoolTest, InitializeAndDestroy) { + TaskpoolTest::ScopedTaskpool pool(2); + EXPECT_NE(pool.Get(), nullptr); + EXPECT_GT(pool.Get()->GetTotalThreadNum(), 0U); +} + +HWTEST_F_L0(TaskpoolTest, 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); +} + +HWTEST_F_L0(TaskpoolTest, TerminateTask) { + TaskpoolTest::ScopedTaskpool pool(2); + Taskpool* taskpool = pool.Get(); + ASSERT_NE(taskpool, nullptr); + + auto task1 = std::make_unique(1); + auto task2 = std::make_unique(2); + taskpool->PostTask(std::move(task1)); + taskpool->PostTask(std::move(task2)); + + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + + taskpool->TerminateTask(1, TaskType::ALL); + + bool isTerminated = false; + taskpool->ForEachTask([&isTerminated](Task* task) { + if (task->GetId() == 1 && task->IsTerminate()) { + isTerminated = true; + } + }); + + EXPECT_FALSE(isTerminated); +} +} \ No newline at end of file diff --git a/common_components/tests/ohos_test.xml b/common_components/tests/ohos_test.xml index a9332b249e..58b48bedd9 100644 --- a/common_components/tests/ohos_test.xml +++ b/common_components/tests/ohos_test.xml @@ -38,11 +38,26 @@