From 7d170c9493f5910ba0d09283eac34d5fd6de4e8e Mon Sep 17 00:00:00 2001 From: yp9522 Date: Tue, 22 Jul 2025 11:29:27 +0800 Subject: [PATCH] add common_components tdd Issue: https://gitee.com/openharmony/arkcompiler_ets_runtime/issues/ICNXCF Change-Id: I02e45479c5a82393039f12422e229de542bfa16d Signed-off-by: yp9522 --- common_components/base/c_string.cpp | 1 + .../heap/collector/tests/BUILD.gn | 27 ++++- .../tests/collector_resources_test.cpp | 5 + .../tests/finalizer_processor_test.cpp | 11 +- .../tests/heuristic_gc_policy_test.cpp | 57 +++++++++- .../collector/tests/trace_collector_test.cpp | 79 +++++++++++-- .../w_collector/tests/w_collector_test.cpp | 104 ++++++++++++++++++ .../taskpool/tests/taskpool_test.cpp | 5 - common_components/tests/ohos_test.xml | 5 + 9 files changed, 270 insertions(+), 24 deletions(-) diff --git a/common_components/base/c_string.cpp b/common_components/base/c_string.cpp index 64631c39ce..ac15016ad0 100755 --- a/common_components/base/c_string.cpp +++ b/common_components/base/c_string.cpp @@ -183,6 +183,7 @@ void CString::EnsureSpace(size_t addLen) } char* newStr = reinterpret_cast(malloc(capacity_)); LOGF_IF(newStr == nullptr) << "CString::Init failed"; + LOGF_IF(memset_s(newStr, capacity_, 0, capacity_) != EOK) << "CString::EnsureSpace memset_s failed"; LOGF_IF(memcpy_s(newStr, capacity_, str_, length_) != EOK) << "CString::EnsureSpace memcpy_s failed"; if (str_ != nullptr) { free(str_); diff --git a/common_components/heap/collector/tests/BUILD.gn b/common_components/heap/collector/tests/BUILD.gn index 5e010969c2..5698c8be71 100755 --- a/common_components/heap/collector/tests/BUILD.gn +++ b/common_components/heap/collector/tests/BUILD.gn @@ -21,7 +21,30 @@ host_unittest_action("Collector_Test") { sources = [ # test file "collector_resources_test.cpp", - # "finalizer_processor_test.cpp", + ] + + configs = [ + "//arkcompiler/ets_runtime/common_components:common_components_test_config", + "//arkcompiler/ets_runtime:icu_path_test_config", + ] + + deps = [ "//arkcompiler/ets_runtime/common_components:libark_common_components_test" ] + + # hiviewdfx libraries + external_deps = [ + "bounds_checking_function:libsec_shared", + "icu:shared_icui18n", + "icu:shared_icuuc", + "zlib:libz", + ] +} + +host_unittest_action("Finalizer_Processor_Test") { + module_out_path = module_output_path + + sources = [ + # test file + "finalizer_processor_test.cpp", ] configs = [ @@ -161,6 +184,7 @@ group("unittest") { # deps file deps = [ ":Collector_Test", + ":Finalizer_Processor_Test", ":Heuristic_Gc_Policy_Test", ":Collector_Proxy_Test", ":Trace_Collector_Test", @@ -175,6 +199,7 @@ group("host_unittest") { # deps file deps = [ ":Collector_TestAction", + ":Finalizer_Processor_TestAction", ":Heuristic_Gc_Policy_TestAction", ":Collector_Proxy_TestAction", ":Trace_Collector_TestAction", diff --git a/common_components/heap/collector/tests/collector_resources_test.cpp b/common_components/heap/collector/tests/collector_resources_test.cpp index 32487e1eb6..490c776ecb 100755 --- a/common_components/heap/collector/tests/collector_resources_test.cpp +++ b/common_components/heap/collector/tests/collector_resources_test.cpp @@ -67,4 +67,9 @@ HWTEST_F_L0(CollectorResourcesTest, RequestGCAndWaitTest) { Heap::GetHeap().GetCollectorResources().RequestGC(reason, false, common::GC_TYPE_FULL); EXPECT_TRUE(!gcRequests.IsSyncGC()); } + +HWTEST_F_L0(CollectorResourcesTest, GetGCThreadCountTest) { + uint32_t res = Heap::GetHeap().GetCollectorResources().GetGCThreadCount(false); + EXPECT_EQ(res, 2u); +} } // namespace common::test \ No newline at end of file diff --git a/common_components/heap/collector/tests/finalizer_processor_test.cpp b/common_components/heap/collector/tests/finalizer_processor_test.cpp index a9f4a7fa06..7d5062043b 100755 --- a/common_components/heap/collector/tests/finalizer_processor_test.cpp +++ b/common_components/heap/collector/tests/finalizer_processor_test.cpp @@ -23,6 +23,7 @@ using namespace common; namespace common::test { const uint32_t TWO_SECONDS = 2; const uint32_t HUNDRED_MILLISECONDS = 100; +constexpr uint64_t TAG_BOOLEAN = 0x04ULL; class FinalizerProcessorTest : public common::test::BaseTestWithScope { protected: @@ -48,7 +49,7 @@ HWTEST_F_L0(FinalizerProcessorTest, RegisterFinalizer_TEST1) { FinalizerProcessor finalizerProcessor; HeapAddress addr = common::HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); - BaseObject *obj = reinterpret_cast(addr); + BaseObject *obj = reinterpret_cast(addr | TAG_BOOLEAN); new (obj) BaseObject(); // Construct BaseObject finalizerProcessor.RegisterFinalizer(obj); bool flag = common::RegionSpace::IsMarkedObject(obj); @@ -59,7 +60,7 @@ HWTEST_F_L0(FinalizerProcessorTest, EnqueueFinalizables_TEST1) { FinalizerProcessor finalizerProcessor; HeapAddress addr = common::HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); - BaseObject *obj = reinterpret_cast(addr); + BaseObject *obj = reinterpret_cast(addr | TAG_BOOLEAN); new (obj) BaseObject(); // Construct BaseObject finalizerProcessor.RegisterFinalizer(obj); std::function finalizable = [](BaseObject* obj) { @@ -74,7 +75,7 @@ HWTEST_F_L0(FinalizerProcessorTest, EnqueueFinalizables_TEST2) { FinalizerProcessor finalizerProcessor; HeapAddress addr = common::HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); - BaseObject *obj = reinterpret_cast(addr); + BaseObject *obj = reinterpret_cast(addr | TAG_BOOLEAN); new (obj) BaseObject(); finalizerProcessor.RegisterFinalizer(obj); RootVisitor visitor = [](ObjectRef&) { @@ -107,7 +108,7 @@ HWTEST_F_L0(FinalizerProcessorTest, EnqueueFinalizables_TEST3) finalizerProcessor.EnqueueFinalizables(finalizable, 1); EXPECT_EQ(num2, 0); HeapAddress addr = common::HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); - BaseObject *obj = reinterpret_cast(addr); + BaseObject *obj = reinterpret_cast(addr | TAG_BOOLEAN); new (obj) BaseObject(); finalizerProcessor.RegisterFinalizer(obj); auto num3 = finalizerProcessor.VisitFinalizers(visitor); @@ -121,7 +122,7 @@ HWTEST_F_L0(FinalizerProcessorTest, Run_TEST1) { FinalizerProcessor finalizerProcessor; HeapAddress addr = common::HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); - BaseObject *obj = reinterpret_cast(addr); + BaseObject *obj = reinterpret_cast(addr | TAG_BOOLEAN); new (obj) BaseObject(); AllocationBuffer* buffer = new (std::nothrow) AllocationBuffer(); RegionDesc* region = RegionDesc::GetRegionDescAt(addr); diff --git a/common_components/heap/collector/tests/heuristic_gc_policy_test.cpp b/common_components/heap/collector/tests/heuristic_gc_policy_test.cpp index fa1defbc71..2e28f25604 100644 --- a/common_components/heap/collector/tests/heuristic_gc_policy_test.cpp +++ b/common_components/heap/collector/tests/heuristic_gc_policy_test.cpp @@ -13,8 +13,10 @@ * limitations under the License. */ +#include "common_components/heap/allocator/allocator.h" #include "common_components/heap/allocator/region_space.h" #include "common_components/heap/collector/heuristic_gc_policy.h" +#include "common_components/heap/heap.h" #include "common_components/tests/test_helper.h" using namespace common; @@ -110,11 +112,64 @@ HWTEST_F_L0(HeuristicGCPolicyTest, NotifyNativeAllocation) EXPECT_NE(gcPolicy.GetNativeHeapThreshold(), initialObjects + 1); } -HWTEST_F_L0(HeuristicGCPolicyTest, NotifyNativeAllocation_TriggerByBytes) { +HWTEST_F_L0(HeuristicGCPolicyTest, NotifyNativeAllocation_TriggerByBytes) +{ + HeuristicGCPolicy gcPolicy; + size_t initialNotified = gcPolicy.GetNotifiedNativeSize(); + size_t initialObjects = gcPolicy.GetNativeHeapThreshold(); + + gcPolicy.NotifyNativeAllocation(NATIVE_IMMEDIATE_THRESHOLD + 1); + + EXPECT_EQ(gcPolicy.GetNotifiedNativeSize(), initialNotified + NATIVE_IMMEDIATE_THRESHOLD + 1); + EXPECT_NE(gcPolicy.GetNativeHeapThreshold(), initialObjects + 1); +} + +HWTEST_F_L0(HeuristicGCPolicyTest, TryHeuristicGC) +{ + HeuristicGCPolicy gcPolicy; + StartupStatusManager::SetStartupStatus(StartupStatus::COLD_STARTUP_FINISH); + Heap::GetHeap().GetCollector().GetGCStats().heapThreshold = 0; + gcPolicy.TryHeuristicGC(); + Heap::GetHeap().GetCollector().GetGCStats().shouldRequestYoung = true; + gcPolicy.TryHeuristicGC(); + EXPECT_EQ(Heap::GetHeap().GetAllocator().GetAllocatedBytes(), + Heap::GetHeap().GetCollector().GetGCStats().GetThreshold()); +} + +HWTEST_F_L0(HeuristicGCPolicyTest, ChangeGCParams) +{ + HeuristicGCPolicy gcPolicy; + gcPolicy.RecordAliveSizeAfterLastGC(1); + gcPolicy.ChangeGCParams(true); + EXPECT_EQ(Heap::GetHeap().GetAllocator().GetAllocatedBytes(), 0); +} + +HWTEST_F_L0(HeuristicGCPolicyTest, CheckAndTriggerHintGC) +{ + HeuristicGCPolicy gcPolicy; + StartupStatusManager::SetStartupStatus(StartupStatus::COLD_STARTUP); + bool result = gcPolicy.CheckAndTriggerHintGC(MemoryReduceDegree::HIGH); + ASSERT_FALSE(result); + + StartupStatusManager::SetStartupStatus(StartupStatus::COLD_STARTUP_FINISH); + result = gcPolicy.CheckAndTriggerHintGC(MemoryReduceDegree::HIGH); + ASSERT_FALSE(result); + + gcPolicy.RecordAliveSizeAfterLastGC(1); + result = gcPolicy.CheckAndTriggerHintGC(MemoryReduceDegree::HIGH); + ASSERT_FALSE(result); + + result = gcPolicy.CheckAndTriggerHintGC(MemoryReduceDegree::LOW); + ASSERT_FALSE(result); +} + +HWTEST_F_L0(HeuristicGCPolicyTest, NotifyNativeAllocation_TriggerByBytes1) +{ HeuristicGCPolicy gcPolicy; size_t initialNotified = gcPolicy.GetNotifiedNativeSize(); size_t initialObjects = gcPolicy.GetNativeHeapThreshold(); + gcPolicy.SetNativeHeapThreshold(1); gcPolicy.NotifyNativeAllocation(NATIVE_IMMEDIATE_THRESHOLD + 1); EXPECT_EQ(gcPolicy.GetNotifiedNativeSize(), initialNotified + NATIVE_IMMEDIATE_THRESHOLD + 1); diff --git a/common_components/heap/collector/tests/trace_collector_test.cpp b/common_components/heap/collector/tests/trace_collector_test.cpp index 71111e4e5b..0c40c5dd80 100755 --- a/common_components/heap/collector/tests/trace_collector_test.cpp +++ b/common_components/heap/collector/tests/trace_collector_test.cpp @@ -23,11 +23,6 @@ using namespace common; namespace common::test { -class TestWCollector : public WCollector { -public: - using WCollector::WCollector; -}; - class TraceCollectorTest : public common::test::BaseTestWithScope { protected: static void SetUpTestCase() @@ -39,6 +34,16 @@ protected: { BaseRuntime::GetInstance()->Fini(); } + void SetUp() override + { + MutatorManager::Instance().CreateRuntimeMutator(ThreadType::ARK_PROCESSOR); + } + + void TearDown() override + { + MutatorManager::Instance().DestroyRuntimeMutator(ThreadType::ARK_PROCESSOR); + } + StaticRootTable rootTable_; bool ContainsRoot(StaticRootTable& table, const StaticRootTable::StaticRootArray* array, uint32_t size) { @@ -56,17 +61,13 @@ protected: } class TableTraceCollctor : public TraceCollector { public: + using TraceCollector::SetGCReason; + using TraceCollector::TraceRoots; + using TraceCollector::PushRootToWorkStack; using TraceCollector::UpdateNativeThreshold; }; }; -std::unique_ptr GetWCollector() -{ - CollectorResources& resources = Heap::GetHeap().GetCollectorResources(); - Allocator& allocator = Heap::GetHeap().GetAllocator(); - return std::make_unique(allocator, resources); -} - HWTEST_F_L0(TraceCollectorTest, RunGarbageCollection) { TraceCollector& collector = reinterpret_cast(Heap::GetHeap().GetCollector()); @@ -98,4 +99,58 @@ HWTEST_F_L0(TraceCollectorTest, UpdateNativeThresholdTest) auto newThreshold = Heap::GetHeap().GetNativeHeapThreshold(); EXPECT_NE(newThreshold, oldThreshold); } + +HWTEST_F_L0(TraceCollectorTest, UpdateNativeThresholdTest2) +{ + TableTraceCollctor& collector = reinterpret_cast(Heap::GetHeap().GetCollector()); + Heap::GetHeap().NotifyNativeAllocation(1100 * MB); + + GCParam param; + collector.UpdateNativeThreshold(param); + ASSERT_TRUE(Heap::GetHeap().GetNotifiedNativeSize() > MAX_NATIVE_SIZE_INC); +} + +HWTEST_F_L0(TraceCollectorTest, TraceRootsTest) +{ + TableTraceCollctor& collector = reinterpret_cast(Heap::GetHeap().GetCollector()); + CArrayList roots; + RegionSpace& theAllocator = reinterpret_cast(Heap::GetHeap().GetAllocator()); + uintptr_t addr = theAllocator.AllocOldRegion(); + ASSERT_NE(addr, 0); + BaseObject* obj = reinterpret_cast(addr); + RegionDesc* region = RegionDesc::GetRegionDescAt(addr); + region->SetRegionType(RegionDesc::RegionType::OLD_REGION); + Heap::GetHeap().SetGCReason(GC_REASON_YOUNG); + collector.SetGCReason(GC_REASON_YOUNG); + + roots.push_back(obj); + collector.TraceRoots(roots); + ASSERT_TRUE(region->IsInOldSpace()); +} + +HWTEST_F_L0(TraceCollectorTest, PushRootToWorkStackTest) +{ + TableTraceCollctor& collector = reinterpret_cast(Heap::GetHeap().GetCollector()); + RegionSpace& theAllocator = reinterpret_cast(Heap::GetHeap().GetAllocator()); + uintptr_t addr = theAllocator.AllocOldRegion(); + ASSERT_NE(addr, 0); + BaseObject* obj = reinterpret_cast(addr); + RootSet roots; + RegionDesc* region = RegionDesc::GetRegionDescAt(addr); + region->SetRegionType(RegionDesc::RegionType::RECENT_LARGE_REGION); + collector.SetGCReason(GC_REASON_NATIVE); + region->MarkObject(obj); + bool result = collector.PushRootToWorkStack(&roots, obj); + ASSERT_FALSE(result); + + region->SetRegionType(RegionDesc::RegionType::RECENT_LARGE_REGION); + collector.SetGCReason(GC_REASON_YOUNG); + result = collector.PushRootToWorkStack(&roots, obj); + ASSERT_FALSE(result); + + region->SetRegionType(RegionDesc::RegionType::OLD_REGION); + collector.SetGCReason(GC_REASON_NATIVE); + result = collector.PushRootToWorkStack(&roots, obj); + ASSERT_FALSE(result); +} } \ No newline at end of file diff --git a/common_components/heap/w_collector/tests/w_collector_test.cpp b/common_components/heap/w_collector/tests/w_collector_test.cpp index 9d3b2f59f5..d32216f13e 100644 --- a/common_components/heap/w_collector/tests/w_collector_test.cpp +++ b/common_components/heap/w_collector/tests/w_collector_test.cpp @@ -212,6 +212,97 @@ HWTEST_F_L0(WCollectorTest, ForwardObject_WithUnmovedObject_ReturnsSameAddress) testableCollector->SetCurrentGCPhaseForTest(GCPhase::GC_PHASE_COPY); EXPECT_EQ(testableCollector->GetCurrentGCPhaseForTest(), GCPhase::GC_PHASE_COPY); } + +HWTEST_F_L0(WCollectorTest, TraceRefField_TEST1) +{ + constexpr uint64_t TAG_BITS_SHIFT = 48; + constexpr uint64_t TAG_MARK = 0xFFFFULL << TAG_BITS_SHIFT; + constexpr uint64_t TAG_SPECIAL = 0x02ULL; + constexpr uint64_t TAG_BOOLEAN = 0x04ULL; + constexpr uint64_t TAG_HEAP_OBJECT_MASK = TAG_MARK | TAG_SPECIAL | TAG_BOOLEAN; + HeapAddress addr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); + BaseObject *obj = reinterpret_cast(addr | TAG_HEAP_OBJECT_MASK); + RefField<> field(obj); + + MarkStack workStack; + WeakStack weakStack; + TraceRefField(nullptr, field, workStack, weakStack, GCReason::GC_REASON_YOUNG); + EXPECT_FALSE(Heap::IsTaggedObject(field.GetFieldValue())); +} + +HWTEST_F_L0(WCollectorTest, TraceRefField_TEST2) +{ + HeapAddress addr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); + RegionDesc* region = RegionDesc::GetRegionDescAt(addr); + region->SetRegionType(RegionDesc::RegionType::ALIVE_REGION_FIRST); + BaseObject* obj = reinterpret_cast(addr); + RefField field(obj); + + MarkStack workStack; + WeakStack weakStack; + TraceRefField(nullptr, field, workStack, weakStack, GCReason::GC_REASON_APPSPAWN); + EXPECT_FALSE(region->IsInOldSpace()); + workStack.pop_back(); +} + +HWTEST_F_L0(WCollectorTest, TraceRefField_TEST3) +{ + HeapAddress addr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); + RegionDesc* region = RegionDesc::GetRegionDescAt(addr); + region->SetRegionType(RegionDesc::RegionType::OLD_REGION); + BaseObject* obj = reinterpret_cast(addr); + RefField field(obj); + + MarkStack workStack; + WeakStack weakStack; + TraceRefField(nullptr, field, workStack, weakStack, GCReason::GC_REASON_APPSPAWN); + EXPECT_TRUE(region->IsInOldSpace()); + workStack.pop_back(); +} + +HWTEST_F_L0(WCollectorTest, TraceRefField_TEST4) +{ + HeapAddress addr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); + RegionDesc* region = RegionDesc::GetRegionDescAt(addr); + region->SetRegionType(RegionDesc::RegionType::ALIVE_REGION_FIRST); + BaseObject* obj = reinterpret_cast(addr); + RefField field(obj); + + MarkStack workStack; + WeakStack weakStack; + TraceRefField(nullptr, field, workStack, weakStack, GCReason::GC_REASON_YOUNG); + EXPECT_FALSE(region->IsInOldSpace()); + workStack.pop_back(); +} + +HWTEST_F_L0(WCollectorTest, TraceRefField_TEST5) +{ + HeapAddress addr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); + RegionDesc* region = RegionDesc::GetRegionDescAt(addr); + region->SetRegionType(RegionDesc::RegionType::OLD_REGION); + BaseObject* obj = reinterpret_cast(addr); + RefField field(obj); + + MarkStack workStack; + WeakStack weakStack; + TraceRefField(nullptr, field, workStack, weakStack, GCReason::GC_REASON_YOUNG); + EXPECT_TRUE(region->IsInOldSpace()); +} + +HWTEST_F_L0(WCollectorTest, TraceRefField_TEST6) +{ + HeapAddress addr = HeapManager::Allocate(sizeof(BaseObject), AllocType::MOVEABLE_OBJECT, true); + RegionDesc* region = RegionDesc::GetRegionDescAt(addr); + region->SetRegionAllocPtr(addr - 1); + region->SetTraceLine(); + BaseObject* obj = reinterpret_cast(addr); + RefField field(obj); + + MarkStack workStack; + TraceRefField(obj, obj, field, workStack, region); + EXPECT_TRUE(region->IsNewObjectSinceTrace(obj)); +} + class TestCreateTraceWCollector : public TraceCollector { public: using TraceCollector::SetGCReason; @@ -239,6 +330,19 @@ public: } }; +HWTEST_F_L0(WCollectorTest, CreateTraceObjectRefFieldsVisitor_TEST1) +{ + std::unique_ptr wcollector = GetWCollector(); + ASSERT_TRUE(wcollector != nullptr); + + MarkStack workStack; + WeakStack weakStack; + TestCreateTraceWCollector* collector = reinterpret_cast(wcollector.get()); + collector->SetGCReason(GCReason::GC_REASON_YOUNG); + auto visitor = wcollector->CreateTraceObjectRefFieldsVisitor(&workStack, &weakStack); + EXPECT_TRUE(visitor.GetRefFieldVisitor() != nullptr); +} + HWTEST_F_L0(WCollectorTest, FixRefField_TEST1) { std::unique_ptr wcollector = GetWCollector(); diff --git a/common_components/taskpool/tests/taskpool_test.cpp b/common_components/taskpool/tests/taskpool_test.cpp index c78b7b3c2e..11e0741a26 100644 --- a/common_components/taskpool/tests/taskpool_test.cpp +++ b/common_components/taskpool/tests/taskpool_test.cpp @@ -82,11 +82,6 @@ HWTEST_F_L0(TaskpoolTest, InitializeAndDestroy) { EXPECT_GT(pool.Get()->GetTotalThreadNum(), 0U); } -HWTEST_F_L0(TaskpoolTest, SetQosPriority) { - TaskpoolTest::ScopedTaskpool pool(1); - pool.Get()->SetThreadPriority(PriorityMode::BACKGROUND); -} - HWTEST_F_L0(TaskpoolTest, TerminateTask) { TaskpoolTest::ScopedTaskpool pool(2); Taskpool* taskpool = pool.Get(); diff --git a/common_components/tests/ohos_test.xml b/common_components/tests/ohos_test.xml index 58b48bedd9..50848caed7 100644 --- a/common_components/tests/ohos_test.xml +++ b/common_components/tests/ohos_test.xml @@ -38,6 +38,11 @@