From 2195ccfc283e3abd5a2e11fdc080647628808807 Mon Sep 17 00:00:00 2001 From: catalinvasile Date: Wed, 10 Jul 2024 11:52:47 +0200 Subject: [PATCH] Added path views for abs and rel paths --- CMakeLists.txt | 11 - include/tl/abs_path.h | 381 +++--- include/tl/abs_path_view.h | 322 +++++ include/tl/detail/path_base.h | 78 +- include/tl/detail/path_system_utils.h | 70 +- include/tl/detail/path_view_base.h | 219 ++++ include/tl/path_system.h | 29 +- include/tl/rel_path.h | 330 +++-- include/tl/rel_path_view.h | 277 ++++ include/tl/utest.h | 1700 +++++++++++++++++++++++++ test/TestHelpers.cpp | 14 + test/TestHelpers.h | 124 ++ test/main.cpp | 24 +- test/test_paths.cpp | 948 ++++++++++++++ test/test_ptr.cpp | 1067 +++++++--------- 15 files changed, 4637 insertions(+), 957 deletions(-) create mode 100644 include/tl/abs_path_view.h create mode 100644 include/tl/detail/path_view_base.h create mode 100644 include/tl/rel_path_view.h create mode 100644 include/tl/utest.h create mode 100644 test/TestHelpers.cpp create mode 100644 test/TestHelpers.h create mode 100644 test/test_paths.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 5274d94..e51c6d8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -59,18 +59,7 @@ target_link_libraries(TL EASTL) #endif() if (0) - #////////////////////////////////// - - set(Boost_INCLUDE_DIR "${PROJECT_SOURCE_DIR}/../boost") - set(Boost_LIBRARY_DIR "${PROJECT_SOURCE_DIR}/../boost/stage/lib") - set(Boost_USE_STATIC_LIBS ON) - set(Boost_USE_MULTITHREADED ON) - set(Boost_USE_STATIC_RUNTIME OFF) - find_package(Boost 1.69 COMPONENTS unit_test_framework) - file(GLOB_RECURSE TEST_SRC "test/*.cpp" "test/*.h") add_executable(TL_Test ${TEST_SRC}) target_link_libraries(TL_Test TL) - target_link_libraries(TL_Test ${Boost_LIBRARIES}) - target_include_directories(TL_Test PUBLIC ${Boost_INCLUDE_DIRS}) endif() \ No newline at end of file diff --git a/include/tl/abs_path.h b/include/tl/abs_path.h index 4d0d7d9..f7496bf 100644 --- a/include/tl/abs_path.h +++ b/include/tl/abs_path.h @@ -2,6 +2,9 @@ #include "tl/detail/prologue.h" #include + +#include "tl/abs_path_view.h" +#include "tl/rel_path_view.h" #include "tl/path_system.h" #include "tl/rel_path.h" #include "tl/detail/path_base.h" @@ -23,8 +26,11 @@ class abs_path : public detail::path_system::path_base public: using rel_path_type = rel_path; + using path_view_type = abs_path_view; - abs_path() noexcept; + abs_path() noexcept = default; + abs_path(abs_path_view view) noexcept; + abs_path(int path_system_id, span elements) noexcept; explicit abs_path(const char* path) noexcept; abs_path(const char* path, size_t size) noexcept; @@ -35,15 +41,13 @@ public: abs_path(abs_path&& other) noexcept; // operators - const string& operator[](size_t idx) const noexcept; - string& operator[](size_t idx) noexcept; - abs_path& operator=(const abs_path& other) noexcept; abs_path& operator=(abs_path&& other) noexcept; abs_path& operator=(const char* path) noexcept; template requires (!std::is_same_v && !std::is_same_v) abs_path& operator=(const Str& path) noexcept; + abs_path& operator=(const abs_path_view& path) noexcept; abs_path operator+(const char* path) const noexcept; abs_path operator+(const rel_path& path) const noexcept; @@ -56,58 +60,64 @@ public: abs_path& operator+=(rel_path&& path) noexcept; template requires (!std::is_same_v && !std::is_same_v) abs_path& operator+=(const Str& path) noexcept; + abs_path& operator+=(const rel_path_view& path) noexcept; + + operator abs_path_view() const noexcept; bool operator==(const abs_path& other) const noexcept; bool operator!=(const abs_path& other) const noexcept; - auto operator<=>(const abs_path& other) const noexcept; + bool operator==(const abs_path_view& other) const noexcept; + bool operator!=(const abs_path_view& other) const noexcept; + auto operator<=>(const abs_path_view& other) const noexcept; + void swap(abs_path& other) noexcept; void clear() noexcept; string str() const noexcept; eastl::string eastl_str() const noexcept; std::string std_str() const noexcept; + abs_path_view view() const noexcept; - rel_path subpath(size_t idx, int count = 0) const noexcept; - abs_path parent() const noexcept; - abs_path parent(size_t levels) const noexcept; + rel_path_view subpath(size_t idx, int count = 0) const noexcept; + abs_path_view parent() const noexcept; + abs_path_view parent(size_t levels) const noexcept; rel_path path_to(const abs_path& to) const noexcept; - void path_to(rel_path& dst, const abs_path& to) const noexcept; - bool is_prefix_of(const abs_path& path) const noexcept; + void path_to(rel_path& dst, const abs_path& to) const noexcept; + bool is_prefix_of(const abs_path& path) const noexcept; template - bool is() const noexcept; - bool is_valid() const noexcept; + bool is() const noexcept; + bool is_valid() const noexcept; - bool push_back(string element) noexcept override; - const string& front() const noexcept; - const string& back() const noexcept; - string& front() noexcept; - string& back() noexcept; + bool push_back(string element) noexcept override; + const string& front() const noexcept; + const string& back() const noexcept; + void replace_back(string element) noexcept; - void take_elements(tl::vector&& elements) noexcept override; + void take_elements(tl::vector&& elements) noexcept override; //Parses a string. - // 1st attempt is done to parse it as an absolute path. If it succeeds, it returns the path. + // 1st attempt is done to parse it as an abs path. If it succeeds, it returns the path. // 2nd attempt is done to parse it as a relative path and if it succeeds, it returns it as fallbackRoot + relative path. This happens ONLY if the fallbackRoot is valid template - static abs_path from_string(const Str& string, const abs_path& fallbackRoot) noexcept; + static abs_path from_string(const Str& string, const abs_path& fallbackRoot) noexcept; - //Parses a string as an absolute path. If it fails it returns an invalid path. + //Parses a string as an abs path. If it fails it returns an invalid path. template - static abs_path from_string(const Str& string) noexcept; + static abs_path from_string(const Str& string) noexcept; template - static bool is_valid_string(const Str& string) noexcept; + static bool is_valid_string(const Str& string) noexcept; template - static bool has_valid_tag(const Str& string) noexcept; + static bool has_valid_tag(const Str& string) noexcept; - bool parse(const char* path, size_t size) noexcept; + bool parse(const char* path, size_t size) noexcept; private: - bool collapse_path() noexcept; + bool collapse_path() noexcept; int m_pathSystemId = -1; }; @@ -124,15 +134,6 @@ namespace tl { ////////////////////////////////////////////////////////////////////////// -template -abs_path::abs_path() noexcept -{ - m_pathSystemId = -1; - this->m_hash = 0; -} - -////////////////////////////////////////////////////////////////////////// - template abs_path::abs_path(const char* path, size_t size) noexcept { @@ -140,7 +141,26 @@ abs_path::abs_path(const char* path, size_t size) noexcept TL_PLAIN_CRASH("null path in abs_path constructor"); if (parse(path, size) == false) - TL_PLAIN_FAIL("Failed to parse absolute path"); + TL_PLAIN_FAIL("Failed to parse abs path"); +} + +////////////////////////////////////////////////////////////////////////// + +template +abs_path::abs_path(abs_path_view view) noexcept + : m_pathSystemId(view.m_pathSystemId) +{ + this->m_elements.insert(this->m_elements.end(), view.begin(), view.end()); + this->m_hash = view.hash(); +} + +////////////////////////////////////////////////////////////////////////// + +template +abs_path::abs_path(int path_system_id, span elements) noexcept + : m_pathSystemId(path_system_id) +{ + this->m_elements.insert(this->m_elements.end(), elements.begin(), elements.end()); } ////////////////////////////////////////////////////////////////////////// @@ -152,7 +172,7 @@ abs_path::abs_path(const char* path) noexcept TL_PLAIN_CRASH("null path in abs_path constructor"); if (parse(path, strlen(path)) == false) - TL_PLAIN_FAIL("Failed to parse absolute path"); + TL_PLAIN_FAIL("Failed to parse abs path"); } ////////////////////////////////////////////////////////////////////////// @@ -162,7 +182,7 @@ template requires (!std::is_same_v && !std::is_ abs_path::abs_path(const Str& path) noexcept { if (parse(path.data(), path.size()) == false) - TL_PLAIN_FAIL("Failed to parse absolute path"); + TL_PLAIN_FAIL("Failed to parse abs path"); } ////////////////////////////////////////////////////////////////////////// @@ -186,23 +206,6 @@ abs_path::abs_path(abs_path&& other) noexcept other.m_hash = 0; } -////////////////////////////////////////////////////////////////////////// - -template -const string& abs_path::operator[](size_t idx) const noexcept -{ - return this->m_elements[idx]; -} - -//////////////////////////////////////////////////////////////////////////////////////////////////////////// - -template -string& abs_path::operator[](size_t idx) noexcept -{ - this->m_hash = 0; - return this->m_elements[idx]; -} - //////////////////////////////////////////////////////////////////////////////////////////////////////////// template @@ -232,13 +235,25 @@ template requires (!std::is_same_v && !std::is_s abs_path& abs_path::operator=(const Str& path) noexcept { if (parse(path.data(), path.size()) == false) - TL_PLAIN_FAIL("Failed to parse absolute path"); + TL_PLAIN_FAIL("Failed to parse abs path"); return *this; } ////////////////////////////////////////////////////////////////////////// +template +abs_path& abs_path::operator=(const abs_path_view& path) noexcept +{ + this->m_elements.clear(); + this->m_elements.insert(this->m_elements.end(), path.m_elements.begin(), path.m_elements.end()); + this->m_hash = path.m_hash; + m_pathSystemId = path.m_pathSystemId; + return *this; +} + +////////////////////////////////////////////////////////////////////////// + template abs_path& abs_path::operator=(const char* path) noexcept { @@ -246,7 +261,7 @@ abs_path& abs_path::operator=(const char* path) noexce TL_PLAIN_CRASH("null path in abs_path assignment"); if (parse(path, strlen(path)) == false) - TL_PLAIN_FAIL("Failed to parse absolute path"); + TL_PLAIN_FAIL("Failed to parse abs path"); return *this; } @@ -261,7 +276,6 @@ abs_path abs_path::operator+(const char* path) const n abs_path p; p.reserve(this->size() + 1); p = *this; - p += path; return p; } @@ -279,7 +293,6 @@ abs_path abs_path::operator+(const Str& path) const no abs_path p; p.reserve(this->size() + 1); p = *this; - p += path; return p; } @@ -294,9 +307,8 @@ abs_path abs_path::operator+(const rel_pathsize() + 1); + p.reserve(this->size() + path.size()); p = *this; - p += path; return p; } @@ -311,9 +323,8 @@ abs_path abs_path::operator+(rel_path&& p if (!path.empty()) { abs_path p; - p.reserve(this->size() + 1); + p.reserve(this->size() + path.size()); p = *this; - p += std::move(path); return p; } @@ -326,7 +337,7 @@ template abs_path& abs_path::operator+=(const char* path) noexcept { if (m_pathSystemId < 0 && this->empty()) - this->operator=(path); + *this = path; else if (path && path[0] != '\0') *this += rel_path(path); @@ -340,7 +351,7 @@ template requires (!std::is_same_v && !std::is_s abs_path& abs_path::operator+=(const Str& path) noexcept { if (m_pathSystemId < 0 && this->empty()) - this->operator=(path); + *this = path; else if (!path.empty()) *this += rel_path(path); @@ -352,12 +363,8 @@ abs_path& abs_path::operator+=(const Str& path) noexce template abs_path& abs_path::operator+=(const rel_path& path) noexcept { - if (!path.empty()) - { - //use the move version - *this += rel_path(path); - this->collapse_path(); - } + //use the move version + *this += rel_path(path); return *this; } @@ -374,8 +381,31 @@ abs_path& abs_path::operator+=(rel_path&& if (!push_back(std::move(e))) return *this; } + path.clear(); + this->m_hash = 0; - this->collapse_path(); + if (!this->collapse_path()) + this->clear(); + } + return *this; +} + +////////////////////////////////////////////////////////////////////////// + +template +abs_path& abs_path::operator+=(const rel_path_view& path) noexcept +{ + if (!path.empty()) + { + this->m_elements.reserve(this->m_elements.size() + path.size()); + for (auto& e : path) + { + if (!push_back(std::move(e))) + return *this; + } + this->m_hash = 0; + if (!this->collapse_path()) + this->clear(); } return *this; } @@ -403,7 +433,41 @@ bool abs_path::operator!=(const abs_path& other) const noexcept template auto abs_path::operator<=>(const abs_path& other) const noexcept { -// return std::compare_three_way{}(this->m_elements, other.m_elements); + const size_t sz1 = this->m_elements.size(); + const size_t sz2 = other.m_elements.size(); + for (size_t i = 0; i < sz1 && i < sz2; ++i) + { + auto r = this->m_elements[i] <=> other.m_elements[i]; + if (r != decltype(r)::equal) + return r; + } + + return sz1 <=> sz2; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////// + +template +bool abs_path::operator==(const abs_path_view& other) const noexcept +{ + return (!this->m_hash || !other.m_hash || this->m_hash == other.m_hash) && + this->m_pathSystemId == other.m_pathSystemId && + tl::span(this->m_elements) == other.m_elements; +} + +////////////////////////////////////////////////////////////////////////// + +template +bool abs_path::operator!=(const abs_path_view& other) const noexcept +{ + return !(*this == other); +} + +////////////////////////////////////////////////////////////////////////// + +template +auto abs_path::operator<=>(const abs_path_view& other) const noexcept +{ const size_t sz1 = this->m_elements.size(); const size_t sz2 = other.m_elements.size(); for (size_t i = 0; i < sz1 && i < sz2; ++i) @@ -429,15 +493,7 @@ bool abs_path::parse(const char* path, size_t size) noexcept if (m_pathSystemId < 0) return false; - PathSystems::parse_absolute(this->m_elements, m_pathSystemId, path, size); - for (const string& element : this->m_elements) - { - if (!this->validate_element(element)) - { - this->clear(); - return false; - } - } + PathSystems::parse_abs(this->m_elements, m_pathSystemId, path, size); if (collapse_path() == false) { @@ -456,7 +512,7 @@ bool abs_path::collapse_path() noexcept if (this->empty()) return is_valid(); - this->m_hash = 0; + const size_t oldSize = this->m_elements.size(); for (size_t i = 0; i < this->m_elements.size();) { if (i >= 1 && @@ -467,11 +523,14 @@ bool abs_path::collapse_path() noexcept i -= 1; } else if (this->m_elements[i] == path_system::current_t::value()) - this->m_elements.erase(this->m_elements.begin() + i); //remove the . + this->m_elements.erase(this->m_elements.begin() + i); //remove the . else i++; } + if (oldSize != this->m_elements.size()) + this->m_hash = 0; + if (!PathSystems::validate_abs_path(m_pathSystemId, this->m_elements)) return false; @@ -510,7 +569,7 @@ string abs_path::str() const noexcept if (!is_valid() && this->empty()) return {}; - return PathSystems::template format_absolute(m_pathSystemId, this->m_elements); + return PathSystems::template format_abs(m_pathSystemId, this->m_elements); } ////////////////////////////////////////////////////////////////////////// @@ -521,7 +580,7 @@ eastl::string abs_path::eastl_str() const noexcept if (!is_valid() && this->empty()) return {}; - return PathSystems::template format_absolute(m_pathSystemId, this->m_elements); + return PathSystems::template format_abs(m_pathSystemId, this->m_elements); } ////////////////////////////////////////////////////////////////////////// @@ -532,93 +591,68 @@ std::string abs_path::std_str() const noexcept if (!is_valid() && this->empty()) return {}; - return PathSystems::template format_absolute(m_pathSystemId, this->m_elements); + return PathSystems::template format_abs(m_pathSystemId, this->m_elements); } ////////////////////////////////////////////////////////////////////////// template -rel_path abs_path::subpath(size_t idx, int count /* = 0 */) const noexcept +abs_path_view abs_path::view() const noexcept +{ + return abs_path_view(m_pathSystemId, this->m_elements); +} + +////////////////////////////////////////////////////////////////////////// + +template +abs_path::operator abs_path_view() const noexcept +{ + return abs_path_view(m_pathSystemId, this->m_elements); +} + +////////////////////////////////////////////////////////////////////////// + +template +rel_path_view abs_path::subpath(size_t index, int count /* = 0 */) const noexcept { rel_path dst; if (count == 0) - count = (int)this->size() - (int)idx; + count = (int)this->size() - (int)index; if (count < 0) - count = (int)this->size() - (int)idx + count; + count = (int)this->size() - (int)index + count; - if (count > 0 && idx < this->size()) - { - dst.reserve(count); - for (int i = 0; i < count; i++) - dst.push_element(this->m_elements[idx + i]); - } - return dst; + if (count > 0 && index < this->size()) + return rel_path_view(tl::span(this->m_elements.begin() + index, this->m_elements.begin() + index + count)); + + return {}; } ////////////////////////////////////////////////////////////////////////// template -abs_path abs_path::parent() const noexcept +abs_path_view abs_path::parent() const noexcept { if (this->empty()) { TL_PLAIN_FAIL("Invalid path"); - return abs_path(); + return {}; } - - abs_path p = *this; - - if (p.back() == path_system::back_t::value()) - { - //do not do a pop_back here!! - //The parent of '/..' is '/../..'!!! - p.push_back(path_system::back_t::value()); - } - else - p.pop_back(); - - if (!PathSystems::validate_abs_path(p.m_pathSystemId, p.m_elements)) - { - TL_PLAIN_FAIL("Invalid path"); - return abs_path(); - } - - return p; + return abs_path_view(m_pathSystemId, tl::span(this->m_elements.begin(), this->m_elements.end() - 1)); } ////////////////////////////////////////////////////////////////////////// template -abs_path abs_path::parent(size_t levels) const noexcept +abs_path_view abs_path::parent(size_t levels) const noexcept { if (this->empty() || this->size() <= levels) { TL_PLAIN_FAIL("Invalid path"); - return abs_path(); + return {}; } - abs_path p = *this; - - if (p.back() == path_system::back_t::value()) - { - //The parent of '/..' is '/../..'!!! - while (levels > 0) - { - levels--; - p.push_back(path_system::back_t::value()); - } - } - else - p.shrink(p.size() - levels); - - if (!PathSystems::validate_abs_path(p.m_pathSystemId, p.m_elements)) - { - TL_PLAIN_FAIL("Invalid path"); - return abs_path(); - } - - return p; + return abs_path_view(m_pathSystemId, tl::span(this->m_elements.begin(), this->m_elements.end() - levels)); } ////////////////////////////////////////////////////////////////////////// @@ -663,7 +697,7 @@ void abs_path::path_to(rel_path& dst, const abs_path& } else if (to.empty()) { - //ms relative path from an absolute path to an empty path should be an empty path + //ms relative path from an abs path to an empty path should be an empty path } else { @@ -772,21 +806,13 @@ const tl::string& abs_path::front() const noexcept ////////////////////////////////////////////////////////////////////////// template -tl::string& abs_path::front() noexcept +void abs_path::replace_back(string element) noexcept { TL_PLAIN_ASSERT(!this->empty()); this->m_hash = 0; - return this->m_elements.front(); -} - -////////////////////////////////////////////////////////////////////////// - -template -tl::string& abs_path::back() noexcept -{ - TL_PLAIN_ASSERT(!this->empty()); - this->m_hash = 0; - return this->m_elements.back(); + this->m_elements.back() = std::move(element); + if (!collapse_path()) + clear(); } ////////////////////////////////////////////////////////////////////////// @@ -838,6 +864,53 @@ bool abs_path::has_valid_tag(const Str& string) noexcept return pathSystemId >= 0; } + +template +abs_path operator+(const abs_path_view& a, const char* b) noexcept +{ + abs_path p; + p.reserve(a.size() + 1); + p = a; + p += b; + return p; +} +template requires (!std::is_same_v && !std::is_same_v) +abs_path operator+(const abs_path_view& a, const Str& b) noexcept +{ + abs_path p; + p.reserve(a.size() + 1); + p = a; + p += b; + return p; +} +template +abs_path operator+(const abs_path_view& a, const rel_path& b) noexcept +{ + abs_path p; + p.reserve(a.size() + b.size()); + p = a; + p += b; + return p; +} +template +abs_path operator+(const abs_path_view& a, const rel_path_view& b) noexcept +{ + abs_path p; + p.reserve(a.size() + b.size()); + p = a; + p += b; + return p; +} +template +abs_path operator+(const abs_path_view& a, const abs_path_view& b) noexcept +{ + abs_path p; + p.reserve(a.size() + b.size()); + p = a; + p += b; + return p; +} + } ////////////////////////////////////////////////////////////////////////// diff --git a/include/tl/abs_path_view.h b/include/tl/abs_path_view.h new file mode 100644 index 0000000..9a22ab5 --- /dev/null +++ b/include/tl/abs_path_view.h @@ -0,0 +1,322 @@ +#pragma once + +#include "tl/detail/prologue.h" +#include +#include "tl/path_system.h" +#include "tl/rel_path_view.h" +#include "tl/detail/path_view_base.h" +#include "tl/plain_crash.h" +#include "tl/format.h" + +namespace tl +{ + +template class abs_path; +template class abs_path_view; +template struct path_view_key_less; + +////////////////////////////////////////////////////////////////////////// + +template +class abs_path_view : public detail::path_system::path_view_base +{ + template friend class rel_path_view; + +public: + using rel_path_view_type = rel_path_view; + + abs_path_view() noexcept; + abs_path_view(int pathSystemId, tl::span elements) noexcept; + + abs_path_view(const abs_path_view& other) noexcept; + + // operators + abs_path_view& operator=(const abs_path_view& other) noexcept; + + bool operator==(const abs_path_view& other) const noexcept; + bool operator!=(const abs_path_view& other) const noexcept; + + auto operator<=>(const abs_path_view& other) const noexcept; + + void swap(abs_path_view& other) noexcept; + + void clear() noexcept; + string str() const noexcept; + eastl::string eastl_str() const noexcept; + std::string std_str() const noexcept; + + rel_path_view subpath(size_t idx, int count = 0) const noexcept; + abs_path_view parent() const noexcept; + abs_path_view parent(size_t levels) const noexcept; + bool is_prefix_of(const abs_path_view& path) const noexcept; + + //This only works if `this` is a prefix of `to`, in other words, only if the resultant path can be expressed as a view of the `to` path + // This is true when going from a parent to a subfolder + //Example: + //Good: ("/a/b/c").prefix_path_to("/a/b/c/d") == ("d") + //Bad: ("/a/b/c").prefix_path_to("/a/b") == ("") will assert and return empty. It should return ".." but it cannot + + + rel_path_view prefix_path_to(const abs_path_view& to) const noexcept; + + + template + bool is() const noexcept; + bool is_valid() const noexcept; + +private: + int m_pathSystemId = -1; + friend class abs_path; +}; + +////////////////////////////////////////////////////////////////////////// + +} + +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// + +namespace tl +{ +////////////////////////////////////////////////////////////////////////// + +template +abs_path_view::abs_path_view() noexcept +{ +} + +////////////////////////////////////////////////////////////////////////// + +template +abs_path_view::abs_path_view(int pathSystemId, tl::span elements) noexcept + : path_view_base(elements) + , m_pathSystemId(pathSystemId) +{ +} + +////////////////////////////////////////////////////////////////////////// + +template +abs_path_view::abs_path_view(const abs_path_view& other) noexcept + : path_view_base(other) + , m_pathSystemId(other.m_pathSystemId) +{ +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////// + +template +abs_path_view& abs_path_view::operator=(const abs_path_view& other) noexcept +{ + m_elements = other.m_elements; + m_hash = other.m_hash; + m_pathSystemId = other.m_pathSystemId; + return *this; +} + +////////////////////////////////////////////////////////////////////////// + +template +bool abs_path_view::operator==(const abs_path_view& other) const noexcept +{ + return (!this->m_hash || !other.m_hash || this->m_hash == other.m_hash) && + this->m_pathSystemId == other.m_pathSystemId && + this->m_elements == other.m_elements; +} + +////////////////////////////////////////////////////////////////////////// + +template +bool abs_path_view::operator!=(const abs_path_view& other) const noexcept +{ + return !(*this == other); +} + +////////////////////////////////////////////////////////////////////////// + +template +void abs_path_view::clear() noexcept +{ + m_elements = {}; + m_hash = 0; + m_pathSystemId = -1; +} + +////////////////////////////////////////////////////////////////////////// + +template +string abs_path_view::str() const noexcept +{ + if (!is_valid() && this->empty()) + return {}; + + return PathSystems::template format_abs(m_pathSystemId, this->m_elements); +} + +////////////////////////////////////////////////////////////////////////// + +template +eastl::string abs_path_view::eastl_str() const noexcept +{ + if (!is_valid() && this->empty()) + return {}; + + return PathSystems::template format_abs(m_pathSystemId, this->m_elements); +} + +////////////////////////////////////////////////////////////////////////// + +template +std::string abs_path_view::std_str() const noexcept +{ + if (!is_valid() && this->empty()) + return {}; + + return PathSystems::template format_abs(m_pathSystemId, this->m_elements); +} + +////////////////////////////////////////////////////////////////////////// + +template +rel_path_view abs_path_view::subpath(size_t idx, int count /* = 0 */) const noexcept +{ + if (count == 0) + count = (int)this->size() - (int)idx; + + if (count < 0) + count = (int)this->size() - (int)idx + count; + + if (count > 0 && idx < this->size()) + return rel_path_view(tl::span(this->m_elements.begin() + idx, this->m_elements.begin() + idx + count)); + + return {}; +} + +////////////////////////////////////////////////////////////////////////// + +template +abs_path_view abs_path_view::parent() const noexcept +{ + if (this->empty()) + { + TL_PLAIN_FAIL("Invalid path"); + return {}; + } + + abs_path_view p = *this; + p.pop_back(); + + if (!PathSystems::validate_abs_path(p.m_pathSystemId, p.m_elements)) + { + TL_PLAIN_FAIL("Invalid path"); + return {}; + } + + return p; +} + +////////////////////////////////////////////////////////////////////////// + +template +abs_path_view abs_path_view::parent(size_t levels) const noexcept +{ + if (this->empty() || this->size() <= levels) + { + TL_PLAIN_FAIL("Invalid path"); + return {}; + } + + abs_path_view p = *this; + p.shrink(p.size() - levels); + + return p; +} + +////////////////////////////////////////////////////////////////////////// + +template +template +bool abs_path_view::is() const noexcept +{ + return PathSystems::template is(m_pathSystemId); +} + +////////////////////////////////////////////////////////////////////////// + +template +bool abs_path_view::is_valid() const noexcept +{ + return m_pathSystemId >= 0; +} + +////////////////////////////////////////////////////////////////////////// + +template +bool abs_path_view::is_prefix_of(const abs_path_view& path) const noexcept +{ + if (m_pathSystemId != path.m_pathSystemId) + return false; + + if (this->size() > path.size()) + return false; + + for (size_t i = 0, _count = this->size(); i < _count; ++i) + { + if ((*this)[i] != path[i]) + return false; + } + + return true; +} + +////////////////////////////////////////////////////////////////////////// + +template +rel_path_view abs_path_view::prefix_path_to(const abs_path_view& to) const noexcept +{ + if (this->empty()) + return rel_path_view(to.m_elements); + + if (!is_prefix_of(to)) + { + TL_PLAIN_FAIL("Invalid path"); + return {}; + } + + return rel_path_view(tl::span(to.m_elements.begin() + size(), to.m_elements.end())); +} + +} + +////////////////////////////////////////////////////////////////////////// + +template +struct std::formatter> +{ + constexpr auto parse(format_parse_context& ctx) noexcept { return ctx.begin(); } + auto format(const tl::abs_path_view& p, std::format_context& ctx) const + { + return format_to(ctx.out(), "{}", p.str()); + } +}; + +template +struct std::hash> +{ + std::size_t operator()(const tl::abs_path_view& p) const + { + return p.hash(); + } +}; + + +template +struct eastl::hash> +{ + std::size_t operator()(const tl::abs_path_view& p) const + { + return p.hash(); + } +}; + diff --git a/include/tl/detail/path_base.h b/include/tl/detail/path_base.h index 1659203..c2a45ee 100644 --- a/include/tl/detail/path_base.h +++ b/include/tl/detail/path_base.h @@ -28,36 +28,38 @@ public: using key_less = path_key_less; using value_type = std::string; - //checked indexing - const string& at(size_t index) const noexcept; + //both have checked indexing + const string& operator[](size_t index) const noexcept; + string& operator[](size_t index) noexcept; + const string& at(size_t index) const noexcept; + string& at(size_t index) noexcept; void shrink(size_t size) noexcept; bool empty() const noexcept; - size_t size() const noexcept; + size_t size() const noexcept; void reserve(size_t capacity) noexcept; // if the path is empty, these operations have no effect. They return the removed element as a string. - string pop_back() noexcept; - virtual bool push_back(string element) noexcept; + string pop_back() noexcept; + virtual bool push_back(string element) noexcept; - virtual void take_elements(tl::vector&& elements) noexcept; + virtual void take_elements(tl::vector&& elements) noexcept; - iterator begin() noexcept; - iterator end() noexcept; + iterator begin() noexcept; + iterator end() noexcept; const_iterator begin() const noexcept; const_iterator end() const noexcept; const_reverse_iterator rbegin() const noexcept; const_reverse_iterator rend() const noexcept; - uint32_t hash() const noexcept; + uint32_t hash() const noexcept; protected: - bool validate_element(const string& element) noexcept; - void push_element(string element) noexcept; + void push_element(string element) noexcept; tl::vector m_elements; - mutable uint32_t m_hash = 0; + mutable uint32_t m_hash = 0; friend bool path_key_less::operator()(const path_base& a1, const path_base& a2) const noexcept; }; @@ -87,9 +89,43 @@ namespace path_system ////////////////////////////////////////////////////////////////////////// +template +const string& path_base::operator[](size_t index) const noexcept +{ + if (index >= m_elements.size()) + TL_PLAIN_CRASH("Illegal access"); + return m_elements[index]; +} + +////////////////////////////////////////////////////////////////////////// + +template +string& path_base::operator[](size_t index) noexcept +{ + if (index >= m_elements.size()) + TL_PLAIN_CRASH("Illegal access"); + m_hash = 0; + return m_elements[index]; +} + +////////////////////////////////////////////////////////////////////////// + template const string& path_base::at(size_t index) const noexcept { + if (index >= m_elements.size()) + TL_PLAIN_CRASH("Illegal access"); + return m_elements[index]; +} + +////////////////////////////////////////////////////////////////////////// + +template +string& path_base::at(size_t index) noexcept +{ + if (index >= m_elements.size()) + TL_PLAIN_CRASH("Illegal access"); + m_hash = 0; return m_elements[index]; } @@ -164,25 +200,7 @@ string path_base::pop_back() noexcept template bool path_base::push_back(string element) noexcept { - if (!validate_element(element)) - { - TL_PLAIN_FAIL("Pushed an invalid path element."); - return false; - } - push_element(std::move(element)); - - return true; -} - -////////////////////////////////////////////////////////////////////////// - -template -bool path_base::validate_element(const string& /*element*/) noexcept -{ - // validate element to be added here - // if not return false - return true; } diff --git a/include/tl/detail/path_system_utils.h b/include/tl/detail/path_system_utils.h index 1b2406d..3bdfd34 100644 --- a/include/tl/detail/path_system_utils.h +++ b/include/tl/detail/path_system_utils.h @@ -1,5 +1,7 @@ #pragma once +#include + #include "tl/detail/prologue.h" #include #include "tl/string.h" @@ -15,9 +17,9 @@ namespace path_system ////////////////////////////////////////////////////////////////////////// template -void simple_format_rel_path(T& o_buffer, const tl::vector& members, const char* separator) noexcept; +void simple_format_rel_path(T& o_buffer, tl::span members, const char* separator) noexcept; template -void simple_format_abs_path(T& o_buffer, const tl::vector& members, const char* root_tag, const char* separator) noexcept; +void simple_format_abs_path(T& o_buffer, tl::span members, const char* root_tag, const char* separator) noexcept; inline bool find_next_separator(const char* const* separators_begin, const char* const* separators_end, const char*& io_startIt, const char* end, const char*& io_endIt) noexcept; @@ -31,10 +33,10 @@ template struct path_system_getter { template - static T format_absolute(int type_idx, const tl::vector& members) noexcept; - static void parse_absolute(tl::vector& o_elements, int type_idx, const char* path, size_t size) noexcept; + static T format_abs(int type_idx, tl::span members) noexcept; + static void parse_abs(tl::vector& o_elements, int type_idx, const char* path, size_t size) noexcept; static int deduce_system_type(const char* path, size_t size) noexcept; - static bool validate_abs_path(int type_idx, const tl::vector& members) noexcept; + static bool validate_abs_path(int type_idx, tl::span members) noexcept; }; // specialization if Head element exists @@ -42,10 +44,10 @@ template struct path_system_getter { template - static T format_absolute(int type_idx, const tl::vector& members) noexcept; - static void parse_absolute(tl::vector& o_elements, int type_idx, const char* path, size_t size) noexcept; + static T format_abs(int type_idx, tl::span members) noexcept; + static void parse_abs(tl::vector& o_elements, int type_idx, const char* path, size_t size) noexcept; static int deduce_system_type(const char* path, size_t size) noexcept; - static bool validate_abs_path(int type_idx, const tl::vector& members) noexcept; + static bool validate_abs_path(int type_idx, tl::span members) noexcept; }; ////////////////////////////////////////////////////////////////////////// @@ -85,7 +87,8 @@ struct base_path_system static const tl::vector& get_parse_separators() noexcept; static const char* get_format_separator() noexcept; - static string format_relative(const tl::vector& members) noexcept; + template + static T format_rel(tl::span members) noexcept; }; ////////////////////////////////////////////////////////////////////////// @@ -110,7 +113,7 @@ namespace path_system ////////////////////////////////////////////////////////////////////////// template -void simple_format_rel_path(T& o_buffer, const tl::vector& members, const char* separator) noexcept +void simple_format_rel_path(T& o_buffer, tl::span members, const char* separator) noexcept { //calculate the size to reserve size_t totalSize = 0; @@ -133,8 +136,18 @@ void simple_format_rel_path(T& o_buffer, const tl::vector& members, cons ////////////////////////////////////////////////////////////////////////// +template<> +inline void simple_format_rel_path(string& o_buffer, tl::span members, const char* separator) noexcept +{ + tl::fixed_string temp; + simple_format_rel_path(temp, members, separator); + o_buffer = string(temp); +} + +////////////////////////////////////////////////////////////////////////// + template -void simple_format_abs_path(T& o_buffer, const tl::vector& members, const char* root_tag, const char* separator) noexcept +void simple_format_abs_path(T& o_buffer, tl::span members, const char* root_tag, const char* separator) noexcept { o_buffer.append(root_tag); detail::path_system::simple_format_rel_path(o_buffer, members, separator); @@ -246,16 +259,16 @@ inline bool simple_match_prefix(const char* path, size_t size, const char* prefi template template -T path_system_getter::format_absolute(int /*type_idx*/, const tl::vector& /*members*/) noexcept +T path_system_getter::format_abs(int /*type_idx*/, tl::span /*members*/) noexcept { TL_PLAIN_FAIL("Failed to format path. Invalid type."); return {}; } template -void path_system_getter::parse_absolute(tl::vector& /*o_elements*/, int /*type_idx*/, const char* /*path*/, size_t /* size */) noexcept +void path_system_getter::parse_abs(tl::vector& /*o_elements*/, int /*type_idx*/, const char* /*path*/, size_t /* size */) noexcept { - TL_PLAIN_FAIL("Failed parsing absolute path. Invalid type."); + TL_PLAIN_FAIL("Failed parsing abs path. Invalid type."); } template @@ -265,7 +278,7 @@ int path_system_getter::deduce_system_type(const char* /*path*/, } template -bool path_system_getter::validate_abs_path(int /*type_idx*/, const tl::vector& /*members*/) noexcept +bool path_system_getter::validate_abs_path(int /*type_idx*/, tl::span /*members*/) noexcept { TL_PLAIN_FAIL("Failed validating path system. Invalid type."); return false; @@ -275,23 +288,23 @@ bool path_system_getter::validate_abs_path(int /*type_idx*/, con template template -T path_system_getter::format_absolute(int type_idx, const tl::vector& members) noexcept +T path_system_getter::format_abs(int type_idx, tl::span members) noexcept { if (type_idx == Index) - return Head::template format_absolute(members); + return Head::template format_abs(members); - return path_system_getter::template format_absolute(type_idx, members); + return path_system_getter::template format_abs(type_idx, members); } template -void path_system_getter::parse_absolute(tl::vector& o_elements, int type_idx, const char* path, size_t size) noexcept +void path_system_getter::parse_abs(tl::vector& o_elements, int type_idx, const char* path, size_t size) noexcept { if (type_idx == Index) { - Head::parse_absolute(o_elements, path, size); + Head::parse_abs(o_elements, path, size); return; } - path_system_getter::parse_absolute(o_elements, type_idx, path, size); + path_system_getter::parse_abs(o_elements, type_idx, path, size); } @@ -305,7 +318,7 @@ int path_system_getter::deduce_system_type(const char* pat } template -bool path_system_getter::validate_abs_path(int type_idx, const tl::vector& members) noexcept +bool path_system_getter::validate_abs_path(int type_idx, tl::span members) noexcept { if (type_idx == Index) return Head::validate_abs_path(members); @@ -365,15 +378,12 @@ const tl::vector& base_path_system -string base_path_system::format_relative(const tl::vector& members) noexcept +template +T base_path_system::format_rel(tl::span members) noexcept { - eastl::string buffer; - buffer.reserve(8192); - detail::path_system::simple_format_rel_path(buffer, members, format_separator::value()); - if (buffer.data()) - return string(buffer.data(), buffer.size()); - - return string(); + T string; + detail::path_system::simple_format_rel_path(string, members, format_separator::value()); + return string; } ////////////////////////////////////////////////////////////////////////// diff --git a/include/tl/detail/path_view_base.h b/include/tl/detail/path_view_base.h new file mode 100644 index 0000000..babb68f --- /dev/null +++ b/include/tl/detail/path_view_base.h @@ -0,0 +1,219 @@ +#pragma once + +#include "tl/detail/prologue.h" +#include "tl/span.h" +#include "tl/string.h" +#include "tl/hash_and_combine.h" + +namespace tl +{ +namespace detail +{ +namespace path_system +{ + +class path_view_base; + +struct path_view_key_less +{ + bool operator()(const path_view_base& a1, const path_view_base& a2) const noexcept; +}; + +////////////////////////////////////////////////////////////////////////// + +// inner path_view_base definition +class path_view_base +{ +public: + path_view_base() noexcept; + path_view_base(tl::span elements) noexcept; + virtual ~path_view_base() noexcept = default; + using iterator = tl::span::iterator; + using const_iterator = tl::span::const_iterator; + using const_reverse_iterator = tl::span::const_reverse_iterator; + using key_less = path_view_key_less; + using value_type = std::string; + + //both have checked indexing + const string& at(size_t index) const noexcept; + const string& operator[](size_t index) const noexcept; + + void shrink(size_t size) noexcept; + + bool empty() const noexcept; + size_t size() const noexcept; + + void pop_back() noexcept; + + iterator begin() noexcept; + iterator end() noexcept; + const_iterator begin() const noexcept; + const_iterator end() const noexcept; + + const string& front() const noexcept; + const string& back() const noexcept; + + uint32_t hash() const noexcept; + +protected: + tl::span m_elements; + mutable uint32_t m_hash = 0; + + friend bool path_view_key_less::operator()(const path_view_base& a1, const path_view_base& a2) const noexcept; +}; + +////////////////////////////////////////////////////////////////////////// + + + +} +} +} + +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// + +namespace tl +{ +namespace detail +{ +namespace path_system +{ + +////////////////////////////////////////////////////////////////////////// + +inline path_view_base::path_view_base() noexcept +{ +} + +////////////////////////////////////////////////////////////////////////// + +inline path_view_base::path_view_base(tl::span elements) noexcept + : m_elements(elements) +{ +} + +////////////////////////////////////////////////////////////////////////// + +inline const string& path_view_base::operator[](size_t index) const noexcept +{ + if (index >= m_elements.size()) + TL_PLAIN_CRASH("Illegal access"); + return m_elements[index]; +} + +////////////////////////////////////////////////////////////////////////// + +inline const string& path_view_base::at(size_t index) const noexcept +{ + if (index >= m_elements.size()) + TL_PLAIN_CRASH("Illegal access"); + return m_elements[index]; +} + +////////////////////////////////////////////////////////////////////////// + +inline void path_view_base::shrink(size_t size) noexcept +{ + if (size < this->size()) + { + m_elements = tl::span(m_elements.data(), size); + m_hash = 0; + } +} + +////////////////////////////////////////////////////////////////////////// + +inline uint32_t path_view_base::hash() const noexcept +{ + if (m_hash == 0) + { + for (const string& e : *this) + hash_and_combine(m_hash, e); + } + return m_hash; +} + +////////////////////////////////////////////////////////////////////////// + +inline size_t path_view_base::size() const noexcept +{ + return m_elements.size(); +} + +////////////////////////////////////////////////////////////////////////// + +inline bool path_view_base::empty() const noexcept +{ + return m_elements.empty(); +} + +////////////////////////////////////////////////////////////////////////// + +inline void path_view_base::pop_back() noexcept +{ + if (empty()) + { + TL_PLAIN_FAIL(); + return; + } + + m_hash = 0; + m_elements = tl::span(m_elements.data(), m_elements.size() - 1); +} + +////////////////////////////////////////////////////////////////////////// + +inline path_view_base::iterator path_view_base::begin() noexcept +{ + return m_elements.begin(); +} + +////////////////////////////////////////////////////////////////////////// + +inline path_view_base::iterator path_view_base::end() noexcept +{ + return m_elements.end(); +} + +////////////////////////////////////////////////////////////////////////// + +inline path_view_base::const_iterator path_view_base::begin() const noexcept +{ + return m_elements.cbegin(); +} + +////////////////////////////////////////////////////////////////////////// + +inline path_view_base::const_iterator path_view_base::end() const noexcept +{ + return m_elements.cend(); +} + +inline const string& path_view_base::front() const noexcept +{ + return m_elements.front(); +} +inline const string& path_view_base::back() const noexcept +{ + return m_elements.back(); +} + +////////////////////////////////////////////////////////////////////////// + +inline bool path_view_key_less::operator()(const path_view_base& a1, const path_view_base& a2) const noexcept +{ + const size_t sz1 = a1.size(); + const size_t sz2 = a2.size(); + for (size_t i = 0; i < sz1 && i < sz2; ++i) + { + if (a1[i] != a2[i]) + return a1[i].unique_key() < a2[i].unique_key(); + } + return sz1 < sz2; +} + +} +} +} diff --git a/include/tl/path_system.h b/include/tl/path_system.h index 84ba0d5..5c078e3 100644 --- a/include/tl/path_system.h +++ b/include/tl/path_system.h @@ -1,6 +1,7 @@ #pragma once #include "tl/detail/prologue.h" +#include #include #include #include "tl/string.h" @@ -60,11 +61,11 @@ template struct path_systems { template - static T format_absolute(int type_id, const tl::vector& members) noexcept; - static void parse_absolute(tl::vector& o_elements, int type_id, const char* path, size_t size) noexcept; + static T format_abs(int type_id, tl::span members) noexcept; + static void parse_abs(tl::vector& o_elements, int type_id, const char* path, size_t size) noexcept; static void parse_relative(tl::vector& o_elements, const char* path, size_t size) noexcept; static int deduce_system_type(const char* path, size_t size) noexcept; - static bool validate_abs_path(int type_id, const tl::vector& members) noexcept; + static bool validate_abs_path(int type_id, tl::span members) noexcept; static const tl::vector >& get_all_parse_separators() noexcept; template @@ -84,9 +85,9 @@ template { template - static T format_absolute(const tl::vector& members) noexcept; - static void parse_absolute(tl::vector& o_elements, const char* path, size_t size) noexcept; - static bool validate_abs_path(const tl::vector& members) noexcept; + static T format_abs(tl::span members) noexcept; + static void parse_abs(tl::vector& o_elements, const char* path, size_t size) noexcept; + static bool validate_abs_path(tl::span members) noexcept; static bool match(const char* path, size_t size) noexcept; }; @@ -105,19 +106,19 @@ namespace tl template template -T path_systems::format_absolute(int type_id, const tl::vector& members) noexcept +T path_systems::format_abs(int type_id, tl::span members) noexcept { TL_PLAIN_ASSERT(type_id >= 0, "Error: trying to format an unknown path system type."); - return detail::path_system::path_system_getter<0, Systems...>::template format_absolute(type_id, members); + return detail::path_system::path_system_getter<0, Systems...>::template format_abs(type_id, members); } ////////////////////////////////////////////////////////////////////////// template -void path_systems::parse_absolute(tl::vector& o_elements, int type_id, const char* path, size_t size) noexcept +void path_systems::parse_abs(tl::vector& o_elements, int type_id, const char* path, size_t size) noexcept { TL_PLAIN_ASSERT(type_id >= 0, "Error: trying to parse an unknown path system type."); - detail::path_system::path_system_getter<0, Systems...>::parse_absolute(o_elements, type_id, path, size); + detail::path_system::path_system_getter<0, Systems...>::parse_abs(o_elements, type_id, path, size); } ////////////////////////////////////////////////////////////////////////// @@ -131,7 +132,7 @@ int path_systems::deduce_system_type(const char* path, size_t size) ////////////////////////////////////////////////////////////////////////// template -bool path_systems::validate_abs_path(int type_id, const tl::vector& members) noexcept +bool path_systems::validate_abs_path(int type_id, tl::span members) noexcept { TL_PLAIN_ASSERT(type_id >= 0, "Error: trying to validate an unknown path system type."); return detail::path_system::path_system_getter<0, Systems...>::validate_abs_path(type_id, members); @@ -232,7 +233,7 @@ bool path_systems::is(int type_id) noexcept template template -T simple_path_system::format_absolute(const tl::vector& members) noexcept +T simple_path_system::format_abs(tl::span members) noexcept { if constexpr (is_same_v) { @@ -252,7 +253,7 @@ T simple_path_system::format_absol ////////////////////////////////////////////////////////////////////////// template -void simple_path_system::parse_absolute(tl::vector& o_elements, const char* path, size_t size) noexcept +void simple_path_system::parse_abs(tl::vector& o_elements, const char* path, size_t size) noexcept { detail::path_system::simple_parse_path(o_elements, path, size, root_tag::value(), parse_separators::vector()); } @@ -268,7 +269,7 @@ bool simple_path_system::match(con ////////////////////////////////////////////////////////////////////////// template -bool simple_path_system::validate_abs_path(const tl::vector& /*members*/) noexcept +bool simple_path_system::validate_abs_path(tl::span /*members*/) noexcept { return true; } diff --git a/include/tl/rel_path.h b/include/tl/rel_path.h index 453dcd4..7a81555 100644 --- a/include/tl/rel_path.h +++ b/include/tl/rel_path.h @@ -2,6 +2,8 @@ #include "tl/detail/prologue.h" #include + +#include "tl/rel_path_view.h" #include "tl/path_system.h" #include "tl/detail/path_base.h" #include "tl/plain_crash.h" @@ -18,7 +20,11 @@ class rel_path : public detail::path_system::path_base { template friend class abs_path; public: - rel_path() noexcept; + using path_view_type = rel_path_view; + + rel_path() noexcept = default; + rel_path(rel_path_view view) noexcept; + rel_path(span elements) noexcept; explicit rel_path(const char* path) noexcept; rel_path(const char* path, size_t size) noexcept; template @@ -27,54 +33,68 @@ public: rel_path(const rel_path& other) noexcept; rel_path(rel_path&& other) noexcept; - // for retro-compatibility with old path system rel_path(const rel_path& from, const rel_path& to) noexcept; // operators - const string& operator[](size_t idx) const noexcept; - rel_path& operator=(const char* path) noexcept; rel_path& operator=(const rel_path& other) noexcept; rel_path& operator=(rel_path&& other) noexcept; template rel_path& operator=(const Str& path) noexcept; + rel_path& operator=(const rel_path_view& path) noexcept; rel_path operator+(const char* path) const noexcept; rel_path operator+(const rel_path& path) const noexcept; rel_path operator+(rel_path&& path) const noexcept; template rel_path operator+(const Str& path) const noexcept; + rel_path operator+(const rel_path_view& path) const noexcept; rel_path& operator+=(const char* path) noexcept; rel_path& operator+=(const rel_path& path) noexcept; rel_path& operator+=(rel_path&& path) noexcept; template rel_path& operator+=(const Str& path) noexcept; + rel_path& operator+=(const rel_path_view& path) noexcept; + + operator rel_path_view() const noexcept; bool operator==(const rel_path& other) const noexcept; bool operator!=(const rel_path& other) const noexcept; + auto operator<=>(const rel_path& other) const noexcept; - auto operator<=>(const rel_path& other) const noexcept; + bool operator==(const rel_path_view& other) const noexcept; + bool operator!=(const rel_path_view& other) const noexcept; + auto operator<=>(const rel_path_view& other) const noexcept; void swap(rel_path& other) noexcept; void clear() noexcept; template - string get_as() const noexcept; + string str() const noexcept; - rel_path subpath(size_t index, int count = 0) const noexcept; + template + eastl::string eastl_str() const noexcept; + + template + std::string std_str() const noexcept; + + template + rel_path_view view() const noexcept; + + + rel_path_view subpath(size_t index, int count = 0) const noexcept; rel_path parent() const noexcept; - bool is_prefix_of(const rel_path& path) const noexcept; + bool is_prefix_of(const rel_path& path) const noexcept; - string pop_front() noexcept; - void push_front(string element) noexcept; - bool push_back(string element) noexcept override; + string pop_front() noexcept; + void push_front(string element) noexcept; + bool push_back(string element) noexcept override; - const string& front() const noexcept; - const string& back() const noexcept; - string& front() noexcept; - string& back() noexcept; + const string& front() const noexcept; + const string& back() const noexcept; + void replace_back(string element) noexcept; void collapse_path() noexcept; @@ -105,9 +125,18 @@ namespace tl ////////////////////////////////////////////////////////////////////////// template -rel_path::rel_path() noexcept +rel_path::rel_path(rel_path_view view) noexcept { - this->m_hash = 0; + this->m_elements.insert(this->m_elements.end(), view.begin(), view.end()); + this->m_hash = view.hash(); +} + +////////////////////////////////////////////////////////////////////////// + +template +rel_path::rel_path(span elements) noexcept +{ + this->m_elements.insert(this->m_elements.end(), elements.begin(), elements.end()); } ////////////////////////////////////////////////////////////////////////// @@ -195,14 +224,8 @@ rel_path::rel_path(const rel_path& from, const rel_path& to) noexce for (size_t i = last; i < to.size(); i++) this->push_element(to.m_elements[i]); -} -//////////////////////////////////////////////////////////////////////////////////////////////////////////// - -template -const string& rel_path::operator[](size_t idx) const noexcept -{ - return this->m_elements[idx]; + collapse_path(); } //////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -237,6 +260,17 @@ rel_path& rel_path::operator=(const Str& path) noexcep return *this; } +//////////////////////////////////////////////////////////////////////////////////////////////////////////// + +template +rel_path& rel_path::operator=(const rel_path_view& path) noexcept +{ + this->m_elements.clear(); + this->m_elements.insert(this->m_elements.end(), path.m_elements.begin(), path.m_elements.end()); + this->m_hash = path.m_hash; + return *this; +} + ////////////////////////////////////////////////////////////////////////// template @@ -262,21 +296,9 @@ rel_path rel_path::operator+(const char* path) const n p.reserve(this->size() + 1); p = *this; - size_t old_index = p.size(); //this will push pack in the m_elements PathSystems::parse_relative(p.m_elements, path, strlen(path)); - for (size_t i = old_index; i < p.m_elements.size(); ++i) - { - const string& element = p.m_elements[i]; - if (!p.validate_element(element)) - { - TL_PLAIN_FAIL("Failed to parse path"); - p.m_elements.resize(old_index); - return p; - } - } - p.collapse_path(); return p; @@ -296,21 +318,9 @@ rel_path rel_path::operator+(const Str& path) const no p.reserve(this->size() + 1); p = *this; - size_t old_index = p.size(); //this will push pack in the m_elements PathSystems::parse_relative(p.m_elements, path.data(), path.size()); - for (size_t i = old_index; i < p.m_elements.size(); ++i) - { - const string& element = p.m_elements[i]; - if (!p.validate_element(element)) - { - TL_PLAIN_FAIL("Failed to parse path"); - p.m_elements.resize(old_index); - return p; - } - } - p.collapse_path(); return p; @@ -328,7 +338,22 @@ rel_path rel_path::operator+(const rel_path& path) con rel_path p; p.reserve(this->size() + path.size()); p = *this; + p += path; + return p; + } + return *this; +} +////////////////////////////////////////////////////////////////////////// + +template +rel_path rel_path::operator+(const rel_path_view& path) const noexcept +{ + if (!path.empty()) + { + rel_path p; + p.reserve(this->size() + path.size()); + p = *this; p += path; return p; } @@ -345,7 +370,6 @@ rel_path rel_path::operator+(rel_path&& path) const no rel_path p; p.reserve(this->size() + path.size()); p = *this; - p += std::move(path); return p; } @@ -359,21 +383,9 @@ rel_path& rel_path::operator+=(const char* path) noexc { if (path && path[0] != '\0') { - size_t old_index = this->size(); //this will push pack in the m_elements PathSystems::parse_relative(this->m_elements, path, strlen(path)); - for (size_t i = old_index; i < this->m_elements.size(); ++i) - { - const string& element = this->m_elements[i]; - if (!this->validate_element(element)) - { - TL_PLAIN_FAIL("Failed to parse path"); - this->m_elements.resize(old_index); - return *this; - } - } - this->m_hash = 0; collapse_path(); } @@ -388,21 +400,9 @@ rel_path& rel_path::operator+=(const Str& path) noexce { if (!path.empty()) { - size_t old_index = this->size(); //this will push pack in the m_elements PathSystems::parse_relative(this->m_elements, path.data(), path.size()); - for (size_t i = old_index; i < this->m_elements.size(); ++i) - { - const string& element = this->m_elements[i]; - if (!this->validate_element(element)) - { - TL_PLAIN_FAIL("Failed to parse path"); - this->m_elements.resize(old_index); - return *this; - } - } - this->m_hash = 0; collapse_path(); } @@ -443,6 +443,31 @@ rel_path& rel_path::operator+=(rel_path&& path) noexce return *this; } +////////////////////////////////////////////////////////////////////////// + +template +rel_path& rel_path::operator+=(const rel_path_view& path) noexcept +{ + if (!path.empty()) + { + this->m_elements.reserve(this->m_elements.size() + path.m_elements.size()); + for (const string& element : path.m_elements) + this->push_element(element); + + this->m_hash = 0; + this->collapse_path(); + } + return *this; +} + +////////////////////////////////////////////////////////////////////////// + +template +rel_path::operator rel_path_view() const noexcept +{ + return rel_path_view(this->m_elements); +} + //////////////////////////////////////////////////////////////////////////////////////////////////////////// template @@ -474,7 +499,42 @@ auto rel_path::operator<=>(const rel_path& other) const noexcept return r; } - return sz1 <=> sz2;} + return sz1 <=> sz2; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////// + +template +bool rel_path::operator==(const rel_path_view& other) const noexcept +{ + return (!this->m_hash || !other.m_hash || this->m_hash == other.m_hash) && + tl::span(this->m_elements) == other.m_elements; +} + +////////////////////////////////////////////////////////////////////////// + +template +bool rel_path::operator!=(const rel_path_view& other) const noexcept +{ + return !(*this == other); +} + +////////////////////////////////////////////////////////////////////////// + +template +auto rel_path::operator<=>(const rel_path_view& other) const noexcept +{ + const size_t sz1 = this->m_elements.size(); + const size_t sz2 = other.m_elements.size(); + for (size_t i = 0; i < sz1 && i < sz2; ++i) + { + auto r = this->m_elements[i] <=> other.m_elements[i]; + if (r != decltype(r)::equal) + return r; + } + + return sz1 <=> sz2; +} ////////////////////////////////////////////////////////////////////////// @@ -487,15 +547,6 @@ bool rel_path::parse(const char* path, size_t size) noexcept PathSystems::parse_relative(this->m_elements, path, size); - for (const string& element : this->m_elements) - { - if (!this->validate_element(element)) - { - this->clear(); - return false; - } - } - collapse_path(); return true; @@ -508,18 +559,21 @@ void rel_path::collapse_path() noexcept { if (!this->empty()) { - this->m_hash = 0; for (size_t i = 0; i < this->m_elements.size();) { if (i >= 1 && this->m_elements[i] == path_system::back_t::value() && this->m_elements[i - 1] != path_system::back_t::value()) { + this->m_hash = 0; this->m_elements.erase(this->m_elements.begin() + i - 1, this->m_elements.begin() + i + 1); //remove the .. and the parent i -= 1; } else if (this->m_elements[i] == path_system::current_t::value()) - this->m_elements.erase(this->m_elements.begin() + i); //remove the . + { + this->m_hash = 0; + this->m_elements.erase(this->m_elements.begin() + i); //remove the . + } else i++; } @@ -534,7 +588,7 @@ bool rel_path::is_prefix_of(const rel_path& path) const noexcept if (this->size() > path.size()) return false; - for (size_t i = 0, _count = this->size(); i < _count; ++i) + for (size_t i = 0, sz = this->size(); i < sz; ++i) { if (this->m_elements[i] != path[i]) return false; @@ -557,7 +611,7 @@ void rel_path::swap(rel_path& other) noexcept template void rel_path::clear() noexcept { - this->m_elements.resize(0); + this->m_elements.clear(); this->m_hash = 0; } @@ -565,17 +619,43 @@ void rel_path::clear() noexcept template template -string rel_path::get_as() const noexcept +string rel_path::str() const noexcept { - return FormatSystem::format_relative(this->m_elements); + return FormatSystem::template format_rel(this->m_elements); +} + +////////////////////////////////////////////////////////////////////////// + +template +template +eastl::string rel_path::eastl_str() const noexcept +{ + return FormatSystem::template format_rel(this->m_elements); +} + +////////////////////////////////////////////////////////////////////////// + +template +template +std::string rel_path::std_str() const noexcept +{ + return FormatSystem::template format_rel(this->m_elements); } ////////////////////////////////////////////////////////////////////////// template -rel_path rel_path::subpath(size_t index, int count /* = 0 */) const noexcept +template +rel_path_view rel_path::view() const noexcept +{ + return rel_path_view(this->m_elements); +} + +////////////////////////////////////////////////////////////////////////// + +template +rel_path_view rel_path::subpath(size_t index, int count /* = 0 */) const noexcept { - rel_path dst; if (count == 0) count = (int)this->size() - (int)index; @@ -583,12 +663,9 @@ rel_path rel_path::subpath(size_t index, int count /* count = (int)this->size() - (int)index + count; if (count > 0 && index < this->size()) - { - dst.m_elements.resize(count); - for (int i = 0; i < count; i++) - dst.m_elements[i] = this->m_elements[index + i]; - } - return dst; + return rel_path_view(tl::span(this->m_elements.begin() + index, this->m_elements.begin() + index + count)); + + return {}; } ////////////////////////////////////////////////////////////////////////// @@ -637,21 +714,15 @@ const string& rel_path::front() const noexcept ////////////////////////////////////////////////////////////////////////// template -string& rel_path::front() noexcept +void rel_path::replace_back(string element) noexcept { TL_PLAIN_ASSERT(!this->empty()); + const bool is_back_element = element == path_system::back_t::value(); this->m_hash = 0; - return this->m_elements.front(); -} + this->m_elements.back() = std::move(element); -////////////////////////////////////////////////////////////////////////// - -template -string& rel_path::back() noexcept -{ - TL_PLAIN_ASSERT(!this->empty()); - this->m_hash = 0; - return this->m_elements.back(); + if (is_back_element) + collapse_path(); } ////////////////////////////////////////////////////////////////////////// @@ -674,8 +745,12 @@ string rel_path::pop_front() noexcept template void rel_path::push_front(string element) noexcept { + const bool is_back_element = element == path_system::back_t::value(); this->m_hash = 0; this->m_elements.insert(this->m_elements.begin(), std::move(element)); + + if (is_back_element) + collapse_path(); } ////////////////////////////////////////////////////////////////////////// @@ -719,6 +794,43 @@ other_rel_path rel_path::move_cast_to() noexcept return ret; } +template +rel_path operator+(const rel_path_view& a, const char* b) noexcept +{ + rel_path p; + p.reserve(a.size() + 1); + p = a; + p += b; + return p; +} +template requires (!std::is_same_v && !std::is_same_v) +rel_path operator+(const rel_path_view& a, const Str& b) noexcept +{ + rel_path p; + p.reserve(a.size() + 1); + p = a; + p += b; + return p; +} +template +rel_path operator+(const rel_path_view& a, const rel_path& b) noexcept +{ + rel_path p; + p.reserve(a.size() + b.size()); + p = a; + p += b; + return p; +} +template +rel_path operator+(const rel_path_view& a, const rel_path_view& b) noexcept +{ + rel_path p; + p.reserve(a.size() + b.size()); + p = a; + p += b; + return p; +} + } @@ -730,7 +842,7 @@ struct std::formatter>> constexpr auto parse(format_parse_context& ctx) noexcept { return ctx.begin(); } auto format(const tl::rel_path>& p, std::format_context& ctx) const { - return format_to(ctx.out(), "{}", p.template get_as()); + return format_to(ctx.out(), "{}", p.template str()); } }; diff --git a/include/tl/rel_path_view.h b/include/tl/rel_path_view.h new file mode 100644 index 0000000..c0dc5fb --- /dev/null +++ b/include/tl/rel_path_view.h @@ -0,0 +1,277 @@ +#pragma once + +#include "tl/detail/prologue.h" +#include +#include "tl/path_system.h" +#include "tl/rel_path_view.h" +#include "tl/detail/path_view_base.h" +#include "tl/plain_crash.h" +#include "tl/format.h" + +namespace tl +{ + +template class rel_path; +template class rel_path_view; +template struct path_view_key_less; + +////////////////////////////////////////////////////////////////////////// + +template +class rel_path_view : public detail::path_system::path_view_base +{ + template friend class rel_path_view; + +public: + using rel_path_view_type = rel_path_view; + + rel_path_view() noexcept; + rel_path_view(tl::span elements) noexcept; + + rel_path_view(const rel_path_view& other) noexcept; + + // operators + rel_path_view& operator=(const rel_path_view& other) noexcept; + + bool operator==(const rel_path_view& other) const noexcept; + bool operator!=(const rel_path_view& other) const noexcept; + auto operator<=>(const rel_path_view& other) const noexcept; + + void clear() noexcept; + + template + string str() const noexcept; + + template + eastl::string eastl_str() const noexcept; + + template + std::string std_str() const noexcept; + + rel_path_view subpath(size_t idx, int count = 0) const noexcept; + rel_path_view parent() const noexcept; + rel_path_view parent(size_t levels) const noexcept; + bool is_prefix_of(const rel_path_view& path) const noexcept; + + template + other_rel_path cast_to() const noexcept; + +private: + friend class rel_path; +}; + +////////////////////////////////////////////////////////////////////////// + +} + +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// + +namespace tl +{ +////////////////////////////////////////////////////////////////////////// + +template +rel_path_view::rel_path_view() noexcept +{ +} + +////////////////////////////////////////////////////////////////////////// + +template +rel_path_view::rel_path_view(tl::span elements) noexcept + : path_view_base(elements) +{ +} + +////////////////////////////////////////////////////////////////////////// + +template +rel_path_view::rel_path_view(const rel_path_view& other) noexcept + : path_view_base(other) +{ +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////// + +template +rel_path_view& rel_path_view::operator=(const rel_path_view& other) noexcept +{ + m_elements = other.m_elements; + m_hash = other.m_hash; + return *this; +} + +////////////////////////////////////////////////////////////////////////// + +template +bool rel_path_view::operator==(const rel_path_view& other) const noexcept +{ + return (!this->m_hash || !other.m_hash || this->m_hash == other.m_hash) && + this->m_elements == other.m_elements; +} + +////////////////////////////////////////////////////////////////////////// + +template +bool rel_path_view::operator!=(const rel_path_view& other) const noexcept +{ + return !(*this == other); +} + +////////////////////////////////////////////////////////////////////////// + +template +void rel_path_view::clear() noexcept +{ + m_elements = {}; + m_hash = 0; +} + +////////////////////////////////////////////////////////////////////////// + +template +template +string rel_path_view::str() const noexcept +{ + if (this->empty()) + return {}; + + return FormatSystem::template format_rel(this->m_elements); +} + +////////////////////////////////////////////////////////////////////////// + +template +template +eastl::string rel_path_view::eastl_str() const noexcept +{ + if (this->empty()) + return {}; + + return FormatSystem::template format_rel(this->m_elements); +} + +////////////////////////////////////////////////////////////////////////// + +template +template +std::string rel_path_view::std_str() const noexcept +{ + if (this->empty()) + return {}; + + return FormatSystem::template format_rel(this->m_elements); +} + +////////////////////////////////////////////////////////////////////////// + +template +rel_path_view rel_path_view::subpath(size_t idx, int count /* = 0 */) const noexcept +{ + if (count == 0) + count = (int)this->size() - (int)idx; + + if (count < 0) + count = (int)this->size() - (int)idx + count; + + if (count > 0 && idx < this->size()) + return rel_path_view(tl::span(this->m_elements.begin() + idx, this->m_elements.begin() + idx + count)); + + return {}; +} + +////////////////////////////////////////////////////////////////////////// + +template +rel_path_view rel_path_view::parent() const noexcept +{ + if (this->empty()) + { + TL_PLAIN_FAIL("Invalid path"); + return {}; + } + + rel_path_view p = *this; + p.pop_back(); + return p; +} + +////////////////////////////////////////////////////////////////////////// + +template +rel_path_view rel_path_view::parent(size_t levels) const noexcept +{ + if (this->empty() || this->size() <= levels) + { + TL_PLAIN_FAIL("Invalid path"); + return {}; + } + + rel_path_view p = *this; + p.shrink(p.size() - levels); + + return p; +} + +////////////////////////////////////////////////////////////////////////// + +template +bool rel_path_view::is_prefix_of(const rel_path_view& path) const noexcept +{ + if (this->size() > path.size()) + return false; + + for (size_t i = 0, _count = this->size(); i < _count; ++i) + { + if ((*this)[i] != path[i]) + return false; + } + + return true; +} + +////////////////////////////////////////////////////////////////////////// + +template +template +other_rel_path rel_path_view::cast_to() const noexcept +{ + return other_rel_path(this->m_elements); +} + + +} + +////////////////////////////////////////////////////////////////////////// + +template +struct std::formatter>> +{ + constexpr auto parse(format_parse_context& ctx) noexcept { return ctx.begin(); } + auto format(const tl::rel_path_view>& p, std::format_context& ctx) const + { + return format_to(ctx.out(), "{}", p.template str()); + } +}; + +template +struct std::hash> +{ + std::size_t operator()(const tl::rel_path_view& p) const + { + return p.hash(); + } +}; + + +template +struct eastl::hash> +{ + std::size_t operator()(const tl::rel_path_view& p) const + { + return p.hash(); + } +}; + diff --git a/include/tl/utest.h b/include/tl/utest.h new file mode 100644 index 0000000..b59b5dd --- /dev/null +++ b/include/tl/utest.h @@ -0,0 +1,1700 @@ +/* + The latest version of this library is available on GitHub; + https://github.com/sheredom/utest.h +*/ + +/* + This is free and unencumbered software released into the public domain. + + Anyone is free to copy, modify, publish, use, compile, sell, or + distribute this software, either in source code form or as a compiled + binary, for any purpose, commercial or non-commercial, and by any + means. + + In jurisdictions that recognize copyright laws, the author or authors + of this software dedicate any and all copyright interest in the + software to the public domain. We make this dedication for the benefit + of the public at large and to the detriment of our heirs and + successors. We intend this dedication to be an overt act of + relinquishment in perpetuity of all present and future rights to this + software under copyright law. + + 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 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. + + For more information, please refer to +*/ + +#ifndef SHEREDOM_UTEST_H_INCLUDED +#define SHEREDOM_UTEST_H_INCLUDED + +#ifdef _MSC_VER +/* + Disable warning about not inlining 'inline' functions. +*/ +#pragma warning(disable : 4710) + +/* + Disable warning about inlining functions that are not marked 'inline'. +*/ +#pragma warning(disable : 4711) + +/* + Disable warning for alignment padding added +*/ +#pragma warning(disable : 4820) + +#if _MSC_VER > 1900 +/* + Disable warning about preprocessor macros not being defined in MSVC headers. +*/ +#pragma warning(disable : 4668) + +/* + Disable warning about no function prototype given in MSVC headers. +*/ +#pragma warning(disable : 4255) + +/* + Disable warning about pointer or reference to potentially throwing function. +*/ +#pragma warning(disable : 5039) + +/* + Disable warning about macro expansion producing 'defined' has undefined + behavior. +*/ +#pragma warning(disable : 5105) +#endif + +#if _MSC_VER > 1930 +/* + Disable warning about 'const' variable is not used. +*/ +#pragma warning(disable : 5264) +#endif + +#pragma warning(push, 1) +#endif + +#if defined(_MSC_VER) && (_MSC_VER < 1920) +typedef __int64 utest_int64_t; +typedef unsigned __int64 utest_uint64_t; +typedef unsigned __int32 utest_uint32_t; +#else +#include +typedef int64_t utest_int64_t; +typedef uint64_t utest_uint64_t; +typedef uint32_t utest_uint32_t; +#endif + +#include +#include +#include +#include +#include + +#if defined(__cplusplus) +#if defined(_MSC_VER) && !defined(_CPPUNWIND) +/* We're on MSVC and the compiler is compiling without exception support! */ +#elif !defined(_MSC_VER) && !defined(__EXCEPTIONS) +/* We're on a GCC/Clang compiler that doesn't have exception support! */ +#else +#define UTEST_HAS_EXCEPTIONS 1 +#endif +#endif + +#if defined(UTEST_HAS_EXCEPTIONS) +#include +#endif + +#if defined(_MSC_VER) +#pragma warning(pop) +#endif + +#if defined(__cplusplus) +#define UTEST_C_FUNC extern "C" +#else +#define UTEST_C_FUNC +#endif + +#define UTEST_TEST_PASSED (0) +#define UTEST_TEST_FAILURE (1) +#define UTEST_TEST_SKIPPED (2) + +#if defined(__TINYC__) +#define UTEST_ATTRIBUTE(a) __attribute((a)) +#else +#define UTEST_ATTRIBUTE(a) __attribute__((a)) +#endif + +#if defined(_MSC_VER) || defined(__MINGW64__) || defined(__MINGW32__) + +#if defined(__MINGW64__) || defined(__MINGW32__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wpragmas" +#pragma GCC diagnostic ignored "-Wunknown-pragmas" +#endif + +#if defined(_WINDOWS_) || defined(_WINDOWS_H) +typedef LARGE_INTEGER utest_large_integer; +#else +// use old QueryPerformanceCounter definitions (not sure is this needed in some +// edge cases or not) on Win7 with VS2015 these extern declaration cause "second +// C linkage of overloaded function not allowed" error +typedef union { + struct { + unsigned long LowPart; + long HighPart; + } DUMMYSTRUCTNAME; + struct { + unsigned long LowPart; + long HighPart; + } u; + utest_int64_t QuadPart; +} utest_large_integer; + +UTEST_C_FUNC __declspec(dllimport) int __stdcall QueryPerformanceCounter( + utest_large_integer *); +UTEST_C_FUNC __declspec(dllimport) int __stdcall QueryPerformanceFrequency( + utest_large_integer *); + +#if defined(__MINGW64__) || defined(__MINGW32__) +#pragma GCC diagnostic pop +#endif +#endif + +#elif defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) || \ + defined(__NetBSD__) || defined(__DragonFly__) || defined(__sun__) || \ + defined(__HAIKU__) +/* + slightly obscure include here - we need to include glibc's features.h, but + we don't want to just include a header that might not be defined for other + c libraries like musl. Instead we include limits.h, which we know on all + glibc distributions includes features.h +*/ +#include + +#if defined(__GLIBC__) && defined(__GLIBC_MINOR__) +#include + +#if ((2 < __GLIBC__) || ((2 == __GLIBC__) && (17 <= __GLIBC_MINOR__))) +/* glibc is version 2.17 or above, so we can just use clock_gettime */ +#define UTEST_USE_CLOCKGETTIME +#else +#include +#include +#endif +#else // Other libc implementations +#include +#define UTEST_USE_CLOCKGETTIME +#endif + +#elif defined(__APPLE__) +#include +#endif + +#if defined(_MSC_VER) && (_MSC_VER < 1920) +#define UTEST_PRId64 "I64d" +#define UTEST_PRIu64 "I64u" +#else +#include + +#define UTEST_PRId64 PRId64 +#define UTEST_PRIu64 PRIu64 +#endif + +#if defined(__cplusplus) +#define UTEST_INLINE inline + +#if defined(__clang__) +#define UTEST_INITIALIZER_BEGIN_DISABLE_WARNINGS \ + _Pragma("clang diagnostic push") \ + _Pragma("clang diagnostic ignored \"-Wglobal-constructors\"") + +#define UTEST_INITIALIZER_END_DISABLE_WARNINGS _Pragma("clang diagnostic pop") +#else +#define UTEST_INITIALIZER_BEGIN_DISABLE_WARNINGS +#define UTEST_INITIALIZER_END_DISABLE_WARNINGS +#endif + +#define UTEST_INITIALIZER(f) \ + struct f##_cpp_struct { \ + f##_cpp_struct(); \ + }; \ + UTEST_INITIALIZER_BEGIN_DISABLE_WARNINGS static f##_cpp_struct \ + f##_cpp_global UTEST_INITIALIZER_END_DISABLE_WARNINGS; \ + f##_cpp_struct::f##_cpp_struct() +#elif defined(_MSC_VER) +#define UTEST_INLINE __forceinline + +#if defined(_WIN64) +#define UTEST_SYMBOL_PREFIX +#else +#define UTEST_SYMBOL_PREFIX "_" +#endif + +#if defined(__clang__) +#define UTEST_INITIALIZER_BEGIN_DISABLE_WARNINGS \ + _Pragma("clang diagnostic push") \ + _Pragma("clang diagnostic ignored \"-Wmissing-variable-declarations\"") + +#define UTEST_INITIALIZER_END_DISABLE_WARNINGS _Pragma("clang diagnostic pop") +#else +#define UTEST_INITIALIZER_BEGIN_DISABLE_WARNINGS +#define UTEST_INITIALIZER_END_DISABLE_WARNINGS +#endif + +#pragma section(".CRT$XCU", read) +#define UTEST_INITIALIZER(f) \ + static void __cdecl f(void); \ + UTEST_INITIALIZER_BEGIN_DISABLE_WARNINGS \ + __pragma(comment(linker, "/include:" UTEST_SYMBOL_PREFIX #f "_")) \ + UTEST_C_FUNC __declspec(allocate(".CRT$XCU")) void(__cdecl * \ + f##_)(void) = f; \ + UTEST_INITIALIZER_END_DISABLE_WARNINGS \ + static void __cdecl f(void) +#else +#if defined(__linux__) +#if defined(__clang__) +#if __has_warning("-Wreserved-id-macro") +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wreserved-id-macro" +#endif +#endif + +#define __STDC_FORMAT_MACROS 1 + +#if defined(__clang__) +#if __has_warning("-Wreserved-id-macro") +#pragma clang diagnostic pop +#endif +#endif +#endif + +#define UTEST_INLINE inline + +#define UTEST_INITIALIZER(f) \ + static void f(void) UTEST_ATTRIBUTE(constructor); \ + static void f(void) +#endif + +#if defined(__cplusplus) +#define UTEST_CAST(type, x) static_cast(x) +#define UTEST_PTR_CAST(type, x) reinterpret_cast(x) +#define UTEST_EXTERN extern "C" +#define UTEST_NULL NULL +#else +#define UTEST_CAST(type, x) ((type)(x)) +#define UTEST_PTR_CAST(type, x) ((type)(x)) +#define UTEST_EXTERN extern +#define UTEST_NULL 0 +#endif + +#ifdef _MSC_VER +/* + io.h contains definitions for some structures with natural padding. This is + uninteresting, but for some reason MSVC's behaviour is to warn about + including this system header. That *is* interesting +*/ +#pragma warning(disable : 4820) +#pragma warning(push, 1) +#include +#pragma warning(pop) +#define UTEST_COLOUR_OUTPUT() (_isatty(_fileno(stdout))) +#else +#if defined(__EMSCRIPTEN__) +#include +#define UTEST_COLOUR_OUTPUT() false +#else +#include +#define UTEST_COLOUR_OUTPUT() (isatty(STDOUT_FILENO)) +#endif +#endif + +static UTEST_INLINE void *utest_realloc(void *const pointer, size_t new_size) { + void *const new_pointer = realloc(pointer, new_size); + + if (UTEST_NULL == new_pointer) { + free(pointer); + } + + return new_pointer; +} + +static UTEST_INLINE utest_int64_t utest_ns(void) { +#if defined(_MSC_VER) || defined(__MINGW64__) || defined(__MINGW32__) + utest_large_integer counter; + utest_large_integer frequency; + QueryPerformanceCounter(&counter); + QueryPerformanceFrequency(&frequency); + return UTEST_CAST(utest_int64_t, + (counter.QuadPart * 1000000000) / frequency.QuadPart); +#elif defined(__linux__) && defined(__STRICT_ANSI__) + return UTEST_CAST(utest_int64_t, clock()) * 1000000000 / CLOCKS_PER_SEC; +#elif defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) || \ + defined(__NetBSD__) || defined(__DragonFly__) || defined(__sun__) || \ + defined(__HAIKU__) + struct timespec ts; +#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) && \ + !defined(__HAIKU__) + timespec_get(&ts, TIME_UTC); +#else + const clockid_t cid = CLOCK_REALTIME; +#if defined(UTEST_USE_CLOCKGETTIME) + clock_gettime(cid, &ts); +#else + syscall(SYS_clock_gettime, cid, &ts); +#endif +#endif + return UTEST_CAST(utest_int64_t, ts.tv_sec) * 1000 * 1000 * 1000 + ts.tv_nsec; +#elif __APPLE__ + return UTEST_CAST(utest_int64_t, clock_gettime_nsec_np(CLOCK_UPTIME_RAW)); +#elif __EMSCRIPTEN__ + return emscripten_performance_now() * 1000000.0; +#else +#error Unsupported platform! +#endif +} + +typedef void (*utest_testcase_t)(int *, size_t); + +struct utest_test_state_s { + utest_testcase_t func; + size_t index; + char *name; +}; + +struct utest_state_s { + struct utest_test_state_s *tests; + size_t tests_length; + FILE *output; +}; + +/* extern to the global state utest needs to execute */ +UTEST_EXTERN struct utest_state_s utest_state; + +#if defined(_MSC_VER) +#define UTEST_WEAK __forceinline +#elif defined(__MINGW32__) || defined(__MINGW64__) +#define UTEST_WEAK static UTEST_ATTRIBUTE(used) +#elif defined(__clang__) || defined(__GNUC__) || defined(__TINYC__) +#define UTEST_WEAK UTEST_ATTRIBUTE(weak) +#else +#error Non clang, non gcc, non MSVC, non tcc compiler found! +#endif + +#if defined(_MSC_VER) +#define UTEST_UNUSED +#else +#define UTEST_UNUSED UTEST_ATTRIBUTE(unused) +#endif + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wvariadic-macros" +#pragma clang diagnostic ignored "-Wc++98-compat-pedantic" +#endif +#define UTEST_PRINTF(...) \ + if (utest_state.output) { \ + fprintf(utest_state.output, __VA_ARGS__); \ + } \ + printf(__VA_ARGS__) +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wvariadic-macros" +#pragma clang diagnostic ignored "-Wc++98-compat-pedantic" +#endif + +#ifdef _MSC_VER +#define UTEST_SNPRINTF(BUFFER, N, ...) _snprintf_s(BUFFER, N, N, __VA_ARGS__) +#else +#define UTEST_SNPRINTF(...) snprintf(__VA_ARGS__) +#endif + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +#if defined(__cplusplus) +/* if we are using c++ we can use overloaded methods (its in the language) */ +#define UTEST_OVERLOADABLE +#elif defined(__clang__) +/* otherwise, if we are using clang with c - use the overloadable attribute */ +#define UTEST_OVERLOADABLE UTEST_ATTRIBUTE(overloadable) +#endif + +#if defined(__cplusplus) && (__cplusplus >= 201103L) + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wc++98-compat-pedantic" +#endif + +#include + +template ::value> +struct utest_type_deducer final { + static void _(const T t); +}; + +template <> struct utest_type_deducer { + static void _(const signed char c) { + UTEST_PRINTF("%d", static_cast(c)); + } +}; + +template <> struct utest_type_deducer { + static void _(const unsigned char c) { + UTEST_PRINTF("%u", static_cast(c)); + } +}; + +template <> struct utest_type_deducer { + static void _(const short s) { UTEST_PRINTF("%d", static_cast(s)); } +}; + +template <> struct utest_type_deducer { + static void _(const unsigned short s) { + UTEST_PRINTF("%u", static_cast(s)); + } +}; + +template <> struct utest_type_deducer { + static void _(const float f) { UTEST_PRINTF("%f", static_cast(f)); } +}; + +template <> struct utest_type_deducer { + static void _(const double d) { UTEST_PRINTF("%f", d); } +}; + +template <> struct utest_type_deducer { + static void _(const long double d) { +#if defined(__MINGW32__) || defined(__MINGW64__) + /* MINGW is weird - doesn't like LF at all?! */ + UTEST_PRINTF("%f", (double)d); +#else + UTEST_PRINTF("%Lf", d); +#endif + } +}; + +template <> struct utest_type_deducer { + static void _(const int i) { UTEST_PRINTF("%d", i); } +}; + +template <> struct utest_type_deducer { + static void _(const unsigned int i) { UTEST_PRINTF("%u", i); } +}; + +template <> struct utest_type_deducer { + static void _(const long i) { UTEST_PRINTF("%ld", i); } +}; + +template <> struct utest_type_deducer { + static void _(const unsigned long i) { UTEST_PRINTF("%lu", i); } +}; + +template <> struct utest_type_deducer { + static void _(const long long i) { UTEST_PRINTF("%lld", i); } +}; + +template <> struct utest_type_deducer { + static void _(const unsigned long long i) { UTEST_PRINTF("%llu", i); } +}; + +template <> struct utest_type_deducer { + static void _(const bool i) { UTEST_PRINTF(i ? "true" : "false"); } +}; + +template struct utest_type_deducer { + static void _(const T *t) { + UTEST_PRINTF("%p", static_cast(const_cast(t))); + } +}; + +template struct utest_type_deducer { + static void _(T *t) { UTEST_PRINTF("%p", static_cast(t)); } +}; + +template struct utest_type_deducer { + static void _(const T t) { + UTEST_PRINTF("%llu", static_cast(t)); + } +}; + +template <> struct utest_type_deducer { + static void _(std::nullptr_t t) { + UTEST_PRINTF("%p", static_cast(t)); + } +}; + +template +UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(const T t) { + utest_type_deducer::_(t); +} + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +#elif defined(UTEST_OVERLOADABLE) + +UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(signed char c); +UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(signed char c) { + UTEST_PRINTF("%d", UTEST_CAST(int, c)); +} + +UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(unsigned char c); +UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(unsigned char c) { + UTEST_PRINTF("%u", UTEST_CAST(unsigned int, c)); +} + +UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(float f); +UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(float f) { + UTEST_PRINTF("%f", UTEST_CAST(double, f)); +} + +UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(double d); +UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(double d) { + UTEST_PRINTF("%f", d); +} + +UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(long double d); +UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(long double d) { +#if defined(__MINGW32__) || defined(__MINGW64__) + /* MINGW is weird - doesn't like LF at all?! */ + UTEST_PRINTF("%f", (double)d); +#else + UTEST_PRINTF("%Lf", d); +#endif +} + +UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(int i); +UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(int i) { + UTEST_PRINTF("%d", i); +} + +UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(unsigned int i); +UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(unsigned int i) { + UTEST_PRINTF("%u", i); +} + +UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(long int i); +UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(long int i) { + UTEST_PRINTF("%ld", i); +} + +UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(long unsigned int i); +UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(long unsigned int i) { + UTEST_PRINTF("%lu", i); +} + +UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(const void *p); +UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(const void *p) { + UTEST_PRINTF("%p", p); +} + +/* + long long is a c++11 extension +*/ +#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) || \ + defined(__cplusplus) && (__cplusplus >= 201103L) || \ + (defined(__MINGW32__) || defined(__MINGW64__)) + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wc++98-compat-pedantic" +#endif + +UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(long long int i); +UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(long long int i) { + UTEST_PRINTF("%lld", i); +} + +UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(long long unsigned int i); +UTEST_WEAK UTEST_OVERLOADABLE void +utest_type_printer(long long unsigned int i) { + UTEST_PRINTF("%llu", i); +} + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +#endif +#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) && \ + !(defined(__MINGW32__) || defined(__MINGW64__)) || \ + defined(__TINYC__) +#define utest_type_printer(val) \ + UTEST_PRINTF(_Generic((val), signed char \ + : "%d", unsigned char \ + : "%u", short \ + : "%d", unsigned short \ + : "%u", int \ + : "%d", long \ + : "%ld", long long \ + : "%lld", unsigned \ + : "%u", unsigned long \ + : "%lu", unsigned long long \ + : "%llu", float \ + : "%f", double \ + : "%f", long double \ + : "%Lf", default \ + : _Generic((val - val), ptrdiff_t \ + : "%p", default \ + : "undef")), \ + (val)) +#else +/* + we don't have the ability to print the values we got, so we create a macro + to tell our users we can't do anything fancy +*/ +#define utest_type_printer(...) UTEST_PRINTF("undef") +#endif + +#if defined(_MSC_VER) +#define UTEST_SURPRESS_WARNING_BEGIN \ + __pragma(warning(push)) __pragma(warning(disable : 4127)) \ + __pragma(warning(disable : 4571)) __pragma(warning(disable : 4130)) +#define UTEST_SURPRESS_WARNING_END __pragma(warning(pop)) +#else +#define UTEST_SURPRESS_WARNING_BEGIN +#define UTEST_SURPRESS_WARNING_END +#endif + +#if defined(__cplusplus) && (__cplusplus >= 201103L) +#define UTEST_AUTO(x) auto +#elif !defined(__cplusplus) + +#if defined(__clang__) +/* clang-format off */ +/* had to disable clang-format here because it malforms the pragmas */ +#define UTEST_AUTO(x) \ + _Pragma("clang diagnostic push") \ + _Pragma("clang diagnostic ignored \"-Wgnu-auto-type\"") __auto_type \ + _Pragma("clang diagnostic pop") +/* clang-format on */ +#else +#define UTEST_AUTO(x) __typeof__(x + 0) +#endif + +#else +#define UTEST_AUTO(x) typeof(x + 0) +#endif + +#if defined(__clang__) +#define UTEST_STRNCMP(x, y, size) \ + _Pragma("clang diagnostic push") \ + _Pragma("clang diagnostic ignored \"-Wdisabled-macro-expansion\"") \ + strncmp(x, y, size) _Pragma("clang diagnostic pop") +#else +#define UTEST_STRNCMP(x, y, size) strncmp(x, y, size) +#endif + +#if defined(_MSC_VER) +#define UTEST_STRNCPY(x, y, size) strcpy_s(x, size, y) +#elif !defined(__clang__) && defined(__GNUC__) +static UTEST_INLINE char * +utest_strncpy_gcc(char *const dst, const char *const src, const size_t size) { +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wstringop-overflow" + return strncpy(dst, src, size); +#pragma GCC diagnostic pop +} + +#define UTEST_STRNCPY(x, y, size) utest_strncpy_gcc(x, y, size) +#else +#define UTEST_STRNCPY(x, y, size) strncpy(x, y, size) +#endif + +#define UTEST_SKIP(msg) \ + do { \ + UTEST_PRINTF(" Skipped : '%s'\n", (msg)); \ + *utest_result = UTEST_TEST_SKIPPED; \ + return; \ + } while (0) + +#if defined(__clang__) +#define UTEST_COND(x, y, cond, msg, is_assert) \ + UTEST_SURPRESS_WARNING_BEGIN do { \ + _Pragma("clang diagnostic push") \ + _Pragma("clang diagnostic ignored \"-Wlanguage-extension-token\"") \ + _Pragma("clang diagnostic ignored \"-Wc++98-compat-pedantic\"") \ + _Pragma("clang diagnostic ignored \"-Wfloat-equal\"") \ + UTEST_AUTO(x) xEval = (x); \ + UTEST_AUTO(y) yEval = (y); \ + if (!((xEval)cond(yEval))) { \ + const char *const xAsString = #x; \ + const char *const yAsString = #y; \ + _Pragma("clang diagnostic pop") \ + UTEST_PRINTF("%s:%i: Failure\n", __FILE__, __LINE__); \ + UTEST_PRINTF(" Expected : ("); \ + UTEST_PRINTF("%s) " #cond " (%s", xAsString, yAsString); \ + UTEST_PRINTF(")\n"); \ + UTEST_PRINTF(" Actual : "); \ + utest_type_printer(xEval); \ + UTEST_PRINTF(" vs "); \ + utest_type_printer(yEval); \ + UTEST_PRINTF("\n"); \ + if (strlen(msg) > 0) { \ + UTEST_PRINTF(" Message : %s\n", msg); \ + } \ + *utest_result = UTEST_TEST_FAILURE; \ + if (is_assert) { \ + return; \ + } \ + } \ + } \ + while (0) \ + UTEST_SURPRESS_WARNING_END +#elif defined(__GNUC__) || defined(__TINYC__) +#define UTEST_COND(x, y, cond, msg, is_assert) \ + UTEST_SURPRESS_WARNING_BEGIN do { \ + UTEST_AUTO(x) xEval = (x); \ + UTEST_AUTO(y) yEval = (y); \ + if (!((xEval)cond(yEval))) { \ + const char *const xAsString = #x; \ + const char *const yAsString = #y; \ + UTEST_PRINTF("%s:%i: Failure\n", __FILE__, __LINE__); \ + UTEST_PRINTF(" Expected : ("); \ + UTEST_PRINTF("%s) " #cond " (%s", xAsString, yAsString); \ + UTEST_PRINTF(")\n"); \ + UTEST_PRINTF(" Actual : "); \ + utest_type_printer(xEval); \ + UTEST_PRINTF(" vs "); \ + utest_type_printer(yEval); \ + UTEST_PRINTF("\n"); \ + if (strlen(msg) > 0) { \ + UTEST_PRINTF(" Message : %s\n", msg); \ + } \ + *utest_result = UTEST_TEST_FAILURE; \ + if (is_assert) { \ + return; \ + } \ + } \ + } \ + while (0) \ + UTEST_SURPRESS_WARNING_END +#else +#define UTEST_COND(x, y, cond, msg, is_assert) \ + UTEST_SURPRESS_WARNING_BEGIN do { \ + if (!((x)cond(y))) { \ + UTEST_PRINTF("%s:%i: Failure (Expected " #cond " Actual)", __FILE__, \ + __LINE__); \ + if (strlen(msg) > 0) { \ + UTEST_PRINTF(" Message : %s", msg); \ + } \ + UTEST_PRINTF("\n"); \ + *utest_result = UTEST_TEST_FAILURE; \ + if constexpr (is_assert) { \ + return; \ + } \ + } \ + } \ + while (0) \ + UTEST_SURPRESS_WARNING_END +#endif + +#define EXPECT_EQ(x, y) UTEST_COND(x, y, ==, "", 0) +#define EXPECT_EQ_MSG(x, y, msg) UTEST_COND(x, y, ==, msg, 0) +#define ASSERT_EQ(x, y) UTEST_COND(x, y, ==, "", 1) +#define ASSERT_EQ_MSG(x, y, msg) UTEST_COND(x, y, ==, msg, 1) + +#define EXPECT_NE(x, y) UTEST_COND(x, y, !=, "", 0) +#define EXPECT_NE_MSG(x, y, msg) UTEST_COND(x, y, !=, msg, 0) +#define ASSERT_NE(x, y) UTEST_COND(x, y, !=, "", 1) +#define ASSERT_NE_MSG(x, y, msg) UTEST_COND(x, y, !=, msg, 1) + +#define EXPECT_LT(x, y) UTEST_COND(x, y, <, "", 0) +#define EXPECT_LT_MSG(x, y, msg) UTEST_COND(x, y, <, msg, 0) +#define ASSERT_LT(x, y) UTEST_COND(x, y, <, "", 1) +#define ASSERT_LT_MSG(x, y, msg) UTEST_COND(x, y, <, msg, 1) + +#define EXPECT_LE(x, y) UTEST_COND(x, y, <=, "", 0) +#define EXPECT_LE_MSG(x, y, msg) UTEST_COND(x, y, <=, msg, 0) +#define ASSERT_LE(x, y) UTEST_COND(x, y, <=, "", 1) +#define ASSERT_LE_MSG(x, y, msg) UTEST_COND(x, y, <=, msg, 1) + +#define EXPECT_GT(x, y) UTEST_COND(x, y, >, "", 0) +#define EXPECT_GT_MSG(x, y, msg) UTEST_COND(x, y, >, msg, 0) +#define ASSERT_GT(x, y) UTEST_COND(x, y, >, "", 1) +#define ASSERT_GT_MSG(x, y, msg) UTEST_COND(x, y, >, msg, 1) + +#define EXPECT_GE(x, y) UTEST_COND(x, y, >=, "", 0) +#define EXPECT_GE_MSG(x, y, msg) UTEST_COND(x, y, >=, msg, 0) +#define ASSERT_GE(x, y) UTEST_COND(x, y, >=, "", 1) +#define ASSERT_GE_MSG(x, y, msg) UTEST_COND(x, y, >=, msg, 1) + +#define UTEST_TRUE(x, msg, is_assert) \ + UTEST_SURPRESS_WARNING_BEGIN do { \ + const int xEval = !!(x); \ + if (!(xEval)) { \ + UTEST_PRINTF("%s:%i: Failure\n", __FILE__, __LINE__); \ + UTEST_PRINTF(" Expected : true\n"); \ + UTEST_PRINTF(" Actual : %s\n", (xEval) ? "true" : "false"); \ + if (strlen(msg) > 0) { \ + UTEST_PRINTF(" Message : %s\n", msg); \ + } \ + *utest_result = UTEST_TEST_FAILURE; \ + if (is_assert) { \ + return; \ + } \ + } \ + } \ + while (0) \ + UTEST_SURPRESS_WARNING_END + +#define EXPECT_TRUE(x) UTEST_TRUE(x, "", 0) +#define EXPECT_TRUE_MSG(x, msg) UTEST_TRUE(x, msg, 0) +#define ASSERT_TRUE(x) UTEST_TRUE(x, "", 1) +#define ASSERT_TRUE_MSG(x, msg) UTEST_TRUE(x, msg, 1) + +#define UTEST_FALSE(x, msg, is_assert) \ + UTEST_SURPRESS_WARNING_BEGIN do { \ + const int xEval = !!(x); \ + if (xEval) { \ + UTEST_PRINTF("%s:%i: Failure\n", __FILE__, __LINE__); \ + UTEST_PRINTF(" Expected : false\n"); \ + UTEST_PRINTF(" Actual : %s\n", (xEval) ? "true" : "false"); \ + if (strlen(msg) > 0) { \ + UTEST_PRINTF(" Message : %s\n", msg); \ + } \ + *utest_result = UTEST_TEST_FAILURE; \ + if constexpr (is_assert) { \ + return; \ + } \ + } \ + } \ + while (0) \ + UTEST_SURPRESS_WARNING_END + +#define EXPECT_FALSE(x) UTEST_FALSE(x, "", 0) +#define EXPECT_FALSE_MSG(x, msg) UTEST_FALSE(x, msg, 0) +#define ASSERT_FALSE(x) UTEST_FALSE(x, "", 1) +#define ASSERT_FALSE_MSG(x, msg) UTEST_FALSE(x, msg, 1) + +#define UTEST_STREQ(x, y, msg, is_assert) \ + UTEST_SURPRESS_WARNING_BEGIN do { \ + const char *xEval = (x); \ + const char *yEval = (y); \ + if (UTEST_NULL == xEval || UTEST_NULL == yEval || \ + 0 != strcmp(xEval, yEval)) { \ + UTEST_PRINTF("%s:%i: Failure\n", __FILE__, __LINE__); \ + UTEST_PRINTF(" Expected : \"%s\"\n", xEval); \ + UTEST_PRINTF(" Actual : \"%s\"\n", yEval); \ + if (strlen(msg) > 0) { \ + UTEST_PRINTF(" Message : %s\n", msg); \ + } \ + *utest_result = UTEST_TEST_FAILURE; \ + if (is_assert) { \ + return; \ + } \ + } \ + } \ + while (0) \ + UTEST_SURPRESS_WARNING_END + +#define EXPECT_STREQ(x, y) UTEST_STREQ(x, y, "", 0) +#define EXPECT_STREQ_MSG(x, y, msg) UTEST_STREQ(x, y, msg, 0) +#define ASSERT_STREQ(x, y) UTEST_STREQ(x, y, "", 1) +#define ASSERT_STREQ_MSG(x, y, msg) UTEST_STREQ(x, y, msg, 1) + +#define UTEST_STRNE(x, y, msg, is_assert) \ + UTEST_SURPRESS_WARNING_BEGIN do { \ + const char *xEval = (x); \ + const char *yEval = (y); \ + if (UTEST_NULL == xEval || UTEST_NULL == yEval || \ + 0 == strcmp(xEval, yEval)) { \ + UTEST_PRINTF("%s:%i: Failure\n", __FILE__, __LINE__); \ + UTEST_PRINTF(" Expected : \"%s\"\n", xEval); \ + UTEST_PRINTF(" Actual : \"%s\"\n", yEval); \ + if (strlen(msg) > 0) { \ + UTEST_PRINTF(" Message : %s\n", msg); \ + } \ + *utest_result = UTEST_TEST_FAILURE; \ + if (is_assert) { \ + return; \ + } \ + } \ + } \ + while (0) \ + UTEST_SURPRESS_WARNING_END + +#define EXPECT_STRNE(x, y) UTEST_STRNE(x, y, "", 0) +#define EXPECT_STRNE_MSG(x, y, msg) UTEST_STRNE(x, y, msg, 0) +#define ASSERT_STRNE(x, y) UTEST_STRNE(x, y, "", 1) +#define ASSERT_STRNE_MSG(x, y, msg) UTEST_STRNE(x, y, msg, 1) + +#define UTEST_STRNEQ(x, y, n, msg, is_assert) \ + UTEST_SURPRESS_WARNING_BEGIN do { \ + const char *xEval = (x); \ + const char *yEval = (y); \ + const size_t nEval = UTEST_CAST(size_t, n); \ + if (UTEST_NULL == xEval || UTEST_NULL == yEval || \ + 0 != UTEST_STRNCMP(xEval, yEval, nEval)) { \ + UTEST_PRINTF("%s:%i: Failure\n", __FILE__, __LINE__); \ + UTEST_PRINTF(" Expected : \"%.*s\"\n", UTEST_CAST(int, nEval), xEval); \ + UTEST_PRINTF(" Actual : \"%.*s\"\n", UTEST_CAST(int, nEval), yEval); \ + if (strlen(msg) > 0) { \ + UTEST_PRINTF(" Message : %s\n", msg); \ + } \ + *utest_result = UTEST_TEST_FAILURE; \ + if (is_assert) { \ + return; \ + } \ + } \ + } \ + while (0) \ + UTEST_SURPRESS_WARNING_END + +#define EXPECT_STRNEQ(x, y, n) UTEST_STRNEQ(x, y, n, "", 0) +#define EXPECT_STRNEQ_MSG(x, y, n, msg) UTEST_STRNEQ(x, y, n, msg, 0) +#define ASSERT_STRNEQ(x, y, n) UTEST_STRNEQ(x, y, n, "", 1) +#define ASSERT_STRNEQ_MSG(x, y, n, msg) UTEST_STRNEQ(x, y, n, msg, 1) + +#define UTEST_STRNNE(x, y, n, msg, is_assert) \ + UTEST_SURPRESS_WARNING_BEGIN do { \ + const char *xEval = (x); \ + const char *yEval = (y); \ + const size_t nEval = UTEST_CAST(size_t, n); \ + if (UTEST_NULL == xEval || UTEST_NULL == yEval || \ + 0 == UTEST_STRNCMP(xEval, yEval, nEval)) { \ + UTEST_PRINTF("%s:%i: Failure\n", __FILE__, __LINE__); \ + UTEST_PRINTF(" Expected : \"%.*s\"\n", UTEST_CAST(int, nEval), xEval); \ + UTEST_PRINTF(" Actual : \"%.*s\"\n", UTEST_CAST(int, nEval), yEval); \ + if (strlen(msg) > 0) { \ + UTEST_PRINTF(" Message : %s\n", msg); \ + } \ + *utest_result = UTEST_TEST_FAILURE; \ + if (is_assert) { \ + return; \ + } \ + } \ + } \ + while (0) \ + UTEST_SURPRESS_WARNING_END + +#define EXPECT_STRNNE(x, y, n) UTEST_STRNNE(x, y, n, "", 0) +#define EXPECT_STRNNE_MSG(x, y, n, msg) UTEST_STRNNE(x, y, n, msg, 0) +#define ASSERT_STRNNE(x, y, n) UTEST_STRNNE(x, y, n, "", 1) +#define ASSERT_STRNNE_MSG(x, y, n, msg) UTEST_STRNNE(x, y, n, msg, 1) + +#define UTEST_NEAR(x, y, epsilon, msg, is_assert) \ + UTEST_SURPRESS_WARNING_BEGIN do { \ + const double diff = \ + utest_fabs(UTEST_CAST(double, x) - UTEST_CAST(double, y)); \ + if (diff > UTEST_CAST(double, epsilon) || utest_isnan(diff)) { \ + UTEST_PRINTF("%s:%i: Failure\n", __FILE__, __LINE__); \ + UTEST_PRINTF(" Expected : %f\n", UTEST_CAST(double, x)); \ + UTEST_PRINTF(" Actual : %f\n", UTEST_CAST(double, y)); \ + if (strlen(msg) > 0) { \ + UTEST_PRINTF(" Message : %s\n", msg); \ + } \ + *utest_result = UTEST_TEST_FAILURE; \ + if (is_assert) { \ + return; \ + } \ + } \ + } \ + while (0) \ + UTEST_SURPRESS_WARNING_END + +#define EXPECT_NEAR(x, y, epsilon) UTEST_NEAR(x, y, epsilon, "", 0) +#define EXPECT_NEAR_MSG(x, y, epsilon, msg) UTEST_NEAR(x, y, epsilon, msg, 0) +#define ASSERT_NEAR(x, y, epsilon) UTEST_NEAR(x, y, epsilon, "", 1) +#define ASSERT_NEAR_MSG(x, y, epsilon, msg) UTEST_NEAR(x, y, epsilon, msg, 1) + +#if defined(UTEST_HAS_EXCEPTIONS) +#define UTEST_EXCEPTION(x, exception_type, msg, is_assert) \ + UTEST_SURPRESS_WARNING_BEGIN do { \ + int exception_caught = 0; \ + try { \ + x; \ + } catch (const exception_type &) { \ + exception_caught = 1; \ + } catch (...) { \ + exception_caught = 2; \ + } \ + if (1 != exception_caught) { \ + UTEST_PRINTF("%s:%i: Failure\n", __FILE__, __LINE__); \ + UTEST_PRINTF(" Expected : %s exception\n", #exception_type); \ + UTEST_PRINTF(" Actual : %s\n", (2 == exception_caught) \ + ? "Unexpected exception" \ + : "No exception"); \ + if (strlen(msg) > 0) { \ + UTEST_PRINTF(" Message : %s\n", msg); \ + } \ + *utest_result = UTEST_TEST_FAILURE; \ + if (is_assert) { \ + return; \ + } \ + } \ + } \ + while (0) \ + UTEST_SURPRESS_WARNING_END + +#define EXPECT_EXCEPTION(x, exception_type) \ + UTEST_EXCEPTION(x, exception_type, "", 0) +#define EXPECT_EXCEPTION_MSG(x, exception_type, msg) \ + UTEST_EXCEPTION(x, exception_type, msg, 0) +#define ASSERT_EXCEPTION(x, exception_type) \ + UTEST_EXCEPTION(x, exception_type, "", 1) +#define ASSERT_EXCEPTION_MSG(x, exception_type, msg) \ + UTEST_EXCEPTION(x, exception_type, msg, 1) + +#define UTEST_EXCEPTION_WITH_MESSAGE(x, exception_type, exception_message, \ + msg, is_assert) \ + UTEST_SURPRESS_WARNING_BEGIN do { \ + int exception_caught = 0; \ + char *message_caught = UTEST_NULL; \ + try { \ + x; \ + } catch (const exception_type &e) { \ + const char *const what = e.what(); \ + exception_caught = 1; \ + if (0 != \ + UTEST_STRNCMP(what, exception_message, strlen(exception_message))) { \ + const size_t message_size = strlen(what) + 1; \ + message_caught = UTEST_PTR_CAST(char *, malloc(message_size)); \ + UTEST_STRNCPY(message_caught, what, message_size); \ + } \ + } catch (...) { \ + exception_caught = 2; \ + } \ + if (1 != exception_caught) { \ + UTEST_PRINTF("%s:%i: Failure\n", __FILE__, __LINE__); \ + UTEST_PRINTF(" Expected : %s exception\n", #exception_type); \ + UTEST_PRINTF(" Actual : %s\n", (2 == exception_caught) \ + ? "Unexpected exception" \ + : "No exception"); \ + if (strlen(msg) > 0) { \ + UTEST_PRINTF(" Message : %s\n", msg); \ + } \ + *utest_result = UTEST_TEST_FAILURE; \ + if (is_assert) { \ + return; \ + } \ + } else if (UTEST_NULL != message_caught) { \ + UTEST_PRINTF("%s:%i: Failure\n", __FILE__, __LINE__); \ + UTEST_PRINTF(" Expected : %s exception with message %s\n", \ + #exception_type, exception_message); \ + UTEST_PRINTF(" Actual message : %s\n", message_caught); \ + if (strlen(msg) > 0) { \ + UTEST_PRINTF(" Message : %s\n", msg); \ + } \ + *utest_result = UTEST_TEST_FAILURE; \ + free(message_caught); \ + if (is_assert) { \ + return; \ + } \ + } \ + } \ + while (0) \ + UTEST_SURPRESS_WARNING_END + +#define EXPECT_EXCEPTION_WITH_MESSAGE(x, exception_type, exception_message) \ + UTEST_EXCEPTION_WITH_MESSAGE(x, exception_type, exception_message, "", 0) +#define EXPECT_EXCEPTION_WITH_MESSAGE_MSG(x, exception_type, \ + exception_message, msg) \ + UTEST_EXCEPTION_WITH_MESSAGE(x, exception_type, exception_message, msg, 0) +#define ASSERT_EXCEPTION_WITH_MESSAGE(x, exception_type, exception_message) \ + UTEST_EXCEPTION_WITH_MESSAGE(x, exception_type, exception_message, "", 1) +#define ASSERT_EXCEPTION_WITH_MESSAGE_MSG(x, exception_type, \ + exception_message, msg) \ + UTEST_EXCEPTION_WITH_MESSAGE(x, exception_type, exception_message, msg, 1) +#endif + +#if defined(__clang__) +#if __has_warning("-Wunsafe-buffer-usage") +#define UTEST_SURPRESS_WARNINGS_BEGIN \ + _Pragma("clang diagnostic push") \ + _Pragma("clang diagnostic ignored \"-Wunsafe-buffer-usage\"") +#define UTEST_SURPRESS_WARNINGS_END _Pragma("clang diagnostic pop") +#else +#define UTEST_SURPRESS_WARNINGS_BEGIN +#define UTEST_SURPRESS_WARNINGS_END +#endif +#elif defined(__GNUC__) && __GNUC__ >= 8 && defined(__cplusplus) +#define UTEST_SURPRESS_WARNINGS_BEGIN \ + _Pragma("GCC diagnostic push") \ + _Pragma("GCC diagnostic ignored \"-Wclass-memaccess\"") +#define UTEST_SURPRESS_WARNINGS_END _Pragma("GCC diagnostic pop") +#else +#define UTEST_SURPRESS_WARNINGS_BEGIN +#define UTEST_SURPRESS_WARNINGS_END +#endif + +#define UTEST(SET, NAME) \ + UTEST_SURPRESS_WARNINGS_BEGIN \ + UTEST_EXTERN struct utest_state_s utest_state; \ + static void utest_run_##SET##_##NAME(int *utest_result); \ + static void utest_##SET##_##NAME(int *utest_result, size_t utest_index) { \ + (void)utest_index; \ + utest_run_##SET##_##NAME(utest_result); \ + } \ + UTEST_INITIALIZER(utest_register_##SET##_##NAME) { \ + const size_t index = utest_state.tests_length++; \ + const char name_part[] = #SET "." #NAME; \ + const size_t name_size = strlen(name_part) + 1; \ + char *name = UTEST_PTR_CAST(char *, malloc(name_size)); \ + utest_state.tests = UTEST_PTR_CAST( \ + struct utest_test_state_s *, \ + utest_realloc(UTEST_PTR_CAST(void *, utest_state.tests), \ + sizeof(struct utest_test_state_s) * \ + utest_state.tests_length)); \ + if (utest_state.tests && name) { \ + utest_state.tests[index].func = &utest_##SET##_##NAME; \ + utest_state.tests[index].name = name; \ + utest_state.tests[index].index = 0; \ + UTEST_SNPRINTF(name, name_size, "%s", name_part); \ + } else { \ + if (utest_state.tests) { \ + free(utest_state.tests); \ + utest_state.tests = NULL; \ + } \ + if (name) { \ + free(name); \ + } \ + } \ + } \ + UTEST_SURPRESS_WARNINGS_END \ + void utest_run_##SET##_##NAME(int *utest_result) + +#define UTEST_F_SETUP(FIXTURE) \ + static void utest_f_setup_##FIXTURE(int *utest_result, \ + struct FIXTURE *utest_fixture) + +#define UTEST_F_TEARDOWN(FIXTURE) \ + static void utest_f_teardown_##FIXTURE(int *utest_result, \ + struct FIXTURE *utest_fixture) + +#define UTEST_F(FIXTURE, NAME) \ + UTEST_SURPRESS_WARNINGS_BEGIN \ + UTEST_EXTERN struct utest_state_s utest_state; \ + static void utest_f_setup_##FIXTURE(int *, struct FIXTURE *); \ + static void utest_f_teardown_##FIXTURE(int *, struct FIXTURE *); \ + static void utest_run_##FIXTURE##_##NAME(int *, struct FIXTURE *); \ + static void utest_f_##FIXTURE##_##NAME(int *utest_result, \ + size_t utest_index) { \ + struct FIXTURE fixture; \ + (void)utest_index; \ + memset(&fixture, 0, sizeof(fixture)); \ + utest_f_setup_##FIXTURE(utest_result, &fixture); \ + if (UTEST_TEST_PASSED != *utest_result) { \ + return; \ + } \ + utest_run_##FIXTURE##_##NAME(utest_result, &fixture); \ + utest_f_teardown_##FIXTURE(utest_result, &fixture); \ + } \ + UTEST_INITIALIZER(utest_register_##FIXTURE##_##NAME) { \ + const size_t index = utest_state.tests_length++; \ + const char name_part[] = #FIXTURE "." #NAME; \ + const size_t name_size = strlen(name_part) + 1; \ + char *name = UTEST_PTR_CAST(char *, malloc(name_size)); \ + utest_state.tests = UTEST_PTR_CAST( \ + struct utest_test_state_s *, \ + utest_realloc(UTEST_PTR_CAST(void *, utest_state.tests), \ + sizeof(struct utest_test_state_s) * \ + utest_state.tests_length)); \ + if (utest_state.tests && name) { \ + utest_state.tests[index].func = &utest_f_##FIXTURE##_##NAME; \ + utest_state.tests[index].name = name; \ + UTEST_SNPRINTF(name, name_size, "%s", name_part); \ + } else { \ + if (utest_state.tests) { \ + free(utest_state.tests); \ + utest_state.tests = NULL; \ + } \ + if (name) { \ + free(name); \ + } \ + } \ + } \ + UTEST_SURPRESS_WARNINGS_END \ + void utest_run_##FIXTURE##_##NAME(int *utest_result, \ + struct FIXTURE *utest_fixture) + +#define UTEST_I_SETUP(FIXTURE) \ + static void utest_i_setup_##FIXTURE( \ + int *utest_result, struct FIXTURE *utest_fixture, size_t utest_index) + +#define UTEST_I_TEARDOWN(FIXTURE) \ + static void utest_i_teardown_##FIXTURE( \ + int *utest_result, struct FIXTURE *utest_fixture, size_t utest_index) + +#define UTEST_I(FIXTURE, NAME, INDEX) \ + UTEST_SURPRESS_WARNINGS_BEGIN \ + UTEST_EXTERN struct utest_state_s utest_state; \ + static void utest_run_##FIXTURE##_##NAME##_##INDEX(int *, struct FIXTURE *); \ + static void utest_i_##FIXTURE##_##NAME##_##INDEX(int *utest_result, \ + size_t index) { \ + struct FIXTURE fixture; \ + memset(&fixture, 0, sizeof(fixture)); \ + utest_i_setup_##FIXTURE(utest_result, &fixture, index); \ + if (UTEST_TEST_PASSED != *utest_result) { \ + return; \ + } \ + utest_run_##FIXTURE##_##NAME##_##INDEX(utest_result, &fixture); \ + utest_i_teardown_##FIXTURE(utest_result, &fixture, index); \ + } \ + UTEST_INITIALIZER(utest_register_##FIXTURE##_##NAME##_##INDEX) { \ + size_t i; \ + utest_uint64_t iUp; \ + for (i = 0; i < (INDEX); i++) { \ + const size_t index = utest_state.tests_length++; \ + const char name_part[] = #FIXTURE "." #NAME; \ + const size_t name_size = strlen(name_part) + 32; \ + char *name = UTEST_PTR_CAST(char *, malloc(name_size)); \ + utest_state.tests = UTEST_PTR_CAST( \ + struct utest_test_state_s *, \ + utest_realloc(UTEST_PTR_CAST(void *, utest_state.tests), \ + sizeof(struct utest_test_state_s) * \ + utest_state.tests_length)); \ + if (utest_state.tests && name) { \ + utest_state.tests[index].func = &utest_i_##FIXTURE##_##NAME##_##INDEX; \ + utest_state.tests[index].index = i; \ + utest_state.tests[index].name = name; \ + iUp = UTEST_CAST(utest_uint64_t, i); \ + UTEST_SNPRINTF(name, name_size, "%s/%" UTEST_PRIu64, name_part, iUp); \ + } else { \ + if (utest_state.tests) { \ + free(utest_state.tests); \ + utest_state.tests = NULL; \ + } \ + if (name) { \ + free(name); \ + } \ + } \ + } \ + } \ + UTEST_SURPRESS_WARNINGS_END \ + void utest_run_##FIXTURE##_##NAME##_##INDEX(int *utest_result, \ + struct FIXTURE *utest_fixture) + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wc++98-compat-pedantic" +#endif + +UTEST_WEAK +double utest_fabs(double d); +UTEST_WEAK +double utest_fabs(double d) { + union { + double d; + utest_uint64_t u; + } both; + both.d = d; + both.u &= 0x7fffffffffffffffu; + return both.d; +} + +UTEST_WEAK +int utest_isnan(double d); +UTEST_WEAK +int utest_isnan(double d) { + union { + double d; + utest_uint64_t u; + } both; + both.d = d; + both.u &= 0x7fffffffffffffffu; + return both.u > 0x7ff0000000000000u; +} + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +#if defined(__clang__) +#if __has_warning("-Wunsafe-buffer-usage") +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunsafe-buffer-usage" +#endif +#endif + +UTEST_WEAK +int utest_should_filter_test(const char *filter, const char *testcase); +UTEST_WEAK int utest_should_filter_test(const char *filter, + const char *testcase) { + if (filter) { + const char *filter_cur = filter; + const char *testcase_cur = testcase; + const char *filter_wildcard = UTEST_NULL; + + while (('\0' != *filter_cur) && ('\0' != *testcase_cur)) { + if ('*' == *filter_cur) { + /* store the position of the wildcard */ + filter_wildcard = filter_cur; + + /* skip the wildcard character */ + filter_cur++; + + while (('\0' != *filter_cur) && ('\0' != *testcase_cur)) { + if ('*' == *filter_cur) { + /* + we found another wildcard (filter is something like *foo*) so we + exit the current loop, and return to the parent loop to handle + the wildcard case + */ + break; + } else if (*filter_cur != *testcase_cur) { + /* otherwise our filter didn't match, so reset it */ + filter_cur = filter_wildcard; + } + + /* move testcase along */ + testcase_cur++; + + /* move filter along */ + filter_cur++; + } + + if (('\0' == *filter_cur) && ('\0' == *testcase_cur)) { + return 0; + } + + /* if the testcase has been exhausted, we don't have a match! */ + if ('\0' == *testcase_cur) { + return 1; + } + } else { + if (*testcase_cur != *filter_cur) { + /* test case doesn't match filter */ + return 1; + } else { + /* move our filter and testcase forward */ + testcase_cur++; + filter_cur++; + } + } + } + + if (('\0' != *filter_cur) || + (('\0' != *testcase_cur) && + ((filter == filter_cur) || ('*' != filter_cur[-1])))) { + /* we have a mismatch! */ + return 1; + } + } + + return 0; +} + +static UTEST_INLINE FILE *utest_fopen(const char *filename, const char *mode) { +#ifdef _MSC_VER + FILE *file; + if (0 == fopen_s(&file, filename, mode)) { + return file; + } else { + return UTEST_NULL; + } +#else + return fopen(filename, mode); +#endif +} + +static UTEST_INLINE int utest_main(int argc, const char *const argv[]); +int utest_main(int argc, const char *const argv[]) { + utest_uint64_t failed = 0; + utest_uint64_t skipped = 0; + size_t index = 0; + size_t *failed_testcases = UTEST_NULL; + size_t failed_testcases_length = 0; + size_t *skipped_testcases = UTEST_NULL; + size_t skipped_testcases_length = 0; + const char *filter = UTEST_NULL; + utest_uint64_t ran_tests = 0; + int enable_mixed_units = 0; + int random_order = 0; + utest_uint32_t seed = 0; + + enum colours { RESET, GREEN, RED, YELLOW }; + + const int use_colours = UTEST_COLOUR_OUTPUT(); + const char *colours[] = {"\033[0m", "\033[32m", "\033[31m", "\033[33m"}; + + if (!use_colours) { + for (index = 0; index < sizeof colours / sizeof colours[0]; index++) { + colours[index] = ""; + } + } + /* loop through all arguments looking for our options */ + for (index = 1; index < UTEST_CAST(size_t, argc); index++) { + /* Informational switches */ + const char help_str[] = "--help"; + const char list_str[] = "--list-tests"; + /* Test config switches */ + const char filter_str[] = "--filter="; + const char output_str[] = "--output="; + const char enable_mixed_units_str[] = "--enable-mixed-units"; + const char random_order_str[] = "--random-order"; + const char random_order_with_seed_str[] = "--random-order="; + + if (0 == UTEST_STRNCMP(argv[index], help_str, strlen(help_str))) { + printf("utest.h - the single file unit testing solution for C/C++!\n" + "Command line Options:\n" + " --help Show this message and exit.\n" + " --filter= Filter the test cases to run (EG. " + "MyTest*.a would run MyTestCase.a but not MyTestCase.b).\n" + " --list-tests List testnames, one per line. Output " + "names can be passed to --filter.\n"); + printf(" --output= Output an xunit XML file to the file " + "specified in .\n" + " --enable-mixed-units Enable the per-test output to contain " + "mixed units (s/ms/us/ns).\n" + " --random-order[=] Randomize the order that the tests are " + "ran in. If the optional argument is not provided, then a " + "random starting seed is used.\n"); + goto cleanup; + } else if (0 == + UTEST_STRNCMP(argv[index], filter_str, strlen(filter_str))) { + /* user wants to filter what test cases run! */ + filter = argv[index] + strlen(filter_str); + } else if (0 == + UTEST_STRNCMP(argv[index], output_str, strlen(output_str))) { + utest_state.output = utest_fopen(argv[index] + strlen(output_str), "w+"); + } else if (0 == UTEST_STRNCMP(argv[index], list_str, strlen(list_str))) { + for (index = 0; index < utest_state.tests_length; index++) { + UTEST_PRINTF("%s\n", utest_state.tests[index].name); + } + /* when printing the test list, don't actually run the tests */ + return 0; + } else if (0 == UTEST_STRNCMP(argv[index], enable_mixed_units_str, + strlen(enable_mixed_units_str))) { + enable_mixed_units = 1; + } else if (0 == UTEST_STRNCMP(argv[index], random_order_with_seed_str, + strlen(random_order_with_seed_str))) { + seed = + UTEST_CAST(utest_uint32_t, + strtoul(argv[index] + strlen(random_order_with_seed_str), + UTEST_NULL, 10)); + random_order = 1; + } else if (0 == UTEST_STRNCMP(argv[index], random_order_str, + strlen(random_order_str))) { + const utest_int64_t ns = utest_ns(); + + // Some really poor pseudo-random using the current time. I do this + // because I really want to avoid using C's rand() because that'd mean our + // random would be affected by any srand() usage by the user (which I + // don't want). + seed = UTEST_CAST(utest_uint32_t, ns >> 32) * 31 + + UTEST_CAST(utest_uint32_t, ns & 0xffffffff); + random_order = 1; + } + } + + if (random_order) { + // Use Fisher-Yates with the Durstenfield's version to randomly re-order the + // tests. + for (index = utest_state.tests_length; index > 1; index--) { + // For the random order we'll use PCG. + const utest_uint32_t state = seed; + const utest_uint32_t word = + ((state >> ((state >> 28u) + 4u)) ^ state) * 277803737u; + const utest_uint32_t next = + ((word >> 22u) ^ word) % UTEST_CAST(utest_uint32_t, index); + + // Swap the randomly chosen element into the last location. + const struct utest_test_state_s copy = utest_state.tests[index - 1]; + utest_state.tests[index - 1] = utest_state.tests[next]; + utest_state.tests[next] = copy; + + // Move the seed onwards. + seed = seed * 747796405u + 2891336453u; + } + } + + for (index = 0; index < utest_state.tests_length; index++) { + if (utest_should_filter_test(filter, utest_state.tests[index].name)) { + continue; + } + + ran_tests++; + } + + printf("%s[==========]%s Running %" UTEST_PRIu64 " test cases.\n", + colours[GREEN], colours[RESET], UTEST_CAST(utest_uint64_t, ran_tests)); + + if (utest_state.output) { + fprintf(utest_state.output, "\n"); + fprintf(utest_state.output, + "\n", + UTEST_CAST(utest_uint64_t, ran_tests)); + fprintf(utest_state.output, + "\n", + UTEST_CAST(utest_uint64_t, ran_tests)); + } + + for (index = 0; index < utest_state.tests_length; index++) { + int result = UTEST_TEST_PASSED; + utest_int64_t ns = 0; + + if (utest_should_filter_test(filter, utest_state.tests[index].name)) { + continue; + } + + printf("%s[ RUN ]%s %s\n", colours[GREEN], colours[RESET], + utest_state.tests[index].name); + + if (utest_state.output) { + fprintf(utest_state.output, "", + utest_state.tests[index].name); + } + + ns = utest_ns(); + errno = 0; +#if defined(UTEST_HAS_EXCEPTIONS) + UTEST_SURPRESS_WARNING_BEGIN + try { + utest_state.tests[index].func(&result, utest_state.tests[index].index); + } catch (const std::exception &err) { + printf(" Exception : %s\n", err.what()); + result = UTEST_TEST_FAILURE; + } catch (...) { + printf(" Exception : Unknown\n"); + result = UTEST_TEST_FAILURE; + } + UTEST_SURPRESS_WARNING_END +#else + utest_state.tests[index].func(&result, utest_state.tests[index].index); +#endif + ns = utest_ns() - ns; + + if (utest_state.output) { + fprintf(utest_state.output, "\n"); + } + + // Record the failing test. + if (UTEST_TEST_FAILURE == result) { + const size_t failed_testcase_index = failed_testcases_length++; + failed_testcases = UTEST_PTR_CAST( + size_t *, utest_realloc(UTEST_PTR_CAST(void *, failed_testcases), + sizeof(size_t) * failed_testcases_length)); + if (UTEST_NULL != failed_testcases) { + failed_testcases[failed_testcase_index] = index; + } + failed++; + } else if (UTEST_TEST_SKIPPED == result) { + const size_t skipped_testcase_index = skipped_testcases_length++; + skipped_testcases = UTEST_PTR_CAST( + size_t *, utest_realloc(UTEST_PTR_CAST(void *, skipped_testcases), + sizeof(size_t) * skipped_testcases_length)); + if (UTEST_NULL != skipped_testcases) { + skipped_testcases[skipped_testcase_index] = index; + } + skipped++; + } + + { + const char *const units[] = {"ns", "us", "ms", "s", UTEST_NULL}; + unsigned int unit_index = 0; + utest_int64_t time = ns; + + if (enable_mixed_units) { + for (unit_index = 0; UTEST_NULL != units[unit_index]; unit_index++) { + if (10000 > time) { + break; + } + + time /= 1000; + } + } + + if (UTEST_TEST_FAILURE == result) { + printf("%s[ FAILED ]%s %s (%" UTEST_PRId64 "%s)\n", colours[RED], + colours[RESET], utest_state.tests[index].name, time, + units[unit_index]); + } else if (UTEST_TEST_SKIPPED == result) { + printf("%s[ SKIPPED ]%s %s (%" UTEST_PRId64 "%s)\n", colours[YELLOW], + colours[RESET], utest_state.tests[index].name, time, + units[unit_index]); + } else { + printf("%s[ OK ]%s %s (%" UTEST_PRId64 "%s)\n", colours[GREEN], + colours[RESET], utest_state.tests[index].name, time, + units[unit_index]); + } + } + } + + printf("%s[==========]%s %" UTEST_PRIu64 " test cases ran.\n", colours[GREEN], + colours[RESET], ran_tests); + printf("%s[ PASSED ]%s %" UTEST_PRIu64 " tests.\n", colours[GREEN], + colours[RESET], ran_tests - failed - skipped); + + if (0 != skipped) { + printf("%s[ SKIPPED ]%s %" UTEST_PRIu64 " tests, listed below:\n", + colours[YELLOW], colours[RESET], skipped); + for (index = 0; index < skipped_testcases_length; index++) { + printf("%s[ SKIPPED ]%s %s\n", colours[YELLOW], colours[RESET], + utest_state.tests[skipped_testcases[index]].name); + } + } + + if (0 != failed) { + printf("%s[ FAILED ]%s %" UTEST_PRIu64 " tests, listed below:\n", + colours[RED], colours[RESET], failed); + for (index = 0; index < failed_testcases_length; index++) { + printf("%s[ FAILED ]%s %s\n", colours[RED], colours[RESET], + utest_state.tests[failed_testcases[index]].name); + } + } + + if (utest_state.output) { + fprintf(utest_state.output, "\n\n"); + } + +cleanup: + for (index = 0; index < utest_state.tests_length; index++) { + free(UTEST_PTR_CAST(void *, utest_state.tests[index].name)); + } + + free(UTEST_PTR_CAST(void *, skipped_testcases)); + free(UTEST_PTR_CAST(void *, failed_testcases)); + free(UTEST_PTR_CAST(void *, utest_state.tests)); + + if (utest_state.output) { + fclose(utest_state.output); + } + + return UTEST_CAST(int, failed); +} + +#if defined(__clang__) +#if __has_warning("-Wunsafe-buffer-usage") +#pragma clang diagnostic pop +#endif +#endif + +/* + we need, in exactly one source file, define the global struct that will hold + the data we need to run utest. This macro allows the user to declare the + data without having to use the UTEST_MAIN macro, thus allowing them to write + their own main() function. +*/ +#define UTEST_STATE() struct utest_state_s utest_state = {0, 0, 0} + +/* + define a main() function to call into utest.h and start executing tests! A + user can optionally not use this macro, and instead define their own main() + function and manually call utest_main. The user must, in exactly one source + file, use the UTEST_STATE macro to declare a global struct variable that + utest requires. +*/ +#define UTEST_MAIN() \ + UTEST_STATE(); \ + int main(int argc, const char *const argv[]) { \ + return utest_main(argc, argv); \ + } + +#endif /* SHEREDOM_UTEST_H_INCLUDED */ diff --git a/test/TestHelpers.cpp b/test/TestHelpers.cpp new file mode 100644 index 0000000..bb9a0c8 --- /dev/null +++ b/test/TestHelpers.cpp @@ -0,0 +1,14 @@ +#include "TestHelpers.h" + +tl::vector ExpectedAssertGuard::s_utest_results; +tl::vector ExpectedAssertGuard::s_msgs; +tl::vector ExpectedAssertGuard::s_oldHandlers; + +tl::vector NoAssertGuard::s_utest_results; +tl::vector NoAssertGuard::s_oldHandlers; + +tl::vector ExpectedCrashGuard::s_utest_results; +tl::vector ExpectedCrashGuard::s_msgs; +tl::vector ExpectedCrashGuard::s_oldHandlers; + +//tl::vector NoCrashesGuard::s_oldHandlers; diff --git a/test/TestHelpers.h b/test/TestHelpers.h new file mode 100644 index 0000000..f7ee8b1 --- /dev/null +++ b/test/TestHelpers.h @@ -0,0 +1,124 @@ +#pragma once + +#include "tl/string.h" +#include "tl/vector.h" +#include "tl/format.h" +#include "tl/utest.h" + +struct ExpectedAssertGuard +{ + ExpectedAssertGuard(tl::string msg, int* utest_result) + { + s_utest_results.push_back(utest_result); + s_msgs.push_back(std::move(msg)); + s_oldHandlers.push_back(tl::assert::set_handler(assertHandler)); + } + + ~ExpectedAssertGuard() + { + tl::assert::set_handler(s_oldHandlers.back()); + s_oldHandlers.pop_back(); + s_msgs.pop_back(); + s_utest_results.pop_back(); + } + +private: + static tl::assert::response assertHandler(const char* condition, const char* file, int line, const char* msg) + { + int* utest_result = s_utest_results.back(); + EXPECT_EQ(s_msgs.back(), msg); + return tl::assert::response::CONTINUE; + } + + static tl::vector s_utest_results; + static tl::vector s_msgs; + static tl::vector s_oldHandlers; +}; + +#define EXPECTED_ASSERT_GUARD(msg) ExpectedAssertGuard eassert##__LINE__(msg, utest_result) + +struct NoAssertGuard +{ + NoAssertGuard(int* utest_result) + { + s_utest_results.push_back(utest_result); + s_oldHandlers.push_back(tl::assert::set_handler(assertHandler)); + } + + ~NoAssertGuard() + { + tl::assert::set_handler(s_oldHandlers.back()); + s_oldHandlers.pop_back(); + s_utest_results.pop_back(); + } + +private: + static tl::assert::response assertHandler(const char* condition, const char* file, int line, const char* msg) + { + int* utest_result = s_utest_results.back(); + EXPECT_FALSE_MSG(true, tl::format("Unexpected assert: [{}] {}({}): {}", condition ? condition : "", file ? file : "", line, msg ? msg : "").c_str()); + return tl::assert::response::CONTINUE; + } + + static tl::vector s_utest_results; + static tl::vector s_oldHandlers; +}; + +#define NO_ASSERT_GUARD NoAssertGuard noassert##__LINE__(utest_result) + + +struct ExpectedCrashGuard +{ + ExpectedCrashGuard(tl::string msg, int* utest_result) + { + s_utest_results.push_back(utest_result); + s_msgs.push_back(std::move(msg)); + s_oldHandlers.push_back(tl::crash::set_handler(crashHandler)); + } + + ~ExpectedCrashGuard() + { + tl::crash::set_handler(s_oldHandlers.back()); + s_oldHandlers.pop_back(); + s_msgs.pop_back(); + s_utest_results.pop_back(); + } + +private: + static tl::crash::response crashHandler(const char* file, int line, const char* msg) + { + int* utest_result = s_utest_results.back(); + EXPECT_EQ(s_msgs.back(), msg); + return tl::crash::response::CONTINUE; + } + + static tl::vector s_utest_results; + static tl::vector s_msgs; + static tl::vector s_oldHandlers; +}; + +#define EXPECTED_CRASH_GUARD(msg) ExpectedCrashGuard ecrash##__LINE__(msg, utest_result) + + +//struct NoCrashesGuard +//{ +// NoCrashesGuard() +// { +// s_oldHandlers.push_back(tl::crash::set_handler(crashHandler)); +// } +// +// ~NoCrashesGuard() +// { +// tl::crash::set_handler(s_oldHandlers.back()); +// s_oldHandlers.pop_back(); +// } +// +//private: +// static tl::crash::response crashHandler(const char* file, int line, const char* msg) +// { +// EXPECT_TRUE_MSG(false, tl::format("Unexpected crash: {}({}): {}", file ? file : "", line, msg ? msg : "").c_str()); +// return tl::crash::response::CONTINUE; +// } +// +// static tl::vector s_oldHandlers; +//}; diff --git a/test/main.cpp b/test/main.cpp index 5ffef4b..3ead9ee 100644 --- a/test/main.cpp +++ b/test/main.cpp @@ -1,11 +1,6 @@ #include "stdafx.h" - -// each test module could contain no more then one 'main' file with init function defined -// alternatively you could define init function yourself -#define BOOST_TEST_MAIN -#include - #include "tl/string.h" +#include "tl/utest.h" void* __cdecl operator new[](size_t size, const char* name, int flags, unsigned debugFlags, const char* file, int line) { @@ -16,19 +11,4 @@ void* __cdecl operator new[](size_t size, size_t, size_t, const char* name, int return new uint8_t[size]; } -//____________________________________________________________________________// - -struct GlobalFixture -{ - GlobalFixture() - { - std::cout << "Starting Tests\n"; - } - ~GlobalFixture() - { - std::cout << "Finishing Tests\n"; - tl::string::free_database(); - } -}; - -BOOST_GLOBAL_FIXTURE(GlobalFixture); +UTEST_MAIN(); diff --git a/test/test_paths.cpp b/test/test_paths.cpp new file mode 100644 index 0000000..47d24c8 --- /dev/null +++ b/test/test_paths.cpp @@ -0,0 +1,948 @@ +#include "StdAfx.h" +#include "tl/abs_path.h" +#include "tl/rel_path.h" + +#include "tl/utest.h" +#include "TestHelpers.h" +#include "tl/abs_path_view.h" + +TL_DECLARE_STRING_LITERAL(posix_root_tag, "/"); +TL_DECLARE_STRING_VECTOR(posix_parse_separators, "/"); +TL_DECLARE_STRING_LITERAL(posix_format_separator, "/"); +using posix_system = tl::simple_path_system; + +TL_DECLARE_STRING_LITERAL(unc_root_tag, "\\\\"); +TL_DECLARE_STRING_VECTOR(unc_parse_separators, "\\", "/"); +TL_DECLARE_STRING_LITERAL(unc_format_separator, "\\"); +using unc_system = tl::simple_path_system; + +using test_abs_path = tl::abs_path>; +using test_rel_path = test_abs_path::rel_path_type; + +using test_abs_path_view = tl::abs_path_view>; +using test_rel_path_view = test_abs_path_view::rel_path_view_type; + +#define PATH_TEST_EQ(a, b) EXPECT_EQ(test_abs_path(a), test_abs_path(b)) + +UTEST(thread_safety, thread_safety) +{ + std::thread thread1; + std::thread thread2; + + thread1 = std::thread([] + { + test_rel_path path; + for (volatile size_t i = 0; i < 1000; i++) + { + path = "a/b/c/d"; + char result = 'a' + static_cast(i % 20); + char buf[2] = { result , 0 }; + path += (const char*)buf; + } + }); + + thread2 = std::thread([] + { + test_rel_path path; + for (volatile size_t i = 0; i < 1000; i++) + { + path = "a/b/c/d"; + char result = 'a' + static_cast(i % 20); + char buf[2] = { result , 0 }; + path += (const char*)buf; + } + }); + + if (thread1.joinable()) + { + thread1.join(); + } + if (thread2.joinable()) + { + thread2.join(); + } +} + +UTEST(Path, Path) +{ + { + test_abs_path path; + EXPECT_TRUE(path.empty()); + EXPECT_EQ(path.size(), 0); + } + { + test_abs_path path("/a"); + EXPECT_TRUE(!path.empty()); + EXPECT_EQ(path.size(), 1); + EXPECT_TRUE(path.is()); + EXPECT_EQ(path[0], "a"); + + test_abs_path path2("/a"); + test_abs_path path3("/"); + EXPECT_EQ(path, path2); + EXPECT_NE(path, path3); + + test_abs_path path4("\\\\"); + EXPECT_NE(path3, path4); + } + { + test_abs_path path("/a/"); + EXPECT_TRUE(!path.empty()); + EXPECT_EQ(path.size(), 1); + EXPECT_TRUE(path.is()); + EXPECT_EQ(path[0], "a"); + } + { + test_abs_path path("\\\\a"); + EXPECT_TRUE(!path.empty()); + EXPECT_EQ(path.size(), 1); + EXPECT_TRUE(path.is()); + EXPECT_EQ(path[0], "a"); + } + { + test_abs_path path("\\\\a\\"); + EXPECT_TRUE(!path.empty()); + EXPECT_EQ(path.size(), 1); + EXPECT_TRUE(path.is()); + EXPECT_EQ(path[0], "a"); + } + { + test_abs_path path("/a/b"); + EXPECT_TRUE(!path.empty()); + EXPECT_EQ(path.size(), 2); + EXPECT_EQ(path[0], "a"); + EXPECT_EQ(path[1], "b"); + } + { + //Note - Here we test that the posix path only uses / as separator + test_abs_path path("/a\\b"); + EXPECT_TRUE(!path.empty()); + EXPECT_EQ(path.size(), 1); + EXPECT_EQ(path[0], "a\\b"); + } + { + test_abs_path path("/"); + path += "a"; + EXPECT_TRUE(!path.empty()); + EXPECT_EQ(path.size(), 1); + EXPECT_EQ(path[0], "a"); + } + { + test_abs_path path; + { + EXPECTED_ASSERT_GUARD("Failed to parse abs path"); + path += "a"; + } + EXPECT_TRUE(path.empty()); + EXPECT_EQ(path.size(), 0); + } + { + test_abs_path path; + path += "/a/b"; + EXPECT_TRUE(!path.empty()); + EXPECT_EQ(path.size(), 2); + EXPECT_EQ(path[0], "a"); + EXPECT_EQ(path[1], "b"); + } + { + test_abs_path path; + { + EXPECTED_ASSERT_GUARD("Failed to parse abs path"); + path += "a"; + } + path += "/a/b"; + EXPECT_TRUE(!path.empty()); + EXPECT_EQ(path.size(), 2); + EXPECT_EQ(path[0], "a"); + EXPECT_EQ(path[1], "b"); + } + { + test_abs_path path("\\\\"); + path += "a"; + path += "b/c/d"; + EXPECT_TRUE(!path.empty()); + EXPECT_EQ(path.size(), 4); + EXPECT_EQ(path[0], "a"); + EXPECT_EQ(path[1], "b"); + EXPECT_EQ(path[3], "d"); + } + { + test_abs_path path("/"); + path += "a/b"; + path += "c"; + EXPECT_TRUE(!path.empty()); + EXPECT_EQ(path.size(), 3); + EXPECT_EQ(path[0], "a"); + EXPECT_EQ(path[1], "b"); + EXPECT_EQ(path[2], "c"); + } + { + test_abs_path path("/"); + path += ("a/b" + tl::string("/df")); + EXPECT_TRUE(!path.empty()); + EXPECT_EQ(path.size(), 3); + EXPECT_EQ(path[0], "a"); + EXPECT_EQ(path[1], "b"); + EXPECT_EQ(path[2], "df"); + } + { + test_abs_path path(tl::string("/")); + path += "a/b"; + path += "c"; + path += ".."; + EXPECT_TRUE(!path.empty()); + EXPECT_EQ(path.size(), 2); + EXPECT_EQ(path[0], "a"); + EXPECT_EQ(path[1], "b"); + path += "../.."; + EXPECT_EQ(path.size(), 0); + EXPECT_TRUE(path.empty()); + EXPECT_TRUE(path.is()); + } + { + test_abs_path path(tl::string("\\\\")); + path += "a/b"; + EXPECTED_ASSERT_GUARD("Invalid path"); + path += "../../.."; + EXPECT_TRUE(path.empty()); + } + { + test_abs_path path(tl::string("\\\\")); + EXPECTED_ASSERT_GUARD("Invalid path"); + path.push_back(".."); + EXPECT_TRUE(path.empty()); + } + { + test_abs_path path(tl::string("/")); + EXPECTED_ASSERT_GUARD("Invalid path"); + test_abs_path newPath = path + "../.."; + EXPECT_TRUE(newPath.empty()); + } + { + test_abs_path path(tl::string("/")); + EXPECTED_ASSERT_GUARD("Invalid path"); + auto pathParent = path.parent(); + EXPECT_TRUE(pathParent.empty()); + } + { + test_abs_path path(tl::string("\\\\")); + EXPECTED_ASSERT_GUARD("Invalid path"); + auto pathParent = path.parent(); + EXPECT_TRUE(pathParent.empty()); + } + { + test_abs_path path(tl::string("/")); + EXPECTED_ASSERT_GUARD("Invalid path"); + auto pathParent = path.parent(); + EXPECT_TRUE(pathParent.empty()); + } + { + test_abs_path path(tl::string("/a/b/c/d")); + test_abs_path newPath = path.parent(2); + EXPECT_EQ(newPath, test_abs_path("/a/b")); + } + { + test_abs_path path(tl::string("/a")); + EXPECTED_ASSERT_GUARD("Invalid path"); + test_abs_path newPath = path.parent(2); + EXPECT_TRUE(newPath.empty()); + } + { + test_abs_path path("/a/b/c/../d"); + EXPECT_TRUE(!path.empty()); + EXPECT_EQ(path.size(), 3); + EXPECT_EQ(path[0], "a"); + EXPECT_EQ(path[1], "b"); + EXPECT_EQ(path[2], "d"); + path.push_back(".."); + EXPECT_EQ(path.size(), 2); + path.push_back("../.."); + EXPECT_EQ(path.size(), 3); + EXPECT_TRUE(path.is()); + } + { + test_abs_path path("\\\\a/b/c/d"); + auto p = path.subpath(0, 0); + EXPECT_EQ(p, test_rel_path("a/b/c/d")); + } + { + test_abs_path path("/a/b/c/d"); + auto p = path.subpath(1, 0); + EXPECT_EQ(p, test_rel_path("b/c/d")); + } + { + test_abs_path path("\\\\a/b/c/d"); + auto p = path.subpath(0, -1); + EXPECT_EQ(p, test_rel_path("a/b/c")); + } + { + test_abs_path path("/a/b/c/d"); + auto p = path.subpath(0, 2); + EXPECT_EQ(p, test_rel_path("a/b")); + } + { + test_abs_path path("\\\\a/b/c"); + auto p = path.parent(); + EXPECT_EQ(p.str(), "\\\\a\\b"); + } + { + test_abs_path path("/a"); + auto p = path.parent(); + EXPECT_EQ(p.str(), "/"); + EXPECT_NE(p.str(), "\\\\"); + } + { + EXPECTED_ASSERT_GUARD("Failed to parse abs path"); + test_abs_path path(".."); + } + { + EXPECTED_ASSERT_GUARD("Failed to parse abs path"); + test_abs_path path("."); + } + { + EXPECTED_ASSERT_GUARD("Invalid path"); + test_abs_path path(""); + auto p = path.parent(); + EXPECT_TRUE(p.empty()); + } + { + test_abs_path path("/a/b/../c"); + auto p = path.parent(); + EXPECT_EQ(p.str(), "/a"); + } + { + test_abs_path path("/a/b/c/d"); + path.shrink(2); + EXPECT_EQ(path, test_abs_path("/a/b")); + } + { + test_abs_path path("/a/b/c/d"); + EXPECT_EQ(path.back(), "d"); + EXPECT_EQ(path.front(), "a"); + } + { + test_abs_path from("/a/b/c/d"); + test_abs_path to("/a/b/x/y"); + auto rel = from.path_to(to); + EXPECT_EQ(rel, test_rel_path("../../x/y")); + rel += ".."; + rel.collapse_path(); + EXPECT_EQ(rel, test_rel_path("../../x")); + + test_abs_path path("/a/b/c/d"); + path += rel; + EXPECT_EQ(path, test_abs_path("/a/b/c/d/../../x")); + } + { + test_abs_path from("/a/b"); + test_abs_path to("/a/b/x/y"); + auto rel = from.path_to(to); + EXPECT_EQ(rel, test_rel_path("x/y")); + } + { + test_abs_path from("/c/d"); + test_abs_path to("/a/b/x/y"); + auto rel = from.path_to(to); + EXPECT_EQ(rel, test_rel_path("../../a/b/x/y")); + } + + { + test_abs_path p("/c/d/m/a/../s/d/a"); + tl::string s = p.str(); + EXPECT_EQ(s, "/c/d/m/s/d/a"); + } + + { + EXPECTED_ASSERT_GUARD("Failed to parse abs path"); + test_abs_path p("/../s/d/a"); + EXPECT_TRUE(p.empty()); + } + + { + EXPECTED_ASSERT_GUARD("Failed to parse abs path"); + test_abs_path p("/s/../../d/a"); + EXPECT_TRUE(p.empty()); + } + + { + EXPECTED_ASSERT_GUARD("Failed to parse abs path"); + test_abs_path p("/s/d/../../../a"); + EXPECT_TRUE(p.empty()); + } + + { + EXPECTED_ASSERT_GUARD("Failed to parse abs path"); + test_abs_path p("\\\\../a"); + EXPECT_TRUE(p.empty()); + } + + { + test_abs_path p("/c/d/m"); + tl::string s = p.str(); + EXPECT_EQ(s, "/c/d/m"); + } + + { + test_abs_path p("/foo/..bar"); + tl::string s = p.str(); + EXPECT_EQ(s, "/foo/..bar"); + } + + { + test_abs_path p("/foo/..."); + tl::string s = p.str(); + EXPECT_EQ(s, "/foo/..."); + } + + { + test_abs_path path = test_abs_path::from_string(tl::string_view{ "/a" }, test_abs_path("/b")); + EXPECT_EQ(test_abs_path("/a"), path); + EXPECT_NE(test_abs_path("/b"), path); + } + + { + test_abs_path path = test_abs_path::from_string(tl::string_view{ "a/b" }, test_abs_path("/x")); + EXPECT_EQ(test_abs_path("/x/a/b"), path); + } + + { + EXPECTED_ASSERT_GUARD("Invalid path"); + test_abs_path path = test_abs_path::from_string(tl::string_view{ ".." }, test_abs_path("/")); + EXPECT_TRUE(path.empty()); + } + + { + test_abs_path path = test_abs_path::from_string(tl::string_view{ "../.." }, test_abs_path("/a/b/d")); + EXPECT_TRUE(path.is_valid()); + EXPECT_EQ(path, test_abs_path("/a")); + } + + { + test_abs_path path = test_abs_path::from_string(tl::string_view{ "/bla" }, test_abs_path("")); + EXPECT_TRUE(path.is_valid()); + EXPECT_EQ(path, test_abs_path("/bla")); + } + + { + test_abs_path path = test_abs_path::from_string(tl::string_view{ "bla" }, test_abs_path("")); + EXPECT_TRUE(!path.is_valid()); + } + { + test_abs_path path = test_abs_path::from_string(tl::string_view{ "bla" }, test_abs_path()); + EXPECT_TRUE(!path.is_valid()); + } + { + test_abs_path path = test_abs_path::from_string(tl::string_view{ "bla" }); + EXPECT_TRUE(!path.is_valid()); + } + { + test_abs_path path = test_abs_path::from_string(tl::string_view{ "/bla" }); + EXPECT_TRUE(path.is_valid()); + EXPECT_EQ(path, test_abs_path("/bla")); + } + + { + test_abs_path p1 = test_abs_path("/a/bc/d"); + test_abs_path p2 = test_abs_path("/a/bd"); + + EXPECT_LT(p1, p2); + EXPECT_GE(p1, p1); + EXPECT_GE(p2, p1); + } +} + +// non_member_tests ----------------------------------------------------------------// + +UTEST(non_member_tests, non_member_tests) +{ + // test non-member functions, particularly operator overloads + + test_abs_path e, e2; + tl::string es, es2; + + char acs[] = "a"; + tl::string as(acs); + test_rel_path a(as); + + char acs2[] = "a"; + tl::string as2(acs2); + test_rel_path a2(as2); + + char bcs[] = "b"; + tl::string bs(bcs); + test_rel_path b(bs); + + // swap + a.swap(b); + EXPECT_EQ(a.str(), "b"); + EXPECT_EQ(b.str(), "a"); + std::swap(a, b); + EXPECT_EQ(a.str(), "a"); + EXPECT_EQ(b.str(), "b"); + + // probe operator / + PATH_TEST_EQ(test_abs_path("/") + ".", "/."); + { + EXPECTED_ASSERT_GUARD("Failed to parse abs path"); + PATH_TEST_EQ(test_abs_path("/") + "..", "/.."); + } + { + PATH_TEST_EQ(test_abs_path("/a") + "b", "/a/b"); + { + EXPECTED_ASSERT_GUARD("Invalid path"); + PATH_TEST_EQ(test_abs_path("/") + "..", ""); + } + PATH_TEST_EQ(test_abs_path("/foo") + test_rel_path("bar"), "/foo/bar"); // path arg + PATH_TEST_EQ(test_abs_path("/foo") + "bar", "/foo/bar"); // const char* arg + PATH_TEST_EQ(test_abs_path("/foo") + test_rel_path("woo/bar").back(), "/foo/bar"); // const std::string & arg + PATH_TEST_EQ(test_abs_path("/foo") + "..", "/"); + PATH_TEST_EQ(test_abs_path("/f") + ".." + "b", "/b"); + PATH_TEST_EQ(test_abs_path("/foo") + "bar" + "..", "/foo"); + PATH_TEST_EQ(test_abs_path("/foo") + "bar" + ".." + "..", "/"); + PATH_TEST_EQ(test_abs_path("/foo") + "bar" + ".." + "blah", "/foo/blah"); + PATH_TEST_EQ(test_abs_path("/f") + "b" + "..", "/f"); + PATH_TEST_EQ(test_abs_path("/foo") + "bar" + "blah" + ".." + "..", "/foo"); + PATH_TEST_EQ(test_abs_path("/foo") + "bar" + "blah" + ".." + ".." + "bletch", "/foo/bletch"); + + PATH_TEST_EQ(test_abs_path("/foo") + ".", "/foo"); + PATH_TEST_EQ(test_abs_path("/foo") + "." + "bar", "/foo/bar"); + PATH_TEST_EQ(test_abs_path("/foo") + "." + ".", "/foo"); + PATH_TEST_EQ(test_abs_path("/foo") + "." + "..", "/"); + + { + test_abs_path path(tl::string("/.")); + EXPECTED_ASSERT_GUARD("Invalid path"); + path += "./.."; + EXPECT_TRUE(path.empty()); + } + + { + test_abs_path path(tl::string("/.")); + EXPECTED_ASSERT_GUARD("Invalid path"); + path += "../."; + EXPECT_TRUE(path.empty()); + } + } + + // make sure basic_path overloads don't conflict with std::string overloads + + //TEST_CHECK(!(as < as)); + //TEST_CHECK(!(as < acs)); + //TEST_CHECK(!(acs < as)); + + // character set reality check before lexicographical tests + EXPECT_LT(std::string("a.b"), std::string("a/b")); + // verify compare is actually lexicographical +// EXPECT_LT(path("a/b") < path("a.b")); + EXPECT_EQ(test_abs_path("/a/b"), test_abs_path("/a///b")); + EXPECT_EQ(test_abs_path("\\\\/a/b"), test_abs_path("\\\\a///b")); + + // operator == and != are implemented separately, so test separately + + test_abs_path p1("/fe/fi/fo/fum"); + test_abs_path p2(p1); + test_abs_path p3("/fe/fi/fo/fumm"); + EXPECT_NE(p1.str(), p3.str()); + + // check each overload + EXPECT_NE(p1, p3); + EXPECT_NE(p1.str(), p3.str()); + EXPECT_NE(p1.str(), p3.str().c_str()); + + p3 = p2; + EXPECT_EQ(p1.str(), p3.str()); + + // check each overload + EXPECT_EQ(p1, p3); + EXPECT_EQ(p1.str(), p3.str()); + EXPECT_EQ(p1.str(), p3.str().c_str()); + +} + +UTEST(is_prefix_tests, is_prefix_tests) +{ + test_abs_path p1{ "\\\\windows" }; + test_abs_path p2{ "\\\\windows\\system" }; + test_abs_path p3{ "\\\\windows\\system32" }; + test_abs_path p4{ "\\\\windows\\system32\\" }; + test_abs_path w1{ "/windows" }; + test_abs_path w2{ "/windows/" }; + test_abs_path w3{ "/windows/system" }; + test_abs_path w4{ "/windows/system32" }; + test_abs_path w5{ "/windows/system32/" }; + + EXPECT_TRUE(p1.is_prefix_of(p2)); + EXPECT_TRUE(!p2.is_prefix_of(p3)); + EXPECT_TRUE(p3.is_prefix_of(p4)); + EXPECT_TRUE(!p4.is_prefix_of(p1)); + + EXPECT_TRUE(w1.is_prefix_of(w2)); + EXPECT_TRUE(w2.is_prefix_of(w3)); + EXPECT_TRUE(w2.is_prefix_of(w4)); + EXPECT_TRUE(!w3.is_prefix_of(w4)); + EXPECT_TRUE(w4.is_prefix_of(w5)); +} + +// composition_tests ----------------------------------------------------------------// + +// construction_tests ---------------------------------------------------------------// + +UTEST(construction_tests, construction_tests) +{ + PATH_TEST_EQ("", ""); + PATH_TEST_EQ("/", "/"); + PATH_TEST_EQ("\\\\", "\\\\"); + + PATH_TEST_EQ("/foo", "/foo"); + + PATH_TEST_EQ("/foo/", "/foo/"); + PATH_TEST_EQ("\\\\f/", "\\\\f/"); + PATH_TEST_EQ("/foo/..", "/foo/.."); + PATH_TEST_EQ("/foo/../", "/foo/../"); + PATH_TEST_EQ("/foo/bar/../..", "/foo/bar/../.."); + PATH_TEST_EQ("/foo/bar/../../", "/foo/bar/../../"); + PATH_TEST_EQ("/f", "/f"); + + PATH_TEST_EQ("/foo/bar/", "/foo/bar/"); + PATH_TEST_EQ("//foo//bar//", "//foo//bar//"); + PATH_TEST_EQ("///foo///bar///", "///foo///bar///"); + PATH_TEST_EQ("\\\\/foo\\/bar\\/", "\\\\/foo\\/bar\\/"); + PATH_TEST_EQ("\\\\//foo\\//bar\\//", "\\\\//foo\\//bar\\//"); + PATH_TEST_EQ("\\\\\\//foo\\//bar\\//", "\\\\//foo\\//bar\\//"); + + PATH_TEST_EQ("/foo/..", "/foo/.."); + PATH_TEST_EQ("/foo/..bar", "/foo/..bar"); + PATH_TEST_EQ("/f/../f", "/f/../f"); + PATH_TEST_EQ("/f/..", "/f/.."); + PATH_TEST_EQ("/foo/../bar", "/foo/../bar"); + PATH_TEST_EQ("/foo/bar/..", "/foo/bar/.."); + PATH_TEST_EQ("/foo/bar/../..", "/foo/bar/../.."); + PATH_TEST_EQ("/foo/bar/../blah", "/foo/bar/../blah"); + PATH_TEST_EQ("/f/../b", "/f/../b"); + PATH_TEST_EQ("/f/b/..", "/f/b/.."); + PATH_TEST_EQ("/f/b/../a", "/f/b/../a"); + PATH_TEST_EQ("/foo/bar/blah/../..", "/foo/bar/blah/../.."); + PATH_TEST_EQ("/foo/bar/blah/../../bletch", "/foo/bar/blah/../../bletch"); + PATH_TEST_EQ("/...", "/..."); + PATH_TEST_EQ("/....", "/...."); + PATH_TEST_EQ("/foo/...", "/foo/..."); + PATH_TEST_EQ("/abc.", "/abc."); + PATH_TEST_EQ("/abc..", "/abc.."); + PATH_TEST_EQ("/foo/abc.", "/foo/abc."); + PATH_TEST_EQ("/foo/abc..", "/foo/abc.."); + + PATH_TEST_EQ("/.abc", "/.abc"); + PATH_TEST_EQ("/a.c", "/a.c"); + PATH_TEST_EQ("/..abc", "/..abc"); + PATH_TEST_EQ("/a..c", "/a..c"); + PATH_TEST_EQ("/foo/.abc", "/foo/.abc"); + PATH_TEST_EQ("/foo/a.c", "/foo/a.c"); + PATH_TEST_EQ("/foo/..abc", "/foo/..abc"); + PATH_TEST_EQ("/foo/a..c", "/foo/a..c"); +} + +// append_tests --------------------------------------------------------------------// + +static void append_test_aux(const test_abs_path& p, const tl::string& s, const tl::string& expect, int* utest_result) +{ + PATH_TEST_EQ((p + s.c_str()).str(), expect); + PATH_TEST_EQ((p + s).str(), expect); + + // path x(p); + // x.append(s.begin(), s.end()); + // PATH_TEST_EQ(x.str(), expect); +} + +UTEST(append_tests, append_tests) +{ + // There are many control paths to be exercised, since empty paths and arguments, + // paths with trailing separators, arguments with leading separators, with or without + // other characters being present, are all separate cases that need to be tested. + // Furthermore, some of the code to be tested is specific to argument categories, + // so that results in further permutations to be tested. + + //// code to generate test cases + //// + //// expected results must be checked by hand + //// "foo\bar" expected result must be edited by hand and moved for Windows/POSIX + //// + //const char* x[] = { "", "/", "foo", "foo/" }; + //const char* y[] = { "", "/", "bar", "/bar" }; + + //for (int i = 0; i < sizeof(x)/sizeof(char*); ++i) + // for (int j = 0; j < sizeof(y)/sizeof(char*); ++j) + // { + // std::cout << "\n PATH_TEST_EQ(path(\"" << x[i] << "\") + \"" << y[j] << "\", \"" + // << path(x[i]) + y[j] << "\");\n"; + // std::cout << " append_test_aux(\"" << x[i] << "\", \"" << y[j] << "\", \"" + // << path(x[i]) + y[j] << "\");\n"; + // } + + PATH_TEST_EQ(test_abs_path("") + "", ""); + // append_test_aux(test_abs_path(""), "", ""); + + test_abs_path abs = test_abs_path("") + "/"; + test_abs_path abs1 = test_abs_path(abs); + test_abs_path abs2 = test_abs_path("/") + "/"; + + PATH_TEST_EQ(test_abs_path("") + "/", "/"); + append_test_aux(test_abs_path(""), "/", "/", utest_result); + + PATH_TEST_EQ(test_abs_path("") + "/bar", "/bar"); + append_test_aux(test_abs_path(""), "/bar", "/bar", utest_result); + + PATH_TEST_EQ(test_abs_path("/") + "", "/"); + append_test_aux(test_abs_path("/"), "", "/", utest_result); + + PATH_TEST_EQ(test_abs_path("/") + "/", "//"); + append_test_aux(test_abs_path("/"), "/", "//", utest_result); + + PATH_TEST_EQ(test_abs_path("/") + "bar", "/bar"); + append_test_aux(test_abs_path("/"), "bar", "/bar", utest_result); + + PATH_TEST_EQ(test_abs_path("/") + "/bar", "//bar"); + append_test_aux(test_abs_path("/"), "/bar", "//bar", utest_result); + + PATH_TEST_EQ(test_abs_path("/foo") + "", "/foo"); + append_test_aux(test_abs_path("/foo"), "", "/foo", utest_result); + + PATH_TEST_EQ(test_abs_path("/foo") + "/", "/foo/"); + append_test_aux(test_abs_path("/foo"), "/", "/foo/", utest_result); + + PATH_TEST_EQ(test_abs_path("/foo") + "/bar", "/foo/bar"); + append_test_aux(test_abs_path("/foo"), "/bar", "/foo/bar", utest_result); + + PATH_TEST_EQ(test_abs_path("/foo/") + "", "/foo/"); + append_test_aux(test_abs_path("/foo/"), "", "/foo/", utest_result); + + PATH_TEST_EQ(test_abs_path("/foo/") + "/", "/foo//"); + append_test_aux(test_abs_path("/foo/"), "/", "/foo//", utest_result); + + PATH_TEST_EQ(test_abs_path("/foo/") + "bar", "/foo/bar"); + append_test_aux(test_abs_path("/foo/"), "bar", "/foo/bar", utest_result); + + PATH_TEST_EQ(test_abs_path("/foo/") + "/bar", "/foo//bar"); + append_test_aux(test_abs_path("/foo/"), "/bar", "/foo//bar", utest_result); + + { + PATH_TEST_EQ(test_abs_path("/foo") + "bar", "/foo/bar"); + append_test_aux(test_abs_path("/foo"), "bar", "/foo/bar", utest_result); + } + + // ticket #6819 + union + { + char a[1]; + char b[3]; + } u; + + u.b[0] = '/'; + u.b[1] = 'a'; + u.b[2] = '\0'; + + test_abs_path p6819; + p6819 += (const char*)u.a; + EXPECT_EQ(p6819, test_abs_path("/a")); +} + +// self_assign_and_append_tests ------------------------------------------------------// + +UTEST(self_assign_and_append_tests, self_assign_and_append_tests) +{ + test_abs_path p; + + p = "/snafubar"; + PATH_TEST_EQ(p = p, "/snafubar"); + + p = "/snafubar"; + p = p.str().c_str(); + PATH_TEST_EQ(p, "/snafubar"); + + // p = "snafubar"; + // p.assign(p.str().c_str(), path::codecvt()); + // PATH_TEST_EQ(p, "snafubar"); + + p = "/snafu/bar"; + PATH_TEST_EQ(p = p.str().c_str() + 6, "/bar"); + + // p = "snafubar"; + // PATH_TEST_EQ(p.assign(p.c_str() + 5, p.c_str() + 7), "ba"); + + p = "/snafubar"; + p += p.str().c_str(); + PATH_TEST_EQ(p, "/snafubar/snafubar"); + + // p = "snafubar"; + // p.append(p.c_str()); + // PATH_TEST_EQ(p, "snafubar/snafubar"); + + // p = "snafubar"; + // PATH_TEST_EQ(p.append(p.c_str() + 5, p.c_str() + 7), "snafubar" BOOST_DIR_SEP "ba"); +} + + + +UTEST(PathView, PathView) +{ + { + test_abs_path path; + test_abs_path_view pathView = path; + EXPECT_TRUE(pathView.empty()); + EXPECT_FALSE(pathView.is_valid()); + EXPECT_EQ(pathView.size(), 0); + EXPECT_EQ(pathView.hash(), path.hash()); + } + { + test_abs_path path("/caca/maca"); + test_abs_path_view pathView = path; + EXPECT_FALSE(pathView.empty()); + EXPECT_TRUE(pathView.is_valid()); + EXPECT_EQ(pathView.size(), path.size()); + EXPECT_EQ(pathView.hash(), path.hash()); + } + { + test_abs_path path("/caca/maca"); + test_abs_path_view pathView = path; + pathView.pop_back(); + EXPECT_FALSE(pathView.empty()); + EXPECT_TRUE(pathView.is_valid()); + EXPECT_EQ(pathView.size(), path.size() - 1); + EXPECT_EQ(pathView.str(), "/caca"); + EXPECT_EQ(pathView.hash(), test_abs_path("/caca").hash()); + EXPECT_EQ(pathView.hash(), test_abs_path(pathView).hash()); + } + + + + { + test_abs_path path("/a"); + test_abs_path_view pathView = path; + + EXPECT_TRUE(!pathView.empty()); + EXPECT_EQ(pathView.size(), 1); + EXPECT_TRUE(pathView.is()); + EXPECT_EQ(pathView[0], "a"); + + test_abs_path path2("/a"); + test_abs_path_view pathView2 = path2; + test_abs_path path3("/"); + test_abs_path_view pathView3 = path3; + EXPECT_EQ(pathView, pathView2); + EXPECT_NE(pathView, pathView3); + + test_abs_path path4("\\\\"); + test_abs_path_view pathView4(path4); + EXPECT_NE(pathView3, pathView4); + } + { + test_abs_path path("\\\\a"); + test_abs_path_view pathView(path); + EXPECT_TRUE(!pathView.empty()); + EXPECT_EQ(pathView.size(), 1); + EXPECT_TRUE(pathView.is()); + EXPECT_EQ(pathView[0], "a"); + } + { + test_abs_path path("/a/b"); + test_abs_path_view pathView(path); + EXPECT_TRUE(!pathView.empty()); + EXPECT_EQ(pathView.size(), 2); + EXPECT_EQ(pathView[0], "a"); + EXPECT_EQ(pathView[1], "b"); + } + //xxx + { + test_abs_path path(tl::string("/")); + path += "a/b"; + path += "c"; + path += ".."; + EXPECT_TRUE(!path.empty()); + EXPECT_EQ(path.size(), 2); + EXPECT_EQ(path[0], "a"); + EXPECT_EQ(path[1], "b"); + path += "../.."; + EXPECT_EQ(path.size(), 0); + EXPECT_TRUE(path.empty()); + EXPECT_TRUE(path.is()); + } + //xxx + { + test_abs_path path(tl::string("\\\\")); + path += "a/b"; + EXPECTED_ASSERT_GUARD("Invalid path"); + path += "../../.."; + EXPECT_TRUE(path.empty()); + } + //xxx + { + test_abs_path path(tl::string("\\\\")); + EXPECTED_ASSERT_GUARD("Invalid path"); + path.push_back(".."); + EXPECT_TRUE(path.empty()); + } + //xxx + { + test_abs_path path(tl::string("/")); + EXPECTED_ASSERT_GUARD("Invalid path"); + test_abs_path newPath = path + "../.."; + EXPECT_TRUE(newPath.empty()); + } + { + EXPECTED_ASSERT_GUARD("Invalid path"); + test_abs_path path(tl::string("/")); + test_abs_path_view pathView(path); + auto pathParentView = pathView.parent(); + EXPECT_TRUE(pathParentView.empty()); + } + { + test_abs_path path(tl::string("/a/b/c/d")); + test_abs_path_view pathView(path); + test_abs_path_view newPathView = pathView.parent(2); + EXPECT_EQ(newPathView.str(), "/a/b"); + } + { + EXPECTED_ASSERT_GUARD("Invalid path"); + test_abs_path path(tl::string("/a")); + test_abs_path_view pathView(path); + test_abs_path_view newPathView = pathView.parent(2); + EXPECT_TRUE(newPathView.empty()); + } + //{ + // test_abs_path path("\\\\a/b/c/d"); + // auto p = path.subpath(0, 0); + // EXPECT_EQ(p, test_rel_path("a/b/c/d")); + //} + //{ + // test_abs_path path("/a/b/c/d"); + // auto p = path.subpath(1, 0); + // EXPECT_EQ(p, test_rel_path("b/c/d")); + //} + //{ + // test_abs_path path("\\\\a/b/c/d"); + // auto p = path.subpath(0, -1); + // EXPECT_EQ(p, test_rel_path("a/b/c")); + //} + //{ + // test_abs_path path("/a/b/c/d"); + // auto p = path.subpath(0, 2); + // EXPECT_EQ(p, test_rel_path("a/b")); + //} + { + test_abs_path path("\\\\a/b/c"); + auto p = path.parent(); + EXPECT_EQ(p, test_abs_path("\\\\a/b")); + } + { + test_abs_path path("/a"); + auto p = path.parent(); + EXPECT_EQ(p, test_abs_path("/")); + EXPECT_NE(p, test_abs_path("\\\\")); + } + + { + test_abs_path path("/a/b/../c"); + auto p = path.parent(); + EXPECT_EQ(p, test_abs_path("/a")); + } +} + diff --git a/test/test_ptr.cpp b/test/test_ptr.cpp index a7659e7..c102c05 100644 --- a/test/test_ptr.cpp +++ b/test/test_ptr.cpp @@ -1,117 +1,9 @@ #include "stdafx.h" #include "tl/ptr.h" #include -// each test module could contain no more then one 'main' file with init function defined -// alternatively you could define init function yourself -#include -// These are sample tests that show the different features of the framework - - -struct ExpectedAssertGuard -{ - ExpectedAssertGuard(tl::string msg) - { - s_msgs.push_back(std::move(msg)); - s_oldHandlers.push_back(tl::assert::set_handler(assertHandler)); - } - - ~ExpectedAssertGuard() - { - tl::assert::set_handler(s_oldHandlers.back()); - s_oldHandlers.pop_back(); - s_msgs.pop_back(); - } - -private: - static tl::assert::response assertHandler(const char* condition, const char* file, int line, const char* msg) - { - BOOST_CHECK(s_msgs.back() == msg); - return tl::assert::response::CONTINUE; - } - - static tl::vector s_msgs; - static tl::vector s_oldHandlers; -}; -tl::vector ExpectedAssertGuard::s_msgs; -tl::vector ExpectedAssertGuard::s_oldHandlers; - -struct NoAssertsGuard -{ - NoAssertsGuard() - { - s_oldHandlers.push_back(tl::assert::set_handler(assertHandler)); - } - - ~NoAssertsGuard() - { - tl::assert::set_handler(s_oldHandlers.back()); - s_oldHandlers.pop_back(); - } - -private: - static tl::assert::response assertHandler(const char* condition, const char* file, int line, const char* msg) - { - BOOST_FAIL(tl::format("Unexpected assert: [{}] {}({}): {}", condition ? condition : "", file ? file : "", line, msg ? msg : "").c_str()); - return tl::assert::response::CONTINUE; - } - - static tl::vector s_oldHandlers; -}; -tl::vector NoAssertsGuard::s_oldHandlers; - - -struct ExpectedCrashGuard -{ - ExpectedCrashGuard(tl::string msg) - { - s_msgs.push_back(std::move(msg)); - s_oldHandlers.push_back(tl::crash::set_handler(crashHandler)); - } - - ~ExpectedCrashGuard() - { - tl::crash::set_handler(s_oldHandlers.back()); - s_oldHandlers.pop_back(); - s_msgs.pop_back(); - } - -private: - static tl::crash::response crashHandler(const char* file, int line, const char* msg) - { - BOOST_CHECK(s_msgs.back() == msg); - return tl::crash::response::CONTINUE; - } - - static tl::vector s_msgs; - static tl::vector s_oldHandlers; -}; -tl::vector ExpectedCrashGuard::s_msgs; -tl::vector ExpectedCrashGuard::s_oldHandlers; - -struct NoCrashesGuard -{ - NoCrashesGuard() - { - s_oldHandlers.push_back(tl::crash::set_handler(crashHandler)); - } - - ~NoCrashesGuard() - { - tl::crash::set_handler(s_oldHandlers.back()); - s_oldHandlers.pop_back(); - } - -private: - static tl::crash::response crashHandler(const char* file, int line, const char* msg) - { - BOOST_FAIL(tl::format("Unexpected crash: {}({}): {}", file ? file : "", line, msg ? msg : "").c_str()); - return tl::crash::response::CONTINUE; - } - - static tl::vector s_oldHandlers; -}; -tl::vector NoCrashesGuard::s_oldHandlers; +#include "tl/utest.h" +#include "TestHelpers.h" struct Counters @@ -183,84 +75,85 @@ struct Test Counters Test::s_counters; +#define SIMPLE_TEST(x) UTEST(x, ##x) -BOOST_AUTO_TEST_CASE(lent_ptr_ctor) +SIMPLE_TEST(lent_ptr_ctor) { - NoAssertsGuard eassert; + NO_ASSERT_GUARD; Test::resetCounters(); tl::lent_ptr lptr; - BOOST_CHECK(lptr.get() == nullptr); - BOOST_CHECK(Test::s_counters == Counters{}); + ASSERT_EQ(lptr.get(), nullptr); + ASSERT_EQ(Test::s_counters, Counters{}); } -BOOST_AUTO_TEST_CASE(lent_ptr_ctor_ptr) +SIMPLE_TEST(lent_ptr_ctor_ptr) { - NoAssertsGuard eassert; + NO_ASSERT_GUARD; Test::resetCounters(); tl::lendable t; tl::lent_ptr lptr(tl::lend(t)); - BOOST_CHECK(lptr.get() == &t.get()); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); + ASSERT_EQ(lptr.get(), &t.get()); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 1}); } -BOOST_AUTO_TEST_CASE(lent_ptr_copy_ctor) +SIMPLE_TEST(lent_ptr_copy_ctor) { - NoAssertsGuard eassert; + NO_ASSERT_GUARD; { Test::resetCounters(); tl::lent_ptr lptr1; tl::lent_ptr lptr2(lptr1); - BOOST_CHECK(lptr2.get() == nullptr); - BOOST_CHECK(Test::s_counters == Counters{}); + ASSERT_EQ(lptr2.get(), nullptr); + ASSERT_EQ(Test::s_counters, Counters{}); } { Test::resetCounters(); tl::lendable t; tl::lent_ptr lptr1(tl::lend(t)); tl::lent_ptr lptr2(lptr1); - BOOST_CHECK(lptr1.get() == &t.get()); - BOOST_CHECK(lptr2.get() == &t.get()); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); + ASSERT_EQ(lptr1.get(), &t.get()); + ASSERT_EQ(lptr2.get(), &t.get()); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 1}); } } -BOOST_AUTO_TEST_CASE(lent_ptr_move_ctor) +SIMPLE_TEST(lent_ptr_move_ctor) { - NoAssertsGuard eassert; + NO_ASSERT_GUARD; { Test::resetCounters(); tl::lent_ptr lptr1; tl::lent_ptr lptr2(std::move(lptr1)); - BOOST_CHECK(lptr1.get() == nullptr); - BOOST_CHECK(lptr2.get() == nullptr); - BOOST_CHECK(Test::s_counters == Counters{}); + ASSERT_EQ(lptr1.get(), nullptr); + ASSERT_EQ(lptr2.get(), nullptr); + ASSERT_EQ(Test::s_counters, Counters{}); } { Test::resetCounters(); tl::lendable t; tl::lent_ptr lptr1(tl::lend(t)); tl::lent_ptr lptr2(std::move(lptr1)); - BOOST_CHECK(lptr1.get() == nullptr); - BOOST_CHECK(lptr2.get() == &t.get()); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); + ASSERT_EQ(lptr1.get(), nullptr); + ASSERT_EQ(lptr2.get(), &t.get()); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 1}); } } -BOOST_AUTO_TEST_CASE(lent_ptr_copy_ass) +SIMPLE_TEST(lent_ptr_copy_ass) { - NoAssertsGuard eassert; + NO_ASSERT_GUARD; { Test::resetCounters(); tl::lent_ptr lptr1; tl::lent_ptr lptr2; lptr2 = lptr1; - BOOST_CHECK(lptr2.get() == nullptr); - BOOST_CHECK(Test::s_counters == Counters{}); + ASSERT_EQ(lptr2.get(), nullptr); + ASSERT_EQ(Test::s_counters, Counters{}); } { Test::resetCounters(); @@ -268,24 +161,24 @@ BOOST_AUTO_TEST_CASE(lent_ptr_copy_ass) tl::lent_ptr lptr1(tl::lend(t)); tl::lent_ptr lptr2; lptr2 = lptr1; - BOOST_CHECK(lptr1.get() == &t.get()); - BOOST_CHECK(lptr2.get() == &t.get()); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); + ASSERT_EQ(lptr1.get(), &t.get()); + ASSERT_EQ(lptr2.get(), &t.get()); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 1}); } } -BOOST_AUTO_TEST_CASE(lent_ptr_move_ass) +SIMPLE_TEST(lent_ptr_move_ass) { - NoAssertsGuard eassert; + NO_ASSERT_GUARD; { Test::resetCounters(); tl::lent_ptr lptr1; tl::lent_ptr lptr2; lptr2 = std::move(lptr1); - BOOST_CHECK(lptr1.get() == nullptr); - BOOST_CHECK(lptr2.get() == nullptr); - BOOST_CHECK(Test::s_counters == Counters{}); + ASSERT_EQ(lptr1.get(), nullptr); + ASSERT_EQ(lptr2.get(), nullptr); + ASSERT_EQ(Test::s_counters, Counters{}); } { Test::resetCounters(); @@ -293,62 +186,62 @@ BOOST_AUTO_TEST_CASE(lent_ptr_move_ass) tl::lent_ptr lptr1(tl::lend(t)); tl::lent_ptr lptr2; lptr2 = std::move(lptr1); - BOOST_CHECK(lptr1.get() == nullptr); - BOOST_CHECK(lptr2.get() == &t.get()); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); + ASSERT_EQ(lptr1.get(), nullptr); + ASSERT_EQ(lptr2.get(), &t.get()); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 1}); } } -BOOST_AUTO_TEST_CASE(lent_ptr_unique_ptr) +SIMPLE_TEST(lent_ptr_unique_ptr) { - NoAssertsGuard eassert; + NO_ASSERT_GUARD; Test::resetCounters(); tl::unique_ptr uptr(new Test(1234)); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 1}); tl::lent_ptr lptr1 = uptr; - BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); - BOOST_CHECK(lptr1.get() == uptr.get()); - BOOST_CHECK((bool)lptr1 != false); - BOOST_CHECK(lptr1 == uptr); - BOOST_CHECK(lptr1 == uptr.get()); - BOOST_CHECK(lptr1.get() == uptr); - BOOST_CHECK(lptr1->data = 1234); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 1}); + ASSERT_EQ(lptr1.get(), uptr.get()); + ASSERT_NE((bool)lptr1, false); + ASSERT_EQ(lptr1, uptr); + ASSERT_EQ(lptr1, uptr.get()); + ASSERT_EQ(lptr1.get(), uptr); + ASSERT_EQ(lptr1->data, 1234); lptr1 = nullptr; - BOOST_CHECK(lptr1.get() == nullptr); - BOOST_CHECK((bool)lptr1 == false); - BOOST_CHECK(lptr1 == nullptr); + ASSERT_EQ(lptr1.get(), nullptr); + ASSERT_EQ((bool)lptr1, false); + ASSERT_EQ(lptr1, nullptr); } -BOOST_AUTO_TEST_CASE(lent_ptr_unique_ref) +SIMPLE_TEST(lent_ptr_unique_ref) { Test::resetCounters(); tl::unique_ref uptr(new Test(1234)); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 1}); tl::lent_ptr lptr1 = uptr; - BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); - BOOST_CHECK(lptr1.get() == uptr.get()); - BOOST_CHECK(lptr1 == uptr); - BOOST_CHECK(lptr1 == uptr.get()); - BOOST_CHECK(lptr1.get() == uptr); - BOOST_CHECK(lptr1->data = 1234); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 1}); + ASSERT_EQ(lptr1.get(), uptr.get()); + ASSERT_EQ(lptr1, uptr); + ASSERT_EQ(lptr1, uptr.get()); + ASSERT_EQ(lptr1.get(), uptr); + ASSERT_EQ(lptr1->data, 1234); lptr1 = nullptr; - BOOST_CHECK(lptr1.get() == nullptr); - BOOST_CHECK((bool)lptr1 == false); - BOOST_CHECK(lptr1 == nullptr); + ASSERT_EQ(lptr1.get(), nullptr); + ASSERT_EQ((bool)lptr1, false); + ASSERT_EQ(lptr1, nullptr); } -BOOST_AUTO_TEST_CASE(lent_ptr_unique_ptr_no_dangling) +SIMPLE_TEST(lent_ptr_unique_ptr_no_dangling) { - NoAssertsGuard eassert; + NO_ASSERT_GUARD; Test::resetCounters(); tl::unique_ptr uptr(new Test(1234)); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 1}); tl::lent_ptr lptr = uptr; lptr = nullptr; @@ -358,14 +251,14 @@ BOOST_AUTO_TEST_CASE(lent_ptr_unique_ptr_no_dangling) lptr = uptr; //no dangling here! } -BOOST_AUTO_TEST_CASE(lent_ptr_unique_ptr_move_no_dangling) +SIMPLE_TEST(lent_ptr_unique_ptr_move_no_dangling) { - NoAssertsGuard eassert; + NO_ASSERT_GUARD; Test::resetCounters(); tl::unique_ptr uptr(new Test(1234)); tl::unique_ptr uptr2; - BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 1}); tl::lent_ptr lptr = uptr; @@ -374,22 +267,22 @@ BOOST_AUTO_TEST_CASE(lent_ptr_unique_ptr_move_no_dangling) lptr = uptr2; //no dangling here! } -BOOST_AUTO_TEST_CASE(lent_ptr_unique_ptr_assign_nullptr_dangling) +SIMPLE_TEST(lent_ptr_unique_ptr_assign_nullptr_dangling) { { Test::resetCounters(); tl::unique_ptr uptr(new Test(1234)); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 1}); tl::lent_ptr lptr = uptr; { - ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("unique: 1 dangling lent ptrs detected"); uptr = nullptr; //dangling here! } { - ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 1 dangling lent ptrs detected"); lptr = nullptr; //dangling here! } } @@ -397,13 +290,13 @@ BOOST_AUTO_TEST_CASE(lent_ptr_unique_ptr_assign_nullptr_dangling) //destructor Test::resetCounters(); tl::unique_ptr uptr(new Test(1234)); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 1}); { - ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 1 dangling lent ptrs detected"); tl::lent_ptr lptr = uptr; { - ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("unique: 1 dangling lent ptrs detected"); uptr = nullptr; //dangling here! } } //dangling here! @@ -412,15 +305,15 @@ BOOST_AUTO_TEST_CASE(lent_ptr_unique_ptr_assign_nullptr_dangling) //reset Test::resetCounters(); tl::unique_ptr uptr(new Test(1234)); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 1}); tl::lent_ptr lptr = uptr; { - ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("unique: 1 dangling lent ptrs detected"); uptr = nullptr; //dangling here! } { - ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 1 dangling lent ptrs detected"); lptr = nullptr; //dangling here! } } @@ -428,15 +321,15 @@ BOOST_AUTO_TEST_CASE(lent_ptr_unique_ptr_assign_nullptr_dangling) //copy assignment to empty ptr Test::resetCounters(); tl::unique_ptr uptr(new Test(1234)); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 1}); tl::lent_ptr lptr = uptr; { - ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("unique: 1 dangling lent ptrs detected"); uptr = nullptr; //dangling here! } { - ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 1 dangling lent ptrs detected"); lptr = {}; //dangling here! } } @@ -445,16 +338,16 @@ BOOST_AUTO_TEST_CASE(lent_ptr_unique_ptr_assign_nullptr_dangling) Test::resetCounters(); tl::unique_ptr uptr1(new Test(1234)); tl::unique_ptr uptr2(new Test(1234)); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 2}); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 2}); tl::lent_ptr lptr1 = uptr1; tl::lent_ptr lptr2 = uptr2; { - ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("unique: 1 dangling lent ptrs detected"); uptr1 = nullptr; //dangling here! } { - ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 1 dangling lent ptrs detected"); lptr1 = lptr2; //dangling here! } } @@ -463,16 +356,16 @@ BOOST_AUTO_TEST_CASE(lent_ptr_unique_ptr_assign_nullptr_dangling) Test::resetCounters(); tl::unique_ptr uptr1(new Test(1234)); tl::unique_ptr uptr2(new Test(1234)); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 2}); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 2}); tl::lent_ptr lptr1 = uptr1; tl::lent_ptr lptr2 = uptr2; { - ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("unique: 1 dangling lent ptrs detected"); uptr1 = nullptr; //dangling here! } { - ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 1 dangling lent ptrs detected"); lptr1 = std::move(lptr2); //dangling here! } } @@ -480,30 +373,30 @@ BOOST_AUTO_TEST_CASE(lent_ptr_unique_ptr_assign_nullptr_dangling) //move assignment to a valid ptr Test::resetCounters(); tl::unique_ptr uptr(new Test(1234)); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 1}); tl::lent_ptr lptr1 = uptr; tl::lent_ptr lptr2 = uptr; tl::lent_ptr lptr3 = uptr; tl::lent_ptr lptr4 = uptr; { - ExpectedAssertGuard eassert("unique: 4 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("unique: 4 dangling lent ptrs detected"); uptr = nullptr; //dangling here! } { - ExpectedAssertGuard eassert("lent: 4 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 4 dangling lent ptrs detected"); lptr1 = {}; //dangling here! } { - ExpectedAssertGuard eassert("lent: 3 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 3 dangling lent ptrs detected"); lptr2 = {}; //dangling here! } { - ExpectedAssertGuard eassert("lent: 2 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 2 dangling lent ptrs detected"); lptr3 = {}; //dangling here! } { - ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 1 dangling lent ptrs detected"); lptr4 = {}; //dangling here! } } @@ -511,41 +404,41 @@ BOOST_AUTO_TEST_CASE(lent_ptr_unique_ptr_assign_nullptr_dangling) //move assignment to a valid ptr Test::resetCounters(); tl::unique_ptr uptr(new Test(1234)); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 1}); tl::lent_ptr lptr1 = uptr; tl::lent_ptr lptr2 = std::move(lptr1); { - ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("unique: 1 dangling lent ptrs detected"); uptr = nullptr; //dangling here! } { - NoAssertsGuard eassert; + NO_ASSERT_GUARD; lptr1 = {}; //dangling here! } { - ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 1 dangling lent ptrs detected"); lptr2 = {}; //dangling here! } } } -BOOST_AUTO_TEST_CASE(lent_ptr_unique_ptr_assign_new_dangling) +SIMPLE_TEST(lent_ptr_unique_ptr_assign_new_dangling) { { Test::resetCounters(); tl::unique_ptr uptr(new Test(1234)); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 1}); tl::lent_ptr lptr = uptr; { - ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("unique: 1 dangling lent ptrs detected"); uptr = {}; //dangling here! } { - ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 1 dangling lent ptrs detected"); lptr = nullptr; //dangling here! } } @@ -553,13 +446,13 @@ BOOST_AUTO_TEST_CASE(lent_ptr_unique_ptr_assign_new_dangling) //destructor Test::resetCounters(); tl::unique_ptr uptr(new Test(1234)); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 1}); { - ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 1 dangling lent ptrs detected"); tl::lent_ptr lptr = uptr; { - ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("unique: 1 dangling lent ptrs detected"); uptr = {}; //dangling here! } } //dangling here! @@ -568,15 +461,15 @@ BOOST_AUTO_TEST_CASE(lent_ptr_unique_ptr_assign_new_dangling) //reset Test::resetCounters(); tl::unique_ptr uptr(new Test(1234)); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 1}); tl::lent_ptr lptr = uptr; { - ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("unique: 1 dangling lent ptrs detected"); uptr = {}; //dangling here! } { - ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 1 dangling lent ptrs detected"); lptr = nullptr; //dangling here! } } @@ -584,15 +477,15 @@ BOOST_AUTO_TEST_CASE(lent_ptr_unique_ptr_assign_new_dangling) //copy assignment to empty ptr Test::resetCounters(); tl::unique_ptr uptr(new Test(1234)); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 1}); tl::lent_ptr lptr = uptr; { - ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("unique: 1 dangling lent ptrs detected"); uptr = {}; //dangling here! } { - ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 1 dangling lent ptrs detected"); lptr = {}; //dangling here! } } @@ -601,16 +494,16 @@ BOOST_AUTO_TEST_CASE(lent_ptr_unique_ptr_assign_new_dangling) Test::resetCounters(); tl::unique_ptr uptr1(new Test(1234)); tl::unique_ptr uptr2(new Test(1234)); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 2}); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 2}); tl::lent_ptr lptr1 = uptr1; tl::lent_ptr lptr2 = uptr2; { - ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("unique: 1 dangling lent ptrs detected"); uptr1 = {}; //dangling here! } { - ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 1 dangling lent ptrs detected"); lptr1 = lptr2; //dangling here! } } @@ -619,16 +512,16 @@ BOOST_AUTO_TEST_CASE(lent_ptr_unique_ptr_assign_new_dangling) Test::resetCounters(); tl::unique_ptr uptr1(new Test(1234)); tl::unique_ptr uptr2(new Test(1234)); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 2}); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 2}); tl::lent_ptr lptr1 = uptr1; tl::lent_ptr lptr2 = uptr2; { - ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("unique: 1 dangling lent ptrs detected"); uptr1 = {}; //dangling here! } { - ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 1 dangling lent ptrs detected"); lptr1 = std::move(lptr2); //dangling here! } } @@ -636,51 +529,51 @@ BOOST_AUTO_TEST_CASE(lent_ptr_unique_ptr_assign_new_dangling) //move assignment to a valid ptr Test::resetCounters(); tl::unique_ptr uptr(new Test(1234)); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 1}); tl::lent_ptr lptr1 = uptr; tl::lent_ptr lptr2 = uptr; tl::lent_ptr lptr3 = uptr; tl::lent_ptr lptr4 = uptr; { - ExpectedAssertGuard eassert("unique: 4 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("unique: 4 dangling lent ptrs detected"); uptr = {}; //dangling here! } { - ExpectedAssertGuard eassert("lent: 4 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 4 dangling lent ptrs detected"); lptr1 = {}; //dangling here! } { - ExpectedAssertGuard eassert("lent: 3 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 3 dangling lent ptrs detected"); lptr2 = {}; //dangling here! } { - ExpectedAssertGuard eassert("lent: 2 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 2 dangling lent ptrs detected"); lptr3 = {}; //dangling here! } { - ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 1 dangling lent ptrs detected"); lptr4 = {}; //dangling here! } } } -BOOST_AUTO_TEST_CASE(lent_ptr_unique_ptr_reset_dangling) +SIMPLE_TEST(lent_ptr_unique_ptr_reset_dangling) { { Test::resetCounters(); tl::unique_ptr uptr(new Test(1234)); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 1}); tl::lent_ptr lptr = uptr; { - ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("unique: 1 dangling lent ptrs detected"); uptr.reset(); //dangling here! } { - ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 1 dangling lent ptrs detected"); lptr = nullptr; //dangling here! } } @@ -688,13 +581,13 @@ BOOST_AUTO_TEST_CASE(lent_ptr_unique_ptr_reset_dangling) //destructor Test::resetCounters(); tl::unique_ptr uptr(new Test(1234)); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 1}); { - ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 1 dangling lent ptrs detected"); tl::lent_ptr lptr = uptr; { - ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("unique: 1 dangling lent ptrs detected"); uptr.reset(); //dangling here! } } //dangling here! @@ -703,15 +596,15 @@ BOOST_AUTO_TEST_CASE(lent_ptr_unique_ptr_reset_dangling) //reset Test::resetCounters(); tl::unique_ptr uptr(new Test(1234)); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 1}); tl::lent_ptr lptr = uptr; { - ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("unique: 1 dangling lent ptrs detected"); uptr.reset(); //dangling here! } { - ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 1 dangling lent ptrs detected"); lptr = nullptr; //dangling here! } } @@ -719,15 +612,15 @@ BOOST_AUTO_TEST_CASE(lent_ptr_unique_ptr_reset_dangling) //copy assignment to empty ptr Test::resetCounters(); tl::unique_ptr uptr(new Test(1234)); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 1}); tl::lent_ptr lptr = uptr; { - ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("unique: 1 dangling lent ptrs detected"); uptr.reset(); //dangling here! } { - ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 1 dangling lent ptrs detected"); lptr = {}; //dangling here! } } @@ -736,16 +629,16 @@ BOOST_AUTO_TEST_CASE(lent_ptr_unique_ptr_reset_dangling) Test::resetCounters(); tl::unique_ptr uptr1(new Test(1234)); tl::unique_ptr uptr2(new Test(1234)); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 2}); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 2}); tl::lent_ptr lptr1 = uptr1; tl::lent_ptr lptr2 = uptr2; { - ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("unique: 1 dangling lent ptrs detected"); uptr1.reset(); //dangling here! } { - ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 1 dangling lent ptrs detected"); lptr1 = lptr2; //dangling here! } } @@ -754,16 +647,16 @@ BOOST_AUTO_TEST_CASE(lent_ptr_unique_ptr_reset_dangling) Test::resetCounters(); tl::unique_ptr uptr1(new Test(1234)); tl::unique_ptr uptr2(new Test(1234)); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 2}); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 2}); tl::lent_ptr lptr1 = uptr1; tl::lent_ptr lptr2 = uptr2; { - ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("unique: 1 dangling lent ptrs detected"); uptr1.reset(); //dangling here! } { - ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 1 dangling lent ptrs detected"); lptr1 = std::move(lptr2); //dangling here! } } @@ -771,52 +664,52 @@ BOOST_AUTO_TEST_CASE(lent_ptr_unique_ptr_reset_dangling) //move assignment to a valid ptr Test::resetCounters(); tl::unique_ptr uptr(new Test(1234)); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 1}); tl::lent_ptr lptr1 = uptr; tl::lent_ptr lptr2 = uptr; tl::lent_ptr lptr3 = uptr; tl::lent_ptr lptr4 = uptr; { - ExpectedAssertGuard eassert("unique: 4 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("unique: 4 dangling lent ptrs detected"); uptr.reset(); //dangling here! } { - ExpectedAssertGuard eassert("lent: 4 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 4 dangling lent ptrs detected"); lptr1 = {}; //dangling here! } { - ExpectedAssertGuard eassert("lent: 3 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 3 dangling lent ptrs detected"); lptr2 = {}; //dangling here! } { - ExpectedAssertGuard eassert("lent: 2 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 2 dangling lent ptrs detected"); lptr3 = {}; //dangling here! } { - ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 1 dangling lent ptrs detected"); lptr4 = {}; //dangling here! } } } -BOOST_AUTO_TEST_CASE(lent_ptr_unique_ptr_assign_move_dangling) +SIMPLE_TEST(lent_ptr_unique_ptr_assign_move_dangling) { { Test::resetCounters(); tl::unique_ptr uptr(new Test(1234)); tl::unique_ptr uptr2(new Test(1234)); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 2}); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 2}); tl::lent_ptr lptr = uptr; { - ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("unique: 1 dangling lent ptrs detected"); uptr = std::move(uptr2); //dangling here! } { - ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 1 dangling lent ptrs detected"); lptr = nullptr; //dangling here! } } @@ -825,13 +718,13 @@ BOOST_AUTO_TEST_CASE(lent_ptr_unique_ptr_assign_move_dangling) Test::resetCounters(); tl::unique_ptr uptr(new Test(1234)); tl::unique_ptr uptr2(new Test(1234)); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 2}); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 2}); { - ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 1 dangling lent ptrs detected"); tl::lent_ptr lptr = uptr; { - ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("unique: 1 dangling lent ptrs detected"); uptr = std::move(uptr2); //dangling here! } } //dangling here! @@ -841,15 +734,15 @@ BOOST_AUTO_TEST_CASE(lent_ptr_unique_ptr_assign_move_dangling) Test::resetCounters(); tl::unique_ptr uptr(new Test(1234)); tl::unique_ptr uptr2(new Test(1234)); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 2}); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 2}); tl::lent_ptr lptr = uptr; { - ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("unique: 1 dangling lent ptrs detected"); uptr = std::move(uptr2); //dangling here! } { - ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 1 dangling lent ptrs detected"); lptr = nullptr; //dangling here! } } @@ -858,15 +751,15 @@ BOOST_AUTO_TEST_CASE(lent_ptr_unique_ptr_assign_move_dangling) Test::resetCounters(); tl::unique_ptr uptr(new Test(1234)); tl::unique_ptr uptr2(new Test(1234)); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 2}); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 2}); tl::lent_ptr lptr = uptr; { - ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("unique: 1 dangling lent ptrs detected"); uptr = std::move(uptr2); //dangling here! } { - ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 1 dangling lent ptrs detected"); lptr = {}; //dangling here! } } @@ -876,16 +769,16 @@ BOOST_AUTO_TEST_CASE(lent_ptr_unique_ptr_assign_move_dangling) tl::unique_ptr uptr1(new Test(1234)); tl::unique_ptr uptr2(new Test(1234)); tl::unique_ptr uptr3(new Test(1234)); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 3}); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 3}); tl::lent_ptr lptr1 = uptr1; tl::lent_ptr lptr2 = uptr2; { - ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("unique: 1 dangling lent ptrs detected"); uptr1 = std::move(uptr3); //dangling here! } { - ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 1 dangling lent ptrs detected"); lptr1 = lptr2; //dangling here! } } @@ -895,16 +788,16 @@ BOOST_AUTO_TEST_CASE(lent_ptr_unique_ptr_assign_move_dangling) tl::unique_ptr uptr1(new Test(1234)); tl::unique_ptr uptr2(new Test(1234)); tl::unique_ptr uptr3(new Test(1234)); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 3}); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 3}); tl::lent_ptr lptr1 = uptr1; tl::lent_ptr lptr2 = uptr2; { - ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("unique: 1 dangling lent ptrs detected"); uptr1 = std::move(uptr3); //dangling here! } { - ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 1 dangling lent ptrs detected"); lptr1 = std::move(lptr2); //dangling here! } } @@ -913,30 +806,30 @@ BOOST_AUTO_TEST_CASE(lent_ptr_unique_ptr_assign_move_dangling) Test::resetCounters(); tl::unique_ptr uptr(new Test(1234)); tl::unique_ptr uptr2(new Test(1234)); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 2}); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 2}); tl::lent_ptr lptr1 = uptr; tl::lent_ptr lptr2 = uptr; tl::lent_ptr lptr3 = uptr; tl::lent_ptr lptr4 = uptr; { - ExpectedAssertGuard eassert("unique: 4 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("unique: 4 dangling lent ptrs detected"); uptr = std::move(uptr2); //dangling here! } { - ExpectedAssertGuard eassert("lent: 4 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 4 dangling lent ptrs detected"); lptr1 = {}; //dangling here! } { - ExpectedAssertGuard eassert("lent: 3 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 3 dangling lent ptrs detected"); lptr2 = {}; //dangling here! } { - ExpectedAssertGuard eassert("lent: 2 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 2 dangling lent ptrs detected"); lptr3 = {}; //dangling here! } { - ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 1 dangling lent ptrs detected"); lptr4 = {}; //dangling here! } } @@ -950,16 +843,16 @@ BOOST_AUTO_TEST_CASE(lent_ptr_unique_ptr_assign_move_dangling) ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -BOOST_AUTO_TEST_CASE(lent_ptr_unique_ref_no_dangling) +SIMPLE_TEST(lent_ptr_unique_ref_no_dangling) { - NoAssertsGuard eassert; + NO_ASSERT_GUARD; tl::lent_ptr lptr; { Test::resetCounters(); tl::unique_ref uref(new Test(1234)); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 1}); lptr = uref; lptr = nullptr; @@ -968,13 +861,13 @@ BOOST_AUTO_TEST_CASE(lent_ptr_unique_ref_no_dangling) lptr = {}; //no dangling here! } -BOOST_AUTO_TEST_CASE(lent_ptr_unique_ref_move_no_dangling) +SIMPLE_TEST(lent_ptr_unique_ref_move_no_dangling) { - NoAssertsGuard eassert; + NO_ASSERT_GUARD; Test::resetCounters(); tl::unique_ref uref(new Test(1234)); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 1}); tl::lent_ptr lptr = uref; @@ -984,22 +877,22 @@ BOOST_AUTO_TEST_CASE(lent_ptr_unique_ref_move_no_dangling) lptr = nullptr; //to avoid a legit dangling when the uref2 goes out of scope } -BOOST_AUTO_TEST_CASE(lent_ptr_unique_ref_assign_nullptr_dangling) +SIMPLE_TEST(lent_ptr_unique_ref_assign_nullptr_dangling) { { Test::resetCounters(); tl::unique_ref uref(new Test(1234)); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 1}); tl::lent_ptr lptr = uref; { - ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("unique: 1 dangling lent ptrs detected"); uref = tl::unique_ref(new Test(1234)); //dangling here! } { - ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 1 dangling lent ptrs detected"); lptr = nullptr; //dangling here! } } @@ -1007,13 +900,13 @@ BOOST_AUTO_TEST_CASE(lent_ptr_unique_ref_assign_nullptr_dangling) //destructor Test::resetCounters(); tl::unique_ref uref(new Test(1234)); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 1}); { - ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 1 dangling lent ptrs detected"); tl::lent_ptr lptr = uref; { - ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("unique: 1 dangling lent ptrs detected"); uref = tl::unique_ref(new Test(1234)); //dangling here! } } //dangling here! @@ -1022,15 +915,15 @@ BOOST_AUTO_TEST_CASE(lent_ptr_unique_ref_assign_nullptr_dangling) //reset Test::resetCounters(); tl::unique_ref uref(new Test(1234)); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 1}); tl::lent_ptr lptr = uref; { - ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("unique: 1 dangling lent ptrs detected"); uref = tl::unique_ref(new Test(1234)); //dangling here! } { - ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 1 dangling lent ptrs detected"); lptr = nullptr; //dangling here! } } @@ -1038,15 +931,15 @@ BOOST_AUTO_TEST_CASE(lent_ptr_unique_ref_assign_nullptr_dangling) //copy assignment to empty ptr Test::resetCounters(); tl::unique_ref uref(new Test(1234)); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 1}); tl::lent_ptr lptr = uref; { - ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("unique: 1 dangling lent ptrs detected"); uref = tl::unique_ref(new Test(1234)); //dangling here! } { - ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 1 dangling lent ptrs detected"); lptr = {}; //dangling here! } } @@ -1055,16 +948,16 @@ BOOST_AUTO_TEST_CASE(lent_ptr_unique_ref_assign_nullptr_dangling) Test::resetCounters(); tl::unique_ref uref1(new Test(1234)); tl::unique_ref uref2(new Test(1234)); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 2}); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 2}); tl::lent_ptr lptr1 = uref1; tl::lent_ptr lptr2 = uref2; { - ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("unique: 1 dangling lent ptrs detected"); uref1 = tl::unique_ref(new Test(1234)); //dangling here! } { - ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 1 dangling lent ptrs detected"); lptr1 = lptr2; //dangling here! } } @@ -1073,16 +966,16 @@ BOOST_AUTO_TEST_CASE(lent_ptr_unique_ref_assign_nullptr_dangling) Test::resetCounters(); tl::unique_ref uref1(new Test(1234)); tl::unique_ref uref2(new Test(1234)); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 2}); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 2}); tl::lent_ptr lptr1 = uref1; tl::lent_ptr lptr2 = uref2; { - ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("unique: 1 dangling lent ptrs detected"); uref1 = tl::unique_ref(new Test(1234)); //dangling here! } { - ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 1 dangling lent ptrs detected"); lptr1 = std::move(lptr2); //dangling here! } } @@ -1090,52 +983,52 @@ BOOST_AUTO_TEST_CASE(lent_ptr_unique_ref_assign_nullptr_dangling) //move assignment to a valid ptr Test::resetCounters(); tl::unique_ref uref(new Test(1234)); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 1}); tl::lent_ptr lptr1 = uref; tl::lent_ptr lptr2 = uref; tl::lent_ptr lptr3 = uref; tl::lent_ptr lptr4 = uref; { - ExpectedAssertGuard eassert("unique: 4 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("unique: 4 dangling lent ptrs detected"); uref = tl::unique_ref(new Test(1234)); //dangling here! } { - ExpectedAssertGuard eassert("lent: 4 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 4 dangling lent ptrs detected"); lptr1 = {}; //dangling here! } { - ExpectedAssertGuard eassert("lent: 3 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 3 dangling lent ptrs detected"); lptr2 = {}; //dangling here! } { - ExpectedAssertGuard eassert("lent: 2 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 2 dangling lent ptrs detected"); lptr3 = {}; //dangling here! } { - ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 1 dangling lent ptrs detected"); lptr4 = {}; //dangling here! } } } -BOOST_AUTO_TEST_CASE(lent_ptr_unique_ref_reset_dangling) +SIMPLE_TEST(lent_ptr_unique_ref_reset_dangling) { { Test::resetCounters(); tl::unique_ref uref(new Test(1234)); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 1}); tl::lent_ptr lptr = uref; { - ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("unique: 1 dangling lent ptrs detected"); uref.reset(new Test(1234)); //dangling here! } { - ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 1 dangling lent ptrs detected"); lptr = nullptr; //dangling here! } } @@ -1143,13 +1036,13 @@ BOOST_AUTO_TEST_CASE(lent_ptr_unique_ref_reset_dangling) //destructor Test::resetCounters(); tl::unique_ref uref(new Test(1234)); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 1}); { - ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 1 dangling lent ptrs detected"); tl::lent_ptr lptr = uref; { - ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("unique: 1 dangling lent ptrs detected"); uref.reset(new Test(1234)); //dangling here! } } //dangling here! @@ -1158,15 +1051,15 @@ BOOST_AUTO_TEST_CASE(lent_ptr_unique_ref_reset_dangling) //reset Test::resetCounters(); tl::unique_ref uref(new Test(1234)); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 1}); tl::lent_ptr lptr = uref; { - ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("unique: 1 dangling lent ptrs detected"); uref.reset(new Test(1234)); //dangling here! } { - ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 1 dangling lent ptrs detected"); lptr = nullptr; //dangling here! } } @@ -1174,15 +1067,15 @@ BOOST_AUTO_TEST_CASE(lent_ptr_unique_ref_reset_dangling) //copy assignment to empty ptr Test::resetCounters(); tl::unique_ref uref(new Test(1234)); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 1}); tl::lent_ptr lptr = uref; { - ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("unique: 1 dangling lent ptrs detected"); uref.reset(new Test(1234)); //dangling here! } { - ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 1 dangling lent ptrs detected"); lptr = {}; //dangling here! } } @@ -1191,16 +1084,16 @@ BOOST_AUTO_TEST_CASE(lent_ptr_unique_ref_reset_dangling) Test::resetCounters(); tl::unique_ref uref1(new Test(1234)); tl::unique_ref uref2(new Test(1234)); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 2}); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 2}); tl::lent_ptr lptr1 = uref1; tl::lent_ptr lptr2 = uref2; { - ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("unique: 1 dangling lent ptrs detected"); uref1.reset(new Test(1234)); //dangling here! } { - ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 1 dangling lent ptrs detected"); lptr1 = lptr2; //dangling here! } } @@ -1209,16 +1102,16 @@ BOOST_AUTO_TEST_CASE(lent_ptr_unique_ref_reset_dangling) Test::resetCounters(); tl::unique_ref uref1(new Test(1234)); tl::unique_ref uref2(new Test(1234)); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 2}); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 2}); tl::lent_ptr lptr1 = uref1; tl::lent_ptr lptr2 = uref2; { - ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("unique: 1 dangling lent ptrs detected"); uref1.reset(new Test(1234)); //dangling here! } { - ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 1 dangling lent ptrs detected"); lptr1 = std::move(lptr2); //dangling here! } } @@ -1226,52 +1119,52 @@ BOOST_AUTO_TEST_CASE(lent_ptr_unique_ref_reset_dangling) //move assignment to a valid ptr Test::resetCounters(); tl::unique_ref uref(new Test(1234)); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 1}); tl::lent_ptr lptr1 = uref; tl::lent_ptr lptr2 = uref; tl::lent_ptr lptr3 = uref; tl::lent_ptr lptr4 = uref; { - ExpectedAssertGuard eassert("unique: 4 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("unique: 4 dangling lent ptrs detected"); uref.reset(new Test(1234)); //dangling here! } { - ExpectedAssertGuard eassert("lent: 4 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 4 dangling lent ptrs detected"); lptr1 = {}; //dangling here! } { - ExpectedAssertGuard eassert("lent: 3 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 3 dangling lent ptrs detected"); lptr2 = {}; //dangling here! } { - ExpectedAssertGuard eassert("lent: 2 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 2 dangling lent ptrs detected"); lptr3 = {}; //dangling here! } { - ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 1 dangling lent ptrs detected"); lptr4 = {}; //dangling here! } } } -BOOST_AUTO_TEST_CASE(lent_ptr_unique_ref_assign_move_dangling) +SIMPLE_TEST(lent_ptr_unique_ref_assign_move_dangling) { { Test::resetCounters(); tl::unique_ref uref(new Test(1234)); tl::unique_ref uref2(new Test(1234)); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 2}); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 2}); tl::lent_ptr lptr = uref; { - ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("unique: 1 dangling lent ptrs detected"); uref = std::move(uref2); //dangling here! } { - ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 1 dangling lent ptrs detected"); lptr = nullptr; //dangling here! } } @@ -1280,13 +1173,13 @@ BOOST_AUTO_TEST_CASE(lent_ptr_unique_ref_assign_move_dangling) Test::resetCounters(); tl::unique_ref uref(new Test(1234)); tl::unique_ref uref2(new Test(1234)); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 2}); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 2}); { - ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 1 dangling lent ptrs detected"); tl::lent_ptr lptr = uref; { - ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("unique: 1 dangling lent ptrs detected"); uref = std::move(uref2); //dangling here! } } //dangling here! @@ -1296,15 +1189,15 @@ BOOST_AUTO_TEST_CASE(lent_ptr_unique_ref_assign_move_dangling) Test::resetCounters(); tl::unique_ref uref(new Test(1234)); tl::unique_ref uref2(new Test(1234)); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 2}); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 2}); tl::lent_ptr lptr = uref; { - ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("unique: 1 dangling lent ptrs detected"); uref = std::move(uref2); //dangling here! } { - ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 1 dangling lent ptrs detected"); lptr = nullptr; //dangling here! } } @@ -1313,15 +1206,15 @@ BOOST_AUTO_TEST_CASE(lent_ptr_unique_ref_assign_move_dangling) Test::resetCounters(); tl::unique_ref uref(new Test(1234)); tl::unique_ref uref2(new Test(1234)); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 2}); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 2}); tl::lent_ptr lptr = uref; { - ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("unique: 1 dangling lent ptrs detected"); uref = std::move(uref2); //dangling here! } { - ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 1 dangling lent ptrs detected"); lptr = {}; //dangling here! } } @@ -1331,16 +1224,16 @@ BOOST_AUTO_TEST_CASE(lent_ptr_unique_ref_assign_move_dangling) tl::unique_ref uref1(new Test(1234)); tl::unique_ref uref2(new Test(1234)); tl::unique_ref uref3(new Test(1234)); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 3}); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 3}); tl::lent_ptr lptr1 = uref1; tl::lent_ptr lptr2 = uref2; { - ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("unique: 1 dangling lent ptrs detected"); uref1 = std::move(uref3); //dangling here! } { - ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 1 dangling lent ptrs detected"); lptr1 = lptr2; //dangling here! } } @@ -1350,16 +1243,16 @@ BOOST_AUTO_TEST_CASE(lent_ptr_unique_ref_assign_move_dangling) tl::unique_ref uref1(new Test(1234)); tl::unique_ref uref2(new Test(1234)); tl::unique_ref uref3(new Test(1234)); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 3}); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 3}); tl::lent_ptr lptr1 = uref1; tl::lent_ptr lptr2 = uref2; { - ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("unique: 1 dangling lent ptrs detected"); uref1 = std::move(uref3); //dangling here! } { - ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 1 dangling lent ptrs detected"); lptr1 = std::move(lptr2); //dangling here! } } @@ -1368,30 +1261,30 @@ BOOST_AUTO_TEST_CASE(lent_ptr_unique_ref_assign_move_dangling) Test::resetCounters(); tl::unique_ref uref(new Test(1234)); tl::unique_ref uref2(new Test(1234)); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 2}); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 2}); tl::lent_ptr lptr1 = uref; tl::lent_ptr lptr2 = uref; tl::lent_ptr lptr3 = uref; tl::lent_ptr lptr4 = uref; { - ExpectedAssertGuard eassert("unique: 4 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("unique: 4 dangling lent ptrs detected"); uref = std::move(uref2); //dangling here! } { - ExpectedAssertGuard eassert("lent: 4 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 4 dangling lent ptrs detected"); lptr1 = {}; //dangling here! } { - ExpectedAssertGuard eassert("lent: 3 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 3 dangling lent ptrs detected"); lptr2 = {}; //dangling here! } { - ExpectedAssertGuard eassert("lent: 2 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 2 dangling lent ptrs detected"); lptr3 = {}; //dangling here! } { - ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 1 dangling lent ptrs detected"); lptr4 = {}; //dangling here! } } @@ -1426,35 +1319,35 @@ BOOST_AUTO_TEST_CASE(lent_ptr_unique_ref_assign_move_dangling) //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -BOOST_AUTO_TEST_CASE(lent_ref_ctor_ptr) +SIMPLE_TEST(lent_ref_ctor_ptr) { - NoAssertsGuard eassert; + NO_ASSERT_GUARD; Test::resetCounters(); tl::lendable t; tl::lent_ref lptr(tl::lend(t)); - BOOST_CHECK(lptr.get() == &t.get()); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); + ASSERT_EQ(lptr.get(), &t.get()); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 1}); } -BOOST_AUTO_TEST_CASE(lent_ref_copy_ctor) +SIMPLE_TEST(lent_ref_copy_ctor) { - NoAssertsGuard eassert; + NO_ASSERT_GUARD; { Test::resetCounters(); tl::lendable t; tl::lent_ref lptr1(tl::lend(t)); tl::lent_ref lptr2(lptr1); - BOOST_CHECK(lptr1.get() == &t.get()); - BOOST_CHECK(lptr2.get() == &t.get()); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); + ASSERT_EQ(lptr1.get(), &t.get()); + ASSERT_EQ(lptr2.get(), &t.get()); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 1}); } } -BOOST_AUTO_TEST_CASE(lent_ref_move_ctor) +SIMPLE_TEST(lent_ref_move_ctor) { - NoAssertsGuard eassert; + NO_ASSERT_GUARD; { Test::resetCounters(); @@ -1462,17 +1355,17 @@ BOOST_AUTO_TEST_CASE(lent_ref_move_ctor) tl::lent_ref lptr1(tl::lend(t)); tl::lent_ref lptr2(std::move(lptr1)); { - ExpectedCrashGuard ecrash("nullptr"); - BOOST_CHECK(lptr1.get() == nullptr); + EXPECTED_CRASH_GUARD("nullptr"); + ASSERT_EQ(lptr1.get(), nullptr); } - BOOST_CHECK(lptr2.get() == &t.get()); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); + ASSERT_EQ(lptr2.get(), &t.get()); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 1}); } } -BOOST_AUTO_TEST_CASE(lent_ref_copy_ass) +SIMPLE_TEST(lent_ref_copy_ass) { - NoAssertsGuard eassert; + NO_ASSERT_GUARD; { Test::resetCounters(); @@ -1481,15 +1374,15 @@ BOOST_AUTO_TEST_CASE(lent_ref_copy_ass) tl::lent_ref lptr1(tl::lend(t1)); tl::lent_ref lptr2(tl::lend(t2)); lptr2 = lptr1; - BOOST_CHECK(lptr1.get() == &t1.get()); - BOOST_CHECK(lptr2.get() == &t1.get()); - BOOST_CHECK(t1->s_counters == Counters{.ctor = 2}); + ASSERT_EQ(lptr1.get(), &t1.get()); + ASSERT_EQ(lptr2.get(), &t1.get()); + ASSERT_EQ(t1->s_counters, Counters{.ctor = 2}); } } -BOOST_AUTO_TEST_CASE(lent_ref_move_ass) +SIMPLE_TEST(lent_ref_move_ass) { - NoAssertsGuard eassert; + NO_ASSERT_GUARD; { Test::resetCounters(); @@ -1499,53 +1392,53 @@ BOOST_AUTO_TEST_CASE(lent_ref_move_ass) tl::lent_ref lptr2(tl::lend(t2)); lptr2 = std::move(lptr1); { - ExpectedCrashGuard ecrash("nullptr"); - BOOST_CHECK(lptr1.get() == nullptr); + EXPECTED_CRASH_GUARD("nullptr"); + ASSERT_EQ(lptr1.get(), nullptr); } - BOOST_CHECK(lptr2.get() == &t1.get()); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 2}); + ASSERT_EQ(lptr2.get(), &t1.get()); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 2}); } } -BOOST_AUTO_TEST_CASE(lent_ref_unique_ptr) +SIMPLE_TEST(lent_ref_unique_ptr) { - NoAssertsGuard eassert; + NO_ASSERT_GUARD; Test::resetCounters(); tl::unique_ptr uptr(new Test(1234)); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 1}); tl::lent_ref lptr1 = tl::promote(uptr); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); - BOOST_CHECK(lptr1.get() == uptr.get()); - BOOST_CHECK(lptr1 == uptr); - BOOST_CHECK(lptr1 == uptr.get()); - BOOST_CHECK(lptr1.get() == uptr); - BOOST_CHECK(lptr1->data = 1234); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 1}); + ASSERT_EQ(lptr1.get(), uptr.get()); + ASSERT_EQ(lptr1, uptr); + ASSERT_EQ(lptr1, uptr.get()); + ASSERT_EQ(lptr1.get(), uptr); + ASSERT_EQ(lptr1->data, 1234); } -BOOST_AUTO_TEST_CASE(lent_ref_unique_ref) +SIMPLE_TEST(lent_ref_unique_ref) { Test::resetCounters(); tl::unique_ref uptr(new Test(1234)); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 1}); tl::lent_ref lptr1 = uptr; - BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); - BOOST_CHECK(lptr1.get() == uptr.get()); - BOOST_CHECK(lptr1 == uptr); - BOOST_CHECK(lptr1 == uptr.get()); - BOOST_CHECK(lptr1.get() == uptr); - BOOST_CHECK(lptr1->data = 1234); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 1}); + ASSERT_EQ(lptr1.get(), uptr.get()); + ASSERT_EQ(lptr1, uptr); + ASSERT_EQ(lptr1, uptr.get()); + ASSERT_EQ(lptr1.get(), uptr); + ASSERT_EQ(lptr1->data, 1234); } -BOOST_AUTO_TEST_CASE(lent_ref_unique_ptr_no_dangling) +SIMPLE_TEST(lent_ref_unique_ptr_no_dangling) { - NoAssertsGuard eassert; + NO_ASSERT_GUARD; Test::resetCounters(); tl::unique_ptr uptr(new Test(1234)); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 1}); { tl::lent_ref lptr = tl::promote(uptr); @@ -1554,14 +1447,14 @@ BOOST_AUTO_TEST_CASE(lent_ref_unique_ptr_no_dangling) uptr = nullptr; } -BOOST_AUTO_TEST_CASE(lent_ref_unique_ptr_move_no_dangling) +SIMPLE_TEST(lent_ref_unique_ptr_move_no_dangling) { - NoAssertsGuard eassert; + NO_ASSERT_GUARD; Test::resetCounters(); tl::unique_ptr uptr(new Test(1234)); tl::unique_ptr uptr2; - BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 1}); tl::lent_ref lptr = tl::promote(uptr); @@ -1570,23 +1463,23 @@ BOOST_AUTO_TEST_CASE(lent_ref_unique_ptr_move_no_dangling) lptr = tl::promote(uptr2); //no dangling here! } -BOOST_AUTO_TEST_CASE(lent_ref_unique_ptr_assign_nullptr_dangling) +SIMPLE_TEST(lent_ref_unique_ptr_assign_nullptr_dangling) { { Test::resetCounters(); tl::lendable t; tl::unique_ptr uptr(new Test(1234)); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 2}); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 2}); tl::lent_ref lptr = tl::promote(uptr); { - ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("unique: 1 dangling lent ptrs detected"); uptr = nullptr; //dangling here! } { - ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 1 dangling lent ptrs detected"); lptr = tl::lend(t); //dangling here! } } @@ -1594,13 +1487,13 @@ BOOST_AUTO_TEST_CASE(lent_ref_unique_ptr_assign_nullptr_dangling) //destructor Test::resetCounters(); tl::unique_ptr uptr(new Test(1234)); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 1}); { - ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 1 dangling lent ptrs detected"); tl::lent_ref lptr = tl::promote(uptr); { - ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("unique: 1 dangling lent ptrs detected"); uptr = nullptr; //dangling here! } } //dangling here! @@ -1609,12 +1502,12 @@ BOOST_AUTO_TEST_CASE(lent_ref_unique_ptr_assign_nullptr_dangling) //reset Test::resetCounters(); tl::unique_ptr uptr(new Test(1234)); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 1}); - ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 1 dangling lent ptrs detected"); tl::lent_ref lptr = tl::promote(uptr); { - ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("unique: 1 dangling lent ptrs detected"); uptr = nullptr; //dangling here! } } @@ -1622,12 +1515,12 @@ BOOST_AUTO_TEST_CASE(lent_ref_unique_ptr_assign_nullptr_dangling) //copy assignment to empty ptr Test::resetCounters(); tl::unique_ptr uptr(new Test(1234)); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 1}); - ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 1 dangling lent ptrs detected"); tl::lent_ref lptr = tl::promote(uptr); { - ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("unique: 1 dangling lent ptrs detected"); uptr = nullptr; //dangling here! } } @@ -1636,16 +1529,16 @@ BOOST_AUTO_TEST_CASE(lent_ref_unique_ptr_assign_nullptr_dangling) Test::resetCounters(); tl::unique_ptr uptr1(new Test(1234)); tl::unique_ptr uptr2(new Test(1234)); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 2}); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 2}); tl::lent_ref lptr1 = tl::promote(uptr1); tl::lent_ref lptr2 = tl::promote(uptr2); { - ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("unique: 1 dangling lent ptrs detected"); uptr1 = nullptr; //dangling here! } { - ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 1 dangling lent ptrs detected"); lptr1 = lptr2; //dangling here! } } @@ -1654,16 +1547,16 @@ BOOST_AUTO_TEST_CASE(lent_ref_unique_ptr_assign_nullptr_dangling) Test::resetCounters(); tl::unique_ptr uptr1(new Test(1234)); tl::unique_ptr uptr2(new Test(1234)); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 2}); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 2}); tl::lent_ref lptr1 = tl::promote(uptr1); tl::lent_ref lptr2 = tl::promote(uptr2); { - ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("unique: 1 dangling lent ptrs detected"); uptr1 = nullptr; //dangling here! } { - ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 1 dangling lent ptrs detected"); lptr1 = std::move(lptr2); //dangling here! } } @@ -1672,52 +1565,52 @@ BOOST_AUTO_TEST_CASE(lent_ref_unique_ptr_assign_nullptr_dangling) Test::resetCounters(); tl::lendable t; tl::unique_ptr uptr(new Test(1234)); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 2}); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 2}); tl::lent_ref lptr1 = tl::promote(uptr); tl::lent_ref lptr2 = tl::promote(uptr); tl::lent_ref lptr3 = tl::promote(uptr); tl::lent_ref lptr4 = tl::promote(uptr); { - ExpectedAssertGuard eassert("unique: 4 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("unique: 4 dangling lent ptrs detected"); uptr = nullptr; //dangling here! } { - ExpectedAssertGuard eassert("lent: 4 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 4 dangling lent ptrs detected"); lptr1 = tl::lend(t); //dangling here! } { - ExpectedAssertGuard eassert("lent: 3 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 3 dangling lent ptrs detected"); lptr2 = tl::lend(t); //dangling here! } { - ExpectedAssertGuard eassert("lent: 2 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 2 dangling lent ptrs detected"); lptr3 = tl::lend(t); //dangling here! } { - ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 1 dangling lent ptrs detected"); lptr4 = tl::lend(t); //dangling here! } } } -BOOST_AUTO_TEST_CASE(lent_ref_unique_ptr_assign_new_dangling) +SIMPLE_TEST(lent_ref_unique_ptr_assign_new_dangling) { { Test::resetCounters(); tl::unique_ptr uptr(new Test(1234)); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 1}); tl::lendable t; tl::lent_ref lptr = tl::promote(uptr); { - ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("unique: 1 dangling lent ptrs detected"); uptr = {}; //dangling here! } { - ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 1 dangling lent ptrs detected"); lptr = tl::lend(t); //dangling here! } } @@ -1725,13 +1618,13 @@ BOOST_AUTO_TEST_CASE(lent_ref_unique_ptr_assign_new_dangling) //destructor Test::resetCounters(); tl::unique_ptr uptr(new Test(1234)); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 1}); { - ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 1 dangling lent ptrs detected"); tl::lent_ref lptr = tl::promote(uptr); { - ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("unique: 1 dangling lent ptrs detected"); uptr = {}; //dangling here! } } //dangling here! @@ -1741,15 +1634,15 @@ BOOST_AUTO_TEST_CASE(lent_ref_unique_ptr_assign_new_dangling) Test::resetCounters(); tl::lendable t; tl::unique_ptr uptr(new Test(1234)); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 2}); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 2}); tl::lent_ref lptr = tl::promote(uptr); { - ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("unique: 1 dangling lent ptrs detected"); uptr = {}; //dangling here! } { - ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 1 dangling lent ptrs detected"); lptr = tl::lend(t); //dangling here! } } @@ -1758,15 +1651,15 @@ BOOST_AUTO_TEST_CASE(lent_ref_unique_ptr_assign_new_dangling) Test::resetCounters(); tl::lendable t; tl::unique_ptr uptr(new Test(1234)); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 2}); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 2}); tl::lent_ref lptr = tl::promote(uptr); { - ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("unique: 1 dangling lent ptrs detected"); uptr = {}; //dangling here! } { - ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 1 dangling lent ptrs detected"); lptr = tl::lend(t); //dangling here! } } @@ -1775,16 +1668,16 @@ BOOST_AUTO_TEST_CASE(lent_ref_unique_ptr_assign_new_dangling) Test::resetCounters(); tl::unique_ptr uptr1(new Test(1234)); tl::unique_ptr uptr2(new Test(1234)); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 2}); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 2}); tl::lent_ref lptr1 = tl::promote(uptr1); tl::lent_ref lptr2 = tl::promote(uptr2); { - ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("unique: 1 dangling lent ptrs detected"); uptr1 = {}; //dangling here! } { - ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 1 dangling lent ptrs detected"); lptr1 = lptr2; //dangling here! } } @@ -1793,16 +1686,16 @@ BOOST_AUTO_TEST_CASE(lent_ref_unique_ptr_assign_new_dangling) Test::resetCounters(); tl::unique_ptr uptr1(new Test(1234)); tl::unique_ptr uptr2(new Test(1234)); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 2}); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 2}); tl::lent_ref lptr1 = tl::promote(uptr1); tl::lent_ref lptr2 = tl::promote(uptr2); { - ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("unique: 1 dangling lent ptrs detected"); uptr1 = {}; //dangling here! } { - ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 1 dangling lent ptrs detected"); lptr1 = std::move(lptr2); //dangling here! } } @@ -1811,52 +1704,52 @@ BOOST_AUTO_TEST_CASE(lent_ref_unique_ptr_assign_new_dangling) Test::resetCounters(); tl::lendable t; tl::unique_ptr uptr(new Test(1234)); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 2}); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 2}); tl::lent_ref lptr1 = tl::promote(uptr); tl::lent_ref lptr2 = tl::promote(uptr); tl::lent_ref lptr3 = tl::promote(uptr); tl::lent_ref lptr4 = tl::promote(uptr); { - ExpectedAssertGuard eassert("unique: 4 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("unique: 4 dangling lent ptrs detected"); uptr = {}; //dangling here! } { - ExpectedAssertGuard eassert("lent: 4 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 4 dangling lent ptrs detected"); lptr1 = tl::lend(t); //dangling here! } { - ExpectedAssertGuard eassert("lent: 3 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 3 dangling lent ptrs detected"); lptr2 = tl::lend(t); //dangling here! } { - ExpectedAssertGuard eassert("lent: 2 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 2 dangling lent ptrs detected"); lptr3 = tl::lend(t); //dangling here! } { - ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 1 dangling lent ptrs detected"); lptr4 = tl::lend(t); //dangling here! } } } -BOOST_AUTO_TEST_CASE(lent_ref_unique_ptr_reset_dangling) +SIMPLE_TEST(lent_ref_unique_ptr_reset_dangling) { { Test::resetCounters(); tl::lendable t; tl::unique_ptr uptr(new Test(1234)); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 2}); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 2}); tl::lent_ref lptr = tl::promote(uptr); { - ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("unique: 1 dangling lent ptrs detected"); uptr.reset(); //dangling here! } { - ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 1 dangling lent ptrs detected"); lptr = tl::lend(t); //dangling here! } } @@ -1864,13 +1757,13 @@ BOOST_AUTO_TEST_CASE(lent_ref_unique_ptr_reset_dangling) //destructor Test::resetCounters(); tl::unique_ptr uptr(new Test(1234)); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 1}); { - ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 1 dangling lent ptrs detected"); tl::lent_ref lptr = tl::promote(uptr); { - ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("unique: 1 dangling lent ptrs detected"); uptr.reset(); //dangling here! } } //dangling here! @@ -1880,15 +1773,15 @@ BOOST_AUTO_TEST_CASE(lent_ref_unique_ptr_reset_dangling) Test::resetCounters(); tl::lendable t; tl::unique_ptr uptr(new Test(1234)); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 2}); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 2}); tl::lent_ref lptr = tl::promote(uptr); { - ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("unique: 1 dangling lent ptrs detected"); uptr.reset(); //dangling here! } { - ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 1 dangling lent ptrs detected"); lptr = tl::lend(t); //dangling here! } } @@ -1897,15 +1790,15 @@ BOOST_AUTO_TEST_CASE(lent_ref_unique_ptr_reset_dangling) Test::resetCounters(); tl::lendable t; tl::unique_ptr uptr(new Test(1234)); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 2}); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 2}); tl::lent_ref lptr = tl::promote(uptr); { - ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("unique: 1 dangling lent ptrs detected"); uptr.reset(); //dangling here! } { - ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 1 dangling lent ptrs detected"); lptr = tl::lend(t); //dangling here! } } @@ -1914,16 +1807,16 @@ BOOST_AUTO_TEST_CASE(lent_ref_unique_ptr_reset_dangling) Test::resetCounters(); tl::unique_ptr uptr1(new Test(1234)); tl::unique_ptr uptr2(new Test(1234)); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 2}); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 2}); tl::lent_ref lptr1 = tl::promote(uptr1); tl::lent_ref lptr2 = tl::promote(uptr2); { - ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("unique: 1 dangling lent ptrs detected"); uptr1.reset(); //dangling here! } { - ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 1 dangling lent ptrs detected"); lptr1 = lptr2; //dangling here! } } @@ -1932,16 +1825,16 @@ BOOST_AUTO_TEST_CASE(lent_ref_unique_ptr_reset_dangling) Test::resetCounters(); tl::unique_ptr uptr1(new Test(1234)); tl::unique_ptr uptr2(new Test(1234)); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 2}); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 2}); tl::lent_ref lptr1 = tl::promote(uptr1); tl::lent_ref lptr2 = tl::promote(uptr2); { - ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("unique: 1 dangling lent ptrs detected"); uptr1.reset(); //dangling here! } { - ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 1 dangling lent ptrs detected"); lptr1 = std::move(lptr2); //dangling here! } } @@ -1950,53 +1843,53 @@ BOOST_AUTO_TEST_CASE(lent_ref_unique_ptr_reset_dangling) Test::resetCounters(); tl::lendable t; tl::unique_ptr uptr(new Test(1234)); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 2}); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 2}); tl::lent_ref lptr1 = tl::promote(uptr); tl::lent_ref lptr2 = tl::promote(uptr); tl::lent_ref lptr3 = tl::promote(uptr); tl::lent_ref lptr4 = tl::promote(uptr); { - ExpectedAssertGuard eassert("unique: 4 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("unique: 4 dangling lent ptrs detected"); uptr.reset(); //dangling here! } { - ExpectedAssertGuard eassert("lent: 4 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 4 dangling lent ptrs detected"); lptr1 = tl::lend(t); //dangling here! } { - ExpectedAssertGuard eassert("lent: 3 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 3 dangling lent ptrs detected"); lptr2 = tl::lend(t); //dangling here! } { - ExpectedAssertGuard eassert("lent: 2 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 2 dangling lent ptrs detected"); lptr3 = tl::lend(t); //dangling here! } { - ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 1 dangling lent ptrs detected"); lptr4 = tl::lend(t); //dangling here! } } } -BOOST_AUTO_TEST_CASE(lent_ref_unique_ptr_assign_move_dangling) +SIMPLE_TEST(lent_ref_unique_ptr_assign_move_dangling) { { Test::resetCounters(); tl::lendable t; tl::unique_ptr uptr(new Test(1234)); tl::unique_ptr uptr2(new Test(1234)); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 3}); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 3}); tl::lent_ref lptr = tl::promote(uptr); { - ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("unique: 1 dangling lent ptrs detected"); uptr = std::move(uptr2); //dangling here! } { - ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 1 dangling lent ptrs detected"); lptr = tl::lend(t); //dangling here! } } @@ -2005,13 +1898,13 @@ BOOST_AUTO_TEST_CASE(lent_ref_unique_ptr_assign_move_dangling) Test::resetCounters(); tl::unique_ptr uptr(new Test(1234)); tl::unique_ptr uptr2(new Test(1234)); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 2}); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 2}); { - ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 1 dangling lent ptrs detected"); tl::lent_ref lptr = tl::promote(uptr); { - ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("unique: 1 dangling lent ptrs detected"); uptr = std::move(uptr2); //dangling here! } } //dangling here! @@ -2022,15 +1915,15 @@ BOOST_AUTO_TEST_CASE(lent_ref_unique_ptr_assign_move_dangling) tl::lendable t; tl::unique_ptr uptr(new Test(1234)); tl::unique_ptr uptr2(new Test(1234)); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 3}); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 3}); tl::lent_ref lptr = tl::promote(uptr); { - ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("unique: 1 dangling lent ptrs detected"); uptr = std::move(uptr2); //dangling here! } { - ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 1 dangling lent ptrs detected"); lptr = tl::lend(t); //dangling here! } } @@ -2040,15 +1933,15 @@ BOOST_AUTO_TEST_CASE(lent_ref_unique_ptr_assign_move_dangling) tl::lendable t; tl::unique_ptr uptr(new Test(1234)); tl::unique_ptr uptr2(new Test(1234)); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 3}); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 3}); tl::lent_ref lptr = tl::promote(uptr); { - ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("unique: 1 dangling lent ptrs detected"); uptr = std::move(uptr2); //dangling here! } { - ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 1 dangling lent ptrs detected"); lptr = tl::lend(t); //dangling here! } } @@ -2058,16 +1951,16 @@ BOOST_AUTO_TEST_CASE(lent_ref_unique_ptr_assign_move_dangling) tl::unique_ptr uptr1(new Test(1234)); tl::unique_ptr uptr2(new Test(1234)); tl::unique_ptr uptr3(new Test(1234)); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 3}); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 3}); tl::lent_ref lptr1 = tl::promote(uptr1); tl::lent_ref lptr2 = tl::promote(uptr2); { - ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("unique: 1 dangling lent ptrs detected"); uptr1 = std::move(uptr3); //dangling here! } { - ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 1 dangling lent ptrs detected"); lptr1 = lptr2; //dangling here! } } @@ -2077,16 +1970,16 @@ BOOST_AUTO_TEST_CASE(lent_ref_unique_ptr_assign_move_dangling) tl::unique_ptr uptr1(new Test(1234)); tl::unique_ptr uptr2(new Test(1234)); tl::unique_ptr uptr3(new Test(1234)); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 3}); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 3}); tl::lent_ref lptr1 = tl::promote(uptr1); tl::lent_ref lptr2 = tl::promote(uptr2); { - ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("unique: 1 dangling lent ptrs detected"); uptr1 = std::move(uptr3); //dangling here! } { - ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 1 dangling lent ptrs detected"); lptr1 = std::move(lptr2); //dangling here! } } @@ -2096,30 +1989,30 @@ BOOST_AUTO_TEST_CASE(lent_ref_unique_ptr_assign_move_dangling) tl::lendable t; tl::unique_ptr uptr(new Test(1234)); tl::unique_ptr uptr2(new Test(1234)); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 3}); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 3}); tl::lent_ref lptr1 = tl::promote(uptr); tl::lent_ref lptr2 = tl::promote(uptr); tl::lent_ref lptr3 = tl::promote(uptr); tl::lent_ref lptr4 = tl::promote(uptr); { - ExpectedAssertGuard eassert("unique: 4 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("unique: 4 dangling lent ptrs detected"); uptr = std::move(uptr2); //dangling here! } { - ExpectedAssertGuard eassert("lent: 4 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 4 dangling lent ptrs detected"); lptr1 = tl::lend(t); //dangling here! } { - ExpectedAssertGuard eassert("lent: 3 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 3 dangling lent ptrs detected"); lptr2 = tl::lend(t); //dangling here! } { - ExpectedAssertGuard eassert("lent: 2 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 2 dangling lent ptrs detected"); lptr3 = tl::lend(t); //dangling here! } { - ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 1 dangling lent ptrs detected"); lptr4 = tl::lend(t); //dangling here! } } @@ -2133,23 +2026,23 @@ BOOST_AUTO_TEST_CASE(lent_ref_unique_ptr_assign_move_dangling) ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -BOOST_AUTO_TEST_CASE(lent_ref_unique_ref_assign_nullptr_dangling) +SIMPLE_TEST(lent_ref_unique_ref_assign_nullptr_dangling) { { Test::resetCounters(); tl::lendable t; tl::unique_ref uref(new Test(1234)); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 2}); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 2}); tl::lent_ref lptr = uref; { - ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("unique: 1 dangling lent ptrs detected"); uref = tl::unique_ref(new Test(1234)); //dangling here! } { - ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 1 dangling lent ptrs detected"); lptr = tl::lend(t); //dangling here! } } @@ -2157,13 +2050,13 @@ BOOST_AUTO_TEST_CASE(lent_ref_unique_ref_assign_nullptr_dangling) //destructor Test::resetCounters(); tl::unique_ref uref(new Test(1234)); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 1}); { - ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 1 dangling lent ptrs detected"); tl::lent_ref lptr = uref; { - ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("unique: 1 dangling lent ptrs detected"); uref = tl::unique_ref(new Test(1234)); //dangling here! } } //dangling here! @@ -2173,15 +2066,15 @@ BOOST_AUTO_TEST_CASE(lent_ref_unique_ref_assign_nullptr_dangling) Test::resetCounters(); tl::lendable t; tl::unique_ref uref(new Test(1234)); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 2}); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 2}); tl::lent_ref lptr = uref; { - ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("unique: 1 dangling lent ptrs detected"); uref = tl::unique_ref(new Test(1234)); //dangling here! } { - ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 1 dangling lent ptrs detected"); lptr = tl::lend(t); //dangling here! } } @@ -2190,15 +2083,15 @@ BOOST_AUTO_TEST_CASE(lent_ref_unique_ref_assign_nullptr_dangling) Test::resetCounters(); tl::lendable t; tl::unique_ref uref(new Test(1234)); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 2}); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 2}); tl::lent_ref lptr = uref; { - ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("unique: 1 dangling lent ptrs detected"); uref = tl::unique_ref(new Test(1234)); //dangling here! } { - ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 1 dangling lent ptrs detected"); lptr = tl::lend(t); //dangling here! } } @@ -2207,16 +2100,16 @@ BOOST_AUTO_TEST_CASE(lent_ref_unique_ref_assign_nullptr_dangling) Test::resetCounters(); tl::unique_ref uref1(new Test(1234)); tl::unique_ref uref2(new Test(1234)); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 2}); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 2}); tl::lent_ref lptr1 = uref1; tl::lent_ref lptr2 = uref2; { - ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("unique: 1 dangling lent ptrs detected"); uref1 = tl::unique_ref(new Test(1234)); //dangling here! } { - ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 1 dangling lent ptrs detected"); lptr1 = lptr2; //dangling here! } } @@ -2225,16 +2118,16 @@ BOOST_AUTO_TEST_CASE(lent_ref_unique_ref_assign_nullptr_dangling) Test::resetCounters(); tl::unique_ref uref1(new Test(1234)); tl::unique_ref uref2(new Test(1234)); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 2}); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 2}); tl::lent_ref lptr1 = uref1; tl::lent_ref lptr2 = uref2; { - ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("unique: 1 dangling lent ptrs detected"); uref1 = tl::unique_ref(new Test(1234)); //dangling here! } { - ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 1 dangling lent ptrs detected"); lptr1 = std::move(lptr2); //dangling here! } } @@ -2243,53 +2136,53 @@ BOOST_AUTO_TEST_CASE(lent_ref_unique_ref_assign_nullptr_dangling) Test::resetCounters(); tl::lendable t; tl::unique_ref uref(new Test(1234)); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 2}); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 2}); tl::lent_ref lptr1 = uref; tl::lent_ref lptr2 = uref; tl::lent_ref lptr3 = uref; tl::lent_ref lptr4 = uref; { - ExpectedAssertGuard eassert("unique: 4 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("unique: 4 dangling lent ptrs detected"); uref = tl::unique_ref(new Test(1234)); //dangling here! } { - ExpectedAssertGuard eassert("lent: 4 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 4 dangling lent ptrs detected"); lptr1 = tl::lend(t); //dangling here! } { - ExpectedAssertGuard eassert("lent: 3 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 3 dangling lent ptrs detected"); lptr2 = tl::lend(t); //dangling here! } { - ExpectedAssertGuard eassert("lent: 2 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 2 dangling lent ptrs detected"); lptr3 = tl::lend(t); //dangling here! } { - ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 1 dangling lent ptrs detected"); lptr4 = tl::lend(t); //dangling here! } } } -BOOST_AUTO_TEST_CASE(lent_ref_unique_ref_reset_dangling) +SIMPLE_TEST(lent_ref_unique_ref_reset_dangling) { { Test::resetCounters(); tl::lendable t; tl::unique_ref uref(new Test(1234)); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 2}); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 2}); tl::lent_ref lptr = uref; { - ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("unique: 1 dangling lent ptrs detected"); uref.reset(new Test(1234)); //dangling here! } { - ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 1 dangling lent ptrs detected"); lptr = tl::lend(t); //dangling here! } } @@ -2297,13 +2190,13 @@ BOOST_AUTO_TEST_CASE(lent_ref_unique_ref_reset_dangling) //destructor Test::resetCounters(); tl::unique_ref uref(new Test(1234)); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 1}); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 1}); { - ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 1 dangling lent ptrs detected"); tl::lent_ref lptr = uref; { - ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("unique: 1 dangling lent ptrs detected"); uref.reset(new Test(1234)); //dangling here! } } //dangling here! @@ -2313,15 +2206,15 @@ BOOST_AUTO_TEST_CASE(lent_ref_unique_ref_reset_dangling) Test::resetCounters(); tl::lendable t; tl::unique_ref uref(new Test(1234)); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 2}); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 2}); tl::lent_ref lptr = uref; { - ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("unique: 1 dangling lent ptrs detected"); uref.reset(new Test(1234)); //dangling here! } { - ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 1 dangling lent ptrs detected"); lptr = tl::lend(t); //dangling here! } } @@ -2330,15 +2223,15 @@ BOOST_AUTO_TEST_CASE(lent_ref_unique_ref_reset_dangling) Test::resetCounters(); tl::lendable t; tl::unique_ref uref(new Test(1234)); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 2}); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 2}); tl::lent_ref lptr = uref; { - ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("unique: 1 dangling lent ptrs detected"); uref.reset(new Test(1234)); //dangling here! } { - ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 1 dangling lent ptrs detected"); lptr = tl::lend(t); //dangling here! } } @@ -2347,16 +2240,16 @@ BOOST_AUTO_TEST_CASE(lent_ref_unique_ref_reset_dangling) Test::resetCounters(); tl::unique_ref uref1(new Test(1234)); tl::unique_ref uref2(new Test(1234)); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 2}); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 2}); tl::lent_ref lptr1 = uref1; tl::lent_ref lptr2 = uref2; { - ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("unique: 1 dangling lent ptrs detected"); uref1.reset(new Test(1234)); //dangling here! } { - ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 1 dangling lent ptrs detected"); lptr1 = lptr2; //dangling here! } } @@ -2365,16 +2258,16 @@ BOOST_AUTO_TEST_CASE(lent_ref_unique_ref_reset_dangling) Test::resetCounters(); tl::unique_ref uref1(new Test(1234)); tl::unique_ref uref2(new Test(1234)); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 2}); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 2}); tl::lent_ref lptr1 = uref1; tl::lent_ref lptr2 = uref2; { - ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("unique: 1 dangling lent ptrs detected"); uref1.reset(new Test(1234)); //dangling here! } { - ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 1 dangling lent ptrs detected"); lptr1 = std::move(lptr2); //dangling here! } } @@ -2383,53 +2276,53 @@ BOOST_AUTO_TEST_CASE(lent_ref_unique_ref_reset_dangling) Test::resetCounters(); tl::lendable t; tl::unique_ref uref(new Test(1234)); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 2}); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 2}); tl::lent_ref lptr1 = uref; tl::lent_ref lptr2 = uref; tl::lent_ref lptr3 = uref; tl::lent_ref lptr4 = uref; { - ExpectedAssertGuard eassert("unique: 4 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("unique: 4 dangling lent ptrs detected"); uref.reset(new Test(1234)); //dangling here! } { - ExpectedAssertGuard eassert("lent: 4 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 4 dangling lent ptrs detected"); lptr1 = tl::lend(t); //dangling here! } { - ExpectedAssertGuard eassert("lent: 3 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 3 dangling lent ptrs detected"); lptr2 = tl::lend(t); //dangling here! } { - ExpectedAssertGuard eassert("lent: 2 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 2 dangling lent ptrs detected"); lptr3 = tl::lend(t); //dangling here! } { - ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 1 dangling lent ptrs detected"); lptr4 = tl::lend(t); //dangling here! } } } -BOOST_AUTO_TEST_CASE(lent_ref_unique_ref_assign_move_dangling) +SIMPLE_TEST(lent_ref_unique_ref_assign_move_dangling) { { Test::resetCounters(); tl::lendable t; tl::unique_ref uref(new Test(1234)); tl::unique_ref uref2(new Test(1234)); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 3}); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 3}); tl::lent_ref lptr = uref; { - ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("unique: 1 dangling lent ptrs detected"); uref = std::move(uref2); //dangling here! } { - ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 1 dangling lent ptrs detected"); lptr = tl::lend(t); //dangling here! } } @@ -2438,13 +2331,13 @@ BOOST_AUTO_TEST_CASE(lent_ref_unique_ref_assign_move_dangling) Test::resetCounters(); tl::unique_ref uref(new Test(1234)); tl::unique_ref uref2(new Test(1234)); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 2}); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 2}); { - ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 1 dangling lent ptrs detected"); tl::lent_ref lptr = uref; { - ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("unique: 1 dangling lent ptrs detected"); uref = std::move(uref2); //dangling here! } } //dangling here! @@ -2455,15 +2348,15 @@ BOOST_AUTO_TEST_CASE(lent_ref_unique_ref_assign_move_dangling) tl::lendable t; tl::unique_ref uref(new Test(1234)); tl::unique_ref uref2(new Test(1234)); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 3}); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 3}); tl::lent_ref lptr = uref; { - ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("unique: 1 dangling lent ptrs detected"); uref = std::move(uref2); //dangling here! } { - ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 1 dangling lent ptrs detected"); lptr = tl::lend(t); //dangling here! } } @@ -2473,15 +2366,15 @@ BOOST_AUTO_TEST_CASE(lent_ref_unique_ref_assign_move_dangling) tl::lendable t; tl::unique_ref uref(new Test(1234)); tl::unique_ref uref2(new Test(1234)); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 3}); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 3}); tl::lent_ref lptr = uref; { - ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("unique: 1 dangling lent ptrs detected"); uref = std::move(uref2); //dangling here! } { - ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 1 dangling lent ptrs detected"); lptr = tl::lend(t); //dangling here! } } @@ -2491,16 +2384,16 @@ BOOST_AUTO_TEST_CASE(lent_ref_unique_ref_assign_move_dangling) tl::unique_ref uref1(new Test(1234)); tl::unique_ref uref2(new Test(1234)); tl::unique_ref uref3(new Test(1234)); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 3}); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 3}); tl::lent_ref lptr1 = uref1; tl::lent_ref lptr2 = uref2; { - ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("unique: 1 dangling lent ptrs detected"); uref1 = std::move(uref3); //dangling here! } { - ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 1 dangling lent ptrs detected"); lptr1 = lptr2; //dangling here! } } @@ -2510,16 +2403,16 @@ BOOST_AUTO_TEST_CASE(lent_ref_unique_ref_assign_move_dangling) tl::unique_ref uref1(new Test(1234)); tl::unique_ref uref2(new Test(1234)); tl::unique_ref uref3(new Test(1234)); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 3}); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 3}); tl::lent_ref lptr1 = uref1; tl::lent_ref lptr2 = uref2; { - ExpectedAssertGuard eassert("unique: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("unique: 1 dangling lent ptrs detected"); uref1 = std::move(uref3); //dangling here! } { - ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 1 dangling lent ptrs detected"); lptr1 = std::move(lptr2); //dangling here! } } @@ -2529,30 +2422,30 @@ BOOST_AUTO_TEST_CASE(lent_ref_unique_ref_assign_move_dangling) tl::lendable t; tl::unique_ref uref(new Test(1234)); tl::unique_ref uref2(new Test(1234)); - BOOST_CHECK(Test::s_counters == Counters{.ctor = 3}); + ASSERT_EQ(Test::s_counters, Counters{.ctor = 3}); tl::lent_ref lptr1 = uref; tl::lent_ref lptr2 = uref; tl::lent_ref lptr3 = uref; tl::lent_ref lptr4 = uref; { - ExpectedAssertGuard eassert("unique: 4 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("unique: 4 dangling lent ptrs detected"); uref = std::move(uref2); //dangling here! } { - ExpectedAssertGuard eassert("lent: 4 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 4 dangling lent ptrs detected"); lptr1 = tl::lend(t); //dangling here! } { - ExpectedAssertGuard eassert("lent: 3 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 3 dangling lent ptrs detected"); lptr2 = tl::lend(t); //dangling here! } { - ExpectedAssertGuard eassert("lent: 2 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 2 dangling lent ptrs detected"); lptr3 = tl::lend(t); //dangling here! } { - ExpectedAssertGuard eassert("lent: 1 dangling lent ptrs detected"); + EXPECTED_ASSERT_GUARD("lent: 1 dangling lent ptrs detected"); lptr4 = tl::lend(t); //dangling here! } }