* test: add unit tests for common utilities from PR #1249 * incorporate review comments specific to tests formatting * use filesystem API instead of std::system for safer cleanup * Add ghc/filesystem submodule v1.5.14 for portable C++17 filesystem support * fix: add cmake/GhcFilesystem.cmake for CI submodule auto-checkout * incorporate review comment * incorporate review comment
This commit is contained in:
zatwierdzone przez
GitHub
rodzic
4a9833e70e
commit
b4e04b07ed
@@ -95,3 +95,6 @@
|
||||
[submodule "projects/rocprofiler-systems/external/googletest"]
|
||||
path = projects/rocprofiler-systems/external/googletest
|
||||
url = https://github.com/google/googletest.git
|
||||
[submodule "projects/rocprofiler-systems/external/filesystem"]
|
||||
path = projects/rocprofiler-systems/external/filesystem
|
||||
url = https://github.com/gulrak/filesystem.git
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
# MIT License
|
||||
#
|
||||
# Copyright (c) 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_guard(GLOBAL)
|
||||
|
||||
message(STATUS "Setting up ghc::filesystem for tests")
|
||||
|
||||
include(FetchContent)
|
||||
|
||||
rocprofiler_systems_checkout_git_submodule(
|
||||
RELATIVE_PATH external/filesystem
|
||||
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
|
||||
TEST_FILE include/ghc/filesystem.hpp
|
||||
REPO_URL https://github.com/gulrak/filesystem.git
|
||||
REPO_BRANCH "v1.5.14"
|
||||
)
|
||||
|
||||
# Configure ghc/filesystem options before adding it
|
||||
set(GHC_FILESYSTEM_BUILD_TESTING OFF CACHE BOOL "Disable ghc filesystem tests" FORCE)
|
||||
set(GHC_FILESYSTEM_BUILD_EXAMPLES OFF CACHE BOOL "Disable ghc filesystem examples" FORCE)
|
||||
set(GHC_FILESYSTEM_WITH_INSTALL OFF CACHE BOOL "Disable ghc filesystem install" FORCE)
|
||||
|
||||
# Declare ghc/filesystem from the submodule
|
||||
FetchContent_Declare(ghc_filesystem SOURCE_DIR ${PROJECT_SOURCE_DIR}/external/filesystem)
|
||||
|
||||
# Make ghc/filesystem available
|
||||
FetchContent_MakeAvailable(ghc_filesystem)
|
||||
|
||||
# Create interface library that wraps ghc::filesystem target
|
||||
add_library(rocprofiler-systems-ghc-filesystem INTERFACE)
|
||||
|
||||
target_link_libraries(rocprofiler-systems-ghc-filesystem INTERFACE ghc_filesystem)
|
||||
|
||||
target_compile_definitions(
|
||||
rocprofiler-systems-ghc-filesystem
|
||||
INTERFACE ROCPROFSYS_TESTS_HAS_GHC_LIB_FILESYSTEM=1
|
||||
)
|
||||
|
||||
message(STATUS "ghc::filesystem configured successfully using FetchContent")
|
||||
@@ -691,6 +691,7 @@ include(NlohmannJson)
|
||||
|
||||
if(ROCPROFSYS_BUILD_TESTING)
|
||||
include(GTest)
|
||||
include(GhcFilesystem)
|
||||
endif()
|
||||
|
||||
# ----------------------------------------------------------------------------------------#
|
||||
|
||||
+1
Submodule projects/rocprofiler-systems/external/filesystem added at 8a2edd6d92
@@ -203,7 +203,8 @@ remove_env(std::vector<char*>& _environ, std::string_view _env_var,
|
||||
}
|
||||
|
||||
// Remove null entries
|
||||
_environ.erase(std::remove_if(_environ.begin(), _environ.end(), match),
|
||||
_environ.erase(std::remove_if(_environ.begin(), _environ.end(),
|
||||
[](const char* ptr) { return ptr == nullptr; }),
|
||||
_environ.end());
|
||||
|
||||
// Restore from original_envs if previously existed
|
||||
|
||||
@@ -20,9 +20,19 @@
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
# THE SOFTWARE.
|
||||
|
||||
add_library(lib-common-tests OBJECT test_update_env.cpp)
|
||||
add_library(
|
||||
lib-common-tests
|
||||
OBJECT
|
||||
test_discover_llvm_libdir.cpp
|
||||
test_path.cpp
|
||||
test_remove_env.cpp
|
||||
test_update_env.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(
|
||||
lib-common-tests
|
||||
PUBLIC rocprofiler-systems-common-library rocprofiler-systems-googletest-library
|
||||
PUBLIC
|
||||
rocprofiler-systems-common-library
|
||||
rocprofiler-systems-googletest-library
|
||||
rocprofiler-systems-ghc-filesystem
|
||||
)
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
// 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.
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(ROCPROFSYS_TESTS_HAS_GHC_LIB_FILESYSTEM)
|
||||
# if defined __has_include
|
||||
# if __has_include(<ghc/filesystem.hpp>)
|
||||
# define ROCPROFSYS_TESTS_HAS_GHC_LIB_FILESYSTEM 1
|
||||
# else
|
||||
# define ROCPROFSYS_TESTS_HAS_GHC_LIB_FILESYSTEM 0
|
||||
# endif
|
||||
# else
|
||||
# define ROCPROFSYS_TESTS_HAS_GHC_LIB_FILESYSTEM 0
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if ROCPROFSYS_TESTS_HAS_GHC_LIB_FILESYSTEM == 0
|
||||
# if defined __has_include
|
||||
# if __has_include(<version>)
|
||||
# include <version>
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# if defined(__cpp_lib_filesystem)
|
||||
# define ROCPROFSYS_TESTS_HAS_CPP_LIB_FILESYSTEM 1
|
||||
# else
|
||||
# if defined __has_include
|
||||
# if __has_include(<filesystem>)
|
||||
# define ROCPROFSYS_TESTS_HAS_CPP_LIB_FILESYSTEM 1
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(ROCPROFSYS_TESTS_HAS_GHC_LIB_FILESYSTEM) && \
|
||||
ROCPROFSYS_TESTS_HAS_GHC_LIB_FILESYSTEM > 0
|
||||
# include <ghc/filesystem.hpp>
|
||||
#elif defined(ROCPROFSYS_TESTS_HAS_CPP_LIB_FILESYSTEM) && \
|
||||
ROCPROFSYS_TESTS_HAS_CPP_LIB_FILESYSTEM > 0
|
||||
# include <filesystem>
|
||||
#else
|
||||
# include <experimental/filesystem>
|
||||
#endif
|
||||
|
||||
namespace test_common
|
||||
{
|
||||
#if defined(ROCPROFSYS_TESTS_HAS_GHC_LIB_FILESYSTEM) && \
|
||||
ROCPROFSYS_TESTS_HAS_GHC_LIB_FILESYSTEM > 0
|
||||
namespace fs = ::ghc::filesystem; // NOLINT(misc-unused-alias-decls)
|
||||
#elif defined(ROCPROFSYS_TESTS_HAS_CPP_LIB_FILESYSTEM) && \
|
||||
ROCPROFSYS_TESTS_HAS_CPP_LIB_FILESYSTEM > 0
|
||||
namespace fs = ::std::filesystem; // NOLINT(misc-unused-alias-decls)
|
||||
#else
|
||||
namespace fs = ::std::experimental::filesystem; // NOLINT(misc-unused-alias-decls)
|
||||
#endif
|
||||
} // namespace test_common
|
||||
+399
@@ -0,0 +1,399 @@
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) 2022-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 "common/environment.hpp"
|
||||
#include "filesystem.hpp"
|
||||
|
||||
#include <fstream>
|
||||
#include <gtest/gtest.h>
|
||||
#include <string>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
using namespace rocprofsys::common;
|
||||
|
||||
class DiscoverLlvmLibdirTest : public ::testing::Test
|
||||
{
|
||||
protected:
|
||||
void SetUp() override
|
||||
{
|
||||
m_test_dir = create_temp_dir();
|
||||
save_env_vars();
|
||||
}
|
||||
|
||||
void TearDown() override
|
||||
{
|
||||
restore_env_vars();
|
||||
cleanup_temp_dir(m_test_dir);
|
||||
}
|
||||
|
||||
std::string create_temp_dir()
|
||||
{
|
||||
char tmpl[] = "/tmp/rocprofsys_llvm_test_XXXXXX";
|
||||
char* dir = mkdtemp(tmpl);
|
||||
if(!dir)
|
||||
{
|
||||
throw std::runtime_error("Failed to create temp directory");
|
||||
}
|
||||
return std::string{ dir };
|
||||
}
|
||||
|
||||
void cleanup_temp_dir(const std::string& dir)
|
||||
{
|
||||
if(dir.empty()) return;
|
||||
std::error_code ec;
|
||||
test_common::fs::remove_all(dir, ec);
|
||||
}
|
||||
|
||||
void create_directory(const std::string& path)
|
||||
{
|
||||
std::error_code ec;
|
||||
test_common::fs::create_directories(path, ec);
|
||||
}
|
||||
|
||||
void create_libomptarget(const std::string& dir)
|
||||
{
|
||||
create_directory(dir);
|
||||
std::string lib_path = dir + "/libomptarget.so";
|
||||
std::ofstream ofs(lib_path);
|
||||
ofs << "fake library content";
|
||||
}
|
||||
|
||||
void save_env_vars()
|
||||
{
|
||||
char* rocm_path = getenv("ROCM_PATH");
|
||||
char* rocmv_dir = getenv("ROCmVersion_DIR");
|
||||
m_saved_rocm_path =
|
||||
rocm_path ? std::optional<std::string>{ rocm_path } : std::nullopt;
|
||||
m_saved_rocmv_dir =
|
||||
rocmv_dir ? std::optional<std::string>{ rocmv_dir } : std::nullopt;
|
||||
}
|
||||
|
||||
void restore_env_vars()
|
||||
{
|
||||
if(m_saved_rocm_path.has_value())
|
||||
setenv("ROCM_PATH", m_saved_rocm_path->c_str(), 1);
|
||||
else
|
||||
unsetenv("ROCM_PATH");
|
||||
|
||||
if(m_saved_rocmv_dir.has_value())
|
||||
setenv("ROCmVersion_DIR", m_saved_rocmv_dir->c_str(), 1);
|
||||
else
|
||||
unsetenv("ROCmVersion_DIR");
|
||||
}
|
||||
|
||||
void set_rocm_path(const std::string& path) { setenv("ROCM_PATH", path.c_str(), 1); }
|
||||
|
||||
void set_rocmv_dir(const std::string& path)
|
||||
{
|
||||
setenv("ROCmVersion_DIR", path.c_str(), 1);
|
||||
}
|
||||
|
||||
void clear_rocm_path() { unsetenv("ROCM_PATH"); }
|
||||
|
||||
void clear_rocmv_dir() { unsetenv("ROCmVersion_DIR"); }
|
||||
|
||||
std::string m_test_dir;
|
||||
std::optional<std::string> m_saved_rocm_path;
|
||||
std::optional<std::string> m_saved_rocmv_dir;
|
||||
};
|
||||
|
||||
TEST_F(DiscoverLlvmLibdirTest, FindsLibInRocmPathLlvmLib)
|
||||
{
|
||||
std::string rocm_path = m_test_dir + "/rocm";
|
||||
std::string llvm_lib = rocm_path + "/llvm/lib";
|
||||
create_libomptarget(llvm_lib);
|
||||
|
||||
set_rocm_path(rocm_path);
|
||||
clear_rocmv_dir();
|
||||
|
||||
std::string result = discover_llvm_libdir_for_ompt();
|
||||
|
||||
EXPECT_EQ(result, llvm_lib);
|
||||
}
|
||||
|
||||
TEST_F(DiscoverLlvmLibdirTest, FindsLibInRocmPathLibLlvmLib)
|
||||
{
|
||||
std::string rocm_path = m_test_dir + "/rocm";
|
||||
std::string lib_llvm_lib = rocm_path + "/lib/llvm/lib";
|
||||
create_libomptarget(lib_llvm_lib);
|
||||
|
||||
set_rocm_path(rocm_path);
|
||||
clear_rocmv_dir();
|
||||
|
||||
std::string result = discover_llvm_libdir_for_ompt();
|
||||
|
||||
EXPECT_EQ(result, lib_llvm_lib);
|
||||
}
|
||||
|
||||
TEST_F(DiscoverLlvmLibdirTest, PrefersLlvmLibOverLibLlvmLib)
|
||||
{
|
||||
std::string rocm_path = m_test_dir + "/rocm";
|
||||
std::string llvm_lib = rocm_path + "/llvm/lib";
|
||||
std::string lib_llvm_lib = rocm_path + "/lib/llvm/lib";
|
||||
create_libomptarget(llvm_lib);
|
||||
create_libomptarget(lib_llvm_lib);
|
||||
|
||||
set_rocm_path(rocm_path);
|
||||
clear_rocmv_dir();
|
||||
|
||||
std::string result = discover_llvm_libdir_for_ompt();
|
||||
|
||||
EXPECT_EQ(result, llvm_lib);
|
||||
}
|
||||
|
||||
TEST_F(DiscoverLlvmLibdirTest, RocmVersionDirLlvmLib)
|
||||
{
|
||||
std::string rocmv_dir = m_test_dir + "/rocm-version";
|
||||
std::string llvm_lib = rocmv_dir + "/llvm/lib";
|
||||
create_libomptarget(llvm_lib);
|
||||
|
||||
clear_rocm_path();
|
||||
set_rocmv_dir(rocmv_dir);
|
||||
|
||||
std::string result = discover_llvm_libdir_for_ompt();
|
||||
|
||||
EXPECT_EQ(result, llvm_lib);
|
||||
}
|
||||
|
||||
TEST_F(DiscoverLlvmLibdirTest, RocmVersionDirLib)
|
||||
{
|
||||
std::string rocmv_dir = m_test_dir + "/rocm-version";
|
||||
std::string lib_dir = rocmv_dir + "/lib";
|
||||
create_libomptarget(lib_dir);
|
||||
|
||||
clear_rocm_path();
|
||||
set_rocmv_dir(rocmv_dir);
|
||||
|
||||
std::string result = discover_llvm_libdir_for_ompt();
|
||||
|
||||
EXPECT_EQ(result, lib_dir);
|
||||
}
|
||||
|
||||
TEST_F(DiscoverLlvmLibdirTest, RocmVersionDirTakesPrecedence)
|
||||
{
|
||||
std::string rocm_path = m_test_dir + "/rocm";
|
||||
std::string rocmv_dir = m_test_dir + "/rocm-version";
|
||||
std::string rocm_llvm_lib = rocm_path + "/llvm/lib";
|
||||
std::string rocmv_lib = rocmv_dir + "/llvm/lib";
|
||||
create_libomptarget(rocm_llvm_lib);
|
||||
create_libomptarget(rocmv_lib);
|
||||
|
||||
set_rocm_path(rocm_path);
|
||||
set_rocmv_dir(rocmv_dir);
|
||||
|
||||
std::string result = discover_llvm_libdir_for_ompt();
|
||||
|
||||
EXPECT_EQ(result, rocmv_lib);
|
||||
}
|
||||
|
||||
TEST_F(DiscoverLlvmLibdirTest, NoLibomptargetFound_InCustomPath)
|
||||
{
|
||||
std::string rocm_path = m_test_dir + "/rocm";
|
||||
create_directory(rocm_path + "/llvm/lib");
|
||||
|
||||
set_rocm_path(rocm_path);
|
||||
clear_rocmv_dir();
|
||||
|
||||
std::string result = discover_llvm_libdir_for_ompt();
|
||||
|
||||
// Result should either be empty (no ROCm installed) or one of the default
|
||||
// fallback paths if ROCm is installed on the system
|
||||
if(!result.empty())
|
||||
{
|
||||
bool is_default_path =
|
||||
(result == "/opt/rocm/llvm/lib" || result == "/opt/rocm/lib/llvm/lib");
|
||||
EXPECT_TRUE(is_default_path)
|
||||
<< "Expected empty or default ROCm path, got: " << result;
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(DiscoverLlvmLibdirTest, TrailingSlashInRocmPath)
|
||||
{
|
||||
std::string rocm_path = m_test_dir + "/rocm";
|
||||
std::string llvm_lib = rocm_path + "/llvm/lib";
|
||||
create_libomptarget(llvm_lib);
|
||||
|
||||
set_rocm_path(rocm_path + "/");
|
||||
clear_rocmv_dir();
|
||||
|
||||
std::string result = discover_llvm_libdir_for_ompt();
|
||||
|
||||
EXPECT_EQ(result, llvm_lib);
|
||||
}
|
||||
|
||||
TEST_F(DiscoverLlvmLibdirTest, TrailingSlashInRocmVersionDir)
|
||||
{
|
||||
std::string rocmv_dir = m_test_dir + "/rocm-version";
|
||||
std::string llvm_lib = rocmv_dir + "/llvm/lib";
|
||||
create_libomptarget(llvm_lib);
|
||||
|
||||
clear_rocm_path();
|
||||
set_rocmv_dir(rocmv_dir + "/");
|
||||
|
||||
std::string result = discover_llvm_libdir_for_ompt();
|
||||
|
||||
EXPECT_EQ(result, llvm_lib);
|
||||
}
|
||||
|
||||
TEST_F(DiscoverLlvmLibdirTest, EmptyRocmVersionDir)
|
||||
{
|
||||
std::string rocm_path = m_test_dir + "/rocm";
|
||||
std::string llvm_lib = rocm_path + "/llvm/lib";
|
||||
create_libomptarget(llvm_lib);
|
||||
|
||||
set_rocm_path(rocm_path);
|
||||
setenv("ROCmVersion_DIR", "", 1);
|
||||
|
||||
std::string result = discover_llvm_libdir_for_ompt();
|
||||
|
||||
EXPECT_EQ(result, llvm_lib);
|
||||
}
|
||||
|
||||
TEST_F(DiscoverLlvmLibdirTest, VerboseModeDoesNotCrash)
|
||||
{
|
||||
std::string rocm_path = m_test_dir + "/rocm";
|
||||
std::string llvm_lib = rocm_path + "/llvm/lib";
|
||||
create_libomptarget(llvm_lib);
|
||||
|
||||
set_rocm_path(rocm_path);
|
||||
clear_rocmv_dir();
|
||||
|
||||
EXPECT_NO_THROW({ discover_llvm_libdir_for_ompt(true); });
|
||||
}
|
||||
|
||||
TEST_F(DiscoverLlvmLibdirTest, VerboseModeNoLibFound)
|
||||
{
|
||||
std::string rocm_path = m_test_dir + "/rocm";
|
||||
create_directory(rocm_path);
|
||||
|
||||
set_rocm_path(rocm_path);
|
||||
clear_rocmv_dir();
|
||||
|
||||
EXPECT_NO_THROW({ discover_llvm_libdir_for_ompt(true); });
|
||||
}
|
||||
|
||||
TEST_F(DiscoverLlvmLibdirTest, RocmVersionDirLlvmLibPreferredOverLib)
|
||||
{
|
||||
std::string rocmv_dir = m_test_dir + "/rocm-version";
|
||||
std::string llvm_lib = rocmv_dir + "/llvm/lib";
|
||||
std::string lib_dir = rocmv_dir + "/lib";
|
||||
create_libomptarget(llvm_lib);
|
||||
create_libomptarget(lib_dir);
|
||||
|
||||
clear_rocm_path();
|
||||
set_rocmv_dir(rocmv_dir);
|
||||
|
||||
std::string result = discover_llvm_libdir_for_ompt();
|
||||
|
||||
EXPECT_EQ(result, llvm_lib);
|
||||
}
|
||||
|
||||
TEST_F(DiscoverLlvmLibdirTest, FallsBackToRocmPathWhenRocmVersionDirHasNoLib)
|
||||
{
|
||||
std::string rocm_path = m_test_dir + "/rocm";
|
||||
std::string rocmv_dir = m_test_dir + "/rocm-version";
|
||||
std::string llvm_lib = rocm_path + "/llvm/lib";
|
||||
create_directory(rocmv_dir + "/llvm/lib");
|
||||
create_libomptarget(llvm_lib);
|
||||
|
||||
set_rocm_path(rocm_path);
|
||||
set_rocmv_dir(rocmv_dir);
|
||||
|
||||
std::string result = discover_llvm_libdir_for_ompt();
|
||||
|
||||
EXPECT_EQ(result, llvm_lib);
|
||||
}
|
||||
|
||||
TEST_F(DiscoverLlvmLibdirTest, MultipleTrailingSlashes)
|
||||
{
|
||||
std::string rocm_path = m_test_dir + "/rocm";
|
||||
std::string llvm_lib = rocm_path + "/llvm/lib";
|
||||
create_libomptarget(llvm_lib);
|
||||
|
||||
set_rocm_path(rocm_path + "/");
|
||||
clear_rocmv_dir();
|
||||
|
||||
std::string result = discover_llvm_libdir_for_ompt();
|
||||
|
||||
EXPECT_FALSE(result.empty());
|
||||
EXPECT_NE(result.find("llvm/lib"), std::string::npos);
|
||||
}
|
||||
|
||||
TEST_F(DiscoverLlvmLibdirTest, PathWithSpaces)
|
||||
{
|
||||
std::string rocm_path = m_test_dir + "/rocm with spaces";
|
||||
std::string llvm_lib = rocm_path + "/llvm/lib";
|
||||
|
||||
std::error_code ec;
|
||||
test_common::fs::create_directories(llvm_lib, ec);
|
||||
|
||||
std::string lib_path = llvm_lib + "/libomptarget.so";
|
||||
std::ofstream ofs(lib_path);
|
||||
ofs << "fake library content";
|
||||
ofs.close();
|
||||
|
||||
set_rocm_path(rocm_path);
|
||||
clear_rocmv_dir();
|
||||
|
||||
std::string result = discover_llvm_libdir_for_ompt();
|
||||
|
||||
EXPECT_EQ(result, llvm_lib);
|
||||
}
|
||||
|
||||
TEST_F(DiscoverLlvmLibdirTest, BothEnvVarsUnset_UsesDefaultRocmPath)
|
||||
{
|
||||
clear_rocm_path();
|
||||
clear_rocmv_dir();
|
||||
|
||||
std::string result = discover_llvm_libdir_for_ompt();
|
||||
|
||||
if(!result.empty())
|
||||
{
|
||||
EXPECT_TRUE(result.find("/opt/rocm") != std::string::npos ||
|
||||
result.find("llvm/lib") != std::string::npos);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(DiscoverLlvmLibdirTest, SymlinkToLibomptarget)
|
||||
{
|
||||
std::string rocm_path = m_test_dir + "/rocm";
|
||||
std::string llvm_lib = rocm_path + "/llvm/lib";
|
||||
std::string actual_dir = m_test_dir + "/actual";
|
||||
std::string actual_file = actual_dir + "/libomptarget.so";
|
||||
|
||||
create_directory(actual_dir);
|
||||
std::ofstream ofs(actual_file);
|
||||
ofs << "fake library content";
|
||||
ofs.close();
|
||||
|
||||
create_directory(llvm_lib);
|
||||
std::string link_path = llvm_lib + "/libomptarget.so";
|
||||
symlink(actual_file.c_str(), link_path.c_str());
|
||||
|
||||
set_rocm_path(rocm_path);
|
||||
clear_rocmv_dir();
|
||||
|
||||
std::string result = discover_llvm_libdir_for_ompt();
|
||||
|
||||
EXPECT_EQ(result, llvm_lib);
|
||||
}
|
||||
@@ -0,0 +1,393 @@
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) 2022-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 "common/path.hpp"
|
||||
#include "filesystem.hpp"
|
||||
|
||||
#include <fstream>
|
||||
#include <gtest/gtest.h>
|
||||
#include <string>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
using namespace rocprofsys::common::path;
|
||||
|
||||
class PathTest : public ::testing::Test
|
||||
{
|
||||
protected:
|
||||
void SetUp() override { m_test_dir = create_temp_dir(); }
|
||||
|
||||
void TearDown() override { cleanup_temp_dir(m_test_dir); }
|
||||
|
||||
std::string create_temp_dir()
|
||||
{
|
||||
char tmpl[] = "/tmp/rocprofsys_path_test_XXXXXX";
|
||||
char* dir = mkdtemp(tmpl);
|
||||
if(!dir)
|
||||
{
|
||||
throw std::runtime_error("Failed to create temp directory");
|
||||
}
|
||||
return std::string{ dir };
|
||||
}
|
||||
|
||||
void cleanup_temp_dir(const std::string& dir)
|
||||
{
|
||||
if(dir.empty()) return;
|
||||
std::error_code ec;
|
||||
test_common::fs::remove_all(dir, ec);
|
||||
}
|
||||
|
||||
std::string create_file(const std::string& name, const std::string& content = "test")
|
||||
{
|
||||
std::string path = m_test_dir + "/" + name;
|
||||
std::ofstream ofs(path);
|
||||
ofs << content;
|
||||
return path;
|
||||
}
|
||||
|
||||
std::string create_symlink(const std::string& target, const std::string& link_name)
|
||||
{
|
||||
std::string link_path = m_test_dir + "/" + link_name;
|
||||
symlink(target.c_str(), link_path.c_str());
|
||||
return link_path;
|
||||
}
|
||||
|
||||
std::string create_subdir(const std::string& name)
|
||||
{
|
||||
std::string path = m_test_dir + "/" + name;
|
||||
mkdir(path.c_str(), 0755);
|
||||
return path;
|
||||
}
|
||||
|
||||
std::string m_test_dir;
|
||||
};
|
||||
|
||||
TEST_F(PathTest, Dirname_StandardPath)
|
||||
{
|
||||
EXPECT_EQ(dirname("/usr/local/bin/program"), "/usr/local/bin");
|
||||
}
|
||||
|
||||
TEST_F(PathTest, Dirname_SingleLevel) { EXPECT_EQ(dirname("/usr/file"), "/usr"); }
|
||||
|
||||
TEST_F(PathTest, Dirname_RootFile) { EXPECT_EQ(dirname("/file"), ""); }
|
||||
|
||||
TEST_F(PathTest, Dirname_NoSlash) { EXPECT_EQ(dirname("filename"), ""); }
|
||||
|
||||
TEST_F(PathTest, Dirname_EmptyString) { EXPECT_EQ(dirname(""), ""); }
|
||||
|
||||
TEST_F(PathTest, Dirname_TrailingSlash)
|
||||
{
|
||||
EXPECT_EQ(dirname("/usr/local/"), "/usr/local");
|
||||
}
|
||||
|
||||
TEST_F(PathTest, Dirname_MultipleSlashes)
|
||||
{
|
||||
EXPECT_EQ(dirname("/a/b/c/d/e"), "/a/b/c/d");
|
||||
}
|
||||
|
||||
TEST_F(PathTest, Exists_ExistingFile)
|
||||
{
|
||||
std::string file_path = create_file("existing_file.txt");
|
||||
EXPECT_TRUE(exists(file_path));
|
||||
}
|
||||
|
||||
TEST_F(PathTest, Exists_NonexistentFile)
|
||||
{
|
||||
EXPECT_FALSE(exists(m_test_dir + "/nonexistent_file.txt"));
|
||||
}
|
||||
|
||||
TEST_F(PathTest, Exists_ExistingDirectory) { EXPECT_TRUE(exists(m_test_dir)); }
|
||||
|
||||
TEST_F(PathTest, Exists_NonexistentDirectory)
|
||||
{
|
||||
EXPECT_FALSE(exists("/nonexistent/path/to/dir"));
|
||||
}
|
||||
|
||||
TEST_F(PathTest, Exists_SymbolicLink)
|
||||
{
|
||||
std::string target = create_file("target.txt");
|
||||
std::string link_path = create_symlink(target, "link_to_target");
|
||||
EXPECT_TRUE(exists(link_path));
|
||||
}
|
||||
|
||||
TEST_F(PathTest, Exists_BrokenSymlink)
|
||||
{
|
||||
std::string link_path = create_symlink("/nonexistent/target", "broken_link");
|
||||
EXPECT_TRUE(exists(link_path));
|
||||
}
|
||||
|
||||
TEST_F(PathTest, Exists_EmptyPath) { EXPECT_FALSE(exists("")); }
|
||||
|
||||
TEST_F(PathTest, IsLink_RegularFile)
|
||||
{
|
||||
std::string file_path = create_file("regular.txt");
|
||||
EXPECT_FALSE(is_link(file_path));
|
||||
}
|
||||
|
||||
TEST_F(PathTest, IsLink_Directory) { EXPECT_FALSE(is_link(m_test_dir)); }
|
||||
|
||||
TEST_F(PathTest, IsLink_SymbolicLink)
|
||||
{
|
||||
std::string target = create_file("target.txt");
|
||||
std::string link_path = create_symlink(target, "symbolic_link");
|
||||
EXPECT_TRUE(is_link(link_path));
|
||||
}
|
||||
|
||||
TEST_F(PathTest, IsLink_NonexistentPath) { EXPECT_FALSE(is_link("/nonexistent/path")); }
|
||||
|
||||
TEST_F(PathTest, Readlink_SymbolicLink)
|
||||
{
|
||||
std::string target = create_file("readlink_target.txt");
|
||||
std::string link_path = create_symlink(target, "readlink_link");
|
||||
EXPECT_EQ(readlink(link_path), target);
|
||||
}
|
||||
|
||||
TEST_F(PathTest, Readlink_NotALink)
|
||||
{
|
||||
std::string file_path = create_file("not_a_link.txt");
|
||||
EXPECT_EQ(readlink(file_path), file_path);
|
||||
}
|
||||
|
||||
TEST_F(PathTest, Readlink_NonexistentPath)
|
||||
{
|
||||
std::string path = "/nonexistent/path";
|
||||
EXPECT_EQ(readlink(path), path);
|
||||
}
|
||||
|
||||
TEST_F(PathTest, Realpath_RelativePath)
|
||||
{
|
||||
std::string file_path = create_file("realpath_test.txt");
|
||||
|
||||
char cwd[PATH_MAX];
|
||||
char* cwd_result = getcwd(cwd, PATH_MAX);
|
||||
ASSERT_NE(cwd_result, nullptr);
|
||||
|
||||
if(chdir(m_test_dir.c_str()) == 0)
|
||||
{
|
||||
std::string resolved = realpath("realpath_test.txt");
|
||||
EXPECT_EQ(resolved, file_path);
|
||||
ASSERT_EQ(chdir(cwd), 0);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(PathTest, Realpath_AbsolutePath)
|
||||
{
|
||||
std::string file_path = create_file("absolute_test.txt");
|
||||
std::string resolved = realpath(file_path);
|
||||
EXPECT_EQ(resolved, file_path);
|
||||
}
|
||||
|
||||
TEST_F(PathTest, Realpath_WithSymlink)
|
||||
{
|
||||
std::string target = create_file("realpath_target.txt");
|
||||
std::string link_path = create_symlink(target, "realpath_link");
|
||||
std::string resolved = realpath(link_path);
|
||||
EXPECT_EQ(resolved, target);
|
||||
}
|
||||
|
||||
TEST_F(PathTest, Realpath_NonexistentPath)
|
||||
{
|
||||
std::string nonexistent = "/nonexistent/path/to/file";
|
||||
std::string resolved = realpath(nonexistent);
|
||||
EXPECT_EQ(resolved, nonexistent);
|
||||
}
|
||||
|
||||
TEST_F(PathTest, Realpath_WithResolvedOutput)
|
||||
{
|
||||
std::string file_path = create_file("resolved_output_test.txt");
|
||||
std::string resolved_output;
|
||||
std::string result = realpath(file_path, &resolved_output);
|
||||
EXPECT_EQ(result, file_path);
|
||||
EXPECT_EQ(resolved_output, file_path);
|
||||
}
|
||||
|
||||
TEST_F(PathTest, IsTextFile_TextFile)
|
||||
{
|
||||
std::string text_content = "This is a text file\nwith multiple lines\n";
|
||||
std::string file_path = create_file("text_file.txt", text_content);
|
||||
EXPECT_TRUE(is_text_file(file_path));
|
||||
}
|
||||
|
||||
TEST_F(PathTest, IsTextFile_BinaryFile)
|
||||
{
|
||||
std::string file_path = m_test_dir + "/binary_file.bin";
|
||||
std::ofstream ofs(file_path, std::ios::binary);
|
||||
char binary_data[] = { 'H', 'e', 'l', 'l', 'o', '\0', 'W', 'o', 'r', 'l', 'd' };
|
||||
ofs.write(binary_data, sizeof(binary_data));
|
||||
ofs.close();
|
||||
EXPECT_FALSE(is_text_file(file_path));
|
||||
}
|
||||
|
||||
TEST_F(PathTest, IsTextFile_EmptyFile)
|
||||
{
|
||||
std::string file_path = create_file("empty_file.txt", "");
|
||||
EXPECT_TRUE(is_text_file(file_path));
|
||||
}
|
||||
|
||||
TEST_F(PathTest, PathType_Directory)
|
||||
{
|
||||
path_type pt(m_test_dir);
|
||||
EXPECT_TRUE(pt.exists());
|
||||
EXPECT_TRUE(static_cast<bool>(pt));
|
||||
}
|
||||
|
||||
TEST_F(PathTest, PathType_RegularFile)
|
||||
{
|
||||
std::string file_path = create_file("pathtype_file.txt");
|
||||
path_type pt(file_path);
|
||||
EXPECT_TRUE(pt.exists());
|
||||
}
|
||||
|
||||
TEST_F(PathTest, PathType_SymbolicLink)
|
||||
{
|
||||
std::string target = create_file("pathtype_target.txt");
|
||||
std::string link_path = create_symlink(target, "pathtype_link");
|
||||
path_type pt(link_path);
|
||||
EXPECT_TRUE(pt.exists());
|
||||
}
|
||||
|
||||
TEST_F(PathTest, PathType_Nonexistent)
|
||||
{
|
||||
path_type pt("/nonexistent/path");
|
||||
EXPECT_FALSE(pt.exists());
|
||||
EXPECT_FALSE(static_cast<bool>(pt));
|
||||
}
|
||||
|
||||
TEST_F(PathTest, GetRocprofsysRoot_ReturnsNonEmpty)
|
||||
{
|
||||
std::string root = get_rocprofsys_root();
|
||||
EXPECT_FALSE(root.empty());
|
||||
}
|
||||
|
||||
TEST_F(PathTest, GetRocprofsysRoot_EndsWithParentDir)
|
||||
{
|
||||
std::string root = get_rocprofsys_root();
|
||||
EXPECT_TRUE(root.length() >= 2);
|
||||
EXPECT_EQ(root.substr(root.length() - 2), "..");
|
||||
}
|
||||
|
||||
TEST_F(PathTest, GetInternalLibdir_ContainsLib)
|
||||
{
|
||||
std::string libdir = get_internal_libdir();
|
||||
EXPECT_NE(libdir.find("lib"), std::string::npos);
|
||||
}
|
||||
|
||||
TEST_F(PathTest, GetInternalScriptPath_ContainsLibexec)
|
||||
{
|
||||
std::string script_path = get_internal_script_path();
|
||||
EXPECT_NE(script_path.find("libexec"), std::string::npos);
|
||||
EXPECT_NE(script_path.find("rocprofiler-systems"), std::string::npos);
|
||||
}
|
||||
|
||||
TEST_F(PathTest, GetInternalLibpath_ContainsLibName)
|
||||
{
|
||||
std::string libpath = get_internal_libpath("librocprof-sys.so");
|
||||
EXPECT_NE(libpath.find("librocprof-sys.so"), std::string::npos);
|
||||
}
|
||||
|
||||
TEST_F(PathTest, GetInternalLibpath_ContainsLib)
|
||||
{
|
||||
std::string libpath = get_internal_libpath("test.so");
|
||||
EXPECT_NE(libpath.find("lib"), std::string::npos);
|
||||
}
|
||||
|
||||
TEST_F(PathTest, GetDefaultLibSearchPaths_ReturnsNonEmpty)
|
||||
{
|
||||
auto paths = get_default_lib_search_paths<std::string>();
|
||||
EXPECT_FALSE(paths.empty());
|
||||
}
|
||||
|
||||
TEST_F(PathTest, GetDefaultLibSearchPaths_AsVector)
|
||||
{
|
||||
auto paths = get_default_lib_search_paths<std::vector<std::string>>();
|
||||
EXPECT_FALSE(paths.empty());
|
||||
}
|
||||
|
||||
TEST_F(PathTest, FindPath_AbsoluteExisting)
|
||||
{
|
||||
std::string file_path = create_file("findpath_test.txt");
|
||||
std::string result = find_path(file_path, 0);
|
||||
EXPECT_EQ(result, file_path);
|
||||
}
|
||||
|
||||
TEST_F(PathTest, FindPath_NonexistentReturnsOriginal)
|
||||
{
|
||||
std::string nonexistent = "nonexistent_file_xyz.txt";
|
||||
std::string result = find_path(nonexistent, 0);
|
||||
EXPECT_EQ(result, nonexistent);
|
||||
}
|
||||
|
||||
TEST_F(PathTest, FindPath_InSearchPath)
|
||||
{
|
||||
std::string file_path = create_file("searchable.txt");
|
||||
std::string result = find_path("searchable.txt", 0, m_test_dir);
|
||||
EXPECT_EQ(result, file_path);
|
||||
}
|
||||
|
||||
TEST_F(PathTest, Dirname_ComplexPath)
|
||||
{
|
||||
EXPECT_EQ(dirname("/opt/rocm/lib/rocprofiler-systems/librocprof-sys.so"),
|
||||
"/opt/rocm/lib/rocprofiler-systems");
|
||||
}
|
||||
|
||||
TEST_F(PathTest, ChainedSymlinks)
|
||||
{
|
||||
std::string target = create_file("chain_target.txt");
|
||||
std::string link1 = create_symlink(target, "chain_link1");
|
||||
std::string link2_path = m_test_dir + "/chain_link2";
|
||||
symlink("chain_link1", link2_path.c_str());
|
||||
|
||||
EXPECT_TRUE(is_link(link1));
|
||||
EXPECT_TRUE(is_link(link2_path));
|
||||
|
||||
std::string resolved = realpath(link2_path);
|
||||
EXPECT_EQ(resolved, target);
|
||||
}
|
||||
|
||||
TEST_F(PathTest, Exists_SpecialCharactersInPath)
|
||||
{
|
||||
std::string file_path = create_file("file with spaces.txt");
|
||||
EXPECT_TRUE(exists(file_path));
|
||||
}
|
||||
|
||||
TEST_F(PathTest, Dirname_RocprofsysTypicalPath)
|
||||
{
|
||||
std::string path = "/opt/rocm-6.0.0/lib/rocprofiler-systems/librocprof-sys-dl.so";
|
||||
std::string result = dirname(path);
|
||||
EXPECT_EQ(result, "/opt/rocm-6.0.0/lib/rocprofiler-systems");
|
||||
}
|
||||
|
||||
TEST_F(PathTest, NestedDirectories)
|
||||
{
|
||||
std::string subdir1 = create_subdir("level1");
|
||||
std::string subdir2 = subdir1 + "/level2";
|
||||
mkdir(subdir2.c_str(), 0755);
|
||||
std::string subdir3 = subdir2 + "/level3";
|
||||
mkdir(subdir3.c_str(), 0755);
|
||||
|
||||
EXPECT_TRUE(exists(subdir1));
|
||||
EXPECT_TRUE(exists(subdir2));
|
||||
EXPECT_TRUE(exists(subdir3));
|
||||
|
||||
EXPECT_EQ(dirname(subdir3), subdir2);
|
||||
EXPECT_EQ(dirname(subdir2), subdir1);
|
||||
}
|
||||
@@ -0,0 +1,308 @@
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) 2022-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 "common/environment.hpp"
|
||||
|
||||
#include <cstring>
|
||||
#include <gtest/gtest.h>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
using namespace rocprofsys::common;
|
||||
|
||||
namespace
|
||||
{
|
||||
std::string
|
||||
find_env_var(const std::vector<char*>& env, std::string_view var_name)
|
||||
{
|
||||
std::string prefix = std::string(var_name) + "=";
|
||||
for(auto* itr : env)
|
||||
{
|
||||
if(!itr) continue;
|
||||
if(std::string_view{ itr }.find(prefix) == 0)
|
||||
{
|
||||
return std::string{ itr };
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
} // namespace
|
||||
|
||||
class RemoveEnvTest : public ::testing::Test
|
||||
{
|
||||
protected:
|
||||
void SetUp() override
|
||||
{
|
||||
m_env_vars.clear();
|
||||
m_original_envs.clear();
|
||||
}
|
||||
|
||||
void TearDown() override
|
||||
{
|
||||
for(auto* ptr : m_env_vars)
|
||||
{
|
||||
if(ptr) free(ptr);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<char*> m_env_vars;
|
||||
std::unordered_set<std::string> m_original_envs;
|
||||
};
|
||||
|
||||
TEST_F(RemoveEnvTest, RemoveSingleVariable)
|
||||
{
|
||||
m_env_vars.push_back(strdup("VAR1=value1"));
|
||||
m_env_vars.push_back(strdup("VAR2=value2"));
|
||||
m_env_vars.push_back(strdup("VAR3=value3"));
|
||||
|
||||
remove_env(m_env_vars, "VAR2", m_original_envs);
|
||||
|
||||
ASSERT_EQ(m_env_vars.size(), 2);
|
||||
EXPECT_STREQ(m_env_vars[0], "VAR1=value1");
|
||||
EXPECT_STREQ(m_env_vars[1], "VAR3=value3");
|
||||
}
|
||||
|
||||
TEST_F(RemoveEnvTest, RemoveFirstVariable)
|
||||
{
|
||||
m_env_vars.push_back(strdup("FIRST_VAR=first"));
|
||||
m_env_vars.push_back(strdup("SECOND_VAR=second"));
|
||||
|
||||
remove_env(m_env_vars, "FIRST_VAR", m_original_envs);
|
||||
|
||||
ASSERT_EQ(m_env_vars.size(), 1);
|
||||
EXPECT_STREQ(m_env_vars[0], "SECOND_VAR=second");
|
||||
}
|
||||
|
||||
TEST_F(RemoveEnvTest, RemoveLastVariable)
|
||||
{
|
||||
m_env_vars.push_back(strdup("FIRST_VAR=first"));
|
||||
m_env_vars.push_back(strdup("LAST_VAR=last"));
|
||||
|
||||
remove_env(m_env_vars, "LAST_VAR", m_original_envs);
|
||||
|
||||
ASSERT_EQ(m_env_vars.size(), 1);
|
||||
EXPECT_STREQ(m_env_vars[0], "FIRST_VAR=first");
|
||||
}
|
||||
|
||||
TEST_F(RemoveEnvTest, RemoveNonexistentVariable)
|
||||
{
|
||||
m_env_vars.push_back(strdup("EXISTING_VAR=value"));
|
||||
|
||||
remove_env(m_env_vars, "NONEXISTENT_VAR", m_original_envs);
|
||||
|
||||
ASSERT_EQ(m_env_vars.size(), 1);
|
||||
EXPECT_STREQ(m_env_vars[0], "EXISTING_VAR=value");
|
||||
}
|
||||
|
||||
TEST_F(RemoveEnvTest, RemoveFromEmptyVector)
|
||||
{
|
||||
remove_env(m_env_vars, "ANY_VAR", m_original_envs);
|
||||
|
||||
EXPECT_TRUE(m_env_vars.empty());
|
||||
}
|
||||
|
||||
TEST_F(RemoveEnvTest, RemoveOnlyVariable)
|
||||
{
|
||||
m_env_vars.push_back(strdup("ONLY_VAR=only_value"));
|
||||
|
||||
remove_env(m_env_vars, "ONLY_VAR", m_original_envs);
|
||||
|
||||
EXPECT_TRUE(m_env_vars.empty());
|
||||
}
|
||||
|
||||
TEST_F(RemoveEnvTest, RestoreFromOriginalEnvs)
|
||||
{
|
||||
m_original_envs.insert("RESTORE_VAR=original_value");
|
||||
|
||||
m_env_vars.push_back(strdup("RESTORE_VAR=modified_value"));
|
||||
m_env_vars.push_back(strdup("OTHER_VAR=other_value"));
|
||||
|
||||
remove_env(m_env_vars, "RESTORE_VAR", m_original_envs);
|
||||
|
||||
ASSERT_EQ(m_env_vars.size(), 2);
|
||||
EXPECT_STREQ(find_env_var(m_env_vars, "OTHER_VAR").c_str(), "OTHER_VAR=other_value");
|
||||
EXPECT_STREQ(find_env_var(m_env_vars, "RESTORE_VAR").c_str(),
|
||||
"RESTORE_VAR=original_value");
|
||||
}
|
||||
|
||||
TEST_F(RemoveEnvTest, RemoveVariableNotInOriginal_NoRestore)
|
||||
{
|
||||
m_env_vars.push_back(strdup("NEW_VAR=new_value"));
|
||||
|
||||
remove_env(m_env_vars, "NEW_VAR", m_original_envs);
|
||||
|
||||
EXPECT_TRUE(m_env_vars.empty());
|
||||
}
|
||||
|
||||
TEST_F(RemoveEnvTest, RemoveWithSimilarPrefixes)
|
||||
{
|
||||
m_env_vars.push_back(strdup("PATH=/usr/bin"));
|
||||
m_env_vars.push_back(strdup("PATH_EXTRA=/extra"));
|
||||
m_env_vars.push_back(strdup("MYPATH=/my"));
|
||||
|
||||
remove_env(m_env_vars, "PATH", m_original_envs);
|
||||
|
||||
ASSERT_EQ(m_env_vars.size(), 2);
|
||||
EXPECT_STREQ(m_env_vars[0], "PATH_EXTRA=/extra");
|
||||
EXPECT_STREQ(m_env_vars[1], "MYPATH=/my");
|
||||
}
|
||||
|
||||
TEST_F(RemoveEnvTest, RemoveWithNullEntries)
|
||||
{
|
||||
m_env_vars.push_back(strdup("VAR1=value1"));
|
||||
m_env_vars.push_back(nullptr);
|
||||
m_env_vars.push_back(strdup("VAR2=value2"));
|
||||
m_env_vars.push_back(nullptr);
|
||||
m_env_vars.push_back(strdup("VAR3=value3"));
|
||||
|
||||
remove_env(m_env_vars, "VAR2", m_original_envs);
|
||||
|
||||
ASSERT_EQ(m_env_vars.size(), 2);
|
||||
EXPECT_STREQ(m_env_vars[0], "VAR1=value1");
|
||||
EXPECT_STREQ(m_env_vars[1], "VAR3=value3");
|
||||
}
|
||||
|
||||
TEST_F(RemoveEnvTest, RemoveMultipleTimes)
|
||||
{
|
||||
m_env_vars.push_back(strdup("A=1"));
|
||||
m_env_vars.push_back(strdup("B=2"));
|
||||
m_env_vars.push_back(strdup("C=3"));
|
||||
m_env_vars.push_back(strdup("D=4"));
|
||||
|
||||
remove_env(m_env_vars, "B", m_original_envs);
|
||||
ASSERT_EQ(m_env_vars.size(), 3);
|
||||
|
||||
remove_env(m_env_vars, "D", m_original_envs);
|
||||
ASSERT_EQ(m_env_vars.size(), 2);
|
||||
|
||||
EXPECT_STREQ(m_env_vars[0], "A=1");
|
||||
EXPECT_STREQ(m_env_vars[1], "C=3");
|
||||
}
|
||||
|
||||
TEST_F(RemoveEnvTest, RealWorld_LD_PRELOAD)
|
||||
{
|
||||
m_env_vars.push_back(strdup("LD_LIBRARY_PATH=/usr/lib"));
|
||||
m_env_vars.push_back(strdup("LD_PRELOAD=/lib/inject.so"));
|
||||
m_env_vars.push_back(strdup("PATH=/usr/bin"));
|
||||
|
||||
remove_env(m_env_vars, "LD_PRELOAD", m_original_envs);
|
||||
|
||||
ASSERT_EQ(m_env_vars.size(), 2);
|
||||
EXPECT_FALSE(find_env_var(m_env_vars, "LD_PRELOAD").length() > 0);
|
||||
EXPECT_STREQ(find_env_var(m_env_vars, "LD_LIBRARY_PATH").c_str(),
|
||||
"LD_LIBRARY_PATH=/usr/lib");
|
||||
EXPECT_STREQ(find_env_var(m_env_vars, "PATH").c_str(), "PATH=/usr/bin");
|
||||
}
|
||||
|
||||
TEST_F(RemoveEnvTest, RealWorld_RestoreROCPROFSYS_Variable)
|
||||
{
|
||||
m_original_envs.insert("ROCPROFSYS_TRACE=false");
|
||||
|
||||
m_env_vars.push_back(strdup("ROCPROFSYS_TRACE=true"));
|
||||
m_env_vars.push_back(strdup("ROCPROFSYS_PROFILE=true"));
|
||||
|
||||
remove_env(m_env_vars, "ROCPROFSYS_TRACE", m_original_envs);
|
||||
|
||||
ASSERT_EQ(m_env_vars.size(), 2);
|
||||
EXPECT_STREQ(find_env_var(m_env_vars, "ROCPROFSYS_TRACE").c_str(),
|
||||
"ROCPROFSYS_TRACE=false");
|
||||
EXPECT_STREQ(find_env_var(m_env_vars, "ROCPROFSYS_PROFILE").c_str(),
|
||||
"ROCPROFSYS_PROFILE=true");
|
||||
}
|
||||
|
||||
TEST_F(RemoveEnvTest, EmptyVariableName)
|
||||
{
|
||||
m_env_vars.push_back(strdup("VAR=value"));
|
||||
|
||||
remove_env(m_env_vars, "", m_original_envs);
|
||||
|
||||
ASSERT_EQ(m_env_vars.size(), 1);
|
||||
EXPECT_STREQ(m_env_vars[0], "VAR=value");
|
||||
}
|
||||
|
||||
TEST_F(RemoveEnvTest, VariableWithEmptyValue)
|
||||
{
|
||||
m_env_vars.push_back(strdup("EMPTY_VALUE="));
|
||||
m_env_vars.push_back(strdup("NORMAL_VAR=value"));
|
||||
|
||||
remove_env(m_env_vars, "EMPTY_VALUE", m_original_envs);
|
||||
|
||||
ASSERT_EQ(m_env_vars.size(), 1);
|
||||
EXPECT_STREQ(m_env_vars[0], "NORMAL_VAR=value");
|
||||
}
|
||||
|
||||
TEST_F(RemoveEnvTest, VariableWithSpecialCharactersInValue)
|
||||
{
|
||||
m_env_vars.push_back(strdup("SPECIAL=a:b:c:/path/with spaces"));
|
||||
m_env_vars.push_back(strdup("OTHER=value"));
|
||||
|
||||
remove_env(m_env_vars, "SPECIAL", m_original_envs);
|
||||
|
||||
ASSERT_EQ(m_env_vars.size(), 1);
|
||||
EXPECT_STREQ(m_env_vars[0], "OTHER=value");
|
||||
}
|
||||
|
||||
TEST_F(RemoveEnvTest, LongVariableName)
|
||||
{
|
||||
std::string long_var_name = "VERY_LONG_ENVIRONMENT_VARIABLE_NAME_FOR_TESTING";
|
||||
std::string entry = long_var_name + "=some_value";
|
||||
m_env_vars.push_back(strdup(entry.c_str()));
|
||||
m_env_vars.push_back(strdup("SHORT=val"));
|
||||
|
||||
remove_env(m_env_vars, long_var_name, m_original_envs);
|
||||
|
||||
ASSERT_EQ(m_env_vars.size(), 1);
|
||||
EXPECT_STREQ(m_env_vars[0], "SHORT=val");
|
||||
}
|
||||
|
||||
TEST_F(RemoveEnvTest, RestoreMultipleOriginalValues)
|
||||
{
|
||||
m_original_envs.insert("VAR1=orig1");
|
||||
m_original_envs.insert("VAR2=orig2");
|
||||
m_original_envs.insert("VAR3=orig3");
|
||||
|
||||
m_env_vars.push_back(strdup("VAR1=modified1"));
|
||||
m_env_vars.push_back(strdup("VAR2=modified2"));
|
||||
m_env_vars.push_back(strdup("VAR3=modified3"));
|
||||
|
||||
remove_env(m_env_vars, "VAR2", m_original_envs);
|
||||
|
||||
ASSERT_EQ(m_env_vars.size(), 3);
|
||||
EXPECT_STREQ(find_env_var(m_env_vars, "VAR1").c_str(), "VAR1=modified1");
|
||||
EXPECT_STREQ(find_env_var(m_env_vars, "VAR2").c_str(), "VAR2=orig2");
|
||||
EXPECT_STREQ(find_env_var(m_env_vars, "VAR3").c_str(), "VAR3=modified3");
|
||||
}
|
||||
|
||||
TEST_F(RemoveEnvTest, CaseSensitiveRemoval)
|
||||
{
|
||||
m_env_vars.push_back(strdup("MyVar=value1"));
|
||||
m_env_vars.push_back(strdup("MYVAR=value2"));
|
||||
m_env_vars.push_back(strdup("myvar=value3"));
|
||||
|
||||
remove_env(m_env_vars, "MYVAR", m_original_envs);
|
||||
|
||||
ASSERT_EQ(m_env_vars.size(), 2);
|
||||
EXPECT_STREQ(m_env_vars[0], "MyVar=value1");
|
||||
EXPECT_STREQ(m_env_vars[1], "myvar=value3");
|
||||
}
|
||||
@@ -51,212 +51,212 @@ class UpdateEnvTest : public ::testing::Test
|
||||
protected:
|
||||
void SetUp() override
|
||||
{
|
||||
env_vars.clear();
|
||||
updated_envs.clear();
|
||||
original_envs.clear();
|
||||
m_env_vars.clear();
|
||||
m_updated_envs.clear();
|
||||
m_original_envs.clear();
|
||||
}
|
||||
|
||||
void TearDown() override
|
||||
{
|
||||
for(auto* ptr : env_vars)
|
||||
for(auto* ptr : m_env_vars)
|
||||
{
|
||||
if(ptr) free(ptr);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<char*> env_vars;
|
||||
std::unordered_set<std::string_view> updated_envs;
|
||||
std::unordered_set<std::string> original_envs;
|
||||
std::vector<char*> m_env_vars;
|
||||
std::unordered_set<std::string_view> m_updated_envs;
|
||||
std::unordered_set<std::string> m_original_envs;
|
||||
};
|
||||
|
||||
TEST_F(UpdateEnvTest, ReplaceMode_NewVariable)
|
||||
{
|
||||
update_env(env_vars, "TEST_VAR", "test_value", update_mode::REPLACE, ":",
|
||||
updated_envs, original_envs);
|
||||
update_env(m_env_vars, "TEST_VAR", "test_value", update_mode::REPLACE, ":",
|
||||
m_updated_envs, m_original_envs);
|
||||
|
||||
ASSERT_EQ(env_vars.size(), 1);
|
||||
EXPECT_STREQ(env_vars[0], "TEST_VAR=test_value");
|
||||
EXPECT_EQ(updated_envs.count("TEST_VAR"), 1);
|
||||
ASSERT_EQ(m_env_vars.size(), 1);
|
||||
EXPECT_STREQ(m_env_vars[0], "TEST_VAR=test_value");
|
||||
EXPECT_EQ(m_updated_envs.count("TEST_VAR"), 1);
|
||||
}
|
||||
|
||||
TEST_F(UpdateEnvTest, ReplaceMode_ExistingVariable)
|
||||
{
|
||||
env_vars.push_back(strdup("TEST_VAR=old_value"));
|
||||
original_envs.insert("TEST_VAR=old_value");
|
||||
m_env_vars.push_back(strdup("TEST_VAR=old_value"));
|
||||
m_original_envs.insert("TEST_VAR=old_value");
|
||||
|
||||
update_env(env_vars, "TEST_VAR", "new_value", update_mode::REPLACE, ":", updated_envs,
|
||||
original_envs);
|
||||
update_env(m_env_vars, "TEST_VAR", "new_value", update_mode::REPLACE, ":",
|
||||
m_updated_envs, m_original_envs);
|
||||
|
||||
ASSERT_EQ(env_vars.size(), 1);
|
||||
EXPECT_STREQ(env_vars[0], "TEST_VAR=new_value");
|
||||
EXPECT_EQ(updated_envs.count("TEST_VAR"), 1);
|
||||
ASSERT_EQ(m_env_vars.size(), 1);
|
||||
EXPECT_STREQ(m_env_vars[0], "TEST_VAR=new_value");
|
||||
EXPECT_EQ(m_updated_envs.count("TEST_VAR"), 1);
|
||||
}
|
||||
|
||||
TEST_F(UpdateEnvTest, AppendMode_NewVariable)
|
||||
{
|
||||
update_env(env_vars, "PATH", "/new/path", update_mode::APPEND, ":", updated_envs,
|
||||
original_envs);
|
||||
update_env(m_env_vars, "PATH", "/new/path", update_mode::APPEND, ":", m_updated_envs,
|
||||
m_original_envs);
|
||||
|
||||
ASSERT_EQ(env_vars.size(), 1);
|
||||
EXPECT_STREQ(env_vars[0], "PATH=/new/path");
|
||||
ASSERT_EQ(m_env_vars.size(), 1);
|
||||
EXPECT_STREQ(m_env_vars[0], "PATH=/new/path");
|
||||
}
|
||||
|
||||
TEST_F(UpdateEnvTest, AppendMode_ExistingVariable)
|
||||
{
|
||||
env_vars.push_back(strdup("PATH=/old/path"));
|
||||
original_envs.insert("PATH=/old/path");
|
||||
m_env_vars.push_back(strdup("PATH=/old/path"));
|
||||
m_original_envs.insert("PATH=/old/path");
|
||||
|
||||
update_env(env_vars, "PATH", "/new/path", update_mode::APPEND, ":", updated_envs,
|
||||
original_envs);
|
||||
update_env(m_env_vars, "PATH", "/new/path", update_mode::APPEND, ":", m_updated_envs,
|
||||
m_original_envs);
|
||||
|
||||
ASSERT_EQ(env_vars.size(), 1);
|
||||
EXPECT_STREQ(env_vars[0], "PATH=/old/path:/new/path");
|
||||
EXPECT_EQ(updated_envs.count("PATH"), 1);
|
||||
ASSERT_EQ(m_env_vars.size(), 1);
|
||||
EXPECT_STREQ(m_env_vars[0], "PATH=/old/path:/new/path");
|
||||
EXPECT_EQ(m_updated_envs.count("PATH"), 1);
|
||||
}
|
||||
|
||||
TEST_F(UpdateEnvTest, PrependMode_ExistingVariable)
|
||||
{
|
||||
env_vars.push_back(strdup("LD_LIBRARY_PATH=/old/lib"));
|
||||
original_envs.insert("LD_LIBRARY_PATH=/old/lib");
|
||||
m_env_vars.push_back(strdup("LD_LIBRARY_PATH=/old/lib"));
|
||||
m_original_envs.insert("LD_LIBRARY_PATH=/old/lib");
|
||||
|
||||
update_env(env_vars, "LD_LIBRARY_PATH", "/new/lib", update_mode::PREPEND, ":",
|
||||
updated_envs, original_envs);
|
||||
update_env(m_env_vars, "LD_LIBRARY_PATH", "/new/lib", update_mode::PREPEND, ":",
|
||||
m_updated_envs, m_original_envs);
|
||||
|
||||
ASSERT_EQ(env_vars.size(), 1);
|
||||
EXPECT_STREQ(env_vars[0], "LD_LIBRARY_PATH=/new/lib:/old/lib");
|
||||
ASSERT_EQ(m_env_vars.size(), 1);
|
||||
EXPECT_STREQ(m_env_vars[0], "LD_LIBRARY_PATH=/new/lib:/old/lib");
|
||||
}
|
||||
|
||||
TEST_F(UpdateEnvTest, WeakMode_OriginalValue)
|
||||
{
|
||||
env_vars.push_back(strdup("WEAK_VAR=original"));
|
||||
original_envs.insert("WEAK_VAR=original");
|
||||
m_env_vars.push_back(strdup("WEAK_VAR=original"));
|
||||
m_original_envs.insert("WEAK_VAR=original");
|
||||
|
||||
update_env(env_vars, "WEAK_VAR", "new_value", update_mode::WEAK, ":", updated_envs,
|
||||
original_envs);
|
||||
update_env(m_env_vars, "WEAK_VAR", "new_value", update_mode::WEAK, ":",
|
||||
m_updated_envs, m_original_envs);
|
||||
|
||||
ASSERT_EQ(env_vars.size(), 1);
|
||||
EXPECT_STREQ(env_vars[0], "WEAK_VAR=new_value");
|
||||
ASSERT_EQ(m_env_vars.size(), 1);
|
||||
EXPECT_STREQ(m_env_vars[0], "WEAK_VAR=new_value");
|
||||
}
|
||||
|
||||
TEST_F(UpdateEnvTest, WeakMode_ModifiedValue)
|
||||
{
|
||||
env_vars.push_back(strdup("WEAK_VAR=original"));
|
||||
original_envs.insert("WEAK_VAR=original");
|
||||
m_env_vars.push_back(strdup("WEAK_VAR=original"));
|
||||
m_original_envs.insert("WEAK_VAR=original");
|
||||
|
||||
free(env_vars[0]);
|
||||
env_vars[0] = strdup("WEAK_VAR=modified");
|
||||
free(m_env_vars[0]);
|
||||
m_env_vars[0] = strdup("WEAK_VAR=modified");
|
||||
|
||||
update_env(env_vars, "WEAK_VAR", "new_value", update_mode::WEAK, ":", updated_envs,
|
||||
original_envs);
|
||||
update_env(m_env_vars, "WEAK_VAR", "new_value", update_mode::WEAK, ":",
|
||||
m_updated_envs, m_original_envs);
|
||||
|
||||
ASSERT_EQ(env_vars.size(), 1);
|
||||
EXPECT_STREQ(env_vars[0], "WEAK_VAR=modified");
|
||||
ASSERT_EQ(m_env_vars.size(), 1);
|
||||
EXPECT_STREQ(m_env_vars[0], "WEAK_VAR=modified");
|
||||
}
|
||||
|
||||
TEST_F(UpdateEnvTest, BooleanValue_True)
|
||||
{
|
||||
update_env(env_vars, "BOOL_VAR", true, update_mode::REPLACE, ":", updated_envs,
|
||||
original_envs);
|
||||
update_env(m_env_vars, "BOOL_VAR", true, update_mode::REPLACE, ":", m_updated_envs,
|
||||
m_original_envs);
|
||||
|
||||
ASSERT_EQ(env_vars.size(), 1);
|
||||
EXPECT_STREQ(env_vars[0], "BOOL_VAR=true");
|
||||
ASSERT_EQ(m_env_vars.size(), 1);
|
||||
EXPECT_STREQ(m_env_vars[0], "BOOL_VAR=true");
|
||||
}
|
||||
|
||||
TEST_F(UpdateEnvTest, BooleanValue_False)
|
||||
{
|
||||
update_env(env_vars, "BOOL_VAR", false, update_mode::REPLACE, ":", updated_envs,
|
||||
original_envs);
|
||||
update_env(m_env_vars, "BOOL_VAR", false, update_mode::REPLACE, ":", m_updated_envs,
|
||||
m_original_envs);
|
||||
|
||||
ASSERT_EQ(env_vars.size(), 1);
|
||||
EXPECT_STREQ(env_vars[0], "BOOL_VAR=false");
|
||||
ASSERT_EQ(m_env_vars.size(), 1);
|
||||
EXPECT_STREQ(m_env_vars[0], "BOOL_VAR=false");
|
||||
}
|
||||
|
||||
TEST_F(UpdateEnvTest, NumericValue)
|
||||
{
|
||||
update_env(env_vars, "NUM_VAR", 42, update_mode::REPLACE, ":", updated_envs,
|
||||
original_envs);
|
||||
update_env(m_env_vars, "NUM_VAR", 42, update_mode::REPLACE, ":", m_updated_envs,
|
||||
m_original_envs);
|
||||
|
||||
ASSERT_EQ(env_vars.size(), 1);
|
||||
EXPECT_STREQ(env_vars[0], "NUM_VAR=42");
|
||||
ASSERT_EQ(m_env_vars.size(), 1);
|
||||
EXPECT_STREQ(m_env_vars[0], "NUM_VAR=42");
|
||||
}
|
||||
|
||||
TEST_F(UpdateEnvTest, AppendMode_AvoidsDuplicates)
|
||||
{
|
||||
env_vars.push_back(strdup("PATH=/existing/path"));
|
||||
original_envs.insert("PATH=/existing/path");
|
||||
m_env_vars.push_back(strdup("PATH=/existing/path"));
|
||||
m_original_envs.insert("PATH=/existing/path");
|
||||
|
||||
update_env(env_vars, "PATH", "/existing/path", update_mode::APPEND, ":", updated_envs,
|
||||
original_envs);
|
||||
update_env(m_env_vars, "PATH", "/existing/path", update_mode::APPEND, ":",
|
||||
m_updated_envs, m_original_envs);
|
||||
|
||||
ASSERT_EQ(env_vars.size(), 1);
|
||||
EXPECT_STREQ(env_vars[0], "PATH=/existing/path");
|
||||
ASSERT_EQ(m_env_vars.size(), 1);
|
||||
EXPECT_STREQ(m_env_vars[0], "PATH=/existing/path");
|
||||
}
|
||||
|
||||
TEST_F(UpdateEnvTest, CustomDelimiter)
|
||||
{
|
||||
env_vars.push_back(strdup("VAR=a"));
|
||||
original_envs.insert("VAR=a");
|
||||
m_env_vars.push_back(strdup("VAR=a"));
|
||||
m_original_envs.insert("VAR=a");
|
||||
|
||||
update_env(env_vars, "VAR", "b", update_mode::APPEND, ",", updated_envs,
|
||||
original_envs);
|
||||
update_env(m_env_vars, "VAR", "b", update_mode::APPEND, ",", m_updated_envs,
|
||||
m_original_envs);
|
||||
|
||||
ASSERT_EQ(env_vars.size(), 1);
|
||||
EXPECT_STREQ(env_vars[0], "VAR=a,b");
|
||||
ASSERT_EQ(m_env_vars.size(), 1);
|
||||
EXPECT_STREQ(m_env_vars[0], "VAR=a,b");
|
||||
}
|
||||
|
||||
TEST_F(UpdateEnvTest, RealWorld_LD_LIBRARY_PATH_Append)
|
||||
{
|
||||
env_vars.push_back(strdup("LD_LIBRARY_PATH=/usr/lib:/usr/local/lib"));
|
||||
original_envs.insert("LD_LIBRARY_PATH=/usr/lib:/usr/local/lib");
|
||||
m_env_vars.push_back(strdup("LD_LIBRARY_PATH=/usr/lib:/usr/local/lib"));
|
||||
m_original_envs.insert("LD_LIBRARY_PATH=/usr/lib:/usr/local/lib");
|
||||
|
||||
update_env(env_vars, "LD_LIBRARY_PATH", "/opt/rocm/lib", update_mode::APPEND, ":",
|
||||
updated_envs, original_envs);
|
||||
update_env(m_env_vars, "LD_LIBRARY_PATH", "/opt/rocm/lib", update_mode::APPEND, ":",
|
||||
m_updated_envs, m_original_envs);
|
||||
|
||||
ASSERT_EQ(env_vars.size(), 1);
|
||||
EXPECT_STREQ(env_vars[0], "LD_LIBRARY_PATH=/usr/lib:/usr/local/lib:/opt/rocm/lib");
|
||||
ASSERT_EQ(m_env_vars.size(), 1);
|
||||
EXPECT_STREQ(m_env_vars[0], "LD_LIBRARY_PATH=/usr/lib:/usr/local/lib:/opt/rocm/lib");
|
||||
}
|
||||
|
||||
TEST_F(UpdateEnvTest, RealWorld_LD_PRELOAD_Prepend)
|
||||
{
|
||||
env_vars.push_back(strdup("LD_PRELOAD=/lib/existing.so"));
|
||||
original_envs.insert("LD_PRELOAD=/lib/existing.so");
|
||||
m_env_vars.push_back(strdup("LD_PRELOAD=/lib/existing.so"));
|
||||
m_original_envs.insert("LD_PRELOAD=/lib/existing.so");
|
||||
|
||||
update_env(env_vars, "LD_PRELOAD", "/opt/rocm/librocprof-sys-dl.so",
|
||||
update_mode::PREPEND, ":", updated_envs, original_envs);
|
||||
update_env(m_env_vars, "LD_PRELOAD", "/opt/rocm/librocprof-sys-dl.so",
|
||||
update_mode::PREPEND, ":", m_updated_envs, m_original_envs);
|
||||
|
||||
ASSERT_EQ(env_vars.size(), 1);
|
||||
EXPECT_STREQ(env_vars[0],
|
||||
ASSERT_EQ(m_env_vars.size(), 1);
|
||||
EXPECT_STREQ(m_env_vars[0],
|
||||
"LD_PRELOAD=/opt/rocm/librocprof-sys-dl.so:/lib/existing.so");
|
||||
}
|
||||
|
||||
TEST_F(UpdateEnvTest, RealWorld_ROCPROFSYS_Environment_Variables)
|
||||
{
|
||||
update_env(env_vars, "ROCPROFSYS_TRACE", true, update_mode::REPLACE, ":",
|
||||
updated_envs, original_envs);
|
||||
update_env(env_vars, "ROCPROFSYS_PROFILE", false, update_mode::REPLACE, ":",
|
||||
updated_envs, original_envs);
|
||||
update_env(env_vars, "ROCPROFSYS_USE_SAMPLING", true, update_mode::REPLACE, ":",
|
||||
updated_envs, original_envs);
|
||||
update_env(m_env_vars, "ROCPROFSYS_TRACE", true, update_mode::REPLACE, ":",
|
||||
m_updated_envs, m_original_envs);
|
||||
update_env(m_env_vars, "ROCPROFSYS_PROFILE", false, update_mode::REPLACE, ":",
|
||||
m_updated_envs, m_original_envs);
|
||||
update_env(m_env_vars, "ROCPROFSYS_USE_SAMPLING", true, update_mode::REPLACE, ":",
|
||||
m_updated_envs, m_original_envs);
|
||||
|
||||
ASSERT_EQ(env_vars.size(), 3);
|
||||
EXPECT_STREQ(find_env_var(env_vars, "ROCPROFSYS_TRACE").c_str(),
|
||||
ASSERT_EQ(m_env_vars.size(), 3);
|
||||
EXPECT_STREQ(find_env_var(m_env_vars, "ROCPROFSYS_TRACE").c_str(),
|
||||
"ROCPROFSYS_TRACE=true");
|
||||
EXPECT_STREQ(find_env_var(env_vars, "ROCPROFSYS_PROFILE").c_str(),
|
||||
EXPECT_STREQ(find_env_var(m_env_vars, "ROCPROFSYS_PROFILE").c_str(),
|
||||
"ROCPROFSYS_PROFILE=false");
|
||||
EXPECT_STREQ(find_env_var(env_vars, "ROCPROFSYS_USE_SAMPLING").c_str(),
|
||||
EXPECT_STREQ(find_env_var(m_env_vars, "ROCPROFSYS_USE_SAMPLING").c_str(),
|
||||
"ROCPROFSYS_USE_SAMPLING=true");
|
||||
}
|
||||
|
||||
TEST_F(UpdateEnvTest, RealWorld_Timing_DoubleValues)
|
||||
{
|
||||
update_env(env_vars, "ROCPROFSYS_TRACE_DELAY", 1.5, update_mode::REPLACE, ":",
|
||||
updated_envs, original_envs);
|
||||
update_env(env_vars, "ROCPROFSYS_SAMPLING_FREQ", 100.0, update_mode::REPLACE, ":",
|
||||
updated_envs, original_envs);
|
||||
update_env(m_env_vars, "ROCPROFSYS_TRACE_DELAY", 1.5, update_mode::REPLACE, ":",
|
||||
m_updated_envs, m_original_envs);
|
||||
update_env(m_env_vars, "ROCPROFSYS_SAMPLING_FREQ", 100.0, update_mode::REPLACE, ":",
|
||||
m_updated_envs, m_original_envs);
|
||||
|
||||
ASSERT_EQ(env_vars.size(), 2);
|
||||
std::string delay_var = find_env_var(env_vars, "ROCPROFSYS_TRACE_DELAY");
|
||||
std::string freq_var = find_env_var(env_vars, "ROCPROFSYS_SAMPLING_FREQ");
|
||||
ASSERT_EQ(m_env_vars.size(), 2);
|
||||
std::string delay_var = find_env_var(m_env_vars, "ROCPROFSYS_TRACE_DELAY");
|
||||
std::string freq_var = find_env_var(m_env_vars, "ROCPROFSYS_SAMPLING_FREQ");
|
||||
|
||||
EXPECT_TRUE(delay_var.find("ROCPROFSYS_TRACE_DELAY=") == 0);
|
||||
EXPECT_TRUE(freq_var.find("ROCPROFSYS_SAMPLING_FREQ=") == 0);
|
||||
@@ -265,156 +265,156 @@ TEST_F(UpdateEnvTest, RealWorld_Timing_DoubleValues)
|
||||
TEST_F(UpdateEnvTest, StringTypes_StdString)
|
||||
{
|
||||
std::string value = "test_string_value";
|
||||
update_env(env_vars, "STRING_VAR", value, update_mode::REPLACE, ":", updated_envs,
|
||||
original_envs);
|
||||
update_env(m_env_vars, "STRING_VAR", value, update_mode::REPLACE, ":", m_updated_envs,
|
||||
m_original_envs);
|
||||
|
||||
ASSERT_EQ(env_vars.size(), 1);
|
||||
EXPECT_STREQ(env_vars[0], "STRING_VAR=test_string_value");
|
||||
ASSERT_EQ(m_env_vars.size(), 1);
|
||||
EXPECT_STREQ(m_env_vars[0], "STRING_VAR=test_string_value");
|
||||
}
|
||||
|
||||
TEST_F(UpdateEnvTest, StringTypes_ConstCharPtr)
|
||||
{
|
||||
const char* value = "const_char_value";
|
||||
update_env(env_vars, "CHAR_VAR", value, update_mode::REPLACE, ":", updated_envs,
|
||||
original_envs);
|
||||
update_env(m_env_vars, "CHAR_VAR", value, update_mode::REPLACE, ":", m_updated_envs,
|
||||
m_original_envs);
|
||||
|
||||
ASSERT_EQ(env_vars.size(), 1);
|
||||
EXPECT_STREQ(env_vars[0], "CHAR_VAR=const_char_value");
|
||||
ASSERT_EQ(m_env_vars.size(), 1);
|
||||
EXPECT_STREQ(m_env_vars[0], "CHAR_VAR=const_char_value");
|
||||
}
|
||||
|
||||
TEST_F(UpdateEnvTest, EmptyStringValue)
|
||||
{
|
||||
update_env(env_vars, "EMPTY_VAR", "", update_mode::REPLACE, ":", updated_envs,
|
||||
original_envs);
|
||||
update_env(m_env_vars, "EMPTY_VAR", "", update_mode::REPLACE, ":", m_updated_envs,
|
||||
m_original_envs);
|
||||
|
||||
ASSERT_EQ(env_vars.size(), 1);
|
||||
EXPECT_STREQ(env_vars[0], "EMPTY_VAR=");
|
||||
ASSERT_EQ(m_env_vars.size(), 1);
|
||||
EXPECT_STREQ(m_env_vars[0], "EMPTY_VAR=");
|
||||
}
|
||||
|
||||
TEST_F(UpdateEnvTest, MultipleVariables_DifferentNames)
|
||||
{
|
||||
update_env(env_vars, "VAR1", "value1", update_mode::REPLACE, ":", updated_envs,
|
||||
original_envs);
|
||||
update_env(env_vars, "VAR2", "value2", update_mode::REPLACE, ":", updated_envs,
|
||||
original_envs);
|
||||
update_env(env_vars, "VAR3", "value3", update_mode::REPLACE, ":", updated_envs,
|
||||
original_envs);
|
||||
update_env(m_env_vars, "VAR1", "value1", update_mode::REPLACE, ":", m_updated_envs,
|
||||
m_original_envs);
|
||||
update_env(m_env_vars, "VAR2", "value2", update_mode::REPLACE, ":", m_updated_envs,
|
||||
m_original_envs);
|
||||
update_env(m_env_vars, "VAR3", "value3", update_mode::REPLACE, ":", m_updated_envs,
|
||||
m_original_envs);
|
||||
|
||||
ASSERT_EQ(env_vars.size(), 3);
|
||||
EXPECT_EQ(updated_envs.size(), 3);
|
||||
EXPECT_STREQ(find_env_var(env_vars, "VAR1").c_str(), "VAR1=value1");
|
||||
EXPECT_STREQ(find_env_var(env_vars, "VAR2").c_str(), "VAR2=value2");
|
||||
EXPECT_STREQ(find_env_var(env_vars, "VAR3").c_str(), "VAR3=value3");
|
||||
ASSERT_EQ(m_env_vars.size(), 3);
|
||||
EXPECT_EQ(m_updated_envs.size(), 3);
|
||||
EXPECT_STREQ(find_env_var(m_env_vars, "VAR1").c_str(), "VAR1=value1");
|
||||
EXPECT_STREQ(find_env_var(m_env_vars, "VAR2").c_str(), "VAR2=value2");
|
||||
EXPECT_STREQ(find_env_var(m_env_vars, "VAR3").c_str(), "VAR3=value3");
|
||||
}
|
||||
|
||||
TEST_F(UpdateEnvTest, NullPointer_InEnvironmentVector)
|
||||
{
|
||||
env_vars.push_back(strdup("VAR1=value1"));
|
||||
env_vars.push_back(nullptr);
|
||||
env_vars.push_back(strdup("VAR2=value2"));
|
||||
original_envs.insert("VAR1=value1");
|
||||
original_envs.insert("VAR2=value2");
|
||||
m_env_vars.push_back(strdup("VAR1=value1"));
|
||||
m_env_vars.push_back(nullptr);
|
||||
m_env_vars.push_back(strdup("VAR2=value2"));
|
||||
m_original_envs.insert("VAR1=value1");
|
||||
m_original_envs.insert("VAR2=value2");
|
||||
|
||||
update_env(env_vars, "VAR2", "new_value2", update_mode::REPLACE, ":", updated_envs,
|
||||
original_envs);
|
||||
update_env(m_env_vars, "VAR2", "new_value2", update_mode::REPLACE, ":",
|
||||
m_updated_envs, m_original_envs);
|
||||
|
||||
EXPECT_STREQ(find_env_var(env_vars, "VAR2").c_str(), "VAR2=new_value2");
|
||||
EXPECT_STREQ(find_env_var(m_env_vars, "VAR2").c_str(), "VAR2=new_value2");
|
||||
}
|
||||
|
||||
TEST_F(UpdateEnvTest, LongPath_Append)
|
||||
{
|
||||
std::string long_path = "/very/long/path/to/some/directory/with/many/subdirectories/"
|
||||
"that/might/be/used/in/real/world";
|
||||
env_vars.push_back(strdup("PATH=/usr/bin:/bin"));
|
||||
original_envs.insert("PATH=/usr/bin:/bin");
|
||||
m_env_vars.push_back(strdup("PATH=/usr/bin:/bin"));
|
||||
m_original_envs.insert("PATH=/usr/bin:/bin");
|
||||
|
||||
update_env(env_vars, "PATH", long_path, update_mode::APPEND, ":", updated_envs,
|
||||
original_envs);
|
||||
update_env(m_env_vars, "PATH", long_path, update_mode::APPEND, ":", m_updated_envs,
|
||||
m_original_envs);
|
||||
|
||||
std::string expected = "PATH=/usr/bin:/bin:" + long_path;
|
||||
EXPECT_STREQ(env_vars[0], expected.c_str());
|
||||
EXPECT_STREQ(m_env_vars[0], expected.c_str());
|
||||
}
|
||||
|
||||
TEST_F(UpdateEnvTest, SpecialCharacters_InValue)
|
||||
{
|
||||
update_env(env_vars, "SPECIAL_VAR", "value-with_special.chars:123",
|
||||
update_mode::REPLACE, ":", updated_envs, original_envs);
|
||||
update_env(m_env_vars, "SPECIAL_VAR", "value-with_special.chars:123",
|
||||
update_mode::REPLACE, ":", m_updated_envs, m_original_envs);
|
||||
|
||||
ASSERT_EQ(env_vars.size(), 1);
|
||||
EXPECT_STREQ(env_vars[0], "SPECIAL_VAR=value-with_special.chars:123");
|
||||
ASSERT_EQ(m_env_vars.size(), 1);
|
||||
EXPECT_STREQ(m_env_vars[0], "SPECIAL_VAR=value-with_special.chars:123");
|
||||
}
|
||||
|
||||
TEST_F(UpdateEnvTest, IntegerValues_Positive)
|
||||
{
|
||||
update_env(env_vars, "INT_VAR", 12345, update_mode::REPLACE, ":", updated_envs,
|
||||
original_envs);
|
||||
update_env(m_env_vars, "INT_VAR", 12345, update_mode::REPLACE, ":", m_updated_envs,
|
||||
m_original_envs);
|
||||
|
||||
ASSERT_EQ(env_vars.size(), 1);
|
||||
EXPECT_STREQ(env_vars[0], "INT_VAR=12345");
|
||||
ASSERT_EQ(m_env_vars.size(), 1);
|
||||
EXPECT_STREQ(m_env_vars[0], "INT_VAR=12345");
|
||||
}
|
||||
|
||||
TEST_F(UpdateEnvTest, IntegerValues_Negative)
|
||||
{
|
||||
update_env(env_vars, "NEGATIVE_VAR", -999, update_mode::REPLACE, ":", updated_envs,
|
||||
original_envs);
|
||||
update_env(m_env_vars, "NEGATIVE_VAR", -999, update_mode::REPLACE, ":",
|
||||
m_updated_envs, m_original_envs);
|
||||
|
||||
ASSERT_EQ(env_vars.size(), 1);
|
||||
EXPECT_STREQ(env_vars[0], "NEGATIVE_VAR=-999");
|
||||
ASSERT_EQ(m_env_vars.size(), 1);
|
||||
EXPECT_STREQ(m_env_vars[0], "NEGATIVE_VAR=-999");
|
||||
}
|
||||
|
||||
TEST_F(UpdateEnvTest, IntegerValues_Zero)
|
||||
{
|
||||
update_env(env_vars, "ZERO_VAR", 0, update_mode::REPLACE, ":", updated_envs,
|
||||
original_envs);
|
||||
update_env(m_env_vars, "ZERO_VAR", 0, update_mode::REPLACE, ":", m_updated_envs,
|
||||
m_original_envs);
|
||||
|
||||
ASSERT_EQ(env_vars.size(), 1);
|
||||
EXPECT_STREQ(env_vars[0], "ZERO_VAR=0");
|
||||
ASSERT_EQ(m_env_vars.size(), 1);
|
||||
EXPECT_STREQ(m_env_vars[0], "ZERO_VAR=0");
|
||||
}
|
||||
|
||||
TEST_F(UpdateEnvTest, UpdateTracking_MultipleUpdates)
|
||||
{
|
||||
update_env(env_vars, "VAR1", "val1", update_mode::REPLACE, ":", updated_envs,
|
||||
original_envs);
|
||||
update_env(env_vars, "VAR2", "val2", update_mode::REPLACE, ":", updated_envs,
|
||||
original_envs);
|
||||
update_env(env_vars, "VAR1", "val1_updated", update_mode::REPLACE, ":", updated_envs,
|
||||
original_envs);
|
||||
update_env(m_env_vars, "VAR1", "val1", update_mode::REPLACE, ":", m_updated_envs,
|
||||
m_original_envs);
|
||||
update_env(m_env_vars, "VAR2", "val2", update_mode::REPLACE, ":", m_updated_envs,
|
||||
m_original_envs);
|
||||
update_env(m_env_vars, "VAR1", "val1_updated", update_mode::REPLACE, ":",
|
||||
m_updated_envs, m_original_envs);
|
||||
|
||||
EXPECT_EQ(updated_envs.count("VAR1"), 1);
|
||||
EXPECT_EQ(updated_envs.count("VAR2"), 1);
|
||||
EXPECT_EQ(updated_envs.size(), 2);
|
||||
EXPECT_EQ(m_updated_envs.count("VAR1"), 1);
|
||||
EXPECT_EQ(m_updated_envs.count("VAR2"), 1);
|
||||
EXPECT_EQ(m_updated_envs.size(), 2);
|
||||
}
|
||||
|
||||
TEST_F(UpdateEnvTest, WeakMode_SequentialUpdates)
|
||||
{
|
||||
env_vars.push_back(strdup("CONFIG_VAR=initial"));
|
||||
original_envs.insert("CONFIG_VAR=initial");
|
||||
m_env_vars.push_back(strdup("CONFIG_VAR=initial"));
|
||||
m_original_envs.insert("CONFIG_VAR=initial");
|
||||
|
||||
update_env(env_vars, "CONFIG_VAR", "weak_update", update_mode::WEAK, ":",
|
||||
updated_envs, original_envs);
|
||||
update_env(m_env_vars, "CONFIG_VAR", "weak_update", update_mode::WEAK, ":",
|
||||
m_updated_envs, m_original_envs);
|
||||
|
||||
EXPECT_STREQ(env_vars[0], "CONFIG_VAR=weak_update");
|
||||
EXPECT_STREQ(m_env_vars[0], "CONFIG_VAR=weak_update");
|
||||
|
||||
free(env_vars[0]);
|
||||
env_vars[0] = strdup("CONFIG_VAR=user_modified");
|
||||
free(m_env_vars[0]);
|
||||
m_env_vars[0] = strdup("CONFIG_VAR=user_modified");
|
||||
|
||||
update_env(env_vars, "CONFIG_VAR", "another_weak_update", update_mode::WEAK, ":",
|
||||
updated_envs, original_envs);
|
||||
update_env(m_env_vars, "CONFIG_VAR", "another_weak_update", update_mode::WEAK, ":",
|
||||
m_updated_envs, m_original_envs);
|
||||
|
||||
EXPECT_STREQ(env_vars[0], "CONFIG_VAR=user_modified");
|
||||
EXPECT_STREQ(m_env_vars[0], "CONFIG_VAR=user_modified");
|
||||
}
|
||||
|
||||
TEST_F(UpdateEnvTest, Append_MultiplePathsInSequence)
|
||||
{
|
||||
update_env(env_vars, "BUILD_PATH", "/path1", update_mode::REPLACE, ":", updated_envs,
|
||||
original_envs);
|
||||
update_env(env_vars, "BUILD_PATH", "/path2", update_mode::APPEND, ":", updated_envs,
|
||||
original_envs);
|
||||
update_env(env_vars, "BUILD_PATH", "/path3", update_mode::APPEND, ":", updated_envs,
|
||||
original_envs);
|
||||
update_env(env_vars, "BUILD_PATH", "/path4", update_mode::APPEND, ":", updated_envs,
|
||||
original_envs);
|
||||
update_env(m_env_vars, "BUILD_PATH", "/path1", update_mode::REPLACE, ":",
|
||||
m_updated_envs, m_original_envs);
|
||||
update_env(m_env_vars, "BUILD_PATH", "/path2", update_mode::APPEND, ":",
|
||||
m_updated_envs, m_original_envs);
|
||||
update_env(m_env_vars, "BUILD_PATH", "/path3", update_mode::APPEND, ":",
|
||||
m_updated_envs, m_original_envs);
|
||||
update_env(m_env_vars, "BUILD_PATH", "/path4", update_mode::APPEND, ":",
|
||||
m_updated_envs, m_original_envs);
|
||||
|
||||
ASSERT_EQ(env_vars.size(), 1);
|
||||
EXPECT_STREQ(env_vars[0], "BUILD_PATH=/path1:/path2:/path3:/path4");
|
||||
ASSERT_EQ(m_env_vars.size(), 1);
|
||||
EXPECT_STREQ(m_env_vars[0], "BUILD_PATH=/path1:/path2:/path3:/path4");
|
||||
}
|
||||
Reference in New Issue
Block a user