Files
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

733 lines
17 KiB
C++

// Copyright © Advanced Micro Devices, Inc., or its affiliates.
// SPDX-License-Identifier: MIT
#include <gtest/gtest.h>
#include <cstdio>
#include <filesystem>
#include <fstream>
#include <string>
#include "harness/TestSettings.hpp"
using hipdnn_integration_tests::TestSettings;
// NOLINTBEGIN(readability-identifier-naming) -- gtest macro-generated names
namespace
{
// Helper to create a temporary TOML file that is auto-deleted on destruction.
class TempTomlFile
{
public:
explicit TempTomlFile(const std::string& content)
: _path(std::filesystem::temp_directory_path()
/ ("test_settings_" + std::to_string(std::rand()) + ".toml"))
{
std::ofstream ofs(_path);
ofs << content;
}
~TempTomlFile()
{
std::filesystem::remove(_path);
}
TempTomlFile(const TempTomlFile&) = delete;
TempTomlFile& operator=(const TempTomlFile&) = delete;
TempTomlFile(TempTomlFile&&) = delete;
TempTomlFile& operator=(TempTomlFile&&) = delete;
const std::filesystem::path& path() const
{
return _path;
}
private:
std::filesystem::path _path;
};
} // namespace
// ---------------------------------------------------------------------------
// Parsing
// ---------------------------------------------------------------------------
TEST(TestSettingsParser, ParsesValidTomlWithOverrides)
{
const TempTomlFile file(R"(
[meta]
version = 1
[[tolerance_overrides]]
filters = ["*ConvFwd*Fp16*"]
atol = 1e-3
rtol = 1e-2
[[tolerance_overrides]]
filters = ["*ConvFwd*Fp32*"]
atol = 1e-5
rtol = 1e-4
)");
const TestSettings settings(file.path());
EXPECT_EQ(settings.toleranceOverrideCount(), 2U);
}
TEST(TestSettingsParser, ParsesValidTomlWithNoOverrides)
{
const TempTomlFile file(R"(
[meta]
version = 1
)");
const TestSettings settings(file.path());
EXPECT_EQ(settings.toleranceOverrideCount(), 0U);
}
TEST(TestSettingsParser, ThrowsOnMissingVersion)
{
const TempTomlFile file(R"(
[meta]
)");
EXPECT_THROW(const TestSettings settings(file.path()), std::runtime_error);
}
TEST(TestSettingsParser, ThrowsOnUnsupportedVersion)
{
const TempTomlFile file(R"(
[meta]
version = 99
)");
EXPECT_THROW(const TestSettings settings(file.path()), std::runtime_error);
}
TEST(TestSettingsParser, ThrowsOnMissingFilters)
{
const TempTomlFile file(R"(
[meta]
version = 1
[[tolerance_overrides]]
atol = 1e-3
rtol = 1e-2
)");
EXPECT_THROW(const TestSettings settings(file.path()), std::runtime_error);
}
TEST(TestSettingsParser, ThrowsOnMissingAtol)
{
const TempTomlFile file(R"(
[meta]
version = 1
[[tolerance_overrides]]
filters = ["*test*"]
rtol = 1e-2
)");
EXPECT_THROW(const TestSettings settings(file.path()), std::runtime_error);
}
TEST(TestSettingsParser, ThrowsOnMissingRtol)
{
const TempTomlFile file(R"(
[meta]
version = 1
[[tolerance_overrides]]
filters = ["*test*"]
atol = 1e-3
)");
EXPECT_THROW(const TestSettings settings(file.path()), std::runtime_error);
}
TEST(TestSettingsParser, ThrowsOnNonexistentFile)
{
EXPECT_THROW(const TestSettings settings("/nonexistent/path.toml"), std::exception);
}
// ---------------------------------------------------------------------------
// Filter matching
// ---------------------------------------------------------------------------
TEST(TestSettingsParser, FindOverrideMatchesWildcard)
{
const TempTomlFile file(R"(
[meta]
version = 1
[[tolerance_overrides]]
filters = ["*ConvFwd*Fp16*"]
atol = 1e-3
rtol = 1e-2
)");
const TestSettings settings(file.path());
auto result = settings.findToleranceOverride(
"IntegrationGpuConvFwd2dFp16/Smoke.Correctness/NCHW_params");
ASSERT_TRUE(result.has_value());
EXPECT_FLOAT_EQ(result->atol, 1e-3F);
EXPECT_FLOAT_EQ(result->rtol, 1e-2F);
}
TEST(TestSettingsParser, FindOverrideReturnsNulloptWhenNoMatch)
{
const TempTomlFile file(R"(
[meta]
version = 1
[[tolerance_overrides]]
filters = ["*ConvFwd*Fp16*"]
atol = 1e-3
rtol = 1e-2
)");
const TestSettings settings(file.path());
auto result
= settings.findToleranceOverride("IntegrationGpuBatchnormFp32/Smoke.Correctness/params");
EXPECT_FALSE(result.has_value());
}
TEST(TestSettingsParser, FindOverrideReturnsNulloptWhenNoOverrides)
{
const TempTomlFile file(R"(
[meta]
version = 1
)");
const TestSettings settings(file.path());
auto result = settings.findToleranceOverride("AnyTestName");
EXPECT_FALSE(result.has_value());
}
TEST(TestSettingsParser, FindOverrideMatchesMultipleFiltersInEntry)
{
const TempTomlFile file(R"(
[meta]
version = 1
[[tolerance_overrides]]
filters = ["*Fp16*", "*Half*"]
atol = 1e-3
rtol = 1e-2
)");
const TestSettings settings(file.path());
// Should match the first filter
auto result1
= settings.findToleranceOverride("IntegrationGpuConvFwd2dFp16/Smoke.Correctness/params");
ASSERT_TRUE(result1.has_value());
// Should match the second filter
auto result2
= settings.findToleranceOverride("IntegrationGpuConvFwdHalf/Smoke.Correctness/params");
ASSERT_TRUE(result2.has_value());
}
// ---------------------------------------------------------------------------
// Precedence: later entries win
// ---------------------------------------------------------------------------
TEST(TestSettingsParser, LaterEntriesTakePrecedence)
{
const TempTomlFile file(R"(
[meta]
version = 1
[[tolerance_overrides]]
filters = ["*ConvFwd*"]
atol = 1e-3
rtol = 1e-2
[[tolerance_overrides]]
filters = ["*ConvFwd*Fp16*"]
atol = 5e-3
rtol = 5e-2
)");
const TestSettings settings(file.path());
// Matches both entries - the later (more specific) one should win
auto result
= settings.findToleranceOverride("IntegrationGpuConvFwd2dFp16/Smoke.Correctness/params");
ASSERT_TRUE(result.has_value());
EXPECT_FLOAT_EQ(result->atol, 5e-3F);
EXPECT_FLOAT_EQ(result->rtol, 5e-2F);
}
TEST(TestSettingsParser, EarlierEntryUsedWhenLaterDoesNotMatch)
{
const TempTomlFile file(R"(
[meta]
version = 1
[[tolerance_overrides]]
filters = ["*ConvFwd*"]
atol = 1e-3
rtol = 1e-2
[[tolerance_overrides]]
filters = ["*ConvFwd*Fp16*"]
atol = 5e-3
rtol = 5e-2
)");
const TestSettings settings(file.path());
// Matches only the first entry (Fp32, not Fp16)
auto result
= settings.findToleranceOverride("IntegrationGpuConvFwd2dFp32/Smoke.Correctness/params");
ASSERT_TRUE(result.has_value());
EXPECT_FLOAT_EQ(result->atol, 1e-3F);
EXPECT_FLOAT_EQ(result->rtol, 1e-2F);
}
// ---------------------------------------------------------------------------
// [[test_skips]] parsing
// ---------------------------------------------------------------------------
TEST(TestSettingsParser, ParsesValidTomlWithSkips)
{
const TempTomlFile file(R"(
[meta]
version = 1
[[test_skips]]
archs = ["gfx1100", "gfx1101"]
filters = ["*Activation*Fp16*"]
reason = "missing activation kernel on RDNA3"
[[test_skips]]
archs = ["gfx942"]
filters = ["*ConvFwd3d*"]
reason = "3d conv unimplemented on MI300"
)");
const TestSettings settings(file.path());
EXPECT_EQ(settings.skipEntryCount(), 2U);
}
TEST(TestSettingsParser, SkipsCoexistWithOverrides)
{
const TempTomlFile file(R"(
[meta]
version = 1
[[tolerance_overrides]]
filters = ["*Fp16*"]
atol = 1e-3
rtol = 1e-2
[[test_skips]]
archs = ["gfx942"]
filters = ["*Conv*"]
reason = "test"
)");
const TestSettings settings(file.path());
EXPECT_EQ(settings.toleranceOverrideCount(), 1U);
EXPECT_EQ(settings.skipEntryCount(), 1U);
}
TEST(TestSettingsParser, ParsesSkipWithoutArchsAsGlobal)
{
// 'archs' omitted => global skip on every arch.
const TempTomlFile file(R"(
[meta]
version = 1
[[test_skips]]
filters = ["*KnownBroken*"]
reason = "tracked in #1234"
)");
const TestSettings settings(file.path());
EXPECT_EQ(settings.skipEntryCount(), 1U);
}
TEST(TestSettingsParser, ParsesSkipWithEmptyArchsAsGlobal)
{
// 'archs = []' is also a global skip.
const TempTomlFile file(R"(
[meta]
version = 1
[[test_skips]]
archs = []
filters = ["*KnownBroken*"]
reason = "tracked in #1234"
)");
const TestSettings settings(file.path());
EXPECT_EQ(settings.skipEntryCount(), 1U);
}
TEST(TestSettingsParser, ThrowsOnMissingSkipFilters)
{
const TempTomlFile file(R"(
[meta]
version = 1
[[test_skips]]
archs = ["gfx942"]
reason = "r"
)");
EXPECT_THROW(const TestSettings settings(file.path()), std::runtime_error);
}
TEST(TestSettingsParser, ThrowsOnMissingSkipReason)
{
const TempTomlFile file(R"(
[meta]
version = 1
[[test_skips]]
archs = ["gfx942"]
filters = ["*test*"]
)");
EXPECT_THROW(const TestSettings settings(file.path()), std::runtime_error);
}
TEST(TestSettingsParser, ThrowsOnEmptySkipReason)
{
const TempTomlFile file(R"(
[meta]
version = 1
[[test_skips]]
archs = ["gfx942"]
filters = ["*test*"]
reason = ""
)");
EXPECT_THROW(const TestSettings settings(file.path()), std::runtime_error);
}
// ---------------------------------------------------------------------------
// [[test_skips]] matching
// ---------------------------------------------------------------------------
TEST(TestSettingsParser, FindSkipMatchesArchSubstring)
{
const TempTomlFile file(R"(
[meta]
version = 1
[[test_skips]]
archs = ["gfx942"]
filters = ["*ConvFwd*"]
reason = "no kernel"
)");
const TestSettings settings(file.path());
// Bare arch in TOML must match against the full ROCm-formatted device string.
auto result
= settings.findSkip("IntegrationGpuConvFwd2dFp16.Test", "gfx942:sramecc+:xnack-", "linux");
ASSERT_TRUE(result.has_value());
EXPECT_EQ(*result, "no kernel");
}
TEST(TestSettingsParser, FindSkipMatchesExactArchString)
{
// A more-qualified arch string in TOML still matches when the device
// string is identical (the substring check is symmetric for equality).
const TempTomlFile file(R"(
[meta]
version = 1
[[test_skips]]
archs = ["gfx942:xnack-"]
filters = ["*Conv*"]
reason = "xnack-only issue"
)");
const TestSettings settings(file.path());
auto matched
= settings.findSkip("IntegrationGpuConvFwd2dFp16.Test", "gfx942:sramecc+:xnack-", "linux");
ASSERT_FALSE(matched.has_value())
<< "literal substring 'gfx942:xnack-' should not appear in 'gfx942:sramecc+:xnack-'";
auto matchedExact
= settings.findSkip("IntegrationGpuConvFwd2dFp16.Test", "gfx942:xnack-", "linux");
ASSERT_TRUE(matchedExact.has_value());
}
TEST(TestSettingsParser, FindSkipReturnsNulloptOnArchMismatch)
{
const TempTomlFile file(R"(
[meta]
version = 1
[[test_skips]]
archs = ["gfx1100"]
filters = ["*ConvFwd*"]
reason = "rdna3 only"
)");
const TestSettings settings(file.path());
auto result
= settings.findSkip("IntegrationGpuConvFwd2dFp16.Test", "gfx942:sramecc+:xnack-", "linux");
EXPECT_FALSE(result.has_value());
}
TEST(TestSettingsParser, FindSkipReturnsNulloptOnFilterMismatch)
{
const TempTomlFile file(R"(
[meta]
version = 1
[[test_skips]]
archs = ["gfx942"]
filters = ["*Batchnorm*"]
reason = "batchnorm only"
)");
const TestSettings settings(file.path());
auto result
= settings.findSkip("IntegrationGpuConvFwd2dFp16.Test", "gfx942:sramecc+:xnack-", "linux");
EXPECT_FALSE(result.has_value());
}
TEST(TestSettingsParser, FindSkipArchScopedReturnsNulloptOnEmptyDeviceArch)
{
// Arch-scoped rule + empty device arch => substring search fails, no skip.
const TempTomlFile file(R"(
[meta]
version = 1
[[test_skips]]
archs = ["gfx942"]
filters = ["*ConvFwd*"]
reason = "r"
)");
const TestSettings settings(file.path());
auto result = settings.findSkip("IntegrationGpuConvFwd2dFp16.Test", "", "linux");
EXPECT_FALSE(result.has_value());
}
TEST(TestSettingsParser, FindSkipGlobalRuleMatchesAnyArch)
{
const TempTomlFile file(R"(
[meta]
version = 1
[[test_skips]]
filters = ["*KnownBroken*"]
reason = "global"
)");
const TestSettings settings(file.path());
// Global rule fires on any arch.
EXPECT_TRUE(
settings.findSkip("KnownBroken.Test", "gfx942:sramecc+:xnack-", "linux").has_value());
EXPECT_TRUE(settings.findSkip("KnownBroken.Test", "gfx1100", "linux").has_value());
EXPECT_TRUE(settings.findSkip("KnownBroken.Test", "anything", "linux").has_value());
// ...even when the device arch could not be detected.
EXPECT_TRUE(settings.findSkip("KnownBroken.Test", "", "linux").has_value());
// But filter still has to match.
EXPECT_FALSE(settings.findSkip("Other.Test", "gfx942", "linux").has_value());
}
TEST(TestSettingsParser, FindSkipReturnsNulloptWhenNoSkipsConfigured)
{
const TempTomlFile file(R"(
[meta]
version = 1
)");
const TestSettings settings(file.path());
auto result = settings.findSkip("AnyTest.Name", "gfx942", "linux");
EXPECT_FALSE(result.has_value());
}
TEST(TestSettingsParser, FindSkipFirstMatchWins)
{
const TempTomlFile file(R"(
[meta]
version = 1
[[test_skips]]
archs = ["gfx942"]
filters = ["*ConvFwd*"]
reason = "first"
[[test_skips]]
archs = ["gfx942"]
filters = ["*ConvFwd*Fp16*"]
reason = "second more specific"
)");
const TestSettings settings(file.path());
auto result = settings.findSkip("IntegrationGpuConvFwd2dFp16.Test", "gfx942", "linux");
ASSERT_TRUE(result.has_value());
EXPECT_EQ(*result, "first");
}
TEST(TestSettingsParser, FindSkipMatchesAnyArchInList)
{
const TempTomlFile file(R"(
[meta]
version = 1
[[test_skips]]
archs = ["gfx1100", "gfx1101", "gfx942"]
filters = ["*ConvFwd*"]
reason = "broad arch list"
)");
const TestSettings settings(file.path());
EXPECT_TRUE(
settings.findSkip("IntegrationGpuConvFwd.Test", "gfx942:xnack-", "linux").has_value());
EXPECT_TRUE(settings.findSkip("IntegrationGpuConvFwd.Test", "gfx1100", "linux").has_value());
EXPECT_FALSE(settings.findSkip("IntegrationGpuConvFwd.Test", "gfx906", "linux").has_value());
}
// ---------------------------------------------------------------------------
// [[test_skips]] platforms
// ---------------------------------------------------------------------------
TEST(TestSettingsParser, ParsesSkipWithPlatforms)
{
const TempTomlFile file(R"(
[meta]
version = 1
[[test_skips]]
archs = ["gfx1100"]
platforms = ["windows"]
filters = ["*Foo*"]
reason = "windows + RDNA3 only"
)");
const TestSettings settings(file.path());
EXPECT_EQ(settings.skipEntryCount(), 1U);
}
TEST(TestSettingsParser, FindSkipMatchesPlatform)
{
const TempTomlFile file(R"(
[meta]
version = 1
[[test_skips]]
platforms = ["windows"]
filters = ["*Foo*"]
reason = "windows-only"
)");
const TestSettings settings(file.path());
auto winMatch = settings.findSkip("Foo.Test", "gfx942", "windows");
ASSERT_TRUE(winMatch.has_value());
EXPECT_EQ(*winMatch, "windows-only");
auto linuxMiss = settings.findSkip("Foo.Test", "gfx942", "linux");
EXPECT_FALSE(linuxMiss.has_value());
}
TEST(TestSettingsParser, FindSkipMatchesAnyPlatformInList)
{
const TempTomlFile file(R"(
[meta]
version = 1
[[test_skips]]
platforms = ["windows", "linux"]
filters = ["*Foo*"]
reason = "broken everywhere"
)");
const TestSettings settings(file.path());
EXPECT_TRUE(settings.findSkip("Foo.Test", "gfx942", "windows").has_value());
EXPECT_TRUE(settings.findSkip("Foo.Test", "gfx942", "linux").has_value());
}
TEST(TestSettingsParser, FindSkipPlatformIsExactNotSubstring)
{
// Unlike archs, platform matching is exact equality. "win" must not match
// "windows".
const TempTomlFile file(R"(
[meta]
version = 1
[[test_skips]]
platforms = ["win"]
filters = ["*Foo*"]
reason = "should not fire"
)");
const TestSettings settings(file.path());
auto result = settings.findSkip("Foo.Test", "gfx942", "windows");
EXPECT_FALSE(result.has_value());
}
TEST(TestSettingsParser, FindSkipOmittedPlatformsMatchesAny)
{
// No 'platforms' field => entry matches any platform (the existing
// arch-only behavior is unchanged).
const TempTomlFile file(R"(
[meta]
version = 1
[[test_skips]]
archs = ["gfx942"]
filters = ["*Foo*"]
reason = "arch-only rule"
)");
const TestSettings settings(file.path());
EXPECT_TRUE(settings.findSkip("Foo.Test", "gfx942", "windows").has_value());
EXPECT_TRUE(settings.findSkip("Foo.Test", "gfx942", "linux").has_value());
}
TEST(TestSettingsParser, FindSkipArchAndPlatformBothRequired)
{
// When both 'archs' and 'platforms' are set, BOTH must match.
const TempTomlFile file(R"(
[meta]
version = 1
[[test_skips]]
archs = ["gfx1100"]
platforms = ["windows"]
filters = ["*Foo*"]
reason = "windows + gfx1100 only"
)");
const TestSettings settings(file.path());
// Both match
EXPECT_TRUE(settings.findSkip("Foo.Test", "gfx1100", "windows").has_value());
// Wrong arch
EXPECT_FALSE(settings.findSkip("Foo.Test", "gfx942", "windows").has_value());
// Wrong platform
EXPECT_FALSE(settings.findSkip("Foo.Test", "gfx1100", "linux").has_value());
}
// NOLINTEND(readability-identifier-naming)