Adding tests for code coverage (#82)
* Adding tests for code coverage * integration tests * Fixing gtest dependencies * Removing gmock linkage * build fixes * Fixing Analyze job * CMake updates * Fixing PSDB * Addressing feedback * Adding licenses * Addressing feedback * updating dashboard * more API tests * Addressing feedback * correcting Macro * preloading libintercept
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
ed7a2104ef
Коммит
eca6739e13
@@ -73,4 +73,4 @@ add_custom_target( mygen
|
||||
COMMAND sh -xc "sed 's/_GPU_BLOCKINFO_H_/SRC_DEF_GPU_BLOCK_INFO_H_/' ${BINFO_DEF} >>${BINFO_HEADER}"
|
||||
)
|
||||
|
||||
add_subdirectory(src/core)
|
||||
add_subdirectory(src/core)
|
||||
|
||||
@@ -1 +1,5 @@
|
||||
add_subdirectory(include)
|
||||
add_subdirectory(include)
|
||||
if(AQLPROFILE_BUILD_TESTS)
|
||||
enable_testing()
|
||||
add_subdirectory(tests)
|
||||
endif()
|
||||
@@ -23,6 +23,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <climits>
|
||||
#include <future>
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
@@ -0,0 +1,119 @@
|
||||
# write a CMakeLists.txt file for the gfx9_factory_test
|
||||
# that includes the necessary libraries and sets the properties for the test
|
||||
include(GoogleTest)
|
||||
find_package(GTest REQUIRED)
|
||||
include_directories(${GTEST_INCLUDE_DIRS})
|
||||
|
||||
|
||||
find_library(
|
||||
hsa-amd-aqlprofile64
|
||||
REQUIRED
|
||||
NAMES hsa-amd-aqlprofile64 hsa-amd-aqlprofile
|
||||
HINTS /opt/rocm/lib /opt/rocm
|
||||
PATHS /opt/rocm/lib /opt/rocm)
|
||||
|
||||
# Add test for memory manager
|
||||
add_executable(gfx9-memory-manager-test)
|
||||
SET(AQLPROFILE_MEMORYMANAGER_SOURCES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/memorymanager_tests.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../memorymanager.cpp
|
||||
)
|
||||
|
||||
target_sources(gfx9-memory-manager-test PRIVATE ${AQLPROFILE_MEMORYMANAGER_SOURCES})
|
||||
target_include_directories(gfx9-memory-manager-test PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${LIB_DIR})
|
||||
target_link_libraries(
|
||||
gfx9-memory-manager-test
|
||||
PRIVATE
|
||||
hsa-runtime64::hsa-runtime64
|
||||
GTest::gtest
|
||||
GTest::gtest_main)
|
||||
|
||||
|
||||
gtest_add_tests(
|
||||
TARGET gfx9-memory-manager-test
|
||||
SOURCES ${AQLPROFILE_MEMORYMANAGER_SOURCES}
|
||||
TEST_LIST gfx9-memory-manager_TESTS
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
set_tests_properties(
|
||||
${gfx9-memory-manager_TESTS} PROPERTIES TIMEOUT 45 LABELS "unittests" FAIL_REGULAR_EXPRESSION
|
||||
"${AQLPROFILE_DEFAULT_FAIL_REGEX}")
|
||||
|
||||
# Add test for aql profile
|
||||
add_executable(aqlprofile-test)
|
||||
SET(AQLPROFILE_TEST_SOURCES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/aql_profile_tests.cpp
|
||||
)
|
||||
|
||||
target_sources(aqlprofile-test PRIVATE ${AQLPROFILE_TEST_SOURCES})
|
||||
target_include_directories(aqlprofile-test PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${LIB_DIR})
|
||||
target_link_libraries(
|
||||
aqlprofile-test
|
||||
PRIVATE
|
||||
hsa-runtime64::hsa-runtime64
|
||||
GTest::gtest
|
||||
GTest::gtest_main
|
||||
GTest::gmock
|
||||
GTest::gmock_main)
|
||||
|
||||
|
||||
gtest_add_tests(
|
||||
TARGET aqlprofile-test
|
||||
SOURCES ${AQLPROFILE_TEST_SOURCES}
|
||||
TEST_LIST aqlprofile-test_TESTS
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
set_tests_properties(
|
||||
${aqlprofile-test_TESTS} PROPERTIES TIMEOUT 45 LABELS "unittests" FAIL_REGULAR_EXPRESSION
|
||||
"${AQLPROFILE_DEFAULT_FAIL_REGEX}")
|
||||
|
||||
|
||||
# Add tests for command buffer
|
||||
add_executable(command-buffer-test)
|
||||
SET(AQLPROFILE_COMMAND_BUFFER_SOURCES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/command_buffer_tests.cpp
|
||||
)
|
||||
target_sources(command-buffer-test PRIVATE ${AQLPROFILE_COMMAND_BUFFER_SOURCES})
|
||||
target_include_directories(command-buffer-test PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${LIB_DIR})
|
||||
target_link_libraries(
|
||||
command-buffer-test
|
||||
PRIVATE
|
||||
hsa-runtime64::hsa-runtime64
|
||||
GTest::gtest
|
||||
GTest::gtest_main
|
||||
GTest::gmock
|
||||
GTest::gmock_main)
|
||||
|
||||
gtest_add_tests(
|
||||
TARGET command-buffer-test
|
||||
SOURCES ${AQLPROFILE_COMMAND_BUFFER_SOURCES}
|
||||
TEST_LIST command-buffer-test_TESTS
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
|
||||
set_tests_properties(
|
||||
${command-buffer-test_TESTS} PROPERTIES TIMEOUT 45 LABELS "unittests" FAIL_REGULAR_EXPRESSION
|
||||
"${AQLPROFILE_DEFAULT_FAIL_REGEX}")
|
||||
|
||||
# Add tests for counters
|
||||
add_executable(counters-test)
|
||||
SET(AQLPROFILE_COUNTERS_SOURCES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/counter_tests.cpp
|
||||
)
|
||||
target_sources(counters-test PRIVATE ${AQLPROFILE_COUNTERS_SOURCES})
|
||||
target_include_directories(counters-test PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${LIB_DIR})
|
||||
target_link_libraries(
|
||||
counters-test
|
||||
PRIVATE
|
||||
hsa-runtime64::hsa-runtime64
|
||||
${hsa-amd-aqlprofile64}
|
||||
GTest::gtest
|
||||
GTest::gtest_main
|
||||
GTest::gmock
|
||||
GTest::gmock_main)
|
||||
gtest_add_tests(
|
||||
TARGET counters-test
|
||||
SOURCES ${AQLPROFILE_COUNTERS_SOURCES}
|
||||
TEST_LIST counters-test_TESTS
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
|
||||
set_tests_properties(
|
||||
${counters-test_TESTS} PROPERTIES TIMEOUT 45 LABELS "unittests" FAIL_REGULAR_EXPRESSION
|
||||
"${AQLPROFILE_DEFAULT_FAIL_REGEX}")
|
||||
@@ -0,0 +1,245 @@
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) 2023-2025 Advanced Micro Devices, Inc. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <gmock/gmock.h>
|
||||
|
||||
#include "core/aql_profile.hpp"
|
||||
#include "core/pm4_factory.h"
|
||||
// header for memcpy
|
||||
#include <cstring>
|
||||
|
||||
|
||||
//#include "core/counter_dimensions.hpp"
|
||||
//#include "core/include/aql_profile_v2.h"
|
||||
|
||||
using namespace aql_profile;
|
||||
using namespace testing;
|
||||
|
||||
namespace aql_profile {
|
||||
bool Pm4Factory::concurrent_create_mode_ = false;
|
||||
bool Pm4Factory::spm_kfd_mode_ = false;
|
||||
Pm4Factory::mutex_t Pm4Factory::mutex_;
|
||||
Pm4Factory::instances_t* Pm4Factory::instances_ = nullptr;
|
||||
}
|
||||
|
||||
// Mock classes to simulate Pm4Factory and related functionality
|
||||
class MockPm4Factory : public Pm4Factory {
|
||||
public:
|
||||
MockPm4Factory() : Pm4Factory(BlockInfoMap(nullptr, 0)) {}
|
||||
MOCK_METHOD(const GpuBlockInfo*, GetBlockInfo, (const hsa_ven_amd_aqlprofile_event_t*), (const));
|
||||
MOCK_METHOD(bool, IsGFX9, (), (const));
|
||||
MOCK_METHOD(bool, IsConcurrent, (), (const));
|
||||
MOCK_METHOD(int, GetNumWGPs, (), (const));
|
||||
MOCK_METHOD(bool, SpmKfdMode, (), (const));
|
||||
MOCK_METHOD(bool, SPISkip, (uint32_t, uint32_t), (const));
|
||||
};
|
||||
|
||||
|
||||
// Helper to create a mock GpuBlockInfo
|
||||
GpuBlockInfo* CreateBlockInfo(uint32_t id, uint32_t counter_count, uint32_t attr = 0) {
|
||||
auto* info = new GpuBlockInfo();
|
||||
info->id = id;
|
||||
info->counter_count = counter_count;
|
||||
info->attr = attr;
|
||||
info->instance_count = 1;
|
||||
return info;
|
||||
}
|
||||
|
||||
// Helper to create a profile with specified events
|
||||
hsa_ven_amd_aqlprofile_profile_t* CreateProfile(const std::vector<hsa_ven_amd_aqlprofile_event_t>& events) {
|
||||
auto* profile = new hsa_ven_amd_aqlprofile_profile_t();
|
||||
profile->event_count = events.size();
|
||||
if (!events.empty()) {
|
||||
memcpy(reinterpret_cast<void*>(&profile->events), &events, sizeof(hsa_ven_amd_aqlprofile_event_t));
|
||||
} else {
|
||||
profile->events = nullptr;
|
||||
}
|
||||
return profile;
|
||||
}
|
||||
|
||||
void DeleteProfile(hsa_ven_amd_aqlprofile_profile_t* profile) {
|
||||
if (profile) {
|
||||
delete[] profile->events;
|
||||
delete profile;
|
||||
}
|
||||
}
|
||||
|
||||
hsa_status_t DefaultTracedataCallback(hsa_ven_amd_aqlprofile_info_type_t info_type,
|
||||
hsa_ven_amd_aqlprofile_info_data_t* info_data,
|
||||
void* callback_data) {
|
||||
hsa_status_t status = HSA_STATUS_SUCCESS;
|
||||
hsa_ven_amd_aqlprofile_info_data_t* passed_data =
|
||||
reinterpret_cast<hsa_ven_amd_aqlprofile_info_data_t*>(callback_data);
|
||||
|
||||
if (info_type == HSA_VEN_AMD_AQLPROFILE_INFO_TRACE_DATA) {
|
||||
if (info_data->sample_id == passed_data->sample_id) {
|
||||
passed_data->trace_data = info_data->trace_data;
|
||||
status = HSA_STATUS_INFO_BREAK;
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
// Test fixture for CountersVec tests
|
||||
class CountersVecTest : public Test {
|
||||
protected:
|
||||
void SetUp() override {
|
||||
pm4_factory = new NiceMock<MockPm4Factory>();
|
||||
ON_CALL(*pm4_factory, IsGFX9()).WillByDefault(Return(true));
|
||||
}
|
||||
void TearDown() override {
|
||||
delete pm4_factory;
|
||||
}
|
||||
NiceMock<MockPm4Factory>* pm4_factory;
|
||||
|
||||
pm4_builder::counters_vector CountersVec(const profile_t* profile, const Pm4Factory* pm4_factory);
|
||||
};
|
||||
|
||||
pm4_builder::counters_vector CountersVecTest::CountersVec(const profile_t* profile,
|
||||
const Pm4Factory* pm4_factory) {
|
||||
pm4_builder::counters_vector vec;
|
||||
std::map<block_des_t, uint32_t, lt_block_des> index_map;
|
||||
for (const hsa_ven_amd_aqlprofile_event_t* p = profile->events;
|
||||
p < profile->events + profile->event_count; ++p) {
|
||||
const GpuBlockInfo* block_info = pm4_factory->GetBlockInfo(p);
|
||||
const block_des_t block_des = {pm4_factory->GetBlockInfo(p)->id, p->block_index};
|
||||
|
||||
// Counting counter register index per block
|
||||
const auto ret = index_map.insert({block_des, 0});
|
||||
uint32_t& reg_index = ret.first->second;
|
||||
|
||||
if (pm4_builder::SPISkip(block_info->attr, p->counter_id))
|
||||
{
|
||||
vec.push_back({p->counter_id, reg_index, block_des, block_info});
|
||||
continue;
|
||||
}
|
||||
|
||||
if (reg_index >= block_info->counter_count) {
|
||||
throw event_exception("Event is out of block counter registers number limit, ", *p);
|
||||
}
|
||||
|
||||
vec.push_back({p->counter_id, reg_index, block_des, block_info});
|
||||
|
||||
++reg_index;
|
||||
}
|
||||
return vec;
|
||||
}
|
||||
|
||||
//Test case: Empty profile (no events)
|
||||
TEST_F(CountersVecTest, EmptyProfile) {
|
||||
auto profile = CreateProfile({});
|
||||
auto counters = CountersVec(profile, pm4_factory);
|
||||
EXPECT_TRUE(counters.empty());
|
||||
DeleteProfile(profile);
|
||||
}
|
||||
|
||||
// Test case: Profile with regular events
|
||||
TEST_F(CountersVecTest, RegularEvents) {
|
||||
GpuBlockInfo* block_info1 = CreateBlockInfo(1, 4);
|
||||
GpuBlockInfo* block_info2 = CreateBlockInfo(2, 2);
|
||||
|
||||
std::vector<hsa_ven_amd_aqlprofile_event_t> events = {
|
||||
{HSA_VEN_AMD_AQLPROFILE_BLOCK_NAME_SQ, 0, 4}
|
||||
};
|
||||
|
||||
auto profile = CreateProfile(events);
|
||||
EXPECT_NE(profile,nullptr);
|
||||
EXPECT_EQ(profile->events->block_index, 0);
|
||||
EXPECT_EQ(profile->events->counter_id, 4);
|
||||
|
||||
pm4_factory->GetBlockInfo(profile->events);
|
||||
bool is_gfx9 = pm4_factory->IsGFX9();
|
||||
EXPECT_TRUE(is_gfx9);
|
||||
|
||||
}
|
||||
|
||||
// Test fixture for the DefaultTracedataCallback function
|
||||
class DefaultTracedataCallbackTest : public Test {
|
||||
protected:
|
||||
hsa_ven_amd_aqlprofile_info_data_t CreateInfoData(uint32_t sample_id) {
|
||||
hsa_ven_amd_aqlprofile_info_data_t data{};
|
||||
data.sample_id = sample_id;
|
||||
data.trace_data.ptr = reinterpret_cast<void*>(0x1000 + sample_id);
|
||||
data.trace_data.size = 0x100 + sample_id;
|
||||
return data;
|
||||
}
|
||||
};
|
||||
|
||||
//Test case: DefaultTracedataCallback with matching sample IDs
|
||||
TEST_F(DefaultTracedataCallbackTest, MatchingSampleId) {
|
||||
auto info_data = CreateInfoData(42);
|
||||
hsa_ven_amd_aqlprofile_info_data_t callback_data{};
|
||||
callback_data.sample_id = 42;
|
||||
callback_data.trace_data.ptr = nullptr;
|
||||
callback_data.trace_data.size = 0;
|
||||
|
||||
hsa_status_t status = DefaultTracedataCallback(
|
||||
HSA_VEN_AMD_AQLPROFILE_INFO_TRACE_DATA,
|
||||
&info_data,
|
||||
&callback_data);
|
||||
|
||||
EXPECT_EQ(status, HSA_STATUS_INFO_BREAK);
|
||||
EXPECT_EQ(callback_data.trace_data.ptr, info_data.trace_data.ptr);
|
||||
EXPECT_EQ(callback_data.trace_data.size, info_data.trace_data.size);
|
||||
}
|
||||
|
||||
// Test case: DefaultTracedataCallback with non-matching sample IDs
|
||||
TEST_F(DefaultTracedataCallbackTest, NonMatchingSampleId) {
|
||||
auto info_data = CreateInfoData(42);
|
||||
hsa_ven_amd_aqlprofile_info_data_t callback_data{};
|
||||
callback_data.sample_id = 24;
|
||||
void* original_ptr = nullptr;
|
||||
size_t original_size = 0;
|
||||
callback_data.trace_data.ptr = original_ptr;
|
||||
callback_data.trace_data.size = original_size;
|
||||
|
||||
hsa_status_t status = DefaultTracedataCallback(
|
||||
HSA_VEN_AMD_AQLPROFILE_INFO_TRACE_DATA,
|
||||
&info_data,
|
||||
&callback_data);
|
||||
|
||||
EXPECT_EQ(status, HSA_STATUS_SUCCESS);
|
||||
EXPECT_EQ(callback_data.trace_data.ptr, original_ptr);
|
||||
EXPECT_EQ(callback_data.trace_data.size, original_size);
|
||||
}
|
||||
|
||||
// Test case: DefaultTracedataCallback with non-trace info type
|
||||
TEST_F(DefaultTracedataCallbackTest, NonTraceInfoType) {
|
||||
auto info_data = CreateInfoData(42);
|
||||
hsa_ven_amd_aqlprofile_info_data_t callback_data{};
|
||||
callback_data.sample_id = 42;
|
||||
void* original_ptr = nullptr;
|
||||
size_t original_size = 0;
|
||||
callback_data.trace_data.ptr = original_ptr;
|
||||
callback_data.trace_data.size = original_size;
|
||||
|
||||
hsa_status_t status = DefaultTracedataCallback(
|
||||
HSA_VEN_AMD_AQLPROFILE_INFO_PMC_DATA,
|
||||
&info_data,
|
||||
&callback_data);
|
||||
|
||||
EXPECT_EQ(status, HSA_STATUS_SUCCESS);
|
||||
EXPECT_EQ(callback_data.trace_data.ptr, original_ptr);
|
||||
EXPECT_EQ(callback_data.trace_data.size, original_size);
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) 2023-2025 Advanced Micro Devices, Inc. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include "core/commandbuffermgr.hpp"
|
||||
#include <climits>
|
||||
|
||||
|
||||
using namespace aql_profile;
|
||||
|
||||
namespace {
|
||||
|
||||
struct DummyBuffer {
|
||||
std::array<char, 4096> data;
|
||||
};
|
||||
|
||||
TEST(CommandBufferMgrTest, BasicPrefixAndSize) {
|
||||
DummyBuffer buf;
|
||||
CommandBufferMgr mgr(buf.data.data(), sizeof(buf.data));
|
||||
// Should not throw and should have a nonzero size
|
||||
EXPECT_GT(mgr.GetSize(), 0u);
|
||||
}
|
||||
|
||||
TEST(CommandBufferMgrTest, FinalizeThrowsOnSmallData) {
|
||||
DummyBuffer buf;
|
||||
CommandBufferMgr mgr(buf.data.data(), sizeof(buf.data));
|
||||
mgr.SetPreSize(128);
|
||||
// Finalize with data_size <= precmds_size should throw
|
||||
EXPECT_THROW(mgr.Finalize(64), aql_profile_exc_msg);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
@@ -0,0 +1,118 @@
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) 2023-2025 Advanced Micro Devices, Inc. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <gmock/gmock.h>
|
||||
#include <hsa/hsa.h>
|
||||
#include "core/include/aql_profile_v2.h"
|
||||
|
||||
// Mocks and helpers
|
||||
namespace {
|
||||
|
||||
struct MockMemory {
|
||||
std::vector<uint8_t> data;
|
||||
void* alloc(size_t size) {
|
||||
data.resize(size);
|
||||
return data.data();
|
||||
}
|
||||
void dealloc(void* /*ptr*/) {
|
||||
// No-op for vector-backed memory
|
||||
}
|
||||
void copy(void* dst, const void* src, size_t size) {
|
||||
memcpy(dst, src, size);
|
||||
}
|
||||
};
|
||||
|
||||
// Corrected mock_alloc matching aqlprofile_memory_alloc_callback_t
|
||||
hsa_status_t mock_alloc(void** ptr, uint64_t size, aqlprofile_buffer_desc_flags_t /*flags*/, void* userdata) {
|
||||
auto* mem = static_cast<MockMemory*>(userdata);
|
||||
*ptr = mem->alloc(size);
|
||||
return HSA_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Corrected mock_dealloc matching aqlprofile_memory_dealloc_callback_t
|
||||
void mock_dealloc(void* /*ptr*/, void* /*userdata*/) {
|
||||
// No-op
|
||||
}
|
||||
|
||||
// Corrected mock_memcpy matching aqlprofile_memory_copy_t
|
||||
hsa_status_t mock_memcpy(void* dst, const void* src, size_t size, void* /*userdata*/) {
|
||||
memcpy(dst, src, size);
|
||||
return HSA_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
// Test: CreatePacketsSuccess
|
||||
TEST(CountersTest, CreatePacketsSuccess) {
|
||||
MockMemory mem;
|
||||
aqlprofile_pmc_profile_t profile = {};
|
||||
// Fill profile with minimal valid data
|
||||
profile.agent.handle = 0; // Use a valid agent handle in real test
|
||||
profile.events = nullptr;
|
||||
profile.event_count = 0;
|
||||
|
||||
aqlprofile_handle_t handle = {};
|
||||
aqlprofile_pmc_aql_packets_t packets = {};
|
||||
|
||||
hsa_status_t status = aqlprofile_pmc_create_packets(
|
||||
&handle, &packets, profile, mock_alloc, mock_dealloc, mock_memcpy, &mem);
|
||||
|
||||
// Accept HSA_STATUS_ERROR if agent/event is not valid in this test context
|
||||
EXPECT_TRUE(status == HSA_STATUS_SUCCESS || status == HSA_STATUS_ERROR);
|
||||
}
|
||||
|
||||
// Test: DeletePackets
|
||||
TEST(CountersTest, DeletePackets) {
|
||||
MockMemory mem;
|
||||
aqlprofile_pmc_profile_t profile = {};
|
||||
profile.agent.handle = 0;
|
||||
profile.events = nullptr;
|
||||
profile.event_count = 0;
|
||||
|
||||
aqlprofile_handle_t handle = {};
|
||||
aqlprofile_pmc_aql_packets_t packets = {};
|
||||
|
||||
hsa_status_t status = aqlprofile_pmc_create_packets(
|
||||
&handle, &packets, profile, mock_alloc, mock_dealloc, mock_memcpy, &mem);
|
||||
|
||||
// Only proceed if creation succeeded
|
||||
if (status == HSA_STATUS_SUCCESS) {
|
||||
// This should not crash or throw
|
||||
aqlprofile_pmc_delete_packets(handle);
|
||||
}
|
||||
}
|
||||
|
||||
// Test: ValidateEvent
|
||||
TEST(CountersTest, ValidateEvent) {
|
||||
aqlprofile_agent_handle_t agent = {};
|
||||
agent.handle = 0;
|
||||
|
||||
aqlprofile_pmc_event_t event = {};
|
||||
event.block_name = HSA_VEN_AMD_AQLPROFILE_BLOCK_NAME_GRBM;
|
||||
|
||||
bool result = true;
|
||||
hsa_status_t status = aqlprofile_validate_pmc_event(agent, &event, &result);
|
||||
|
||||
// In a mock environment, we can't guarantee validation, but we can check that it runs
|
||||
EXPECT_TRUE(status == HSA_STATUS_SUCCESS || status == HSA_STATUS_ERROR);
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) 2023-2025 Advanced Micro Devices, Inc. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#include "core/memorymanager.hpp"
|
||||
#include "gtest/gtest.h"
|
||||
#include <cstring>
|
||||
|
||||
// Dummy alloc/dealloc functions for testing
|
||||
hsa_status_t dummy_alloc(void** ptr, size_t size, aqlprofile_buffer_desc_flags_t, void*) {
|
||||
*ptr = malloc(size);
|
||||
return *ptr ? HSA_STATUS_SUCCESS : HSA_STATUS_ERROR;
|
||||
}
|
||||
void dummy_dealloc(void* ptr, void*) {
|
||||
free(ptr);
|
||||
}
|
||||
hsa_status_t dummy_alloc_fail(void**, size_t, aqlprofile_buffer_desc_flags_t, void*) {
|
||||
return HSA_STATUS_ERROR;
|
||||
}
|
||||
hsa_status_t dummy_copy(void* dst, const void* src, size_t size, void*) {
|
||||
memcpy(dst, src, size);
|
||||
return HSA_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Helper subclass to expose protected AllocMemory for testing
|
||||
class TestCounterMemoryManager : public CounterMemoryManager {
|
||||
public:
|
||||
using CounterMemoryManager::CounterMemoryManager;
|
||||
using CounterMemoryManager::AllocMemory;
|
||||
};
|
||||
|
||||
TEST(CounterMemoryManagerTest, AllocMemory_Success) {
|
||||
hsa_agent_t agent = {.handle = 1};
|
||||
TestCounterMemoryManager mgr(agent, dummy_alloc, dummy_dealloc, nullptr);
|
||||
aqlprofile_buffer_desc_flags_t flags{};
|
||||
auto mem = mgr.AllocMemory(64, flags);
|
||||
ASSERT_NE(mem.get(), nullptr);
|
||||
}
|
||||
|
||||
TEST(CounterMemoryManagerTest, AllocMemory_FailureThrows) {
|
||||
hsa_agent_t agent = {.handle = 1};
|
||||
TestCounterMemoryManager mgr(agent, dummy_alloc_fail, dummy_dealloc, nullptr);
|
||||
aqlprofile_buffer_desc_flags_t flags{};
|
||||
EXPECT_THROW(mgr.AllocMemory(64, flags), hsa_status_t);
|
||||
}
|
||||
|
||||
TEST(CounterMemoryManagerTest, CmdBufAndOutputBuf) {
|
||||
hsa_agent_t agent = {.handle = 1};
|
||||
CounterMemoryManager mgr(agent, dummy_alloc, dummy_dealloc, nullptr);
|
||||
mgr.CreateCmdBuf(128);
|
||||
ASSERT_NE(mgr.GetCmdBuf(), nullptr);
|
||||
mgr.CreateOutputBuf(256);
|
||||
ASSERT_NE(mgr.GetOutputBuf(), nullptr);
|
||||
ASSERT_EQ(mgr.GetOutputBufSize(), 256u);
|
||||
}
|
||||
|
||||
TEST(CounterMemoryManagerTest, RegisterAndGetManager) {
|
||||
hsa_agent_t agent = {.handle = 1};
|
||||
auto mgr = std::make_shared<CounterMemoryManager>(agent, dummy_alloc, dummy_dealloc, nullptr);
|
||||
size_t handle = mgr->GetHandler();
|
||||
CounterMemoryManager::RegisterManager(mgr);
|
||||
auto found = CounterMemoryManager::GetManager(handle);
|
||||
ASSERT_EQ(found.get(), mgr.get());
|
||||
CounterMemoryManager::DeleteManager(handle);
|
||||
ASSERT_EQ(CounterMemoryManager::GetManager(handle), nullptr);
|
||||
}
|
||||
|
||||
TEST(CounterMemoryManagerTest, CopyEvents) {
|
||||
hsa_agent_t agent = {.handle = 1};
|
||||
CounterMemoryManager mgr(agent, dummy_alloc, dummy_dealloc, nullptr);
|
||||
|
||||
aqlprofile_pmc_event_t events[2]{};
|
||||
events[0].event_id = 1;
|
||||
events[0].flags.raw = 0;
|
||||
events[1].event_id = 2;
|
||||
events[1].flags.raw = 1;
|
||||
|
||||
mgr.CopyEvents(events, 2);
|
||||
auto& ev = mgr.GetEvents();
|
||||
ASSERT_GE(ev.size(), 2u);
|
||||
}
|
||||
|
||||
TEST(TraceMemoryManagerTest, TraceControlBufAndATTParams) {
|
||||
hsa_agent_t agent = {.handle = 1};
|
||||
TraceMemoryManager mgr(agent, dummy_alloc, dummy_dealloc, dummy_copy, nullptr);
|
||||
mgr.CreateTraceControlBuf(64);
|
||||
auto buf = mgr.GetTraceControlBuf<uint8_t>();
|
||||
ASSERT_NE(buf, nullptr);
|
||||
|
||||
hsa_ven_amd_aqlprofile_parameter_t params[2]{};
|
||||
params[0].parameter_name = HSA_VEN_AMD_AQLPROFILE_PARAMETER_NAME_COMPUTE_UNIT_TARGET;
|
||||
params[0].value = 42;
|
||||
params[1].parameter_name = HSA_VEN_AMD_AQLPROFILE_PARAMETER_NAME_SIMD_SELECTION;
|
||||
params[1].value = 0xF;
|
||||
|
||||
mgr.CopyATTParams(params, 2);
|
||||
ASSERT_EQ(mgr.GetSimdMask(), 0xF);
|
||||
const auto& att_params = mgr.GetATTParams();
|
||||
ASSERT_EQ(att_params.size(), 2u);
|
||||
}
|
||||
|
||||
TEST(CodeobjMemoryManagerTest, CmdBufferAlloc) {
|
||||
hsa_agent_t agent = {.handle = 1};
|
||||
CodeobjMemoryManager mgr(agent, dummy_alloc, dummy_dealloc, 128, nullptr);
|
||||
ASSERT_NE(mgr.cmd_buffer.get(), nullptr);
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
include(GoogleTest)
|
||||
find_package(GTest REQUIRED)
|
||||
include_directories(${GTEST_INCLUDE_DIRS})
|
||||
|
||||
|
||||
# Add a test for gfx9 command builder
|
||||
add_executable(gfx9-command-builder-test)
|
||||
SET(AQLPROFILE_COMMAND_BUILDER_SOURCES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/cmd_builder_tests.cpp
|
||||
)
|
||||
target_sources(gfx9-command-builder-test PRIVATE ${AQLPROFILE_COMMAND_BUILDER_SOURCES})
|
||||
target_include_directories(gfx9-command-builder-test PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${LIB_DIR})
|
||||
target_link_libraries(
|
||||
gfx9-command-builder-test
|
||||
PRIVATE
|
||||
hsa-runtime64::hsa-runtime64
|
||||
GTest::gtest
|
||||
GTest::gtest_main
|
||||
GTest::gmock
|
||||
GTest::gmock_main)
|
||||
gtest_add_tests(
|
||||
TARGET gfx9-command-builder-test
|
||||
SOURCES ${AQLPROFILE_COMMAND_BUILDER_SOURCES}
|
||||
TEST_LIST gfx9-command-builder-test_TESTS
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
|
||||
set_tests_properties(
|
||||
${gfx9-command-builder-test_TESTS} PROPERTIES TIMEOUT 45 LABELS "unittests" FAIL_REGULAR_EXPRESSION
|
||||
"${AQLPROFILE_DEFAULT_FAIL_REGEX}")
|
||||
@@ -0,0 +1,71 @@
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) 2023-2025 Advanced Micro Devices, Inc. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include "pm4/cmd_builder.h"
|
||||
|
||||
using pm4_builder::CmdBuffer;
|
||||
|
||||
struct DummyPacket {
|
||||
uint32_t a;
|
||||
uint32_t b;
|
||||
};
|
||||
|
||||
TEST(CmdBufferTest, AppendSinglePacket) {
|
||||
CmdBuffer buf;
|
||||
DummyPacket pkt{0x12345678, 0x9abcdef0};
|
||||
buf.Append(pkt);
|
||||
|
||||
// Should have 2 dwords
|
||||
EXPECT_EQ(buf.DwSize(), 2u);
|
||||
|
||||
// Data should match what we appended
|
||||
const uint32_t* data = static_cast<const uint32_t*>(buf.Data());
|
||||
EXPECT_EQ(data[0], 0x12345678u);
|
||||
EXPECT_EQ(data[1], 0x9abcdef0u);
|
||||
}
|
||||
|
||||
TEST(CmdBufferTest, AppendMultiplePackets) {
|
||||
CmdBuffer buf;
|
||||
DummyPacket pkt1{1, 2};
|
||||
DummyPacket pkt2{3, 4};
|
||||
buf.Append(pkt1, pkt2);
|
||||
|
||||
EXPECT_EQ(buf.DwSize(), 4u);
|
||||
const uint32_t* data = static_cast<const uint32_t*>(buf.Data());
|
||||
EXPECT_EQ(data[0], 1u);
|
||||
EXPECT_EQ(data[1], 2u);
|
||||
EXPECT_EQ(data[2], 3u);
|
||||
EXPECT_EQ(data[3], 4u);
|
||||
}
|
||||
|
||||
TEST(CmdBufferTest, AppendRawData) {
|
||||
CmdBuffer buf;
|
||||
uint32_t raw[3] = {10, 20, 30};
|
||||
buf.Append(raw, 3);
|
||||
|
||||
EXPECT_EQ(buf.DwSize(), 4u);
|
||||
const uint32_t* data = static_cast<const uint32_t*>(buf.Data());
|
||||
EXPECT_EQ(data[0], 10u);
|
||||
EXPECT_EQ(data[1], 20u);
|
||||
EXPECT_EQ(data[2], 30u);
|
||||
}
|
||||
Ссылка в новой задаче
Block a user