-
Notifications
You must be signed in to change notification settings - Fork 38
Add: unit tests for C++ runtime modules and Python utilities #427
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
chenshengxin2026
wants to merge
1
commit into
hw-native-sys:main
Choose a base branch
from
chenshengxin2026:add-unit-tests-cpp-and-python
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,120 @@ | ||
| cmake_minimum_required(VERSION 3.15) | ||
| project(pto_runtime_tests CXX) | ||
|
|
||
| set(CMAKE_CXX_STANDARD 17) | ||
| set(CMAKE_CXX_STANDARD_REQUIRED ON) | ||
|
|
||
| # Disable profiling to avoid device_time.h dependency in hot paths | ||
| add_compile_definitions( | ||
| PTO2_PROFILING=0 | ||
| PTO2_ORCH_PROFILING=0 | ||
| PTO2_SCHED_PROFILING=0 | ||
| PTO2_TENSORMAP_PROFILING=0 | ||
| PTO2_SPIN_VERBOSE_LOGGING=0 | ||
| _GLIBCXX_USE_CXX11_ABI=0 | ||
| ) | ||
|
|
||
| # GoogleTest: prefer system installation, fallback to FetchContent | ||
| find_package(GTest QUIET) | ||
| if(NOT GTest_FOUND) | ||
| include(FetchContent) | ||
| FetchContent_Declare(googletest | ||
| GIT_REPOSITORY https://github.com/google/googletest.git | ||
| GIT_TAG v1.14.0 | ||
| ) | ||
| set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) | ||
| FetchContent_MakeAvailable(googletest) | ||
| endif() | ||
|
|
||
| enable_testing() | ||
|
|
||
| # Source directories (use a2a3 as the reference arch for UT) | ||
| set(PROJECT_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/../../..) | ||
| set(TMR_RUNTIME_DIR ${PROJECT_ROOT}/src/a2a3/runtime/tensormap_and_ringbuffer/runtime) | ||
| set(TMR_ORCH_DIR ${PROJECT_ROOT}/src/a2a3/runtime/tensormap_and_ringbuffer/orchestration) | ||
| set(TMR_COMMON_DIR ${PROJECT_ROOT}/src/a2a3/runtime/tensormap_and_ringbuffer/common) | ||
| set(PLATFORM_INCLUDE_DIR ${PROJECT_ROOT}/src/a2a3/platform/include) | ||
| set(COMMON_TASK_DIR ${PROJECT_ROOT}/src/common/task_interface) | ||
|
|
||
| set(COMMON_INCLUDE_DIRS | ||
| ${TMR_RUNTIME_DIR} | ||
| ${TMR_ORCH_DIR} | ||
| ${TMR_COMMON_DIR} | ||
| ${PLATFORM_INCLUDE_DIR} | ||
| ${COMMON_TASK_DIR} | ||
| ) | ||
|
|
||
| # Determine the GTest link target name | ||
| if(TARGET GTest::gtest_main) | ||
| set(GTEST_TARGET GTest::gtest_main) | ||
| else() | ||
| set(GTEST_TARGET gtest_main) | ||
| endif() | ||
|
|
||
| # Stub sources | ||
| set(STUB_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/stubs/test_stubs.cpp) | ||
|
|
||
| # Helper: add a test target (only if source file exists) | ||
| function(add_gtest_target name) | ||
| cmake_parse_arguments(ARG "" "" "SOURCES;EXTRA_SOURCES" ${ARGN}) | ||
| # Check all source files exist | ||
| foreach(src ${ARG_SOURCES}) | ||
| if(NOT IS_ABSOLUTE "${src}") | ||
| set(src "${CMAKE_CURRENT_SOURCE_DIR}/${src}") | ||
| endif() | ||
| if(NOT EXISTS "${src}") | ||
| message(STATUS "Skipping ${name}: ${src} not found") | ||
| return() | ||
| endif() | ||
| endforeach() | ||
| add_executable(${name} ${ARG_SOURCES} ${STUB_SOURCES} ${ARG_EXTRA_SOURCES}) | ||
| target_include_directories(${name} PRIVATE ${COMMON_INCLUDE_DIRS}) | ||
| target_link_libraries(${name} ${GTEST_TARGET}) | ||
| add_test(NAME ${name} COMMAND ${name}) | ||
| set_tests_properties(${name} PROPERTIES LABELS "no_hardware") | ||
| endfunction() | ||
|
|
||
| # --- Header-only tests (no runtime .cpp sources needed) --- | ||
|
|
||
| add_gtest_target(test_submit_types SOURCES test_submit_types.cpp) | ||
| add_gtest_target(test_core_types SOURCES test_core_types.cpp) | ||
| add_gtest_target(test_tensor SOURCES test_tensor.cpp) | ||
|
|
||
| # --- Tests requiring runtime .cpp sources --- | ||
|
|
||
| add_gtest_target(test_shared_memory | ||
| SOURCES test_shared_memory.cpp | ||
| EXTRA_SOURCES ${TMR_RUNTIME_DIR}/pto_shared_memory.cpp | ||
| ) | ||
|
|
||
| add_gtest_target(test_ring_buffer | ||
| SOURCES test_ring_buffer.cpp | ||
| EXTRA_SOURCES | ||
| ${TMR_RUNTIME_DIR}/pto_shared_memory.cpp | ||
| ${TMR_RUNTIME_DIR}/pto_scheduler.cpp | ||
| ${TMR_RUNTIME_DIR}/pto_ring_buffer.cpp | ||
| ) | ||
|
|
||
| add_gtest_target(test_tensormap | ||
| SOURCES test_tensormap.cpp | ||
| EXTRA_SOURCES | ||
| ${TMR_RUNTIME_DIR}/pto_tensormap.cpp | ||
| ) | ||
|
|
||
| add_gtest_target(test_ready_queue | ||
| SOURCES test_ready_queue.cpp | ||
| EXTRA_SOURCES | ||
| ${TMR_RUNTIME_DIR}/pto_scheduler.cpp | ||
| ${TMR_RUNTIME_DIR}/pto_shared_memory.cpp | ||
| ) | ||
|
|
||
| add_gtest_target(test_scheduler_state | ||
| SOURCES test_scheduler_state.cpp | ||
| EXTRA_SOURCES | ||
| ${TMR_RUNTIME_DIR}/pto_scheduler.cpp | ||
| ${TMR_RUNTIME_DIR}/pto_shared_memory.cpp | ||
| ) | ||
|
|
||
| add_gtest_target(test_pto_types SOURCES test_pto_types.cpp) | ||
|
|
||
| add_gtest_target(test_dispatch_payload SOURCES test_dispatch_payload.cpp) | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,99 @@ | ||
| /** | ||
| * 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 <chrono> | ||
| #include <cstdarg> | ||
| #include <cstdint> | ||
| #include <cstdio> | ||
| #include <stdexcept> | ||
| #include <string> | ||
|
|
||
| // ============================================================================= | ||
| // 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<uint64_t>( | ||
| std::chrono::duration_cast<std::chrono::nanoseconds>(now.time_since_epoch()).count()); | ||
| } | ||
|
|
||
| // ============================================================================= | ||
| // common.h stubs (assert_impl, get_stacktrace, AssertionError) | ||
| // ============================================================================= | ||
|
|
||
| std::string get_stacktrace(int /* skip_frames */) { | ||
| return "<stacktrace not available in test stubs>"; | ||
| } | ||
|
|
||
| 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); | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,141 @@ | ||
| /** | ||
| * Unit tests for core types in pto_runtime2_types.h | ||
| * | ||
| * Tests PTO2TaskId encoding, alignment assertions, and utility macros. | ||
| */ | ||
|
|
||
| #include <gtest/gtest.h> | ||
|
|
||
| #include "pto_runtime2_types.h" | ||
|
|
||
| // ============================================================================= | ||
| // PTO2TaskId encoding/extraction | ||
| // ============================================================================= | ||
|
|
||
| TEST(TaskId, DefaultIsZero) { | ||
| PTO2TaskId id; | ||
| EXPECT_EQ(id.raw, 0u); | ||
| EXPECT_EQ(id.ring(), 0); | ||
| EXPECT_EQ(id.local(), 0u); | ||
| } | ||
|
|
||
| TEST(TaskId, MakeAndExtract) { | ||
| auto id = pto2_make_task_id(2, 42); | ||
| EXPECT_EQ(id.ring(), 2); | ||
| EXPECT_EQ(id.local(), 42u); | ||
| } | ||
|
|
||
| TEST(TaskId, RingInUpperBits) { | ||
| auto id = pto2_make_task_id(3, 0); | ||
| EXPECT_EQ(id.raw, static_cast<uint64_t>(3) << 32); | ||
| EXPECT_EQ(id.ring(), 3); | ||
| EXPECT_EQ(id.local(), 0u); | ||
| } | ||
|
|
||
| TEST(TaskId, MaxRingMaxLocal) { | ||
| auto id = pto2_make_task_id(255, 0xFFFFFFFF); | ||
| EXPECT_EQ(id.ring(), 255); | ||
| EXPECT_EQ(id.local(), 0xFFFFFFFF); | ||
| } | ||
|
|
||
| TEST(TaskId, Roundtrip) { | ||
| for (uint8_t ring = 0; ring < PTO2_MAX_RING_DEPTH; ring++) { | ||
| for (uint32_t local : {0u, 1u, 100u, 0xFFFFu, 0xFFFFFFFFu}) { | ||
| auto id = pto2_make_task_id(ring, local); | ||
| EXPECT_EQ(id.ring(), ring); | ||
| EXPECT_EQ(id.local(), local); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| TEST(TaskId, Equality) { | ||
| auto a = pto2_make_task_id(1, 42); | ||
| auto b = pto2_make_task_id(1, 42); | ||
| auto c = pto2_make_task_id(1, 43); | ||
| auto d = pto2_make_task_id(2, 42); | ||
|
|
||
| EXPECT_TRUE(a == b); | ||
| EXPECT_FALSE(a != b); | ||
| EXPECT_TRUE(a != c); | ||
| EXPECT_TRUE(a != d); | ||
| } | ||
|
|
||
| TEST(TaskId, SizeIs8Bytes) { | ||
| EXPECT_EQ(sizeof(PTO2TaskId), 8u); | ||
| } | ||
|
|
||
| // ============================================================================= | ||
| // PTO2TaskSlotState size (cache-line aligned) | ||
| // ============================================================================= | ||
|
|
||
| TEST(TaskSlotState, SizeIs64Bytes) { | ||
| EXPECT_EQ(sizeof(PTO2TaskSlotState), 64u); | ||
| } | ||
|
|
||
| // ============================================================================= | ||
| // PTO2_ALIGN_UP macro | ||
| // ============================================================================= | ||
|
|
||
| TEST(AlignUp, Zero) { | ||
| EXPECT_EQ(PTO2_ALIGN_UP(0, 64), 0u); | ||
| } | ||
|
|
||
| TEST(AlignUp, AlreadyAligned) { | ||
| EXPECT_EQ(PTO2_ALIGN_UP(64, 64), 64u); | ||
| EXPECT_EQ(PTO2_ALIGN_UP(128, 64), 128u); | ||
| } | ||
|
|
||
| TEST(AlignUp, NotAligned) { | ||
| EXPECT_EQ(PTO2_ALIGN_UP(1, 64), 64u); | ||
| EXPECT_EQ(PTO2_ALIGN_UP(63, 64), 64u); | ||
| EXPECT_EQ(PTO2_ALIGN_UP(65, 64), 128u); | ||
| } | ||
|
|
||
| TEST(AlignUp, SmallAlignment) { | ||
| EXPECT_EQ(PTO2_ALIGN_UP(5, 4), 8u); | ||
| EXPECT_EQ(PTO2_ALIGN_UP(4, 4), 4u); | ||
| EXPECT_EQ(PTO2_ALIGN_UP(3, 4), 4u); | ||
| } | ||
|
|
||
| // ============================================================================= | ||
| // Task state enum values | ||
| // ============================================================================= | ||
|
|
||
| TEST(TaskState, EnumValues) { | ||
| EXPECT_EQ(PTO2_TASK_PENDING, 0); | ||
| EXPECT_EQ(PTO2_TASK_READY, 1); | ||
| EXPECT_EQ(PTO2_TASK_RUNNING, 2); | ||
| EXPECT_EQ(PTO2_TASK_COMPLETED, 3); | ||
| EXPECT_EQ(PTO2_TASK_CONSUMED, 4); | ||
| } | ||
|
|
||
| // ============================================================================= | ||
| // Error code constants | ||
| // ============================================================================= | ||
|
|
||
| TEST(ErrorCodes, Values) { | ||
| EXPECT_EQ(PTO2_ERROR_NONE, 0); | ||
| EXPECT_EQ(PTO2_ERROR_SCOPE_DEADLOCK, 1); | ||
| EXPECT_EQ(PTO2_ERROR_HEAP_RING_DEADLOCK, 2); | ||
| EXPECT_EQ(PTO2_ERROR_FLOW_CONTROL_DEADLOCK, 3); | ||
| EXPECT_EQ(PTO2_ERROR_DEP_POOL_OVERFLOW, 4); | ||
| EXPECT_EQ(PTO2_ERROR_INVALID_ARGS, 5); | ||
| EXPECT_EQ(PTO2_ERROR_SCHEDULER_TIMEOUT, 100); | ||
| } | ||
|
|
||
| // ============================================================================= | ||
| // Configuration constants | ||
| // ============================================================================= | ||
|
|
||
| TEST(Config, TaskWindowSizeIsPowerOf2) { | ||
| EXPECT_GT(PTO2_TASK_WINDOW_SIZE, 0); | ||
| EXPECT_EQ(PTO2_TASK_WINDOW_SIZE & (PTO2_TASK_WINDOW_SIZE - 1), 0); | ||
| } | ||
|
|
||
| TEST(Config, MaxRingDepth) { | ||
| EXPECT_EQ(PTO2_MAX_RING_DEPTH, 4); | ||
| } | ||
|
|
||
| TEST(Config, AlignSize) { | ||
| EXPECT_EQ(PTO2_ALIGN_SIZE, 64); | ||
| } |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The
foreachloop for checking source file existence only iterates overARG_SOURCES. It should also check files inARG_EXTRA_SOURCESto prevent build failures when an extra source file is missing or misspelled. This will make the helper function more robust.