Files
TheRock/rocm-libraries/projects/hipblaslt/tensilelite/tests/MasterSolutionLibraryMapping_test.cpp
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

188 lines
7.7 KiB
C++

/*******************************************************************************
*
* MIT License
*
* Copyright (C) 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.
*
*******************************************************************************/
// Host-only tests for MasterSolutionLibrary::initLibraryMapping.
//
// These tests exercise the per-arch Mapping-file routing introduced so that
// single-arch shard installs do not collide on a shared
// "TensileLiteLibrary_lazy_Mapping.dat" filename. They run without a GPU
// because initLibraryMapping only inspects filenames and reads a small
// msgpack file from disk; no kernels are launched.
#include <gtest/gtest.h>
#include <filesystem>
#include <fstream>
#include <map>
#include <string>
#include <msgpack.hpp>
#include <Tensile/ContractionProblem.hpp>
#include <Tensile/ContractionSolution.hpp>
#include <Tensile/MasterSolutionLibrary.hpp>
namespace fs = std::filesystem;
namespace
{
using TestLibrary
= TensileLite::MasterSolutionLibrary<TensileLite::ContractionProblemGemm,
TensileLite::ContractionSolution>;
// Write a minimal msgpack mapping file in the format
// MessagePackLoadLibraryMapping expects: a top-level map of
// string-encoded-int -> string.
void writeMappingFile(const fs::path& path,
const std::map<std::string, std::string>& entries)
{
msgpack::sbuffer buffer;
msgpack::pack(buffer, entries);
std::ofstream out(path, std::ios::binary);
ASSERT_TRUE(out.good()) << "could not open " << path << " for writing";
out.write(buffer.data(), static_cast<std::streamsize>(buffer.size()));
ASSERT_TRUE(out.good()) << "write failed for " << path;
}
struct MasterSolutionLibraryMappingTest : public ::testing::Test
{
fs::path tmpDir;
void SetUp() override
{
tmpDir = fs::temp_directory_path()
/ fs::path("hipblaslt-mapping-test-"
+ std::to_string(::testing::UnitTest::GetInstance()->random_seed())
+ "-"
+ ::testing::UnitTest::GetInstance()->current_test_info()->name());
fs::create_directories(tmpDir);
}
void TearDown() override
{
std::error_code ec;
fs::remove_all(tmpDir, ec);
}
// Build a master library file path inside tmpDir for a given arch.
// initLibraryMapping never reads this file; it only parses the name.
fs::path masterPath(const std::string& arch) const
{
return tmpDir / ("TensileLibrary_lazy_" + arch + ".dat");
}
fs::path perArchMappingPath(const std::string& arch) const
{
return tmpDir / ("TensileLiteLibrary_lazy_" + arch + "_Mapping.dat");
}
fs::path legacyGlobalMappingPath() const
{
return tmpDir / "TensileLiteLibrary_lazy_Mapping.dat";
}
};
}
// Per-arch file present and well-formed: must succeed and load all entries.
TEST_F(MasterSolutionLibraryMappingTest, LoadsPerArchMapping)
{
const std::string arch = "gfx9999";
writeMappingFile(perArchMappingPath(arch),
{{"0", "kernel_a_" + arch},
{"1", "kernel_b_" + arch},
{"42", "kernel_c_" + arch}});
TestLibrary lib;
ASSERT_TRUE(lib.initLibraryMapping(masterPath(arch).string()));
EXPECT_EQ(lib.libraryMapping.size(), 3u);
EXPECT_EQ(lib.libraryMapping.at(0), "kernel_a_" + arch);
EXPECT_EQ(lib.libraryMapping.at(1), "kernel_b_" + arch);
EXPECT_EQ(lib.libraryMapping.at(42), "kernel_c_" + arch);
}
// The kpack-collision regression: the legacy global Mapping.dat sitting in
// the same directory must NOT be picked up when the per-arch file is absent.
// If it ever were, two shard installs that overlay onto the same prefix
// would silently load each other's kernels.
TEST_F(MasterSolutionLibraryMappingTest, DoesNotFallBackToLegacyGlobalMapping)
{
const std::string arch = "gfx9999";
// Legacy global file exists with plausible content...
writeMappingFile(legacyGlobalMappingPath(),
{{"0", "wrong_kernel_" + arch}, {"1", "wrong_kernel2_" + arch}});
// ...but the per-arch file does not.
TestLibrary lib;
EXPECT_FALSE(lib.initLibraryMapping(masterPath(arch).string()));
EXPECT_TRUE(lib.libraryMapping.empty());
}
// Arch is derived dynamically from the master filename; a second arch in the
// same directory must not see the first arch's entries, even if both
// per-arch files exist.
TEST_F(MasterSolutionLibraryMappingTest, RoutesByArchDerivedFromMasterFilename)
{
writeMappingFile(perArchMappingPath("gfx1100"),
{{"0", "k1100_a"}, {"1", "k1100_b"}});
writeMappingFile(perArchMappingPath("gfx1101"),
{{"100", "k1101_a"}, {"101", "k1101_b"}, {"102", "k1101_c"}});
TestLibrary lib1100;
ASSERT_TRUE(lib1100.initLibraryMapping(masterPath("gfx1100").string()));
EXPECT_EQ(lib1100.libraryMapping.size(), 2u);
EXPECT_EQ(lib1100.libraryMapping.at(0), "k1100_a");
TestLibrary lib1101;
ASSERT_TRUE(lib1101.initLibraryMapping(masterPath("gfx1101").string()));
EXPECT_EQ(lib1101.libraryMapping.size(), 3u);
EXPECT_EQ(lib1101.libraryMapping.at(100), "k1101_a");
EXPECT_EQ(lib1101.libraryMapping.find(0), lib1101.libraryMapping.end());
}
// Master filename without the expected "TensileLibrary_lazy_" prefix:
// initLibraryMapping must refuse rather than guess at a Mapping path.
//
// Discrimination guard: a legacy implementation that ignores the master
// filename and just opens a hardcoded global "TensileLiteLibrary_lazy_Mapping.dat"
// would happily load the planted global file and return true. The patched
// implementation must reject the malformed name *before* touching the disk.
TEST_F(MasterSolutionLibraryMappingTest, RejectsMalformedMasterFilename)
{
const fs::path badMaster = tmpDir / "something_unexpected.dat";
// Plant a well-formed legacy global file. A non-validating implementation
// would find this and incorrectly succeed.
writeMappingFile(legacyGlobalMappingPath(),
{{"0", "junk_value_a"}, {"1", "junk_value_b"}});
// Also plant a per-arch file under a plausible arch so an implementation
// that guesses an arch from anywhere has something to pick up.
writeMappingFile(perArchMappingPath("gfx1100"), {{"0", "k1100_a"}});
TestLibrary lib;
EXPECT_FALSE(lib.initLibraryMapping(badMaster.string()));
EXPECT_TRUE(lib.libraryMapping.empty());
}