Files
TheRock/rocm-libraries/projects/rocsparse/clients/tests/test.hpp
T
derek.holloway 7502bf64a4
CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
Flatten subprojects into a single base monorepo
2026-09-02 16:34:47 -07:00

409 lines
26 KiB
C++

/*! \file */
/* ************************************************************************
* Copyright (C) 2022-2026 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.
*
* ************************************************************************ */
#pragma once
#include "rocsparse_data.hpp"
#include "rocsparse_reproducibility.hpp"
#include "rocsparse_reproducibility_test_label.hpp"
#include "rocsparse_test.hpp"
#include "rocsparse_test_template_traits.hpp"
#include "test_check.hpp"
void rocsparse_seedrand();
template <rocsparse_test_enum::value_type ROUTINE, typename F>
inline void testing_reproducibility(const Arguments& arg, F test_execute)
{
using status_t = rocsparse_reproducibility_t::status_t;
rocsparse_reproducibility_t::results_test_t results_test;
results_test.set_name(
std::string(arg.category) + std::string("/") + std::string(arg.function) + std::string(".")
+ std::string(::testing::UnitTest::GetInstance()->current_test_info()->name()));
std::string err_description = "<none>";
if(false == rocsparse_reproducibility_t::instance().is_enabled() || arg.skip_reproducibility)
{
return;
}
auto& test = rocsparse_reproducibility_t::instance().test();
test.reset();
//
// Reset random.
//
rocsparse_seedrand();
auto status = status_t::reproducible;
//
// Run the first time.
//
try
{
test_execute(arg);
if(::testing::Test::HasFailure())
{
status = status_t::test_failed;
}
}
catch(...)
{
status = status_t::execution_failed;
}
if(status == status_t::reproducible)
{
auto* test_data_initial = test.get_initial_data();
if(test_data_initial == nullptr)
{
// no reproducibility data
status = status_t::non_tested;
}
else
{
// tell the test we will loop now.
test.set_next();
//
results_test.set_hash(test_data_initial->compute_hash());
const uint32_t rn = rocsparse_reproducibility_t::instance().get_num_iterations();
auto next_status = status_t::reproducible;
for(uint32_t ri = 1; ri < rn; ++ri)
{
//
// Reinitialize random numbers.
//
rocsparse_seedrand();
//
// Reset the next one.
//
test.reset_next();
try
{
test_execute(arg);
if(::testing::Test::HasFailure())
{
next_status = status_t::test_failed;
break;
}
else
{
auto* current_data = test.get_current_data();
std::stringstream descr_binary_data_error;
const bool are_same
= test_data_initial->is_same(current_data, descr_binary_data_error);
const uint64_t hash_current_data = current_data->compute_hash();
if(are_same == false)
{
next_status = status_t::non_reproducible;
results_test.set_description(descr_binary_data_error.str());
#if NDEBUG
if(hash_current_data == test_data_initial->compute_hash())
{
std::cout << "rocSPARSE.REPRODUCIBILITY collision hashing"
<< std::endl;
}
#endif
break;
}
else
{
if(hash_current_data != test_data_initial->compute_hash())
{
std::cerr << "rocSPARSE.REPRODUCIBILITY ERROR: Inconsistent "
"reproducibility hashing, data are binary identical "
"but hash values are different, "
<< hash_current_data << " vs "
<< test_data_initial->compute_hash()
<< ". rocSPARSE.REPRODUCIBILITY Abort." << std::endl;
throw(rocsparse_status_internal_error);
}
}
}
}
catch(...)
{
next_status = status_t::execution_failed;
}
}
if(next_status != status_t::reproducible)
{
status = next_status;
}
}
}
//
// Set the status.
//
results_test.set_status(status);
rocsparse_test_functors<ROUTINE>::set_reproducibility_test(arg, results_test);
test.reset();
}
//
// INTERNAL MACRO TO SPECIALIZE TEST CALL NEEDED TO INSTANTIATE
//
#ifdef ROCSPARSE_DEBUGGING
#define SPECIALIZE_ROCSPARSE_TEST_CALL(ROUTINE) \
template <> \
struct rocsparse_test_call<rocsparse_test_enum::ROUTINE> \
{ \
template <typename... P> \
static void testing_bad_arg(const Arguments& arg) \
{ \
const bool was_enabled = rocsparse_clients_test::hip_debug_t::instance().enabled(); \
if(was_enabled) \
{ \
rocsparse_clients_test::hip_debug_t::instance().disable(); \
} \
test_check::reset_auto_testing_bad_arg(); \
testing_##ROUTINE##_bad_arg<P...>(arg); \
if(false && false == test_check::did_auto_testing_bad_arg()) \
{ \
std::cerr << "rocsparse_test warning testing bad arguments of " \
<< rocsparse_test_enum::to_string(rocsparse_test_enum::ROUTINE) \
<< " must use auto_testing_bad_arg, or bad_arg_analysis." << std::endl; \
CHECK_ROCSPARSE_ERROR(rocsparse_status_internal_error); \
} \
if(was_enabled) \
{ \
rocsparse_clients_test::hip_debug_t::instance().enable(); \
} \
} \
\
static void testing_extra(const Arguments& arg) \
{ \
try \
{ \
testing_##ROUTINE##_extra(arg); \
} \
catch(rocsparse_status & status) \
{ \
CHECK_ROCSPARSE_ERROR(status); \
} \
catch(hipError_t & error) \
{ \
CHECK_HIP_ERROR(error); \
} \
catch(std::exception & error) \
{ \
CHECK_ROCSPARSE_ERROR(rocsparse_status_thrown_exception); \
} \
} \
\
template <typename... P> \
static void testing(const Arguments& arg) \
{ \
if(rocsparse_reproducibility_t::instance().is_enabled() \
&& arg.skip_reproducibility == false) \
{ \
testing_reproducibility<rocsparse_test_enum::ROUTINE>(arg, \
testing_##ROUTINE<P...>); \
} \
else \
{ \
try \
{ \
testing_##ROUTINE<P...>(arg); \
} \
catch(rocsparse_status & status) \
{ \
CHECK_ROCSPARSE_ERROR(status); \
} \
catch(hipError_t & error) \
{ \
CHECK_HIP_ERROR(error); \
} \
catch(std::exception & error) \
{ \
CHECK_ROCSPARSE_ERROR(rocsparse_status_thrown_exception); \
} \
} \
} \
};
#else
#define SPECIALIZE_ROCSPARSE_TEST_CALL(ROUTINE) \
template <> \
struct rocsparse_test_call<rocsparse_test_enum::ROUTINE> \
{ \
template <typename... P> \
static void testing_bad_arg(const Arguments& arg) \
{ \
test_check::reset_auto_testing_bad_arg(); \
testing_##ROUTINE##_bad_arg<P...>(arg); \
if(false && false == test_check::did_auto_testing_bad_arg()) \
{ \
std::cerr << "rocsparse_test warning testing bad arguments of " \
<< rocsparse_test_enum::to_string(rocsparse_test_enum::ROUTINE) \
<< " must use auto_testing_bad_arg, or bad_arg_analysis." << std::endl; \
CHECK_ROCSPARSE_ERROR(rocsparse_status_internal_error); \
} \
} \
\
static void testing_extra(const Arguments& arg) \
{ \
try \
{ \
testing_##ROUTINE##_extra(arg); \
} \
catch(rocsparse_status & status) \
{ \
CHECK_ROCSPARSE_ERROR(status); \
} \
catch(hipError_t & error) \
{ \
CHECK_HIP_ERROR(error); \
} \
catch(std::exception & error) \
{ \
CHECK_ROCSPARSE_ERROR(rocsparse_status_thrown_exception); \
} \
} \
\
template <typename... P> \
static void testing(const Arguments& arg) \
{ \
if(rocsparse_reproducibility_t::instance().is_enabled() \
&& arg.skip_reproducibility == false) \
{ \
testing_reproducibility<rocsparse_test_enum::ROUTINE>(arg, \
testing_##ROUTINE<P...>); \
} \
else \
{ \
try \
{ \
testing_##ROUTINE<P...>(arg); \
} \
catch(rocsparse_status & status) \
{ \
CHECK_ROCSPARSE_ERROR(status); \
} \
catch(hipError_t & error) \
{ \
CHECK_HIP_ERROR(error); \
} \
catch(std::exception & error) \
{ \
CHECK_ROCSPARSE_ERROR(rocsparse_status_thrown_exception); \
} \
} \
} \
};
#endif
/////////////////////////////////////////////////////////////////////////////////////////////////////
//
// INTERNAL MACRO TO SPECIALIZE TEST FUNCTOR NEEDED TO INSTANTIATE
//
#define SPECIALIZE_ROCSPARSE_TEST_FUNCTORS(ROUTINE, ...) \
template <> \
struct rocsparse_test_functors<rocsparse_test_enum::ROUTINE> \
{ \
static void set_reproducibility_test( \
const Arguments& arg, const rocsparse_reproducibility_t::results_test_t& results_test) \
{ \
rocsparse_reproducibility_t::results_test_input_t results_test_input; \
rocsparse_reproducibility_utils::record(results_test_input, __VA_ARGS__); \
rocsparse_reproducibility_t::instance().results().add( \
arg.function, results_test_input, results_test); \
} \
static std::string name_suffix(const Arguments& arg) \
{ \
std::ostringstream s; \
rocsparse_test_name_suffix_generator(s, __VA_ARGS__); \
return s.str(); \
} \
}
/////////////////////////////////////////////////////////////////////////////////////////////////////
//
// INTERNAL MACRO TO SPECIALIZE TEST TRAITS NEEDED TO INSTANTIATE
//
#define SPECIALIZE_ROCSPARSE_TEST_TRAITS(ROUTINE, CONFIG) \
/**/ template <> /**/ struct rocsparse_test_traits<rocsparse_test_enum::ROUTINE> : CONFIG \
/**/ { \
/**/ }
/////////////////////////////////////////////////////////////////////////////////////////////////////
//
// INSTANTIATE TESTS
//
template <rocsparse_test_enum::value_type ROUTINE>
using test_template_traits_t
= rocsparse_test_template_traits<ROUTINE, rocsparse_test_traits<ROUTINE>::s_dispatch>;
template <rocsparse_test_enum::value_type ROUTINE>
using test_dispatch_t = rocsparse_test_dispatch<rocsparse_test_traits<ROUTINE>::s_dispatch>;
#define INSTANTIATE_ROCSPARSE_TEST(ROUTINE, CATEGORY) \
/**/ using ROUTINE = test_template_traits_t<rocsparse_test_enum::ROUTINE>::filter; \
/**/ \
/**/ template <typename... P> \
/**/ using ROUTINE##_call \
= test_template_traits_t<rocsparse_test_enum::ROUTINE>::caller<P...>; \
/**/ \
/**/ TEST_P(ROUTINE, CATEGORY) \
/**/ { \
/**/ test_dispatch_t<rocsparse_test_enum::ROUTINE>::template dispatch<ROUTINE##_call>( \
GetParam()); \
/**/ } \
/**/ \
/**/ INSTANTIATE_TEST_CATEGORIES(ROUTINE)
/////////////////////////////////////////////////////////////////////////////////////////////////////
//
// DEFINE ALL REQUIRED INFORMATION FOR A TEST ROUTINE BUT WITH A PREDEFINED CONFIGURATION
// (i.e. [T (default) | <I,T> | <I,J,T>] + a selection of numeric types (all (default), real_only, complex_only, some other specific situations (?) ) )
//
#define TEST_ROUTINE_WITH_CONFIG(ROUTINE, CATEGORY, CONFIG, ...) \
/**/ \
/**/ SPECIALIZE_ROCSPARSE_TEST_TRAITS(ROUTINE, CONFIG); \
/**/ SPECIALIZE_ROCSPARSE_TEST_FUNCTORS(ROUTINE, __VA_ARGS__); \
/**/ SPECIALIZE_ROCSPARSE_TEST_CALL(ROUTINE); \
/**/ namespace \
/**/ { \
/**/ INSTANTIATE_ROCSPARSE_TEST(ROUTINE, CATEGORY); \
/**/ }
//
// DEFINE ALL REQUIRED INFORMATION FOR A TEST ROUTINE WITH A DEFAULT CONFIGURATION (i.e T + all numeric types)
//
#define TEST_ROUTINE(ROUTINE, CATEGORY, ...) \
TEST_ROUTINE_WITH_CONFIG(ROUTINE, CATEGORY, rocsparse_test_config, __VA_ARGS__)
/////////////////////////////////////////////////////////////////////////////////////////////////////