From 144d7018e7caf8e8f52e515ab2e85cf656f5e26e Mon Sep 17 00:00:00 2001 From: "Jonathan R. Madsen" Date: Wed, 30 Aug 2023 22:31:36 -0500 Subject: [PATCH] Cleanup and reorg of lib/common (#34) * Cleanup and reorg of lib/common - remove stale code in helper.cpp - move helper.hpp to demangle.hpp - move helper.cpp to demangle.cpp - update CMakeLists.txt with new filenames - fix includes in config.cpp * Remove log.hpp and join.hpp - replace with glog and fmt * Update lib/common/environment - move implementation functions into cpp file * Common library tests - tests for demangling - tests for mpl (template metaprogramming) - tests for environment [ROCm/rocprofiler-sdk commit: ba0eb11e96471d6675f2aa5d6d1d5dc10249845c] --- .../source/lib/common/CMakeLists.txt | 5 +- .../source/lib/common/config.cpp | 48 ++-- .../lib/common/{helper.cpp => demangle.cpp} | 223 +++--------------- .../lib/common/{helper.hpp => demangle.hpp} | 27 +-- .../source/lib/common/environment.cpp | 102 ++++++++ .../source/lib/common/environment.hpp | 138 ++--------- .../source/lib/common/join.hpp | 183 -------------- .../rocprofiler-sdk/source/lib/common/log.hpp | 138 ----------- .../source/lib/tests/CMakeLists.txt | 1 + .../source/lib/tests/common/CMakeLists.txt | 23 ++ .../source/lib/tests/common/demangling.cpp | 95 ++++++++ .../source/lib/tests/common/environment.cpp | 115 +++++++++ .../source/lib/tests/common/mpl.cpp | 70 ++++++ 13 files changed, 474 insertions(+), 694 deletions(-) rename projects/rocprofiler-sdk/source/lib/common/{helper.cpp => demangle.cpp} (57%) rename projects/rocprofiler-sdk/source/lib/common/{helper.hpp => demangle.hpp} (72%) create mode 100644 projects/rocprofiler-sdk/source/lib/common/environment.cpp delete mode 100644 projects/rocprofiler-sdk/source/lib/common/join.hpp delete mode 100644 projects/rocprofiler-sdk/source/lib/common/log.hpp create mode 100644 projects/rocprofiler-sdk/source/lib/tests/common/CMakeLists.txt create mode 100644 projects/rocprofiler-sdk/source/lib/tests/common/demangling.cpp create mode 100644 projects/rocprofiler-sdk/source/lib/tests/common/environment.cpp create mode 100644 projects/rocprofiler-sdk/source/lib/tests/common/mpl.cpp diff --git a/projects/rocprofiler-sdk/source/lib/common/CMakeLists.txt b/projects/rocprofiler-sdk/source/lib/common/CMakeLists.txt index 6e9ba5a1b7..d720fefb1b 100644 --- a/projects/rocprofiler-sdk/source/lib/common/CMakeLists.txt +++ b/projects/rocprofiler-sdk/source/lib/common/CMakeLists.txt @@ -1,9 +1,8 @@ # # Builds common utilities into a static library # -set(common_sources config.cpp helper.cpp) -set(common_headers config.hpp defines.hpp environment.hpp join.hpp log.hpp helper.hpp - mpl.hpp) +set(common_sources config.cpp environment.cpp demangle.cpp) +set(common_headers config.hpp defines.hpp environment.hpp demangle.hpp mpl.hpp) add_library(rocprofiler-common-library STATIC) add_library(rocprofiler::rocprofiler-common-library ALIAS rocprofiler-common-library) diff --git a/projects/rocprofiler-sdk/source/lib/common/config.cpp b/projects/rocprofiler-sdk/source/lib/common/config.cpp index e2f7604364..7fa1403f18 100644 --- a/projects/rocprofiler-sdk/source/lib/common/config.cpp +++ b/projects/rocprofiler-sdk/source/lib/common/config.cpp @@ -20,10 +20,10 @@ // #include "lib/common/config.hpp" +#include "lib/common/demangle.hpp" #include "lib/common/environment.hpp" -#include "lib/common/helper.hpp" -#include "lib/common/join.hpp" -#include "lib/common/log.hpp" + +#include #include #include @@ -210,13 +210,13 @@ output_keys(std::string _tag) auto _mpi_size = get_env("OMPI_COMM_WORLD_SIZE", get_env("MV2_COMM_WORLD_SIZE", 0)); auto _mpi_rank = get_env("OMPI_COMM_WORLD_RANK", get_env("MV2_COMM_WORLD_RANK", -1)); - auto _dmp_size = join("", (_mpi_size) > 0 ? _mpi_size : 1); - auto _dmp_rank = join("", (_mpi_rank) > 0 ? _mpi_rank : 0); - auto _proc_id = join("", getpid()); - auto _parent_id = join("", getppid()); - auto _pgroup_id = join("", getpgid(getpid())); - auto _session_id = join("", getsid(getpid())); - auto _proc_size = join("", get_num_siblings()); + auto _dmp_size = fmt::format("{}", (_mpi_size) > 0 ? _mpi_size : 1); + auto _dmp_rank = fmt::format("{}", (_mpi_rank) > 0 ? _mpi_rank : 0); + auto _proc_id = fmt::format("{}", getpid()); + auto _parent_id = fmt::format("{}", getppid()); + auto _pgroup_id = fmt::format("{}", getpgid(getpid())); + auto _session_id = fmt::format("{}", getsid(getpid())); + auto _proc_size = fmt::format("{}", get_num_siblings()); auto _pwd_string = get_env("PWD", "."); auto _slurm_job_id = get_env("SLURM_JOB_ID", "0"); auto _slurm_proc_id = get_env("SLURM_PROCID", _dmp_rank); @@ -248,7 +248,7 @@ output_keys(std::string _tag) for(size_t i = 0; i < _cmdline.size(); ++i) { auto _v = _cmdline.at(i); - _options.emplace_back(join("", "%arg", i, "%"), _v, join("", "Argument #", i)); + _options.emplace_back(fmt::format("%arg{}%", i), _v, fmt::format("Argument #{}", i)); } } @@ -317,19 +317,13 @@ format(std::string _fpath, const std::string& _tag) } auto _beg = std::regex_replace(_fpath, _re, "$1"); auto _end = std::regex_replace(_fpath, _re, "$4"); - _fpath = join("", _beg, _val, _end); + _fpath = fmt::format("{}{}{}", _beg, _val, _end); } } } catch(std::exception& _e) { - fprintf(stderr, - "%s[rocprofiler][%s:%i] %s threw exception :: %s\n%s", - log::color::dmesg(), - __FILE__, - __LINE__, - __FUNCTION__, - _e.what(), - log::color::end()); + LOG(WARNING) << "[rocprofiler] " << __FUNCTION__ << " threw an exception :: " << _e.what() + << "\n"; } // remove %arg% where N >= argc @@ -340,14 +334,8 @@ format(std::string _fpath, const std::string& _tag) _fpath = std::regex_replace(_fpath, _re, "$1$4"); } catch(std::exception& _e) { - fprintf(stderr, - "%s[rocprofiler][%s:%i] %s threw exception :: %s\n%s", - log::color::dmesg(), - __FILE__, - __LINE__, - __FUNCTION__, - _e.what(), - log::color::end()); + LOG(WARNING) << "[rocprofiler] " << __FUNCTION__ << " threw an exception :: " << _e.what() + << "\n"; } return _fpath; @@ -365,11 +353,11 @@ compose_filename(const config& _cfg) { if(_cfg.mpi_rank >= 0) { - _output_file = join('.', _output_file, _cfg.mpi_rank); + _output_file = fmt::format("{}.{}", _output_file, _cfg.mpi_rank); } else { - _output_file = join('.', _output_file, getpid()); + _output_file = fmt::format("{}.{}", _output_file, getpid()); } } if(!_output_ext.empty()) diff --git a/projects/rocprofiler-sdk/source/lib/common/helper.cpp b/projects/rocprofiler-sdk/source/lib/common/demangle.cpp similarity index 57% rename from projects/rocprofiler-sdk/source/lib/common/helper.cpp rename to projects/rocprofiler-sdk/source/lib/common/demangle.cpp index c69016aaca..71b6baddf4 100644 --- a/projects/rocprofiler-sdk/source/lib/common/helper.cpp +++ b/projects/rocprofiler-sdk/source/lib/common/demangle.cpp @@ -18,7 +18,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#include "lib/common/helper.hpp" +#include "lib/common/demangle.hpp" #include @@ -32,11 +32,6 @@ #include #include -#define ENABLE_BACKTRACE -#if defined(ENABLE_BACKTRACE) -# include -#endif - #define amd_comgr_(call) \ do \ { \ @@ -127,79 +122,39 @@ cxa_demangle(std::string_view _mangled_name, int* _status) return _demangled_name; } -namespace +// C++ symbol demangle +std::string +cxx_demangle(std::string_view symbol) { -#if defined(ENABLE_BACKTRACE) + int _status = 0; + auto demangled_str = cxa_demangle(symbol, &_status); + if(_status == 0) + { + return demangled_str; + } -// struct BackTraceInfo -// { -// struct ::backtrace_state* state = nullptr; -// std::stringstream sstream{}; -// int depth = 0; -// int error = 0; -// }; + amd_comgr_data_t mangled_data; + amd_comgr_(create_data(AMD_COMGR_DATA_KIND_BYTES, &mangled_data)); + amd_comgr_(set_data(mangled_data, symbol.size(), symbol.data())); -// void -// errorCallback(void* data, const char* message, int errnum) -// { -// BackTraceInfo* info = static_cast(data); -// info->sstream << "ROCProfiler: error: " << message << '(' << errnum << ')'; -// info->error = 1; -// } + amd_comgr_data_t demangled_data; + amd_comgr_(demangle_symbol_name(mangled_data, &demangled_data)); -// void -// syminfoCallback(void* data, -// uintptr_t /* pc */, -// const char* symname, -// uintptr_t /* symval */, -// uintptr_t /* symsize */) -// { -// BackTraceInfo* info = static_cast(data); + size_t demangled_size = 0; + amd_comgr_(get_data(demangled_data, &demangled_size, nullptr)); -// if(symname == nullptr) return; + demangled_str.resize(demangled_size); + amd_comgr_(get_data(demangled_data, &demangled_size, demangled_str.data())); -// int status = 0; -// auto&& _demangled = cxa_demangle(symname, &status); -// info->sstream << ' ' -// << (status == 0 ? std::string_view{_demangled} : std::string_view{symname}); -// } + amd_comgr_(release_data(mangled_data)); + amd_comgr_(release_data(demangled_data)); + return demangled_str; +} -// int -// fullCallback(void* data, uintptr_t pc, const char* filename, int lineno, const char* function) -// { -// BackTraceInfo* info = static_cast(data); - -// info->sstream << std::endl -// << " #" << std::dec << info->depth++ << ' ' << "0x" << std::noshowbase -// << std::hex << std::setfill('0') << std::setw(sizeof(pc) * 2) << pc; -// if(function == nullptr) -// { -// backtrace_syminfo(info->state, pc, syminfoCallback, errorCallback, data); -// } -// else -// { -// int status = 0; -// auto&& _demangled = cxa_demangle(function, &status); -// info->sstream << ' ' -// << (status == 0 ? std::string_view{_demangled} : -// std::string_view{function}); - -// if(filename != nullptr) -// { -// info->sstream << " in " << filename; -// if(lineno != 0) info->sstream << ':' << std::dec << lineno; -// } -// } - -// return info->error; -// } -#endif // defined (ENABLE_BACKTRACE) -} // namespace - -/* The function extracts the kernel name from -input string. By using the iterators it finds the -window in the string which contains only the kernel name. -For example 'Foo::foo(a[], int (int))' -> 'foo'*/ +// The function extracts the kernel name from +// input string. By using the iterators it finds the +// window in the string which contains only the kernel name. +// For example 'Foo::foo(a[], int (int))' -> 'foo' std::string truncate_name(std::string_view name) { @@ -245,129 +200,5 @@ truncate_name(std::string_view name) rit++; return std::string{name.substr(rend - rit, rit - rbeg)}; } - -// C++ symbol demangle -std::string -cxx_demangle(std::string_view symbol) -{ - int _status = 0; - auto demangled_str = cxa_demangle(symbol, &_status); - if(_status == 0) - { - return demangled_str; - } - - amd_comgr_data_t mangled_data; - amd_comgr_(create_data(AMD_COMGR_DATA_KIND_BYTES, &mangled_data)); - amd_comgr_(set_data(mangled_data, symbol.size(), symbol.data())); - - amd_comgr_data_t demangled_data; - amd_comgr_(demangle_symbol_name(mangled_data, &demangled_data)); - - size_t demangled_size = 0; - amd_comgr_(get_data(demangled_data, &demangled_size, nullptr)); - - demangled_str.resize(demangled_size); - amd_comgr_(get_data(demangled_data, &demangled_size, demangled_str.data())); - - amd_comgr_(release_data(mangled_data)); - amd_comgr_(release_data(demangled_data)); - return demangled_str; -} - -// check if string has special char -bool -has_special_char(std::string_view str) -{ - return std::find_if(str.begin(), str.end(), [](unsigned char ch) { - return !((isalnum(ch) != 0) || ch == '_' || ch == ':' || ch == ' '); - }) != str.end(); -} - -// check if string has correct counter format -bool -has_counter_format(std::string_view str) -{ - return std::find_if(str.begin(), str.end(), [](unsigned char ch) { - return ((isalnum(ch) != 0) || ch == '_'); - }) != str.end(); -} - -// trims the begining of the line for spaces -std::string -left_trim(std::string_view s) -{ - constexpr std::string_view WHITESPACE = " \n\r\t\f\v"; - size_t start = s.find_first_not_of(WHITESPACE); - if(start == std::string_view::npos) return std::string{}; - return std::string{s.substr(start)}; -} - -// trims begining and end of input line in place -void -trim(std::string& str) -{ - // Remove leading spaces. - str.erase(str.begin(), std::find_if(str.begin(), str.end(), [](unsigned char ch) { - return std::isspace(ch) == 0; - })); - // Remove trailing spaces. - str.erase(std::find_if( - str.rbegin(), str.rend(), [](unsigned char ch) { return std::isspace(ch) == 0; }) - .base(), - str.end()); -} - -// replace unsuported specail chars with space -static void -handle_special_chars(std::string& str) -{ - std::set specialChars = {'!', '@', '#', '$', '%', '&', '(', ')', ',', - '*', '+', '-', '.', '/', ';', '<', '=', '>', - '?', '@', '{', '}', '^', '`', '~', '|', ':'}; - - // Iterate over the string and replace any special characters with a space. - for(char& i : str) - { - if(specialChars.find(i) != specialChars.end()) - { - i = ' '; - } - } -} - -// validate input coutners and correct format if needed -void -validate_counters_format(std::vector& counters, std::string line) -{ - // trim line for any white spaces - trim(line); - - if(!(line[0] == '#' || line.find("pmc") == std::string::npos)) - { - handle_special_chars(line); - - std::stringstream input_line(line); - std::string counter; - while(getline(input_line, counter, ' ')) - { - if(counter.substr(0, 3) != "pmc" && has_counter_format(counter)) - { - counters.push_back(counter); - } - } - } - - // raise exception with correct usage if user still managed to corrupt input - for(const auto& itr : counters) - { - if(!has_counter_format(itr)) - { - fprintf(stderr, - "[rocprofiler] Bad input metric. usage --> pmc: \n"); - } - } -} - } // namespace common } // namespace rocprofiler diff --git a/projects/rocprofiler-sdk/source/lib/common/helper.hpp b/projects/rocprofiler-sdk/source/lib/common/demangle.hpp similarity index 72% rename from projects/rocprofiler-sdk/source/lib/common/helper.hpp rename to projects/rocprofiler-sdk/source/lib/common/demangle.hpp index 4cd36c09a7..d71689c8aa 100644 --- a/projects/rocprofiler-sdk/source/lib/common/helper.hpp +++ b/projects/rocprofiler-sdk/source/lib/common/demangle.hpp @@ -37,32 +37,15 @@ namespace common [[nodiscard]] std::string cxa_demangle(std::string_view _mangled_name, int* _status) __attribute__((nonnull(2))); -/* The function extracts the kernel name from -input string. By using the iterators it finds the -window in the string which contains only the kernel name. -For example 'Foo::foo(a[], int (int))' -> 'foo'*/ -std::string -truncate_name(std::string_view name); - // C++ symbol demangle std::string cxx_demangle(std::string_view symbol); -// check if string has special char -bool -has_special_char(std::string_view str); - -// check if string has correct counter format -bool -has_counter_format(std::string_view str); - -// trims the begining of the line for spaces +// The function extracts the kernel name from +// input string. By using the iterators it finds the +// window in the string which contains only the kernel name. +// For example 'Foo::foo(a[], int (int))' -> 'foo' std::string -left_trim(std::string_view s); - -// validates pmc user input format -void -validate_counters_format(std::vector& counters, std::string line); - +truncate_name(std::string_view name); } // namespace common } // namespace rocprofiler diff --git a/projects/rocprofiler-sdk/source/lib/common/environment.cpp b/projects/rocprofiler-sdk/source/lib/common/environment.cpp new file mode 100644 index 0000000000..815f37fa04 --- /dev/null +++ b/projects/rocprofiler-sdk/source/lib/common/environment.cpp @@ -0,0 +1,102 @@ +// Copyright (c) 2023 Advanced Micro Devices, Inc. +// +// 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 "lib/common/environment.hpp" + +#include +#include +#include +#include +#include +#include + +namespace rocprofiler +{ +namespace common +{ +namespace impl +{ +std::string +get_env(std::string_view env_id, std::string_view _default) +{ + if(env_id.empty()) return std::string{_default}; + char* env_var = ::std::getenv(env_id.data()); + if(env_var) return std::string{env_var}; + return std::string{_default}; +} + +std::string +get_env(std::string_view env_id, const char* _default) +{ + return get_env(env_id, std::string_view{_default}); +} + +int +get_env(std::string_view env_id, int _default) +{ + if(env_id.empty()) return _default; + char* env_var = ::std::getenv(env_id.data()); + if(env_var) + { + try + { + return std::stoi(env_var); + } catch(std::exception& _e) + { + LOG(WARNING) << "[rocprofiler][get_env] Exception thrown converting getenv(\"" << env_id + << "\") = " << env_var << " to integer :: " << _e.what() + << ". Using default value of " << _default << "\n"; + } + return _default; + } + return _default; +} + +bool +get_env(std::string_view env_id, bool _default) +{ + if(env_id.empty()) return _default; + char* env_var = ::std::getenv(env_id.data()); + if(env_var) + { + if(std::string_view{env_var}.empty()) + { + throw std::runtime_error(std::string{"No boolean value provided for "} + + std::string{env_id}); + } + + if(std::string_view{env_var}.find_first_not_of("0123456789") == std::string_view::npos) + { + return static_cast(std::stoi(env_var)); + } + + for(size_t i = 0; i < std::string_view{env_var}.length(); ++i) + env_var[i] = tolower(env_var[i]); + + for(const auto& itr : {"off", "false", "no", "n", "f", "0"}) + if(std::string_view{env_var} == itr) return false; + + return true; + } + return _default; +} +} // namespace impl +} // namespace common +} // namespace rocprofiler diff --git a/projects/rocprofiler-sdk/source/lib/common/environment.hpp b/projects/rocprofiler-sdk/source/lib/common/environment.hpp index 24e6a8e463..d55f9c0b54 100644 --- a/projects/rocprofiler-sdk/source/lib/common/environment.hpp +++ b/projects/rocprofiler-sdk/source/lib/common/environment.hpp @@ -20,133 +20,30 @@ #pragma once -#include "lib/common/log.hpp" +#include #include -#include -#include -#include -#include -#include #include #include #include -#if !defined(ROCPROFILER_ENVIRON_LOG_NAME) -# if defined(ROCPROFILER_COMMON_LIBRARY_NAME) -# define ROCPROFILER_ENVIRON_LOG_NAME "[" ROCPROFILER_COMMON_LIBRARY_NAME "]" -# else -# define ROCPROFILER_ENVIRON_LOG_NAME "[environ]" -# endif -#endif - -#if !defined(ROCPROFILER_ENVIRON_LOG_START) -# if defined(ROCPROFILER_COMMON_LIBRARY_LOG_START) -# define ROCPROFILER_ENVIRON_LOG_START ROCPROFILER_COMMON_LIBRARY_LOG_START -# elif defined(ROCPROFILER_LOG_COLORS_AVAILABLE) -# define ROCPROFILER_ENVIRON_LOG_START \ - fprintf(stderr, "%s", ::rocprofiler::common::log::color::dmesg()); -# else -# define ROCPROFILER_ENVIRON_LOG_START -# endif -#endif - -#if !defined(ROCPROFILER_ENVIRON_LOG_END) -# if defined(ROCPROFILER_COMMON_LIBRARY_LOG_END) -# define ROCPROFILER_ENVIRON_LOG_END ROCPROFILER_COMMON_LIBRARY_LOG_END -# elif defined(ROCPROFILER_LOG_COLORS_AVAILABLE) -# define ROCPROFILER_ENVIRON_LOG_END \ - fprintf(stderr, "%s", ::rocprofiler::common::log::color::dmesg()); -# else -# define ROCPROFILER_ENVIRON_LOG_END -# endif -#endif - -#define ROCPROFILER_ENVIRON_LOG(CONDITION, ...) \ - if(CONDITION) \ - { \ - fflush(stderr); \ - ROCPROFILER_ENVIRON_LOG_START \ - fprintf(stderr, "[rocprofiler]" ROCPROFILER_ENVIRON_LOG_NAME "[%i] ", getpid()); \ - fprintf(stderr, __VA_ARGS__); \ - ROCPROFILER_ENVIRON_LOG_END \ - fflush(stderr); \ - } - namespace rocprofiler { namespace common { -namespace +namespace impl { -inline std::string -get_env_impl(std::string_view env_id, std::string_view _default) -{ - if(env_id.empty()) return std::string{_default}; - char* env_var = ::std::getenv(env_id.data()); - if(env_var) return std::string{env_var}; - return std::string{_default}; -} +std::string get_env(std::string_view, std::string_view); -inline std::string -get_env_impl(std::string_view env_id, const char* _default) -{ - return get_env_impl(env_id, std::string_view{_default}); -} +std::string +get_env(std::string_view, const char*); -inline int -get_env_impl(std::string_view env_id, int _default) -{ - if(env_id.empty()) return _default; - char* env_var = ::std::getenv(env_id.data()); - if(env_var) - { - try - { - return std::stoi(env_var); - } catch(std::exception& _e) - { - fprintf(stderr, - "[rocprofiler][get_env] Exception thrown converting getenv(\"%s\") = " - "%s to integer :: %s. Using default value of %i\n", - env_id.data(), - env_var, - _e.what(), - _default); - } - return _default; - } - return _default; -} +int +get_env(std::string_view, int); -inline bool -get_env_impl(std::string_view env_id, bool _default) -{ - if(env_id.empty()) return _default; - char* env_var = ::std::getenv(env_id.data()); - if(env_var) - { - if(std::string_view{env_var}.empty()) - { - throw std::runtime_error(std::string{"No boolean value provided for "} + - std::string{env_id}); - } - - if(std::string_view{env_var}.find_first_not_of("0123456789") == std::string_view::npos) - { - return static_cast(std::stoi(env_var)); - } - - for(size_t i = 0; i < strlen(env_var); ++i) - env_var[i] = tolower(env_var[i]); - for(const auto& itr : {"off", "false", "no", "n", "f", "0"}) - if(strcmp(env_var, itr) == 0) return false; - - return true; - } - return _default; -} -} // namespace +bool +get_env(std::string_view, bool); +} // namespace impl template inline auto @@ -156,11 +53,11 @@ get_env(std::string_view env_id, Tp&& _default) { using Up = std::underlying_type_t; // cast to underlying type -> get_env -> cast to enum type - return static_cast(get_env_impl(env_id, static_cast(_default))); + return static_cast(impl::get_env(env_id, static_cast(_default))); } else { - return get_env_impl(env_id, std::forward(_default)); + return impl::get_env(env_id, std::forward(_default)); } } @@ -168,17 +65,14 @@ struct env_config { std::string env_name = {}; std::string env_value = {}; - int override = 0; + int overwrite = 0; auto operator()(bool _verbose = false) const { if(env_name.empty()) return -1; - ROCPROFILER_ENVIRON_LOG(_verbose, - "setenv(\"%s\", \"%s\", %i)\n", - env_name.c_str(), - env_value.c_str(), - override); - return setenv(env_name.c_str(), env_value.c_str(), override); + LOG_IF(INFO, _verbose) << "[rocprofiler][set_env] setenv(\"" << env_name << "\", \"" + << env_value << "\", " << overwrite << ")\n"; + return setenv(env_name.c_str(), env_value.c_str(), overwrite); } }; } // namespace common diff --git a/projects/rocprofiler-sdk/source/lib/common/join.hpp b/projects/rocprofiler-sdk/source/lib/common/join.hpp deleted file mode 100644 index 0814125c4e..0000000000 --- a/projects/rocprofiler-sdk/source/lib/common/join.hpp +++ /dev/null @@ -1,183 +0,0 @@ -// Copyright (c) 2023 Advanced Micro Devices, Inc. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -#pragma once - -#include -#include -#include -#include -#include -#include -#include -#include - -#if !defined(ROCPROFILER_FOLD_EXPRESSION) -# define ROCPROFILER_FOLD_EXPRESSION(...) ((__VA_ARGS__), ...) -#endif - -namespace rocprofiler -{ -namespace common -{ -namespace -{ -template -struct is_string_impl : std::false_type -{}; - -template <> -struct is_string_impl : std::true_type -{}; - -template <> -struct is_string_impl : std::true_type -{}; - -template <> -struct is_string_impl : std::true_type -{}; - -template <> -struct is_string_impl : std::true_type -{}; - -template -struct is_string : is_string_impl>> -{}; - -template -auto -as_string(ArgT&& _v, std::enable_if_t::value, int> = 0) -{ - if constexpr(std::is_pointer>::value) - { - return (_v == nullptr) ? std::string{"\"\""} : (std::string{"\""} + _v + std::string{"\""}); - } - else - { - return std::string{"\""} + _v + std::string{"\""}; - } -} - -template -auto -as_string(ArgT&& _v, std::enable_if_t::value, long> = 0) -{ - return _v; -} - -template -auto -join(DelimT&& _delim, Args&&... _args) -{ - using delim_type = std::remove_cv_t>; - - std::stringstream _ss{}; - _ss << std::boolalpha; - - if constexpr(std::is_same::value) - { - const char _delim_c[2] = {_delim, '\0'}; - ROCPROFILER_FOLD_EXPRESSION(_ss << _delim_c << _args); - auto _ret = _ss.str(); - return (_ret.length() > 1) ? _ret.substr(1) : std::string{}; - } - else - { - ROCPROFILER_FOLD_EXPRESSION(_ss << _delim << _args); - auto _ret = _ss.str(); - auto&& _len = std::string{_delim}.length(); - return (_ret.length() > _len) ? _ret.substr(_len) : std::string{}; - } -} - -struct QuoteStrings -{}; - -template -auto -join(QuoteStrings&&, DelimT&& _delim, Args&&... _args) -{ - using delim_type = std::remove_cv_t>; - - std::stringstream _ss{}; - _ss << std::boolalpha; - - if constexpr(std::is_same::value) - { - const char _delim_c[2] = {_delim, '\0'}; - ROCPROFILER_FOLD_EXPRESSION(_ss << _delim_c << as_string(_args)); - auto _ret = _ss.str(); - return (_ret.length() > 1) ? _ret.substr(1) : std::string{}; - } - else - { - ROCPROFILER_FOLD_EXPRESSION(_ss << _delim << as_string(_args)); - auto _ret = _ss.str(); - auto&& _len = std::string{_delim}.length(); - return (_ret.length() > _len) ? _ret.substr(_len) : std::string{}; - } -} - -template -auto -join(std::array&& _delim, Args&&... _args) -{ - return join("", - std::get<0>(_delim), - join(std::get<1>(_delim), std::forward(_args)...), - std::get<2>(_delim)); -} - -template -auto -join(QuoteStrings&&, std::array&& _delim, Args&&... _args) -{ - return join(QuoteStrings{}, - "", - std::get<0>(_delim), - join(std::get<1>(_delim), std::forward(_args)...), - std::get<2>(_delim)); -} - -template -auto -join(std::tuple&& _delim, Args&&... _args) -{ - return join("", - std::get<0>(_delim), - join(std::get<1>(_delim), std::forward(_args)...), - std::get<2>(_delim)); -} - -template -auto -join(QuoteStrings&&, std::tuple&& _delim, Args&&... _args) -{ - return join(QuoteStrings{}, - "", - std::get<0>(_delim), - join(std::get<1>(_delim), std::forward(_args)...), - std::get<2>(_delim)); -} -} // namespace -} // namespace common -} // namespace rocprofiler diff --git a/projects/rocprofiler-sdk/source/lib/common/log.hpp b/projects/rocprofiler-sdk/source/lib/common/log.hpp deleted file mode 100644 index 084f870d59..0000000000 --- a/projects/rocprofiler-sdk/source/lib/common/log.hpp +++ /dev/null @@ -1,138 +0,0 @@ -// MIT License -// -// Copyright (c) 2023 ROCm Developer Tools -// -// 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 - -#ifndef ROCPROFILER_LOG_COLORS_AVAILABLE -# define ROCPROFILER_LOG_COLORS_AVAILABLE 1 -#endif - -#include -#include -#include - -namespace rocprofiler -{ -namespace common -{ -namespace log -{ -bool& -monochrome(); - -inline bool& -monochrome() -{ - static bool _v = []() { - auto _val = false; - const char* _env_cstr = nullptr; -#if defined(ROCPROFILER_LOG_COLORS_ENV) - _env_cstr = std::getenv(ROCPROFILER_LOG_COLORS_ENV); -#elif defined(ROCPROFILER_PROJECT_NAME) - auto _env_name = std::string{ROCPROFILER_PROJECT_NAME} + "_MONOCHROME"; - for(auto& itr : _env_name) - itr = toupper(itr); - _env_cstr = std::getenv(_env_name.c_str()); -#else - _env_cstr = std::getenv("ROCPROFILER_MONOCHROME"); -#endif - - if(!_env_cstr) _env_cstr = std::getenv("MONOCHROME"); - - if(_env_cstr) - { - auto _env = std::string{_env_cstr}; - - // check if numeric - if(_env.find_first_not_of("0123456789") == std::string::npos) - { - return _env.length() > 1 || _env[0] != '0'; - } - - for(auto& itr : _env) - itr = tolower(itr); - - // check for matches to acceptable forms of false - for(const auto& itr : {"off", "false", "no", "n", "f"}) - { - if(_env == itr) return false; - } - - // check for matches to acceptable forms of true - for(const auto& itr : {"on", "true", "yes", "y", "t"}) - { - if(_env == itr) return true; - } - } - return _val; - }(); - return _v; -} - -namespace color -{ -static constexpr auto info_value = "\033[01;34m"; -static constexpr auto warning_value = "\033[01;33m"; -static constexpr auto fatal_value = "\033[01;31m"; -static constexpr auto source_value = "\033[01;32m"; -static constexpr auto dmesg_value = "\033[01;37m"; -static constexpr auto end_value = "\033[0m"; - -inline const char* -info() -{ - return (log::monochrome()) ? "" : info_value; -} - -inline const char* -warning() -{ - return (log::monochrome()) ? "" : warning_value; -} - -inline const char* -fatal() -{ - return (log::monochrome()) ? "" : fatal_value; -} - -inline const char* -source() -{ - return (log::monochrome()) ? "" : source_value; -} - -inline const char* -dmesg() -{ - return (log::monochrome()) ? "" : dmesg_value; -} - -inline const char* -end() -{ - return (log::monochrome()) ? "" : end_value; -} -} // namespace color -} // namespace log -} // namespace common -} // namespace rocprofiler diff --git a/projects/rocprofiler-sdk/source/lib/tests/CMakeLists.txt b/projects/rocprofiler-sdk/source/lib/tests/CMakeLists.txt index 1e3564092c..95eb96df37 100644 --- a/projects/rocprofiler-sdk/source/lib/tests/CMakeLists.txt +++ b/projects/rocprofiler-sdk/source/lib/tests/CMakeLists.txt @@ -2,3 +2,4 @@ # # add_subdirectory(buffering) +add_subdirectory(common) diff --git a/projects/rocprofiler-sdk/source/lib/tests/common/CMakeLists.txt b/projects/rocprofiler-sdk/source/lib/tests/common/CMakeLists.txt new file mode 100644 index 0000000000..f4702ef6d8 --- /dev/null +++ b/projects/rocprofiler-sdk/source/lib/tests/common/CMakeLists.txt @@ -0,0 +1,23 @@ +# +# Tests for the common library +# +project(rocprofiler-tests-common LANGUAGES C CXX) + +include(GoogleTest) + +set(common_sources demangling.cpp environment.cpp mpl.cpp) + +add_executable(common-tests) +target_sources(common-tests PRIVATE ${common_sources}) +target_link_libraries( + common-tests + PRIVATE rocprofiler::rocprofiler-headers rocprofiler::rocprofiler-common-library + GTest::gtest GTest::gtest_main) + +gtest_add_tests( + TARGET common-tests + SOURCES ${common_sources} + TEST_LIST common-tests_TESTS + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) + +set_tests_properties(${common-tests_TESTS} PROPERTIES TIMEOUT 45 LABELS "unittests") diff --git a/projects/rocprofiler-sdk/source/lib/tests/common/demangling.cpp b/projects/rocprofiler-sdk/source/lib/tests/common/demangling.cpp new file mode 100644 index 0000000000..df7aff8cdb --- /dev/null +++ b/projects/rocprofiler-sdk/source/lib/tests/common/demangling.cpp @@ -0,0 +1,95 @@ +// MIT License +// +// Copyright (c) 2023 ROCm Developer Tools +// +// 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 "lib/common/demangle.hpp" + +#include + +#include +#include + +TEST(common, demangling) +{ + // the purpose of this test is to verify the cxx_demangle function. + // We want to make sure that the function produces the right demangling + // when it is a correctly mangled string and does not change the string + // when demangling fails + + using strview_pair_t = std::pair; + for(auto [mangled, demangled] : + {strview_pair_t{"_ZN11rocprofiler8internal18correlation_config20get_unique_record_idEv", + "rocprofiler::internal::correlation_config::get_unique_record_id()"}, + strview_pair_t{"_ZN11rocprofiler8internal18get_active_configsEv", + "rocprofiler::internal::get_active_configs()"}, + strview_pair_t{"_ZN11rocprofiler8internal22get_registered_configsEv", + "rocprofiler::internal::get_registered_configs()"}, + strview_pair_t{ + "_ZZN11rocprofiler8internal18correlation_config20get_unique_record_idEvE2_v", + "rocprofiler::internal::correlation_config::get_unique_record_id()::_v"}, + strview_pair_t{"_ZZN11rocprofiler8internal18get_active_configsEvE2_v", + "rocprofiler::internal::get_active_configs()::_v"}, + strview_pair_t{"_ZZN11rocprofiler8internal22get_registered_configsEvE2_v", + "rocprofiler::internal::get_registered_configs()::_v"}}) + { + // verify the demangling works + EXPECT_EQ(rocprofiler::common::cxx_demangle(mangled), demangled) + << "failed to demangle '" << mangled << "'"; + + // verify we get same string in when improperly mangled string + auto bad_mangled = std::string{"_Z"} + std::string{mangled}; + EXPECT_EQ(rocprofiler::common::cxx_demangle(bad_mangled), bad_mangled) + << "demangling succeeded for '" << bad_mangled << "'"; + } +} + +TEST(common, truncate) +{ + // this test is verify that the truncate_name function correctly finds the function + // name in a complex template instantiation + + auto mangled = std::string_view{"_ZSt16__do_uninit_copyIPKSt4pairINSt7__cxx1112basic_" + "stringIcSt11char_traitsIcESaIcEEES6_EPS7_ET0_T_SC_SB_"}; + + auto untruncated = std::string_view{ + "std::pair, std::allocator " + ">, std::__cxx11::basic_string, std::allocator > >* " + "std::__do_uninit_copy, " + "std::allocator >, std::__cxx11::basic_string, " + "std::allocator > > const*, std::pair, std::allocator >, std::__cxx11::basic_string, std::allocator > " + ">*>(std::pair, " + "std::allocator >, std::__cxx11::basic_string, " + "std::allocator > > const*, std::pair, std::allocator >, std::__cxx11::basic_string, std::allocator > > const*, " + "std::pair, std::allocator " + ">, std::__cxx11::basic_string, std::allocator > >*)"}; + + EXPECT_EQ(rocprofiler::common::cxx_demangle(mangled), untruncated); + + EXPECT_EQ(rocprofiler::common::truncate_name(untruncated), + std::string_view{"__do_uninit_copy"}); + + EXPECT_EQ(rocprofiler::common::truncate_name(rocprofiler::common::cxx_demangle(mangled)), + std::string_view{"__do_uninit_copy"}); +} diff --git a/projects/rocprofiler-sdk/source/lib/tests/common/environment.cpp b/projects/rocprofiler-sdk/source/lib/tests/common/environment.cpp new file mode 100644 index 0000000000..66e06ccc3a --- /dev/null +++ b/projects/rocprofiler-sdk/source/lib/tests/common/environment.cpp @@ -0,0 +1,115 @@ +// MIT License +// +// Copyright (c) 2023 ROCm Developer Tools +// +// 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 "lib/common/environment.hpp" + +#include + +TEST(common, environment) +{ + using rocprofiler::common::env_config; + using rocprofiler::common::get_env; + + enum TestBareEnum : unsigned short // NOLINT(performance-enum-size) + { + BZero = 0, + BOne = 1, + }; + + enum class TestClassEnum : unsigned short // NOLINT(performance-enum-size) + { + CZero = 0, + COne = 1, + }; + + // + // int testing section + // + EXPECT_EQ(get_env("ROCPROFILER_ENV_TEST_INT", 0), 0); + + setenv("ROCPROFILER_ENV_TEST_INT", "1", 1); + EXPECT_EQ(get_env("ROCPROFILER_ENV_TEST_INT", 0), 1); + + env_config{"ROCPROFILER_ENV_TEST_INT", "2"}(); + EXPECT_EQ(get_env("ROCPROFILER_ENV_TEST_INT", 0), 1); + + env_config{"ROCPROFILER_ENV_TEST_INT", "2", 1}(); + EXPECT_EQ(get_env("ROCPROFILER_ENV_TEST_INT", 0), 2); + + // + // enum testing section + // + EXPECT_EQ(get_env("ROCPROFILER_ENV_TEST_BARE_ENUM", BZero), BZero); + + env_config{"ROCPROFILER_ENV_TEST_BARE_ENUM", "1", 1}(); + EXPECT_EQ(get_env("ROCPROFILER_ENV_TEST_BARE_ENUM", BZero), BOne); + + EXPECT_EQ(get_env("ROCPROFILER_ENV_TEST_CLASS_ENUM", TestClassEnum::CZero), + TestClassEnum::CZero); + + env_config{"ROCPROFILER_ENV_TEST_CLASS_ENUM", "1", 1}(); + EXPECT_EQ(get_env("ROCPROFILER_ENV_TEST_CLASS_ENUM", TestClassEnum::CZero), + TestClassEnum::COne); + + // + // string testing section + // + EXPECT_EQ(get_env("ROCPROFILER_ENV_TEST_STR", "nostr"), std::string_view{"nostr"}); + + env_config{"ROCPROFILER_ENV_TEST_STR", "hasstr", 0}(); + EXPECT_EQ(get_env("ROCPROFILER_ENV_TEST_STR", "nostr"), std::string_view{"hasstr"}); + + // + // bool testing section + // + EXPECT_FALSE(get_env("ROCPROFILER_ENV_TEST_BOOL", false)); + + env_config{"ROCPROFILER_ENV_TEST_BOOL", "YES", 1}(); + EXPECT_TRUE(get_env("ROCPROFILER_ENV_TEST_BOOL", false)); + + env_config{"ROCPROFILER_ENV_TEST_BOOL", "yes", 1}(); + EXPECT_TRUE(get_env("ROCPROFILER_ENV_TEST_BOOL", false)); + + env_config{"ROCPROFILER_ENV_TEST_BOOL", "y", 1}(); + EXPECT_TRUE(get_env("ROCPROFILER_ENV_TEST_BOOL", false)); + + env_config{"ROCPROFILER_ENV_TEST_BOOL", "true", 1}(); + EXPECT_TRUE(get_env("ROCPROFILER_ENV_TEST_BOOL", false)); + + env_config{"ROCPROFILER_ENV_TEST_BOOL", "on", 1}(); + EXPECT_TRUE(get_env("ROCPROFILER_ENV_TEST_BOOL", false)); + + env_config{"ROCPROFILER_ENV_TEST_BOOL", "no", 1}(); + EXPECT_FALSE(get_env("ROCPROFILER_ENV_TEST_BOOL", true)); + + env_config{"ROCPROFILER_ENV_TEST_BOOL", "false", 1}(); + EXPECT_FALSE(get_env("ROCPROFILER_ENV_TEST_BOOL", true)); + + env_config{"ROCPROFILER_ENV_TEST_BOOL", "0", 1}(); + EXPECT_FALSE(get_env("ROCPROFILER_ENV_TEST_BOOL", true)); + + for(auto n : {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}) + { + env_config{"ROCPROFILER_ENV_TEST_BOOL", std::to_string(n), 1}(); + EXPECT_TRUE(get_env("ROCPROFILER_ENV_TEST_BOOL", false)); + } +} diff --git a/projects/rocprofiler-sdk/source/lib/tests/common/mpl.cpp b/projects/rocprofiler-sdk/source/lib/tests/common/mpl.cpp new file mode 100644 index 0000000000..b0c0705f16 --- /dev/null +++ b/projects/rocprofiler-sdk/source/lib/tests/common/mpl.cpp @@ -0,0 +1,70 @@ +// MIT License +// +// Copyright (c) 2023 ROCm Developer Tools +// +// 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 "lib/common/mpl.hpp" + +#include + +#include + +TEST(common, mpl) +{ + namespace mpl = ::rocprofiler::common::mpl; + struct Foo; + using test_type_list_t = mpl::type_list; + using test_tuple_t = std::tuple; + + EXPECT_EQ(mpl::size_of::value, 5); + EXPECT_EQ(mpl::size_of::value, 5); + + { + constexpr bool _foo_p_is_one_of = mpl::is_one_of::value; + constexpr bool _int_is_one_of = mpl::is_one_of::value; + constexpr bool _double_is_one_of = mpl::is_one_of::value; + + EXPECT_TRUE(_foo_p_is_one_of); + EXPECT_TRUE(_int_is_one_of); + EXPECT_FALSE(_double_is_one_of); + + constexpr auto _foo_p_index_of = mpl::index_of::value; + constexpr auto _int_index_of = mpl::index_of::value; + + EXPECT_EQ(_foo_p_index_of, 4); + EXPECT_EQ(_int_index_of, 0); + } + + { + constexpr bool _foo_p_is_one_of = mpl::is_one_of::value; + constexpr bool _int_is_one_of = mpl::is_one_of::value; + constexpr bool _double_is_one_of = mpl::is_one_of::value; + + EXPECT_TRUE(_foo_p_is_one_of); + EXPECT_TRUE(_int_is_one_of); + EXPECT_FALSE(_double_is_one_of); + + constexpr auto _foo_p_index_of = mpl::index_of::value; + constexpr auto _int_index_of = mpl::index_of::value; + + EXPECT_EQ(_foo_p_index_of, 4); + EXPECT_EQ(_int_index_of, 0); + } +}