From 43b168b9dbd733844385e8c1073596404c296680 Mon Sep 17 00:00:00 2001 From: chenshengxin Date: Thu, 23 Apr 2026 11:40:57 +0800 Subject: [PATCH] Refactor: reorganize C++ UT into domain-based subdirectories MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move existing tests into hierarchical/, a2a3/, a5/, types/, hardware/ subdirectories. Add shared stubs/test_stubs.cpp for reusable test infrastructure. Introduce add_a2a3_runtime_test() CMake helper for runtime-linked tests. Remove unused test_helpers.h. No new test coverage — structural reorganization only. --- tests/ut/cpp/CMakeLists.txt | 84 +++++++++++--- .../test_a2a3_fatal.cpp} | 36 +++--- .../test_a5_fatal.cpp} | 36 +++--- .../ut/cpp/{ => hardware}/test_hccl_comm.cpp | 16 +-- .../{ => hierarchical}/test_orchestrator.cpp | 10 +- tests/ut/cpp/{ => hierarchical}/test_ring.cpp | 12 +- .../cpp/{ => hierarchical}/test_scheduler.cpp | 6 +- .../ut/cpp/{ => hierarchical}/test_scope.cpp | 2 +- .../cpp/{ => hierarchical}/test_tensormap.cpp | 0 tests/ut/cpp/stubs/test_stubs.cpp | 105 ++++++++++++++++++ .../ut/cpp/{ => types}/test_child_memory.cpp | 1 + 11 files changed, 238 insertions(+), 70 deletions(-) rename tests/ut/cpp/{test_a5_pto2_fatal.cpp => a2a3/test_a2a3_fatal.cpp} (88%) rename tests/ut/cpp/{test_a2a3_pto2_fatal.cpp => a5/test_a5_fatal.cpp} (88%) rename tests/ut/cpp/{ => hardware}/test_hccl_comm.cpp (96%) rename tests/ut/cpp/{ => hierarchical}/test_orchestrator.cpp (96%) rename tests/ut/cpp/{ => hierarchical}/test_ring.cpp (96%) rename tests/ut/cpp/{ => hierarchical}/test_scheduler.cpp (98%) rename tests/ut/cpp/{ => hierarchical}/test_scope.cpp (97%) rename tests/ut/cpp/{ => hierarchical}/test_tensormap.cpp (100%) create mode 100644 tests/ut/cpp/stubs/test_stubs.cpp rename tests/ut/cpp/{ => types}/test_child_memory.cpp (98%) diff --git a/tests/ut/cpp/CMakeLists.txt b/tests/ut/cpp/CMakeLists.txt index ced571d80..06f83d1de 100644 --- a/tests/ut/cpp/CMakeLists.txt +++ b/tests/ut/cpp/CMakeLists.txt @@ -74,6 +74,49 @@ if(NOT GTEST_LIB OR NOT GTEST_MAIN_LIB) set(GTEST_INCLUDE_DIRS "") # include dirs are carried by the gtest target endif() +# --------------------------------------------------------------------------- +# A2A3 runtime sources and stubs for ring-buffer / tensormap tests +# --------------------------------------------------------------------------- +set(A2A3_RUNTIME_DIR ${CMAKE_SOURCE_DIR}/../../../src/a2a3/runtime/tensormap_and_ringbuffer/runtime) +set(A2A3_STUB_SOURCES ${CMAKE_SOURCE_DIR}/stubs/test_stubs.cpp) +set(A2A3_RUNTIME_SOURCES + ${A2A3_RUNTIME_DIR}/pto_ring_buffer.cpp + ${A2A3_RUNTIME_DIR}/pto_shared_memory.cpp + ${A2A3_RUNTIME_DIR}/pto_scheduler.cpp + ${A2A3_RUNTIME_DIR}/pto_tensormap.cpp +) + +set(A2A3_COMMON_INCLUDE_DIRS + ${CMAKE_SOURCE_DIR}/../../../src/a2a3/runtime/tensormap_and_ringbuffer/orchestration + ${CMAKE_SOURCE_DIR}/../../../src/a2a3/runtime/tensormap_and_ringbuffer/runtime + ${CMAKE_SOURCE_DIR}/../../../src/a2a3/runtime/tensormap_and_ringbuffer/common + ${CMAKE_SOURCE_DIR}/../../../src/a2a3/platform/include + ${CMAKE_SOURCE_DIR}/../../../src/common/task_interface +) + +function(add_a2a3_runtime_test name) + cmake_parse_arguments(ARG "" "" "SOURCES;EXTRA_SOURCES" ${ARGN}) + set(_all_sources ${ARG_SOURCES} ${A2A3_STUB_SOURCES}) + foreach(src ${ARG_SOURCES} ${ARG_EXTRA_SOURCES}) + if(EXISTS ${src}) + list(APPEND _all_sources ${src}) + endif() + endforeach() + add_executable(${name} ${_all_sources}) + target_include_directories(${name} PRIVATE + ${GTEST_INCLUDE_DIRS} + ${A2A3_COMMON_INCLUDE_DIRS} + ) + target_compile_options(${name} PRIVATE -D_GLIBCXX_USE_CXX11_ABI=0) + target_link_libraries(${name} PRIVATE + ${GTEST_MAIN_LIB} + ${GTEST_LIB} + pthread + ) + add_test(NAME ${name} COMMAND ${name}) + set_tests_properties(${name} PROPERTIES LABELS "no_hardware") +endfunction() + # --------------------------------------------------------------------------- # Distributed runtime sources under test # --------------------------------------------------------------------------- @@ -113,7 +156,7 @@ function(add_hierarchical_test name src) add_test(NAME ${name} COMMAND ${name}) endfunction() -function(add_a2a3_pto2_test name src) +function(add_a2a3_test name src) add_executable(${name} ${src}) target_include_directories(${name} PRIVATE ${GTEST_INCLUDE_DIRS} @@ -132,7 +175,7 @@ function(add_a2a3_pto2_test name src) add_test(NAME ${name} COMMAND ${name}) endfunction() -function(add_a5_pto2_test name src) +function(add_a5_test name src) add_executable(${name} ${src}) target_include_directories(${name} PRIVATE ${GTEST_INCLUDE_DIRS} @@ -151,13 +194,6 @@ function(add_a5_pto2_test name src) add_test(NAME ${name} COMMAND ${name}) endfunction() -enable_testing() - -add_hierarchical_test(test_tensormap test_tensormap.cpp) -add_hierarchical_test(test_ring test_ring.cpp) -add_hierarchical_test(test_scope test_scope.cpp) -add_hierarchical_test(test_orchestrator test_orchestrator.cpp) -add_hierarchical_test(test_scheduler test_scheduler.cpp) function(add_task_interface_test name src) add_executable(${name} ${src}) target_include_directories(${name} PRIVATE @@ -173,9 +209,31 @@ function(add_task_interface_test name src) add_test(NAME ${name} COMMAND ${name}) endfunction() -add_task_interface_test(test_child_memory test_child_memory.cpp) -add_a2a3_pto2_test(test_a2a3_pto2_fatal test_a2a3_pto2_fatal.cpp) -add_a5_pto2_test(test_a5_pto2_fatal test_a5_pto2_fatal.cpp) +enable_testing() + +# --------------------------------------------------------------------------- +# Hierarchical runtime tests (src/common/hierarchical/) +# --------------------------------------------------------------------------- +add_hierarchical_test(test_tensormap hierarchical/test_tensormap.cpp) +add_hierarchical_test(test_ring hierarchical/test_ring.cpp) +add_hierarchical_test(test_scope hierarchical/test_scope.cpp) +add_hierarchical_test(test_orchestrator hierarchical/test_orchestrator.cpp) +add_hierarchical_test(test_scheduler hierarchical/test_scheduler.cpp) + +# --------------------------------------------------------------------------- +# Types / task_interface tests (src/common/task_interface/) +# --------------------------------------------------------------------------- +add_task_interface_test(test_child_memory types/test_child_memory.cpp) + +# --------------------------------------------------------------------------- +# A2A3 tests (src/a2a3/runtime/tensormap_and_ringbuffer/) +# --------------------------------------------------------------------------- +add_a2a3_test(test_a2a3_fatal a2a3/test_a2a3_fatal.cpp) + +# --------------------------------------------------------------------------- +# A5 tests (src/a5/runtime/tensormap_and_ringbuffer/) +# --------------------------------------------------------------------------- +add_a5_test(test_a5_fatal a5/test_a5_fatal.cpp) # Hardware-gated tests. Block is only entered when the project is configured # with -DSIMPLER_ENABLE_HARDWARE_TESTS=ON. CI's no-hw `ut` job does not pass @@ -238,5 +296,5 @@ if(SIMPLER_ENABLE_HARDWARE_TESTS) ) endfunction() - add_comm_api_test(test_hccl_comm test_hccl_comm.cpp) + add_comm_api_test(test_hccl_comm hardware/test_hccl_comm.cpp) endif() diff --git a/tests/ut/cpp/test_a5_pto2_fatal.cpp b/tests/ut/cpp/a2a3/test_a2a3_fatal.cpp similarity index 88% rename from tests/ut/cpp/test_a5_pto2_fatal.cpp rename to tests/ut/cpp/a2a3/test_a2a3_fatal.cpp index 83d9483b1..4d55788d7 100644 --- a/tests/ut/cpp/test_a5_pto2_fatal.cpp +++ b/tests/ut/cpp/a2a3/test_a2a3_fatal.cpp @@ -41,6 +41,8 @@ struct FakeRuntime { std::string last_fatal_message; }; +static_assert(offsetof(FakeRuntime, ops) == 0); // Guard: reinterpret_cast below assumes ops is first member. + FakeRuntime *as_fake(PTO2Runtime *rt) { return reinterpret_cast(rt); } TaskOutputTensors fake_submit(PTO2Runtime *rt, const MixedKernels &, const Arg &) { @@ -87,20 +89,20 @@ TaskOutputTensors fake_alloc_tensors(PTO2Runtime *rt, const Arg &) { } const PTO2RuntimeOps kFakeOps = { - fake_submit, - fake_scope_begin, - fake_scope_end, - fake_orchestration_done, - fake_is_fatal, - fake_report_fatal, - fake_log, - fake_log, - fake_log, - fake_log, - fake_log, - fake_get_tensor_data, - fake_set_tensor_data, - fake_alloc_tensors, + .submit_task = fake_submit, + .scope_begin = fake_scope_begin, + .scope_end = fake_scope_end, + .orchestration_done = fake_orchestration_done, + .is_fatal = fake_is_fatal, + .report_fatal = fake_report_fatal, + .log_error = fake_log, + .log_warn = fake_log, + .log_info = fake_log, + .log_debug = fake_log, + .log_always = fake_log, + .get_tensor_data = fake_get_tensor_data, + .set_tensor_data = fake_set_tensor_data, + .alloc_tensors = fake_alloc_tensors, }; class RuntimeBindingGuard { @@ -116,7 +118,7 @@ TensorCreateInfo make_ci() { } // namespace -TEST(A5PTO2Fatal, ApiShortCircuitsAfterFatal) { +TEST(A2A3Fatal, ApiShortCircuitsAfterFatal) { FakeRuntime runtime{}; runtime.ops = &kFakeOps; runtime.fatal = true; @@ -148,7 +150,7 @@ TEST(A5PTO2Fatal, ApiShortCircuitsAfterFatal) { EXPECT_EQ(runtime.report_fatal_calls, 0); } -TEST(A5PTO2Fatal, ExplicitFatalRoutesThroughOps) { +TEST(A2A3Fatal, ExplicitFatalRoutesThroughOps) { FakeRuntime runtime{}; runtime.ops = &kFakeOps; RuntimeBindingGuard bind(reinterpret_cast(&runtime)); @@ -167,7 +169,7 @@ TEST(A5PTO2Fatal, ExplicitFatalRoutesThroughOps) { EXPECT_EQ(runtime.submit_calls, 0); } -TEST(A5PTO2Fatal, AllocTensorConvenienceReportsInvalidArgsInsteadOfAsserting) { +TEST(A2A3Fatal, AllocTensorConvenienceReportsInvalidArgsInsteadOfAsserting) { FakeRuntime runtime{}; runtime.ops = &kFakeOps; RuntimeBindingGuard bind(reinterpret_cast(&runtime)); diff --git a/tests/ut/cpp/test_a2a3_pto2_fatal.cpp b/tests/ut/cpp/a5/test_a5_fatal.cpp similarity index 88% rename from tests/ut/cpp/test_a2a3_pto2_fatal.cpp rename to tests/ut/cpp/a5/test_a5_fatal.cpp index b4e2c8e00..b61442b8f 100644 --- a/tests/ut/cpp/test_a2a3_pto2_fatal.cpp +++ b/tests/ut/cpp/a5/test_a5_fatal.cpp @@ -41,6 +41,8 @@ struct FakeRuntime { std::string last_fatal_message; }; +static_assert(offsetof(FakeRuntime, ops) == 0); // Guard: reinterpret_cast below assumes ops is first member. + FakeRuntime *as_fake(PTO2Runtime *rt) { return reinterpret_cast(rt); } TaskOutputTensors fake_submit(PTO2Runtime *rt, const MixedKernels &, const Arg &) { @@ -87,20 +89,20 @@ TaskOutputTensors fake_alloc_tensors(PTO2Runtime *rt, const Arg &) { } const PTO2RuntimeOps kFakeOps = { - fake_submit, - fake_scope_begin, - fake_scope_end, - fake_orchestration_done, - fake_is_fatal, - fake_report_fatal, - fake_log, - fake_log, - fake_log, - fake_log, - fake_log, - fake_get_tensor_data, - fake_set_tensor_data, - fake_alloc_tensors, + .submit_task = fake_submit, + .scope_begin = fake_scope_begin, + .scope_end = fake_scope_end, + .orchestration_done = fake_orchestration_done, + .is_fatal = fake_is_fatal, + .report_fatal = fake_report_fatal, + .log_error = fake_log, + .log_warn = fake_log, + .log_info = fake_log, + .log_debug = fake_log, + .log_always = fake_log, + .get_tensor_data = fake_get_tensor_data, + .set_tensor_data = fake_set_tensor_data, + .alloc_tensors = fake_alloc_tensors, }; class RuntimeBindingGuard { @@ -116,7 +118,7 @@ TensorCreateInfo make_ci() { } // namespace -TEST(A2A3PTO2Fatal, ApiShortCircuitsAfterFatal) { +TEST(A5Fatal, ApiShortCircuitsAfterFatal) { FakeRuntime runtime{}; runtime.ops = &kFakeOps; runtime.fatal = true; @@ -148,7 +150,7 @@ TEST(A2A3PTO2Fatal, ApiShortCircuitsAfterFatal) { EXPECT_EQ(runtime.report_fatal_calls, 0); } -TEST(A2A3PTO2Fatal, ExplicitFatalRoutesThroughOps) { +TEST(A5Fatal, ExplicitFatalRoutesThroughOps) { FakeRuntime runtime{}; runtime.ops = &kFakeOps; RuntimeBindingGuard bind(reinterpret_cast(&runtime)); @@ -167,7 +169,7 @@ TEST(A2A3PTO2Fatal, ExplicitFatalRoutesThroughOps) { EXPECT_EQ(runtime.submit_calls, 0); } -TEST(A2A3PTO2Fatal, AllocTensorConvenienceReportsInvalidArgsInsteadOfAsserting) { +TEST(A5Fatal, AllocTensorConvenienceReportsInvalidArgsInsteadOfAsserting) { FakeRuntime runtime{}; runtime.ops = &kFakeOps; RuntimeBindingGuard bind(reinterpret_cast(&runtime)); diff --git a/tests/ut/cpp/test_hccl_comm.cpp b/tests/ut/cpp/hardware/test_hccl_comm.cpp similarity index 96% rename from tests/ut/cpp/test_hccl_comm.cpp rename to tests/ut/cpp/hardware/test_hccl_comm.cpp index 858c488de..73c5cb91e 100644 --- a/tests/ut/cpp/test_hccl_comm.cpp +++ b/tests/ut/cpp/hardware/test_hccl_comm.cpp @@ -12,12 +12,12 @@ /* * Hardware UT guarding the CANN/HCCL-private ABI coupling in comm_hccl.cpp. * - * The call chain (dlopen → create_device_context → ensure_acl_ready_ctx → - * aclrtCreateStream → comm_init → comm_alloc_windows → ...) is not the - * interesting part — the interesting part is *what's inside* CommContext + * The call chain (dlopen -> create_device_context -> ensure_acl_ready_ctx -> + * aclrtCreateStream -> comm_init -> comm_alloc_windows -> ...) is not the + * interesting part -- the interesting part is *what's inside* CommContext * after comm_alloc_windows returns. That struct comes from one of: * - * - MESH topology: `reinterpret_cast(HCCL's return ptr)` — + * - MESH topology: `reinterpret_cast(HCCL's return ptr)` -- * our layout is *assumed* to match HCCL's internal MESH context. * - RING topology: our parser reads HcclOpResParam / HcclRankRelationResV2 * field-by-field using offsetof against reverse-engineered struct defs. @@ -40,7 +40,7 @@ * gate SIMPLER_ENABLE_HARDWARE_TESTS. Device allocation is driven by * CTest RESOURCE_GROUPS + --resource-spec-file. * - * Linking strategy: libhost_runtime.so is dlopen'd — it is the subject + * Linking strategy: libhost_runtime.so is dlopen'd -- it is the subject * under test and mirrors how ChipWorker loads a runtime backend in * production. libascendcl.so is linked directly at compile time because * it is generic CANN infra; going through dlsym for acl* here buys nothing @@ -122,14 +122,14 @@ constexpr int EXIT_WINDOW_SIZE = 50; // the CommContext returned by HCCL (MESH reinterpret_cast) or built by our // RING parser actually contains the fields we expect at the offsets we // expect. Failure here means our reverse-engineered CANN ABI disagrees with -// the live HCCL build — the CANN-coupling fragility this test is here for. +// the live HCCL build -- the CANN-coupling fragility this test is here for. constexpr int EXIT_CTX_MEMCPY = 55; constexpr int EXIT_CTX_FIELDS = 56; constexpr int EXIT_BARRIER = 60; constexpr int EXIT_DESTROY = 70; int run_rank(int rank, int nranks, int device_id, const char *rootinfo_path) { - // libhost_runtime.so is the subject under test — dlopen mirrors + // libhost_runtime.so is the subject under test -- dlopen mirrors // ChipWorker. libascendcl is linked in, so acl* is available directly. void *host_handle = dlopen(PTO_HOST_RUNTIME_LIB_PATH, RTLD_NOW | RTLD_LOCAL); if (host_handle == nullptr) { @@ -215,7 +215,7 @@ int run_rank(int rank, int nranks, int device_id, const char *rootinfo_path) { host_ctx.windowsIn[rank] != local_base) { fprintf( stderr, - "[rank %d] CommContext field mismatch — CANN ABI drift?\n" + "[rank %d] CommContext field mismatch -- CANN ABI drift?\n" " got: rankId=%u rankNum=%u winSize=%lu windowsIn[%d]=0x%lx\n" " expected: rankId=%d rankNum=%d winSize=%zu windowsIn[%d]=0x%lx\n", rank, host_ctx.rankId, host_ctx.rankNum, static_cast(host_ctx.winSize), rank, diff --git a/tests/ut/cpp/test_orchestrator.cpp b/tests/ut/cpp/hierarchical/test_orchestrator.cpp similarity index 96% rename from tests/ut/cpp/test_orchestrator.cpp rename to tests/ut/cpp/hierarchical/test_orchestrator.cpp index 14919b11e..82fac02d7 100644 --- a/tests/ut/cpp/test_orchestrator.cpp +++ b/tests/ut/cpp/hierarchical/test_orchestrator.cpp @@ -48,7 +48,7 @@ struct OrchestratorFixture : public ::testing::Test { void TearDown() override { allocator.shutdown(); } - // Per-slot accessor — slot state lives inside the Ring now. + // Per-slot accessor -- slot state lives inside the Ring now. TaskSlotState &S(TaskSlot id) { return *allocator.slot_state(id); } // Helper: build a TaskArgs whose only tensor has the given (data, tag). @@ -86,7 +86,7 @@ TEST_F(OrchestratorFixture, DependentTaskIsPending) { TaskSlot a_slot; rq.try_pop(a_slot); - // Task B reads INPUT at the same key — depends on A + // Task B reads INPUT at the same key -- depends on A auto args_b = single_tensor_args(0xBEEF, TensorArgType::INPUT); auto b = orch.submit_next_level(0xDEAD, args_b, cfg); EXPECT_EQ(S(b.task_slot).state.load(), TaskState::PENDING); @@ -151,7 +151,7 @@ TEST_F(OrchestratorFixture, NoDepTagSkipsDependencyTracking) { TaskSlot drain_slot; rq.try_pop(drain_slot); - // Second task references same key but tagged NO_DEP — should be independent + // Second task references same key but tagged NO_DEP -- should be independent auto args_b = single_tensor_args(0xAAAA, TensorArgType::NO_DEP); auto b = orch.submit_next_level(0xDEAD, args_b, cfg); EXPECT_EQ(S(b.task_slot).state.load(), TaskState::READY); @@ -215,7 +215,7 @@ TEST_F(OrchestratorFixture, OutputAutoAllocsFromHeapRing) { TEST_F(OrchestratorFixture, InoutWiresCreatorAsFanin) { // INOUT is the only tag that pulls in the prior writer as a fanin - // producer — matching L2's pto_orchestrator.cpp Step B where only + // producer -- matching L2's pto_orchestrator.cpp Step B where only // INPUT / INOUT do tensor_map.lookup. Users who want a WaW dep on // the alloc-slot (so its HeapRing slab stays live while they write) // must tag the buffer INOUT. @@ -250,7 +250,7 @@ TEST_F(OrchestratorFixture, InoutWiresCreatorAsFanin) { TEST_F(OrchestratorFixture, OutputAndOutputExistingAreInsertOnly) { // Contrast with INOUT: plain OUTPUT and OUTPUT_EXISTING are pure - // overwrites — insert into TensorMap, no lookup, so no fanin wire + // overwrites -- insert into TensorMap, no lookup, so no fanin wire // on the prior writer. Matches L2 semantics for both tags. Users // who need creator lifetime must tag the buffer INOUT. struct Case { diff --git a/tests/ut/cpp/test_ring.cpp b/tests/ut/cpp/hierarchical/test_ring.cpp similarity index 96% rename from tests/ut/cpp/test_ring.cpp rename to tests/ut/cpp/hierarchical/test_ring.cpp index 05152972d..7f0689b7d 100644 --- a/tests/ut/cpp/test_ring.cpp +++ b/tests/ut/cpp/hierarchical/test_ring.cpp @@ -129,7 +129,7 @@ TEST(Ring, SlotStateIsPointerStable) { TaskSlotState *p0 = a.slot_state(r0.slot); ASSERT_NE(p0, nullptr); - // Push many more slots through — the deque may grow/chain, but the + // Push many more slots through -- the deque may grow/chain, but the // pointer we grabbed for slot 0 has to stay valid. for (int i = 0; i < 1000; ++i) { (void)a.alloc(); @@ -227,7 +227,7 @@ TEST(Ring, ScopeDepthMapsToRingIdx) { } TEST(Ring, PerRingHeapsAreDistinctMmaps) { - // Total VA = 4 × 4 KiB; verify each ring has its own mapping. + // Total VA = 4 x 4 KiB; verify each ring has its own mapping. Ring a; a.init(kSmallHeap, kQuickTimeoutMs); @@ -241,7 +241,7 @@ TEST(Ring, PerRingHeapsAreDistinctMmaps) { for (int i = 0; i < MAX_RING_DEPTH; ++i) { for (int j = i + 1; j < MAX_RING_DEPTH; ++j) { EXPECT_NE(bases[i], bases[j]) - << "rings " << i << " and " << j << " share a mapping — expected 4 separate mmaps"; + << "rings " << i << " and " << j << " share a mapping -- expected 4 separate mmaps"; } } } @@ -292,7 +292,7 @@ TEST(Ring, RingsReclaimIndependently) { EXPECT_EQ(r1a.ring_idx, 1); EXPECT_EQ(r1b.ring_idx, 1); - // Ring 0 is untouched — this must succeed instantly, not time out. + // Ring 0 is untouched -- this must succeed instantly, not time out. auto r0 = a.alloc(HEAP_ALIGN, /*scope_depth=*/0); EXPECT_EQ(r0.ring_idx, 0); ASSERT_NE(r0.heap_ptr, nullptr); @@ -322,7 +322,7 @@ TEST(Ring, InnerRingReclaimsWhileOuterHolds) { EXPECT_EQ(a.heap_top(0), HEAP_ALIGN); EXPECT_EQ(a.heap_tail(0), 0u); - // Churn on the inner ring — allocate, release, allocate, release, ... + // Churn on the inner ring -- allocate, release, allocate, release, ... for (int i = 0; i < 8; ++i) { auto inner = a.alloc(HEAP_ALIGN, /*scope_depth=*/1); a.release(inner.slot); @@ -331,7 +331,7 @@ TEST(Ring, InnerRingReclaimsWhileOuterHolds) { // Outer ring unchanged (one live slab at offset 0). EXPECT_EQ(a.heap_top(0), HEAP_ALIGN); EXPECT_EQ(a.heap_tail(0), 0u); - // Inner ring reclaimed each slab — tail caught up to top. + // Inner ring reclaimed each slab -- tail caught up to top. EXPECT_EQ(a.heap_tail(1), a.heap_top(1)); a.release(outer.slot); diff --git a/tests/ut/cpp/test_scheduler.cpp b/tests/ut/cpp/hierarchical/test_scheduler.cpp similarity index 98% rename from tests/ut/cpp/test_scheduler.cpp rename to tests/ut/cpp/hierarchical/test_scheduler.cpp index f13dd240f..87c50a895 100644 --- a/tests/ut/cpp/test_scheduler.cpp +++ b/tests/ut/cpp/hierarchical/test_scheduler.cpp @@ -205,7 +205,7 @@ TEST_F(SchedulerFixture, DependentTaskDispatchedAfterProducerCompletes) { } // =========================================================================== -// Group task tests — fixture with 2 MockWorkers +// Group task tests -- fixture with 2 MockWorkers // =========================================================================== struct GroupSchedulerFixture : public ::testing::Test { @@ -405,7 +405,7 @@ TEST_F(MixedTypeSchedulerFixture, SubTaskDispatchesWhileNextLevelPoolSaturated) EXPECT_TRUE(next_level_worker.is_running.load()) << "chip worker must still be busy"; // Complete the sub task first; it reaches CONSUMED while the chip task - // is still running — demonstrating independent per-type dispatch. + // is still running -- demonstrating independent per-type dispatch. sub_worker.complete(); wait_consumed(sub.task_slot); EXPECT_FALSE(is_consumed(chip.task_slot)); @@ -416,7 +416,7 @@ TEST_F(MixedTypeSchedulerFixture, SubTaskDispatchesWhileNextLevelPoolSaturated) TEST_F(GroupSchedulerFixture, GroupDependencyChain) { // Group A (2 workers) produces an OUTPUT at key 0xCAFE. - // Task B reads INPUT at the same key — depends on group A. + // Task B reads INPUT at the same key -- depends on group A. TaskArgs a0 = single_tensor_args(0xCAFE, TensorArgType::OUTPUT); TaskArgs a1 = single_tensor_args(0xCAFE, TensorArgType::OUTPUT); auto a = orch.submit_next_level_group(0xDEAD, {a0, a1}, cfg); diff --git a/tests/ut/cpp/test_scope.cpp b/tests/ut/cpp/hierarchical/test_scope.cpp similarity index 97% rename from tests/ut/cpp/test_scope.cpp rename to tests/ut/cpp/hierarchical/test_scope.cpp index d8350d1c6..273b33bfc 100644 --- a/tests/ut/cpp/test_scope.cpp +++ b/tests/ut/cpp/hierarchical/test_scope.cpp @@ -43,7 +43,7 @@ TEST(Scope, SingleScope_ReleasesRegisteredTasks) { TEST(Scope, RegisterOutsideScopeIsNoop) { Scope sc; - sc.register_task(5); // no open scope — should not throw + sc.register_task(5); // no open scope -- should not throw EXPECT_EQ(sc.depth(), 0); } diff --git a/tests/ut/cpp/test_tensormap.cpp b/tests/ut/cpp/hierarchical/test_tensormap.cpp similarity index 100% rename from tests/ut/cpp/test_tensormap.cpp rename to tests/ut/cpp/hierarchical/test_tensormap.cpp diff --git a/tests/ut/cpp/stubs/test_stubs.cpp b/tests/ut/cpp/stubs/test_stubs.cpp new file mode 100644 index 000000000..b9593ed08 --- /dev/null +++ b/tests/ut/cpp/stubs/test_stubs.cpp @@ -0,0 +1,105 @@ +/* + * Copyright (c) PyPTO Contributors. + * This program is free software, you can redistribute it and/or modify it under the terms and conditions of + * CANN Open Software License Agreement Version 2.0 (the "License"). + * Please refer to the License for details. You may not use this file except in compliance with the License. + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. + * See LICENSE in the root of the software repository for the full text of the License. + * ----------------------------------------------------------------------------------------------------------- + */ +/** + * Link-time stubs for platform APIs used by runtime headers. + * + * Provides x86-compatible implementations of functions declared in + * platform headers (unified_log.h, device_time.h, common.h) so that + * runtime data structures can be unit-tested on CI runners without + * Ascend hardware or SDK. + */ + +#include +#include +#include +#include +#include +#include + +// ============================================================================= +// unified_log.h stubs (5 log-level functions) +// ============================================================================= + +extern "C" { + +void unified_log_error(const char *func, const char *fmt, ...) { + va_list args; + va_start(args, fmt); + fprintf(stderr, "[ERROR] %s: ", func); + vfprintf(stderr, fmt, args); + fprintf(stderr, "\n"); + va_end(args); +} + +void unified_log_warn(const char *func, const char *fmt, ...) { + va_list args; + va_start(args, fmt); + fprintf(stderr, "[WARN] %s: ", func); + vfprintf(stderr, fmt, args); + fprintf(stderr, "\n"); + va_end(args); +} + +void unified_log_info(const char * /* func */, const char * /* fmt */, ...) { + // Suppress info in tests +} + +void unified_log_debug(const char * /* func */, const char * /* fmt */, ...) { + // Suppress debug in tests +} + +void unified_log_always(const char *func, const char *fmt, ...) { + va_list args; + va_start(args, fmt); + fprintf(stderr, "[ALWAYS] %s: ", func); + vfprintf(stderr, fmt, args); + fprintf(stderr, "\n"); + va_end(args); +} + +} // extern "C" + +// ============================================================================= +// device_time.h stub +// ============================================================================= + +uint64_t get_sys_cnt_aicpu() { + auto now = std::chrono::steady_clock::now(); + return static_cast(std::chrono::duration_cast(now.time_since_epoch()).count()); +} + +// ============================================================================= +// common.h stubs (assert_impl, get_stacktrace, AssertionError) +// ============================================================================= + +std::string get_stacktrace(int /* skip_frames */) { return ""; } + +class AssertionError : public std::runtime_error { +public: + AssertionError(const char *condition, const char *file, int line) : + std::runtime_error(std::string("Assertion failed: ") + condition + " at " + file + ":" + std::to_string(line)), + condition_(condition), + file_(file), + line_(line) {} + + const char *condition() const { return condition_; } + const char *file() const { return file_; } + int line() const { return line_; } + +private: + const char *condition_; + const char *file_; + int line_; +}; + +[[noreturn]] void assert_impl(const char *condition, const char *file, int line) { + throw AssertionError(condition, file, line); +} diff --git a/tests/ut/cpp/test_child_memory.cpp b/tests/ut/cpp/types/test_child_memory.cpp similarity index 98% rename from tests/ut/cpp/test_child_memory.cpp rename to tests/ut/cpp/types/test_child_memory.cpp index 2ac7073a2..418cfdc7c 100644 --- a/tests/ut/cpp/test_child_memory.cpp +++ b/tests/ut/cpp/types/test_child_memory.cpp @@ -20,6 +20,7 @@ // ContinuousTensor layout // --------------------------------------------------------------------------- +// ABI contract: size must match serialization format. TEST(ChildMemory, SizeofUnchanged) { EXPECT_EQ(sizeof(ContinuousTensor), 40u); } TEST(ChildMemory, DefaultIsZero) {