// Copyright © Advanced Micro Devices, Inc., or its affiliates. // SPDX-License-Identifier: MIT #include #include #include #include #include #include #include #include #include "gtest_common.hpp" #include #include using ::testing::_; using ::testing::Return; namespace fs = miopen::fs; MIOPEN_LIB_ENV_VAR(MIOPEN_USER_DB_PATH) MIOPEN_LIB_ENV_VAR(MIOPEN_CUSTOM_CACHE_DIR) // Helper function to build expected version string std::string GetExpectedVersionString() { std::ostringstream oss; oss << MIOPEN_VERSION_MAJOR << "." << MIOPEN_VERSION_MINOR << "." << MIOPEN_VERSION_PATCH << "." << MIOPEN_STRINGIZE(MIOPEN_VERSION_TWEAK); return oss.str(); } // Helper function to check if a path contains a substring bool PathContains(const fs::path& path, const std::string& substring) { return path.string().find(substring) != std::string::npos; } // Mock filesystem checker for testing class MockFilesystemChecker : public miopen::IFilesystemChecker { public: MOCK_METHOD(bool, IsNetworkedFilesystem, (const fs::path& path), (const, override)); }; // Test fixture for db_path tests with filesystem mocking class CPU_DbPaths_NONE : public ::testing::Test { protected: MockFilesystemChecker mock_checker; void SetUp() override { // Reset cached paths to allow fresh initialization with new mock/env settings miopen::testing::ResetCachedPaths(); miopen::testing::ResetUserDbPath(); // Install the mock checker before any path functions are called miopen::SetFilesystemChecker(&mock_checker); } void TearDown() override { // Restore default checker miopen::SetFilesystemChecker(nullptr); } }; // ============================================================================ // Tests for GetUserDbPath() - 4 scenarios // ============================================================================ TEST_F(CPU_DbPaths_NONE, UserDbPath_LocalFS_NoEnvVar) { // Ensure environment variable is NOT set for this test ScopedEnvironment unset_user_db(MIOPEN_USER_DB_PATH, ""); // Scenario 1: Local filesystem, no environment variable set EXPECT_CALL(mock_checker, IsNetworkedFilesystem(_)).WillRepeatedly(Return(false)); const auto& user_db_path = miopen::GetUserDbPath(); if(user_db_path.empty()) { GTEST_SKIP() << "User DB is disabled (MIOPEN_DISABLE_USERDB)"; } // Should use default path containing "miopen" EXPECT_TRUE(PathContains(user_db_path, "miopen")) << "User DB path '" << user_db_path.string() << "' should contain 'miopen' folder"; } TEST_F(CPU_DbPaths_NONE, UserDbPath_LocalFS_EnvVarSet) { // Scenario 2: Local filesystem, environment variable set const std::string custom_path = "/custom/user/db/path"; ScopedEnvironment scoped_env(MIOPEN_USER_DB_PATH, custom_path); EXPECT_CALL(mock_checker, IsNetworkedFilesystem(_)).WillRepeatedly(Return(false)); const auto& user_db_path = miopen::GetUserDbPath(); if(user_db_path.empty()) { GTEST_SKIP() << "User DB is disabled (MIOPEN_DISABLE_USERDB)"; } // Should use the custom path from environment variable EXPECT_TRUE(PathContains(user_db_path, custom_path)) << "User DB path '" << user_db_path.string() << "' should contain custom path '" << custom_path << "'"; } TEST_F(CPU_DbPaths_NONE, UserDbPath_NetworkFS_NoEnvVar) { #if MIOPEN_BUILD_DEV GTEST_SKIP() << "Network filesystem detection is disabled in MIOPEN_BUILD_DEV mode"; #else // Ensure environment variable is NOT set for this test ScopedEnvironment unset_user_db(MIOPEN_USER_DB_PATH, ""); // Scenario 3: Network filesystem, no environment variable set EXPECT_CALL(mock_checker, IsNetworkedFilesystem(_)).WillRepeatedly(Return(true)); const auto& user_db_path = miopen::GetUserDbPath(); if(user_db_path.empty()) { GTEST_SKIP() << "User DB is disabled (MIOPEN_DISABLE_USERDB)"; } // Should fallback to temp directory const auto temp_dir = fs::temp_directory_path(); EXPECT_TRUE(PathContains(user_db_path, temp_dir.string())) << "User DB path '" << user_db_path.string() << "' should be in temp directory for network filesystem"; // Should contain .config/miopen EXPECT_TRUE(PathContains(user_db_path, ".config")) << "User DB path should contain '.config' folder"; EXPECT_TRUE(PathContains(user_db_path, "miopen")) << "User DB path should contain 'miopen' folder"; #endif } TEST_F(CPU_DbPaths_NONE, UserDbPath_NetworkFS_EnvVarSet) { // Scenario 4: Network filesystem, environment variable set // Environment variable should take precedence over network detection const std::string custom_path = "/custom/network/db/path"; ScopedEnvironment scoped_env(MIOPEN_USER_DB_PATH, custom_path); EXPECT_CALL(mock_checker, IsNetworkedFilesystem(_)).WillRepeatedly(Return(true)); const auto& user_db_path = miopen::GetUserDbPath(); if(user_db_path.empty()) { GTEST_SKIP() << "User DB is disabled (MIOPEN_DISABLE_USERDB)"; } // Should use the custom path from environment variable (takes precedence) EXPECT_TRUE(PathContains(user_db_path, custom_path)) << "User DB path '" << user_db_path.string() << "' should use custom path even on network filesystem"; } // ============================================================================ // Tests for GetCachePath() - 4 scenarios // ============================================================================ TEST_F(CPU_DbPaths_NONE, CachePath_LocalFS_NoEnvVar) { // Ensure environment variable is NOT set for this test ScopedEnvironment unset_cache(MIOPEN_CUSTOM_CACHE_DIR, ""); // Scenario 1: Local filesystem, no environment variable set EXPECT_CALL(mock_checker, IsNetworkedFilesystem(_)).WillRepeatedly(Return(false)); const auto cache_path = miopen::GetCachePath(false); if(cache_path.empty()) { GTEST_SKIP() << "User cache is disabled (MIOPEN_DISABLE_USERDB)"; } // Should contain version string const std::string expected_version = GetExpectedVersionString(); EXPECT_TRUE(PathContains(cache_path, expected_version)) << "Cache path '" << cache_path.string() << "' should contain version string '" << expected_version << "'"; // Should contain "miopen" EXPECT_TRUE(PathContains(cache_path, "miopen")) << "Cache path should contain 'miopen' folder"; } TEST_F(CPU_DbPaths_NONE, CachePath_LocalFS_EnvVarSet) { // Scenario 2: Local filesystem, environment variable set const std::string custom_cache = (fs::temp_directory_path() / "custom/cache/dir").string(); ScopedEnvironment scoped_env(MIOPEN_CUSTOM_CACHE_DIR, custom_cache); EXPECT_CALL(mock_checker, IsNetworkedFilesystem(_)).WillRepeatedly(Return(false)); const auto cache_path = miopen::GetCachePath(false); if(cache_path.empty()) { GTEST_SKIP() << "User cache is disabled (MIOPEN_DISABLE_USERDB)"; } // Should use the custom cache directory EXPECT_TRUE(PathContains(cache_path, custom_cache)) << "Cache path '" << cache_path.string() << "' should contain custom cache dir '" << custom_cache << "'"; } TEST_F(CPU_DbPaths_NONE, CachePath_NetworkFS_NoEnvVar) { #if MIOPEN_BUILD_DEV GTEST_SKIP() << "Network filesystem detection is disabled in MIOPEN_BUILD_DEV mode"; #else // Ensure environment variable is NOT set for this test ScopedEnvironment unset_cache(MIOPEN_CUSTOM_CACHE_DIR, ""); // Scenario 3: Network filesystem, no environment variable set EXPECT_CALL(mock_checker, IsNetworkedFilesystem(_)).WillRepeatedly(Return(true)); const auto cache_path = miopen::GetCachePath(false); if(cache_path.empty()) { GTEST_SKIP() << "User cache is disabled (MIOPEN_DISABLE_USERDB)"; } // Should fallback to temp directory const auto temp_dir = fs::temp_directory_path(); EXPECT_TRUE(PathContains(cache_path, temp_dir.string())) << "Cache path '" << cache_path.string() << "' should be in temp directory for network filesystem"; // Should contain .cache/miopen/ EXPECT_TRUE(PathContains(cache_path, ".cache")) << "Cache path should contain '.cache' folder"; EXPECT_TRUE(PathContains(cache_path, "miopen")) << "Cache path should contain 'miopen' folder"; const std::string expected_version = GetExpectedVersionString(); EXPECT_TRUE(PathContains(cache_path, expected_version)) << "Cache path should contain version string '" << expected_version << "'"; #endif } TEST_F(CPU_DbPaths_NONE, CachePath_NetworkFS_EnvVarSet) { // Scenario 4: Network filesystem, environment variable set // Environment variable should take precedence over network detection const std::string custom_cache = (fs::temp_directory_path() / "custom/network/cache").string(); ScopedEnvironment scoped_env(MIOPEN_CUSTOM_CACHE_DIR, custom_cache); EXPECT_CALL(mock_checker, IsNetworkedFilesystem(_)).WillRepeatedly(Return(true)); const auto cache_path = miopen::GetCachePath(false); if(cache_path.empty()) { GTEST_SKIP() << "User cache is disabled (MIOPEN_DISABLE_USERDB)"; } // Should use the custom cache directory (takes precedence) EXPECT_TRUE(PathContains(cache_path, custom_cache)) << "Cache path '" << cache_path.string() << "' should use custom cache even on network filesystem"; } // ============================================================================ // Additional tests // ============================================================================ TEST_F(CPU_DbPaths_NONE, UserDbSuffix_ContainsVersionInfo) { const std::string suffix = miopen::GetUserDbSuffix(); EXPECT_FALSE(suffix.empty()) << "User DB suffix should not be empty"; // Suffix should contain version numbers separated by underscores std::ostringstream expected_pattern; expected_pattern << MIOPEN_VERSION_MAJOR << "_" << MIOPEN_VERSION_MINOR << "_" << MIOPEN_VERSION_PATCH; EXPECT_TRUE(suffix.find(expected_pattern.str()) != std::string::npos) << "Suffix '" << suffix << "' should contain version pattern '" << expected_pattern.str() << "'"; } TEST_F(CPU_DbPaths_NONE, UserAndSystemCachePaths_AreDifferent) { EXPECT_CALL(mock_checker, IsNetworkedFilesystem(_)).WillRepeatedly(Return(false)); const auto user_cache = miopen::GetCachePath(false); const auto sys_cache = miopen::GetCachePath(true); if(!user_cache.empty() && !sys_cache.empty()) { EXPECT_NE(user_cache, sys_cache) << "User and system cache paths should be different"; } } TEST_F(CPU_DbPaths_NONE, Paths_AreValid) { EXPECT_CALL(mock_checker, IsNetworkedFilesystem(_)).WillRepeatedly(Return(false)); const auto& user_db_path = miopen::GetUserDbPath(); const auto cache_path = miopen::GetCachePath(false); const auto sys_cache_path = miopen::GetCachePath(true); // Paths should either be empty (if disabled) or valid filesystem paths if(!user_db_path.empty()) { EXPECT_FALSE(user_db_path.string().empty()); } if(!cache_path.empty()) { EXPECT_FALSE(cache_path.string().empty()); } if(!sys_cache_path.empty()) { EXPECT_FALSE(sys_cache_path.string().empty()); } } TEST_F(CPU_DbPaths_NONE, CacheDisabled_ReturnsCorrectly) { EXPECT_CALL(mock_checker, IsNetworkedFilesystem(_)).WillRepeatedly(Return(false)); const bool is_disabled = miopen::IsCacheDisabled(); // The result depends on build configuration // Just verify it returns a valid boolean without crashing EXPECT_TRUE(is_disabled == true || is_disabled == false); }