From 7ce51b3de9c0e7498d88587390af83820be53be5 Mon Sep 17 00:00:00 2001 From: Antoine Prouvost Date: Wed, 4 Jun 2025 11:28:11 +0200 Subject: [PATCH] Compile with C++20 (#3965) --- .clang-format | 2 +- dev/CMakePresetsMamba.json | 2 +- libmamba/CMakeLists.txt | 11 +- libmamba/ext/solv-cpp/CMakeLists.txt | 9 +- libmamba/include/mamba/fs/filesystem.hpp | 79 ++-------- libmamba/include/mamba/util/cast.hpp | 25 ++- libmamba/include/mamba/util/compare.hpp | 83 ---------- libmamba/include/mamba/util/deprecation.hpp | 6 - libmamba/include/mamba/util/encoding.hpp | 15 ++ .../mamba/util/flat_bool_expr_tree.hpp | 3 +- libmamba/include/mamba/util/flat_set.hpp | 7 +- libmamba/include/mamba/util/functional.hpp | 32 ---- libmamba/include/mamba/util/string.hpp | 4 +- libmamba/src/core/download_progress_bar.cpp | 2 +- libmamba/src/core/progress_bar_impl.cpp | 5 +- libmamba/src/core/subdir_index.cpp | 3 +- libmamba/src/core/util.cpp | 6 +- libmamba/src/fs/filesystem.cpp | 26 ++-- libmamba/src/util/encoding.cpp | 23 ++- libmamba/tests/CMakeLists.txt | 19 ++- libmamba/tests/src/core/test_filesystem.cpp | 147 ++++++++++++------ .../tests/src/solver/test_problems_graph.cpp | 39 +++-- libmamba/tests/src/specs/test_repo_data.cpp | 16 +- libmamba/tests/src/util/test_cast.cpp | 19 ++- libmamba/tests/src/util/test_compare.cpp | 88 ----------- libmamba/tests/src/util/test_encoding.cpp | 10 +- libmamba/tests/src/util/test_environment.cpp | 57 +++---- libmamba/tests/src/util/test_os_win.cpp | 3 +- libmambapy/CMakeLists.txt | 9 +- mamba_package/CMakeLists.txt | 9 +- micromamba/CMakeLists.txt | 9 +- 31 files changed, 329 insertions(+), 439 deletions(-) delete mode 100644 libmamba/include/mamba/util/compare.hpp delete mode 100644 libmamba/include/mamba/util/functional.hpp delete mode 100644 libmamba/tests/src/util/test_compare.cpp diff --git a/.clang-format b/.clang-format index 3f4eb2c68..7a94999b3 100644 --- a/.clang-format +++ b/.clang-format @@ -1,6 +1,6 @@ BasedOnStyle: Mozilla Language: Cpp -Standard: c++17 +Standard: c++20 AccessModifierOffset: "-4" AlignAfterOpenBracket: BlockIndent diff --git a/dev/CMakePresetsMamba.json b/dev/CMakePresetsMamba.json index 7379a1eb0..510b0fcc9 100644 --- a/dev/CMakePresetsMamba.json +++ b/dev/CMakePresetsMamba.json @@ -48,7 +48,7 @@ "CMAKE_COLOR_MAKEFILE": "ON", "CMAKE_CXX_COMPILER_LAUNCHER": "ccache", "CMAKE_CXX_EXTENSIONS": "OFF", - "CMAKE_CXX_STANDARD": "17", + "CMAKE_CXX_STANDARD": "20", "CMAKE_CXX_STANDARD_REQUIRED": "ON", "CMAKE_C_COMPILER_LAUNCHER": "ccache", "CMAKE_EXPORT_COMPILE_COMMANDS": "ON" diff --git a/libmamba/CMakeLists.txt b/libmamba/CMakeLists.txt index ddd9b9cd1..7b909fef8 100644 --- a/libmamba/CMakeLists.txt +++ b/libmamba/CMakeLists.txt @@ -294,7 +294,6 @@ set( ${LIBMAMBA_INCLUDE_DIR}/mamba/util/build.hpp ${LIBMAMBA_INCLUDE_DIR}/mamba/util/cast.hpp ${LIBMAMBA_INCLUDE_DIR}/mamba/util/cfile.hpp - ${LIBMAMBA_INCLUDE_DIR}/mamba/util/compare.hpp ${LIBMAMBA_INCLUDE_DIR}/mamba/util/conditional.hpp ${LIBMAMBA_INCLUDE_DIR}/mamba/util/cryptography.hpp ${LIBMAMBA_INCLUDE_DIR}/mamba/util/deprecation.hpp @@ -303,7 +302,6 @@ set( ${LIBMAMBA_INCLUDE_DIR}/mamba/util/flat_binary_tree.hpp ${LIBMAMBA_INCLUDE_DIR}/mamba/util/flat_bool_expr_tree.hpp ${LIBMAMBA_INCLUDE_DIR}/mamba/util/flat_set.hpp - ${LIBMAMBA_INCLUDE_DIR}/mamba/util/functional.hpp ${LIBMAMBA_INCLUDE_DIR}/mamba/util/graph.hpp ${LIBMAMBA_INCLUDE_DIR}/mamba/util/heap_optional.hpp ${LIBMAMBA_INCLUDE_DIR}/mamba/util/iterator.hpp @@ -454,7 +452,14 @@ macro(libmamba_create_target target_name linkage output_name) # Header only libraries are always linked the same way target_link_libraries(${target_name} PUBLIC tl::expected nlohmann_json::nlohmann_json) - target_compile_features(${target_name} PUBLIC cxx_std_17) + target_compile_features(${target_name} PUBLIC cxx_std_20) + set_target_properties( + ${target_name} + PROPERTIES + CXX_STANDARD 20 + CXX_STANDARD_REQUIRED YES + CXX_EXTENSIONS NO + ) mamba_target_add_compile_warnings(${target_name} WARNING_AS_ERROR ${MAMBA_WARNING_AS_ERROR}) mamba_target_set_lto(${target_name} MODE ${MAMBA_LTO}) diff --git a/libmamba/ext/solv-cpp/CMakeLists.txt b/libmamba/ext/solv-cpp/CMakeLists.txt index 010928a41..07905b6a0 100644 --- a/libmamba/ext/solv-cpp/CMakeLists.txt +++ b/libmamba/ext/solv-cpp/CMakeLists.txt @@ -35,7 +35,14 @@ else() endif() target_link_libraries(solv-cpp PUBLIC tl::expected ${LIBSOLV_DEPS}) -target_compile_features(solv-cpp PUBLIC cxx_std_17) +target_compile_features(solv-cpp PUBLIC cxx_std_20) +set_target_properties( + solv-cpp + PROPERTIES + CXX_STANDARD 20 + CXX_STANDARD_REQUIRED YES + CXX_EXTENSIONS NO +) mamba_target_add_compile_warnings(solv-cpp WARNING_AS_ERROR ${MAMBA_WARNING_AS_ERROR}) mamba_target_set_lto(solv-cpp MODE ${MAMBA_LTO}) diff --git a/libmamba/include/mamba/fs/filesystem.hpp b/libmamba/include/mamba/fs/filesystem.hpp index 8771a1b19..aff43b5b4 100644 --- a/libmamba/include/mamba/fs/filesystem.hpp +++ b/libmamba/include/mamba/fs/filesystem.hpp @@ -431,35 +431,14 @@ namespace mamba::fs } //---- Operators ---- - friend bool operator==(const u8path& left, const u8path& right) noexcept { return left.m_path == right.m_path; } - friend bool operator!=(const u8path& left, const u8path& right) noexcept + friend std::strong_ordering operator<=>(const u8path& left, const u8path& right) noexcept { - return left.m_path != right.m_path; - } - - friend bool operator<(const u8path& left, const u8path& right) noexcept - { - return left.m_path < right.m_path; - } - - friend bool operator<=(const u8path& left, const u8path& right) noexcept - { - return left.m_path <= right.m_path; - } - - friend bool operator>(const u8path& left, const u8path& right) noexcept - { - return left.m_path > right.m_path; - } - - friend bool operator>=(const u8path& left, const u8path& right) noexcept - { - return left.m_path >= right.m_path; + return left.m_path <=> right.m_path; } friend bool operator==(const u8path& left, const std::filesystem::path& right) noexcept @@ -467,29 +446,10 @@ namespace mamba::fs return left.m_path == right; } - friend bool operator!=(const u8path& left, const std::filesystem::path& right) noexcept + friend std::strong_ordering + operator<=>(const u8path& left, const std::filesystem::path& right) noexcept { - return left.m_path != right; - } - - friend bool operator<(const u8path& left, const std::filesystem::path& right) noexcept - { - return left.m_path < right; - } - - friend bool operator<=(const u8path& left, const std::filesystem::path& right) noexcept - { - return left.m_path <= right; - } - - friend bool operator>(const u8path& left, const std::filesystem::path& right) noexcept - { - return left.m_path > right; - } - - friend bool operator>=(const u8path& left, const std::filesystem::path& right) noexcept - { - return left.m_path >= right; + return left.m_path <=> right; } friend bool operator==(const u8path& left, const std::string& right) noexcept @@ -497,9 +457,9 @@ namespace mamba::fs return left.m_path == from_utf8(right); } - friend bool operator!=(const u8path& left, const std::string& right) noexcept + friend std::strong_ordering operator<=>(const u8path& left, const std::string& right) noexcept { - return left.m_path != from_utf8(right); + return left.m_path <=> from_utf8(right); } friend bool operator==(const u8path& left, const char* right) noexcept @@ -507,29 +467,29 @@ namespace mamba::fs return left.m_path == from_utf8(right); } - friend bool operator!=(const u8path& left, const char* right) noexcept + friend std::strong_ordering operator<=>(const u8path& left, const char* right) noexcept { - return left.m_path != from_utf8(right); + return left.m_path <=> from_utf8(right); } friend bool operator==(const u8path& left, const std::wstring& right) noexcept { - return left.m_path == right; + return left.m_path == std::filesystem::path(right); } - friend bool operator!=(const u8path& left, const std::wstring& right) noexcept + friend std::strong_ordering operator<=>(const u8path& left, const std::wstring& right) noexcept { - return left.m_path != right; + return left.m_path <=> std::filesystem::path(right); } friend bool operator==(const u8path& left, const wchar_t* right) noexcept { - return left.m_path == right; + return left.m_path == std::filesystem::path(right); } - friend bool operator!=(const u8path& left, const wchar_t* right) noexcept + friend std::strong_ordering operator<=>(const u8path& left, const wchar_t* right) noexcept { - return left.m_path != right; + return left.m_path <=> std::filesystem::path(right); } //---- State ---- @@ -680,14 +640,9 @@ namespace mamba::fs return *this; } - bool operator==(const directory_entry& other) const noexcept + std::strong_ordering operator<=>(const directory_entry& other) const noexcept { - return std::filesystem::directory_entry::operator==(other); - } - - bool operator!=(const directory_entry& other) const noexcept - { - return std::filesystem::directory_entry::operator!=(other); + return std::filesystem::directory_entry::operator<=>(other); } u8path path() const diff --git a/libmamba/include/mamba/util/cast.hpp b/libmamba/include/mamba/util/cast.hpp index cbac84e4d..0bdc3579b 100644 --- a/libmamba/include/mamba/util/cast.hpp +++ b/libmamba/include/mamba/util/cast.hpp @@ -10,11 +10,10 @@ #include #include #include +#include #include -#include "mamba/util/compare.hpp" - namespace mamba::util { /** @@ -56,23 +55,37 @@ namespace mamba::util constexpr auto from_lowest = std::numeric_limits::lowest(); constexpr auto from_max = std::numeric_limits::max(); + // Handle cases of char which std::cmp_xxx does not accept. + // WARNING: Only use during comparison + constexpr auto with_char_as_int = [](auto x) + { + if constexpr (std::is_same_v) + { + return static_cast(x); + } + else + { + return x; + } + }; + if constexpr (std::is_same_v) { return val; } else if constexpr (std::is_integral_v && std::is_integral_v) { - if constexpr (cmp_less(from_lowest, to_lowest)) + if constexpr (std::cmp_less(with_char_as_int(from_lowest), with_char_as_int(to_lowest))) { - if (cmp_less(val, to_lowest)) + if (std::cmp_less(with_char_as_int(val), with_char_as_int(to_lowest))) { throw detail::make_overflow_error(val); } } - if constexpr (cmp_greater(from_max, to_max)) + if constexpr (std::cmp_greater(with_char_as_int(from_max), with_char_as_int(to_max))) { - if (cmp_greater(val, to_max)) + if (std::cmp_greater(with_char_as_int(val), with_char_as_int(to_max))) { throw detail::make_overflow_error(val); } diff --git a/libmamba/include/mamba/util/compare.hpp b/libmamba/include/mamba/util/compare.hpp deleted file mode 100644 index 45cf2e274..000000000 --- a/libmamba/include/mamba/util/compare.hpp +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright (c) 2022, Cppreference.com -// -// Distributed under the terms of the Copyright/CC-BY-SA License. -// -// The full license can be found at the address -// https://en.cppreference.com/w/Cppreference:Copyright/CC-BY-SA - -/** - * Backport of C++20 ``std::cmp_*`` functions for signed comparison. - */ - -#ifndef MAMBA_CORE_UTIL_COMPARE_HPP -#define MAMBA_CORE_UTIL_COMPARE_HPP - -#include - -#include "mamba/util/deprecation.hpp" - -namespace mamba::util -{ - template - MAMBA_DEPRECATED_CXX20 constexpr bool cmp_equal(T t, U u) noexcept - { - using UT = std::make_unsigned_t; - using UU = std::make_unsigned_t; - if constexpr (std::is_signed_v == std::is_signed_v) - { - return t == u; - } - else if constexpr (std::is_signed_v) - { - return t < 0 ? false : UT(t) == u; - } - else - { - return u < 0 ? false : t == UU(u); - } - } - - template - MAMBA_DEPRECATED_CXX20 constexpr bool cmp_not_equal(T t, U u) noexcept - { - return !cmp_equal(t, u); - } - - template - MAMBA_DEPRECATED_CXX20 constexpr bool cmp_less(T t, U u) noexcept - { - using UT = std::make_unsigned_t; - using UU = std::make_unsigned_t; - if constexpr (std::is_signed_v == std::is_signed_v) - { - return t < u; - } - else if constexpr (std::is_signed_v) - { - return t < 0 ? true : UT(t) < u; - } - else - { - return u < 0 ? false : t < UU(u); - } - } - - template - MAMBA_DEPRECATED_CXX20 constexpr bool cmp_greater(T t, U u) noexcept - { - return cmp_less(u, t); - } - - template - MAMBA_DEPRECATED_CXX20 constexpr bool cmp_less_equal(T t, U u) noexcept - { - return !cmp_greater(t, u); - } - - template - MAMBA_DEPRECATED_CXX20 constexpr bool cmp_greater_equal(T t, U u) noexcept - { - return !cmp_less(t, u); - } -} -#endif diff --git a/libmamba/include/mamba/util/deprecation.hpp b/libmamba/include/mamba/util/deprecation.hpp index 1706688ca..4d1906121 100644 --- a/libmamba/include/mamba/util/deprecation.hpp +++ b/libmamba/include/mamba/util/deprecation.hpp @@ -7,12 +7,6 @@ #ifndef MAMBA_UTIL_DEPRECATION_HPP #define MAMBA_UTIL_DEPRECATION_HPP -#if __cplusplus >= 202002L -#define MAMBA_DEPRECATED_CXX20 [[deprecated("Use C++20 functions with the same name")]] -#else -#define MAMBA_DEPRECATED_CXX20 [[]] -#endif - #if __cplusplus >= 202302L #define MAMBA_DEPRECATED_CXX23 [[deprecated("Use C++23 functions with the same name")]] #else diff --git a/libmamba/include/mamba/util/encoding.hpp b/libmamba/include/mamba/util/encoding.hpp index 9012aa800..0e76bdc63 100644 --- a/libmamba/include/mamba/util/encoding.hpp +++ b/libmamba/include/mamba/util/encoding.hpp @@ -108,5 +108,20 @@ namespace mamba::util */ [[nodiscard]] auto decode_base64(std::string_view input) -> tl::expected; + + /** + * Convert a ``std::u8string`` to a UTF-8 encoded ``std::string``. + * + * We assume here that ``char`` and ``char8_t`` are containing the same Unicode data. + */ + [[nodiscard]] auto to_utf8_std_string(std::u8string_view text) -> std::string; + + /** + * Convert a UTF-8 encoded ``std::string`` to a ``std::u8string` . + * + * We assume here that ``char`` and ``char8_t`` are containing the same Unicode data. + * No checks are made. + */ + [[nodiscard]] auto to_u8string(std::string_view text) -> std::u8string; } #endif diff --git a/libmamba/include/mamba/util/flat_bool_expr_tree.hpp b/libmamba/include/mamba/util/flat_bool_expr_tree.hpp index eea8ca07a..637aff372 100644 --- a/libmamba/include/mamba/util/flat_bool_expr_tree.hpp +++ b/libmamba/include/mamba/util/flat_bool_expr_tree.hpp @@ -14,7 +14,6 @@ #include #include "mamba/util/flat_binary_tree.hpp" -#include "mamba/util/functional.hpp" namespace mamba::util { @@ -166,7 +165,7 @@ namespace mamba::util void clear(); void reserve(size_type size); - template + template [[nodiscard]] auto evaluate(UnaryFunc&& var_evaluator = {}, bool empty_val = true) const -> bool; diff --git a/libmamba/include/mamba/util/flat_set.hpp b/libmamba/include/mamba/util/flat_set.hpp index 835aa97ca..52947a13b 100644 --- a/libmamba/include/mamba/util/flat_set.hpp +++ b/libmamba/include/mamba/util/flat_set.hpp @@ -9,15 +9,16 @@ #define MAMBA_UTILFLAT_SET_HPP #include +#include #include #include +#include "mamba/util/deprecation.hpp" #include "mamba/util/tuple_hash.hpp" namespace mamba::util { - struct sorted_unique_t { explicit sorted_unique_t() = default; @@ -31,11 +32,9 @@ namespace mamba::util * Like, ``std::set``, uniqueness is determined by using the equivalence relation. * In imprecise terms, two objects ``a`` and ``b`` are considered equivalent if neither * compares less than the other: ``!comp(a, b) && !comp(b, a)`` - * - * @todo C++23 This is implemented in */ template , typename Allocator = std::allocator> - class flat_set : private std::vector + class MAMBA_DEPRECATED_CXX23 flat_set : private std::vector { public: diff --git a/libmamba/include/mamba/util/functional.hpp b/libmamba/include/mamba/util/functional.hpp deleted file mode 100644 index b63aedf29..000000000 --- a/libmamba/include/mamba/util/functional.hpp +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (c) 2023, QuantStack and Mamba Contributors -// -// Distributed under the terms of the BSD 3-Clause License. -// -// The full license is in the file LICENSE, distributed with this software. - -#ifndef MAMBA_UTIL_FUNCTIONAL_HPP -#define MAMBA_UTIL_FUNCTIONAL_HPP - -#include - -#include "mamba/util/deprecation.hpp" - -namespace mamba::util -{ - struct MAMBA_DEPRECATED_CXX20 identity - { - template - constexpr auto operator()(T&& t) const noexcept -> T&&; - }; - - /******************************** - * Implementation of identity * - ********************************/ - - template - constexpr auto identity::operator()(T&& t) const noexcept -> T&& - { - return std::forward(t); - } -} -#endif diff --git a/libmamba/include/mamba/util/string.hpp b/libmamba/include/mamba/util/string.hpp index 66ead50dd..4c4133041 100644 --- a/libmamba/include/mamba/util/string.hpp +++ b/libmamba/include/mamba/util/string.hpp @@ -19,8 +19,6 @@ #include #include -#include "mamba/util/compare.hpp" - namespace mamba::util { /** @@ -662,7 +660,7 @@ namespace mamba::util std::pair show ) -> UnaryFunction { - if (util::cmp_less_equal(last - first, threshold)) + if (std::cmp_less_equal(last - first, threshold)) { return join_for_each(first, last, std::move(func), sep); } diff --git a/libmamba/src/core/download_progress_bar.cpp b/libmamba/src/core/download_progress_bar.cpp index 50cd48d99..04d842380 100644 --- a/libmamba/src/core/download_progress_bar.cpp +++ b/libmamba/src/core/download_progress_bar.cpp @@ -272,7 +272,7 @@ namespace mamba { m_extract_bar.push_back(Console::instance().add_progress_bar(extract_tasks[i].name(), 1)); init_extract_bar(m_extract_bar.back()); - extract_tasks[i].set_progress_callback([=](PackageExtractEvent e) + extract_tasks[i].set_progress_callback([=, this](PackageExtractEvent e) { update_extract_bar(i, e); }); if (i < dl_requests.size()) diff --git a/libmamba/src/core/progress_bar_impl.cpp b/libmamba/src/core/progress_bar_impl.cpp index beb5038ae..ee3a56e00 100644 --- a/libmamba/src/core/progress_bar_impl.cpp +++ b/libmamba/src/core/progress_bar_impl.cpp @@ -9,7 +9,6 @@ #include "mamba/core/context.hpp" #include "mamba/core/execution.hpp" -#include "mamba/util/compare.hpp" #include "progress_bar_impl.hpp" @@ -974,10 +973,10 @@ namespace mamba std::size_t spinner_width = 8; - std::size_t spinner_start = util::cmp_greater(pos, spinner_width) + std::size_t spinner_start = std::cmp_greater(pos, spinner_width) ? pos - spinner_width : 0; - std::size_t spinner_length = (util::cmp_less(pos + spinner_width, width) + std::size_t spinner_length = (std::cmp_less(pos + spinner_width, width) ? pos + spinner_width : width) - spinner_start; diff --git a/libmamba/src/core/subdir_index.cpp b/libmamba/src/core/subdir_index.cpp index 1153b5255..72e14eb06 100644 --- a/libmamba/src/core/subdir_index.cpp +++ b/libmamba/src/core/subdir_index.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include "mamba/core/channel_context.hpp" #include "mamba/core/output.hpp" @@ -687,7 +688,7 @@ namespace mamba const auto cache_age_seconds = std::chrono::duration_cast(cache_age) .count(); - if (util::cmp_less(cache_age_seconds, max_age) || params.offline) + if (std::cmp_less(cache_age_seconds, max_age) || params.offline) { // valid json cache found if (!m_valid_cache_found) diff --git a/libmamba/src/core/util.cpp b/libmamba/src/core/util.cpp index e9e615fc4..4b4e12bdf 100644 --- a/libmamba/src/core/util.cpp +++ b/libmamba/src/core/util.cpp @@ -17,8 +17,6 @@ #include #include #include -#include -#include #include @@ -45,6 +43,8 @@ extern "C" #include #include } + +#include "mamba/core/shell_init.hpp" #endif #include @@ -54,13 +54,11 @@ extern "C" #include "mamba/core/execution.hpp" #include "mamba/core/invoke.hpp" #include "mamba/core/output.hpp" -#include "mamba/core/shell_init.hpp" #include "mamba/core/thread_utils.hpp" #include "mamba/core/util.hpp" #include "mamba/core/util_os.hpp" #include "mamba/fs/filesystem.hpp" #include "mamba/util/build.hpp" -#include "mamba/util/compare.hpp" #include "mamba/util/environment.hpp" #include "mamba/util/random.hpp" #include "mamba/util/string.hpp" diff --git a/libmamba/src/fs/filesystem.cpp b/libmamba/src/fs/filesystem.cpp index 1bb0cbcfd..40491bdb6 100644 --- a/libmamba/src/fs/filesystem.cpp +++ b/libmamba/src/fs/filesystem.cpp @@ -21,6 +21,7 @@ #endif #include "mamba/fs/filesystem.hpp" +#include "mamba/util/encoding.hpp" namespace mamba::fs { @@ -44,26 +45,27 @@ namespace mamba::fs } #endif -#if __cplusplus == 201703L std::string to_utf8(const std::filesystem::path& path, Utf8Options utf8_options) { - if (utf8_options.normalize_sep) + const auto u8str = [&] { - return normalized_separators(path).u8string(); - } - else - { - return path.u8string(); - } + if (utf8_options.normalize_sep) + { + return normalized_separators(path).u8string(); + } + else + { + return path.u8string(); + } + }(); + + return util::to_utf8_std_string(u8str); } std::filesystem::path from_utf8(std::string_view u8string) { - return normalized_separators(std::filesystem::u8path(u8string)); + return normalized_separators(util::to_u8string(u8string)); } -#else -#error UTF8 functions implementation is specific to C++17, using another version requires a different implementation. -#endif void last_write_time(const u8path& path, now, std::error_code& ec) noexcept { diff --git a/libmamba/src/util/encoding.cpp b/libmamba/src/util/encoding.cpp index ab30d3867..08033f3d9 100644 --- a/libmamba/src/util/encoding.cpp +++ b/libmamba/src/util/encoding.cpp @@ -7,10 +7,11 @@ #include #include #include +#include +#include #include -#include "mamba/util/compare.hpp" #include "mamba/util/conditional.hpp" #include "mamba/util/encoding.hpp" #include "mamba/util/string.hpp" @@ -268,7 +269,7 @@ namespace mamba::util static_cast(input.size()) ); - if (util::cmp_not_equal(expected_size, written_size)) + if (std::cmp_not_equal(expected_size, written_size)) { return tl::make_unexpected(EncodingError()); } @@ -285,7 +286,7 @@ namespace mamba::util reinterpret_cast(input.data()), static_cast(input.size()) ); - if (util::cmp_not_equal(max_expected_size, max_possible_written_size)) + if (std::cmp_not_equal(max_expected_size, max_possible_written_size)) { return tl::make_unexpected(EncodingError()); } @@ -296,4 +297,20 @@ namespace mamba::util out.resize(min_expected_size + extra); return { std::move(out) }; } + + auto to_utf8_std_string(std::u8string_view text) -> std::string + { + static constexpr auto to_char = [](char8_t c) { return static_cast(c); }; + auto bytes = text | std::ranges::views::transform(to_char); + // TODO(C++23): Use std::ranges::to + return { bytes.begin(), bytes.end() }; + } + + auto to_u8string(std::string_view text) -> std::u8string + { + static constexpr auto to_char8_t = [](char c) { return static_cast(c); }; + auto bytes = text | std::ranges::views::transform(to_char8_t); + // TODO(C++23): Use std::ranges::to + return { bytes.begin(), bytes.end() }; + } } diff --git a/libmamba/tests/CMakeLists.txt b/libmamba/tests/CMakeLists.txt index 920746189..297c04ac9 100644 --- a/libmamba/tests/CMakeLists.txt +++ b/libmamba/tests/CMakeLists.txt @@ -4,7 +4,14 @@ add_executable(testing_libmamba_lock libmamba_lock/lock.cpp) target_link_libraries(testing_libmamba_lock PUBLIC mamba::libmamba) -target_compile_features(testing_libmamba_lock PUBLIC cxx_std_17) +target_compile_features(testing_libmamba_lock PUBLIC cxx_std_20) +set_target_properties( + testing_libmamba_lock + PROPERTIES + CXX_STANDARD 20 + CXX_STANDARD_REQUIRED YES + CXX_EXTENSIONS NO +) mamba_target_add_compile_warnings(testing_libmamba_lock WARNING_AS_ERROR ${MAMBA_WARNING_AS_ERROR}) @@ -18,7 +25,6 @@ set( src/catch-utils/msvc_catch_string_view.cpp # Utility library src/util/test_cast.cpp - src/util/test_compare.cpp src/util/test_charconv.cpp src/util/test_cryptography.cpp src/util/test_encoding.cpp @@ -143,7 +149,14 @@ target_compile_definitions( MAMBA_TEST_LOCK_EXE="$" ) -target_compile_features(test_libmamba PUBLIC cxx_std_17) +target_compile_features(test_libmamba PUBLIC cxx_std_20) +set_target_properties( + test_libmamba + PROPERTIES + CXX_STANDARD 20 + CXX_STANDARD_REQUIRED YES + CXX_EXTENSIONS NO +) add_custom_target( test diff --git a/libmamba/tests/src/core/test_filesystem.cpp b/libmamba/tests/src/core/test_filesystem.cpp index 485ee6a78..9ba979b0e 100644 --- a/libmamba/tests/src/core/test_filesystem.cpp +++ b/libmamba/tests/src/core/test_filesystem.cpp @@ -13,6 +13,7 @@ #include "mamba/core/util_scope.hpp" #include "mamba/fs/filesystem.hpp" #include "mamba/util/build.hpp" +#include "mamba/util/encoding.hpp" namespace mamba { @@ -23,17 +24,20 @@ namespace mamba static constexpr auto value = u8"a/b/c"; std::filesystem::path x{ value }; const auto y = fs::normalized_separators(x); -#if defined(_WIN32) - REQUIRE(y.u8string() == u8R"(a\b\c)"); -#else - REQUIRE(y.u8string() == value); -#endif + if (util::on_win) + { + REQUIRE(y.u8string() == u8R"(a\b\c)"); + } + else + { + REQUIRE(y.u8string() == value); + } } TEST_CASE("normalized_separators_unicode") { static constexpr auto value = u8"日本語"; - const std::filesystem::path x = fs::from_utf8(value); + const std::filesystem::path x = fs::from_utf8(util::to_utf8_std_string(value)); REQUIRE(x.u8string() == u8"日本語"); // check assumption const auto y = fs::normalized_separators(x); REQUIRE(y.u8string() == u8"日本語"); @@ -42,63 +46,108 @@ namespace mamba TEST_CASE("to_utf8_check_separators") { static constexpr auto some_path_str = u8"a/b/c"; - std::filesystem::path some_path = std::filesystem::u8path(some_path_str); + std::filesystem::path some_path = some_path_str; - REQUIRE(fs::to_utf8(some_path, { /*normalize_sep=*/false }) == some_path_str); -#if defined(_WIN32) - REQUIRE(fs::to_utf8(some_path, { /*normalize_sep=*/true }) == u8"a\\b\\c"); -#else - REQUIRE(fs::to_utf8(some_path, { /*normalize_sep=*/true }) == some_path_str); -#endif + REQUIRE( + fs::to_utf8(some_path, { .normalize_sep = false }) + == util::to_utf8_std_string(some_path_str) + ); + if (util::on_win) + { + REQUIRE( + fs::to_utf8(some_path, { .normalize_sep = true }) + == util::to_utf8_std_string(u8"a\\b\\c") + ); + } + else + { + REQUIRE( + fs::to_utf8(some_path, { .normalize_sep = true }) + == util::to_utf8_std_string(some_path_str) + ); + } } TEST_CASE("to_utf8_check_separators_unicode") { static constexpr auto some_path_str = u8"日/本/語"; - std::filesystem::path some_path = std::filesystem::u8path(some_path_str); + std::filesystem::path some_path = some_path_str; - REQUIRE(fs::to_utf8(some_path, { /*normalize_sep=*/false }) == some_path_str); -#if defined(_WIN32) - REQUIRE(fs::to_utf8(some_path, { /*normalize_sep=*/true }) == u8"日\\本\\語"); -#else - REQUIRE(fs::to_utf8(some_path, { /*normalize_sep=*/true }) == some_path_str); -#endif + REQUIRE( + fs::to_utf8(some_path, { .normalize_sep = false }) + == util::to_utf8_std_string(some_path_str) + ); + if (util::on_win) + { + REQUIRE( + fs::to_utf8(some_path, { .normalize_sep = true }) + == util::to_utf8_std_string(u8"日\\本\\語") + ); + } + else + { + REQUIRE( + fs::to_utf8(some_path, { .normalize_sep = true }) + == util::to_utf8_std_string(some_path_str) + ); + } } TEST_CASE("from_utf8_check_separators") { static constexpr auto some_path_str = u8"a/b/c"; -#if defined(_WIN32) - REQUIRE(fs::from_utf8(some_path_str) == std::filesystem::u8path(u8"a\\b\\c")); -#else - REQUIRE(fs::from_utf8(some_path_str) == std::filesystem::u8path(u8"a/b/c")); -#endif + if (util::on_win) + { + REQUIRE( + fs::from_utf8(util::to_utf8_std_string(some_path_str)) + == std::filesystem::path(u8"a\\b\\c") + ); + } + else + { + REQUIRE( + fs::from_utf8(util::to_utf8_std_string(some_path_str)) + == std::filesystem::path(u8"a/b/c") + ); + } } TEST_CASE("from_utf8_check_separators_unicode") { static constexpr auto some_path_str = u8"日/本/語"; -#if defined(_WIN32) - REQUIRE(fs::from_utf8(some_path_str) == std::filesystem::u8path(u8"日\\本\\語")); -#else - REQUIRE(fs::from_utf8(some_path_str) == std::filesystem::u8path(u8"日/本/語")); -#endif + if (util::on_win) + { + REQUIRE( + fs::from_utf8(util::to_utf8_std_string(some_path_str)) + == std::filesystem::path(u8"日\\本\\語") + ); + } + else + { + REQUIRE( + fs::from_utf8(util::to_utf8_std_string(some_path_str)) + == std::filesystem::path(u8"日/本/語") + ); + } } TEST_CASE("u8path_separators_formatting") { static constexpr auto some_path_str = u8"a/b/c"; - std::filesystem::path some_path = std::filesystem::u8path(some_path_str); + std::filesystem::path some_path = std::filesystem::path(some_path_str); const fs::u8path u8_path(some_path); -#if defined(_WIN32) - REQUIRE(u8_path.string() == u8"a\\b\\c"); -#else - REQUIRE(u8_path.string() == some_path_str); -#endif - REQUIRE(u8_path.generic_string() == some_path_str); + if (util::on_win) + { + REQUIRE(u8_path.string() == util::to_utf8_std_string(u8"a\\b\\c")); + } + else + { + REQUIRE(u8_path.string() == util::to_utf8_std_string(some_path_str)); + } + REQUIRE(u8_path.generic_string() == util::to_utf8_std_string(some_path_str)); } TEST_CASE("consistent_encoding") @@ -106,10 +155,10 @@ namespace mamba const auto utf8_string = u8"日本語"; const fs::u8path filename(utf8_string); const auto str = filename.string(); - REQUIRE(str == utf8_string); + REQUIRE(str == util::to_utf8_std_string(utf8_string)); const fs::u8path file_path = fs::temp_directory_path() / filename; - REQUIRE(file_path.filename().string() == utf8_string); + REQUIRE(file_path.filename().string() == util::to_utf8_std_string(utf8_string)); const auto std_path = file_path.std_path(); REQUIRE(std_path.filename().u8string() == utf8_string); @@ -118,7 +167,8 @@ namespace mamba TEST_CASE("string_stream_encoding") { const auto utf8_string = u8"日本語"; - const std::string quoted_utf8_string = std::string("\"") + utf8_string + const std::string quoted_utf8_string = std::string("\"") + + util::to_utf8_std_string(utf8_string) + std::string("\""); const fs::u8path filename(utf8_string); std::stringstream stream; @@ -128,7 +178,7 @@ namespace mamba fs::u8path path_read; stream.seekg(0); stream >> path_read; - REQUIRE(path_read.string() == utf8_string); + REQUIRE(path_read.string() == util::to_utf8_std_string(utf8_string)); } TEST_CASE("directory_iteration") @@ -143,7 +193,7 @@ namespace mamba { std::ofstream file(file_path.std_path(), std::ios::binary | std::ios::trunc); - file << u8"日本語"; + file << util::to_utf8_std_string(u8"日本語"); } { @@ -232,14 +282,15 @@ namespace mamba fs::create_directories(long_path); } -#if defined(_WIN32) TEST_CASE("append_maintains_slash_type") { - const fs::u8path path = u8R"(a/b/c/d)"; - const auto path_1 = path / u8R"(e\f\g)"; - REQUIRE(path_1.string() == u8R"(a\b\c\d\e\f\g)"); + if (util::on_win) + { + const fs::u8path path = util::to_utf8_std_string(u8R"(a/b/c/d)"); + const auto path_1 = path / u8R"(e\f\g)"; + REQUIRE(path_1.string() == util::to_utf8_std_string(u8R"(a\b\c\d\e\f\g)")); + } } -#endif } namespace @@ -294,7 +345,7 @@ namespace mamba const auto create_readonly_files = [](const fs::u8path& dir_path) { - assert(fs::is_directory(dir_path)); + REQUIRE(fs::is_directory(dir_path)); for (int file_idx = 0; file_idx < file_count_per_directory; ++file_idx) { const auto readonly_file_path = dir_path diff --git a/libmamba/tests/src/solver/test_problems_graph.cpp b/libmamba/tests/src/solver/test_problems_graph.cpp index 57a3e3e90..4e20c60a9 100644 --- a/libmamba/tests/src/solver/test_problems_graph.cpp +++ b/libmamba/tests/src/solver/test_problems_graph.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -635,9 +636,6 @@ TEST_CASE("NamedList", "[mamba::solver]") TEST_CASE("Create problem graph", "[mamba::solver]") { - using PbGr = ProblemsGraph; - using CpPbGr = CompressedProblemsGraph; - const auto [name, factory] = GENERATE( std::pair{ "Basic conflict", &create_basic_conflict }, std::pair{ "PubGrub example", &create_pubgrub }, @@ -672,7 +670,7 @@ TEST_CASE("Create problem graph", "[mamba::solver]") graph_init.for_each_node_id( [&](auto id) { - const auto& node = graph_init.node(id); + const ProblemsGraph::node_t& node = graph_init.node(id); // Currently we do not make assumption about virtual package since // we are not sure we are including them the same way than they would be in // practice @@ -682,15 +680,15 @@ TEST_CASE("Create problem graph", "[mamba::solver]") { // Only one root node REQUIRE(id == pbs_init.root_node()); - REQUIRE(std::holds_alternative(node)); + REQUIRE(std::holds_alternative(node)); } else if (graph_init.out_degree(id) == 0) { - REQUIRE_FALSE(std::holds_alternative(node)); + REQUIRE_FALSE(std::holds_alternative(node)); } else { - REQUIRE(std::holds_alternative(node)); + REQUIRE(std::holds_alternative(node)); } // All nodes reachable from the root REQUIRE(is_reachable(pbs_init.graph(), pbs_init.root_node(), id)); @@ -701,8 +699,8 @@ TEST_CASE("Create problem graph", "[mamba::solver]") const auto& conflicts_init = pbs_init.conflicts(); for (const auto& [n, _] : conflicts_init) { - bool tmp = std::holds_alternative(graph_init.node(n)) - || std::holds_alternative(graph_init.node(n)); + bool tmp = std::holds_alternative(graph_init.node(n)) + || std::holds_alternative(graph_init.node(n)); REQUIRE(tmp); } @@ -731,7 +729,7 @@ TEST_CASE("Create problem graph", "[mamba::solver]") SECTION("Compress graph") { - const auto pbs_comp = CpPbGr::from_problems_graph(pbs_simplified); + const auto pbs_comp = CompressedProblemsGraph::from_problems_graph(pbs_simplified); const auto& graph_comp = pbs_comp.graph(); REQUIRE(pbs_init.graph().number_of_nodes() >= graph_comp.number_of_nodes()); @@ -739,7 +737,7 @@ TEST_CASE("Create problem graph", "[mamba::solver]") graph_comp.for_each_node_id( [&](auto id) { - const auto& node = graph_comp.node(id); + const CompressedProblemsGraph::node_t& node = graph_comp.node(id); // Currently we do not make assumption about virtual package since // we are not sure we are including them the same way than they // would be in @@ -749,15 +747,18 @@ TEST_CASE("Create problem graph", "[mamba::solver]") { // Only one root node REQUIRE(id == pbs_init.root_node()); - REQUIRE(std::holds_alternative(node)); + REQUIRE(std::holds_alternative(node)); } else if (graph_comp.out_degree(id) == 0) { - REQUIRE_FALSE(std::holds_alternative(node)); + REQUIRE_FALSE( + std::holds_alternative(node) + ); } else { - REQUIRE(std::holds_alternative(node)); + REQUIRE(std::holds_alternative(node + )); } // All nodes reachable from the root REQUIRE(is_reachable(graph_comp, pbs_comp.root_node(), id)); @@ -768,8 +769,12 @@ TEST_CASE("Create problem graph", "[mamba::solver]") const auto& conflicts_comp = pbs_comp.conflicts(); for (const auto& [n, _] : conflicts_comp) { - bool tmp = std::holds_alternative(graph_comp.node(n)) - || std::holds_alternative(graph_comp.node(n)); + bool tmp = std::holds_alternative( + graph_comp.node(n) + ) + || std::holds_alternative( + graph_comp.node(n) + ); REQUIRE(tmp); } @@ -780,7 +785,7 @@ TEST_CASE("Create problem graph", "[mamba::solver]") auto message_contains = [&message, &name_copy](const auto& node) { using Node = std::remove_cv_t>; - if constexpr (!std::is_same_v) + if constexpr (!std::is_same_v) { if ((name_copy == "Pin conflict") && util::contains(node.name(), "pin on")) { diff --git a/libmamba/tests/src/specs/test_repo_data.cpp b/libmamba/tests/src/specs/test_repo_data.cpp index 5a31c3f59..60e48846f 100644 --- a/libmamba/tests/src/specs/test_repo_data.cpp +++ b/libmamba/tests/src/specs/test_repo_data.cpp @@ -53,12 +53,12 @@ namespace j["track_features"] = nl::json::array(); { const auto p = j.get(); - REQUIRE(p.name == j.at("name")); + REQUIRE(j.at("name") == p.name); // Note Version::parse is not injective - REQUIRE(p.version.to_string() == j.at("version")); - REQUIRE(p.build_string == j.at("build")); - REQUIRE(p.build_number == j.at("build_number")); - REQUIRE(p.subdir == j.at("subdir")); + REQUIRE(j.at("version") == p.version.to_string()); + REQUIRE(j.at("build") == p.build_string); + REQUIRE(j.at("build_number") == p.build_number); + REQUIRE(j.at("subdir") == p.subdir); REQUIRE_FALSE(p.md5.has_value()); REQUIRE_FALSE(p.platform.has_value()); REQUIRE(p.depends == decltype(p.depends){ "libsolv>=1.0" }); @@ -134,11 +134,11 @@ namespace REQUIRE(data.info.has_value()); REQUIRE(platform_name(data.info.value().subdir) == j["info"]["subdir"].get()); REQUIRE( - data.packages.at("mamba-1.0-h12345.tar.bz2").name - == j["packages"]["mamba-1.0-h12345.tar.bz2"]["name"] + j["packages"]["mamba-1.0-h12345.tar.bz2"]["name"] + == data.packages.at("mamba-1.0-h12345.tar.bz2").name ); REQUIRE(data.conda_packages.empty()); - REQUIRE(data.removed == j["removed"]); + REQUIRE(j["removed"] == data.removed); } TEST_CASE("repodata_json") diff --git a/libmamba/tests/src/util/test_cast.cpp b/libmamba/tests/src/util/test_cast.cpp index 8f74d22a1..f50cf2c00 100644 --- a/libmamba/tests/src/util/test_cast.cpp +++ b/libmamba/tests/src/util/test_cast.cpp @@ -6,7 +6,6 @@ #include #include -#include #include @@ -28,7 +27,7 @@ namespace REQUIRE(safe_num_cast(from_max) == static_cast(from_max)); } - TEST_CASE("Exact num cast widen - integers") + TEST_CASE("Exact num cast widen - integers", "[mamba::util]") { check_exact_num_cast_widen(); check_exact_num_cast_widen(); @@ -38,12 +37,12 @@ namespace check_exact_num_cast_widen(); } - TEST_CASE("Exact num cast widen - floats") + TEST_CASE("Exact num cast widen - floats", "[mamba::util]") { check_exact_num_cast_widen(); } - TEST_CASE("Exact num cast widen - mixed") + TEST_CASE("Exact num cast widen - mixed", "[mamba::util]") { check_exact_num_cast_widen(); check_exact_num_cast_widen(); @@ -58,7 +57,7 @@ namespace REQUIRE(safe_num_cast(From(1)) == To(1)); } - TEST_CASE("Exact num cast narrow - integers") + TEST_CASE("Exact num cast narrow - integers", "[mamba::util]") { check_exact_num_cast_narrow(); check_exact_num_cast_narrow(); @@ -66,7 +65,7 @@ namespace check_exact_num_cast_narrow(); } - TEST_CASE("Exact num cast narrow - floats") + TEST_CASE("Exact num cast narrow - floats", "[mamba::util]") { check_exact_num_cast_narrow(); } @@ -78,7 +77,7 @@ namespace REQUIRE_THROWS_AS(safe_num_cast(from_lowest), std::overflow_error); } - TEST_CASE("Exact num cast overflow - integers") + TEST_CASE("Exact num cast overflow - integers", "[mamba::util]") { check_exact_num_cast_overflow(); check_exact_num_cast_overflow(); @@ -86,18 +85,18 @@ namespace check_exact_num_cast_overflow(); } - TEST_CASE("Exact num cast overflow - floats") + TEST_CASE("Exact num cast overflow - floats", "[mamba::util]") { check_exact_num_cast_overflow(); } - TEST_CASE("Exact num cast overflow - mixed") + TEST_CASE("Exact num cast overflow - mixed", "[mamba::util]") { check_exact_num_cast_overflow(); check_exact_num_cast_overflow(); } - TEST_CASE("precision") + TEST_CASE("precision", "[mamba::util]") { REQUIRE_THROWS_AS(safe_num_cast(1.1), std::runtime_error); REQUIRE_THROWS_AS(safe_num_cast(std::nextafter(double(1), 2)), std::runtime_error); diff --git a/libmamba/tests/src/util/test_compare.cpp b/libmamba/tests/src/util/test_compare.cpp deleted file mode 100644 index a4419d73a..000000000 --- a/libmamba/tests/src/util/test_compare.cpp +++ /dev/null @@ -1,88 +0,0 @@ -// Copyright (c) 2023, QuantStack and Mamba Contributors -// -// Distributed under the terms of the BSD 3-Clause License. -// -// The full license is in the file LICENSE, distributed with this software. - -#include -#include - -#include - -#include "mamba/util/compare.hpp" - -using namespace mamba::util; - -namespace -{ - TEST_CASE("equal") - { - REQUIRE(cmp_equal(char{ 0 }, char{ 0 })); - REQUIRE(cmp_equal(char{ 1 }, char{ 1 })); - REQUIRE(cmp_equal(char{ -1 }, char{ -1 })); - REQUIRE(cmp_equal(int{ 0 }, int{ 0 })); - REQUIRE(cmp_equal(int{ 1 }, int{ 1 })); - REQUIRE(cmp_equal(int{ -1 }, int{ -1 })); - REQUIRE(cmp_equal(std::size_t{ 0 }, std::size_t{ 0 })); - REQUIRE(cmp_equal(std::size_t{ 1 }, std::size_t{ 1 })); - - REQUIRE(cmp_equal(char{ 0 }, int{ 0 })); - REQUIRE(cmp_equal(char{ 1 }, int{ 1 })); - REQUIRE(cmp_equal(char{ -1 }, int{ -1 })); - REQUIRE(cmp_equal(std::size_t{ 0 }, char{ 0 })); - REQUIRE(cmp_equal(std::size_t{ 1 }, char{ 1 })); - REQUIRE(cmp_equal(std::size_t{ 0 }, int{ 0 })); - REQUIRE(cmp_equal(std::size_t{ 1 }, int{ 1 })); - - REQUIRE_FALSE(cmp_equal(char{ 0 }, char{ 1 })); - REQUIRE_FALSE(cmp_equal(char{ 1 }, char{ -1 })); - REQUIRE_FALSE(cmp_equal(int{ 0 }, int{ 1 })); - REQUIRE_FALSE(cmp_equal(int{ -1 }, int{ 1 })); - REQUIRE_FALSE(cmp_equal(std::size_t{ 0 }, std::size_t{ 1 })); - - REQUIRE_FALSE(cmp_equal(char{ 0 }, int{ 1 })); - REQUIRE_FALSE(cmp_equal(char{ 1 }, int{ -1 })); - REQUIRE_FALSE(cmp_equal(char{ -1 }, int{ 1 })); - REQUIRE_FALSE(cmp_equal(std::size_t{ 1 }, int{ -1 })); - REQUIRE_FALSE(cmp_equal(static_cast(-1), int{ -1 })); - REQUIRE_FALSE(cmp_equal(std::size_t{ 1 }, int{ 0 })); - REQUIRE_FALSE(cmp_equal(std::numeric_limits::max(), int{ 0 })); - } - - TEST_CASE("less") - { - REQUIRE(cmp_less(char{ 0 }, char{ 1 })); - REQUIRE(cmp_less(char{ -1 }, char{ 0 })); - REQUIRE(cmp_less(int{ 0 }, int{ 1 })); - REQUIRE(cmp_less(int{ -1 }, int{ 1 })); - REQUIRE(cmp_less(std::size_t{ 0 }, std::size_t{ 1 })); - - REQUIRE(cmp_less(char{ 0 }, int{ 1 })); - REQUIRE(cmp_less(char{ -1 }, int{ 0 })); - REQUIRE(cmp_less(char{ -1 }, int{ 1 })); - REQUIRE(cmp_less(char{ -1 }, std::size_t{ 1 })); - REQUIRE(cmp_less(std::size_t{ 0 }, int{ 1 })); - REQUIRE(cmp_less(std::numeric_limits::min(), char{ 0 })); - REQUIRE(cmp_less(std::numeric_limits::min(), std::size_t{ 0 })); - REQUIRE(cmp_less(int{ -1 }, std::numeric_limits::max())); - REQUIRE(cmp_less(std::size_t{ 1 }, std::numeric_limits::max())); - - REQUIRE_FALSE(cmp_less(char{ 1 }, char{ 0 })); - REQUIRE_FALSE(cmp_less(char{ 1 }, char{ 1 })); - REQUIRE_FALSE(cmp_less(char{ 0 }, char{ -1 })); - REQUIRE_FALSE(cmp_less(int{ 1 }, int{ 0 })); - REQUIRE_FALSE(cmp_less(int{ 1 }, int{ -1 })); - REQUIRE_FALSE(cmp_less(std::size_t{ 1 }, std::size_t{ 0 })); - - REQUIRE_FALSE(cmp_less(char{ 1 }, int{ 1 })); - REQUIRE_FALSE(cmp_less(char{ 1 }, int{ 0 })); - REQUIRE_FALSE(cmp_less(char{ 0 }, int{ -1 })); - REQUIRE_FALSE(cmp_less(char{ 1 }, int{ -11 })); - REQUIRE_FALSE(cmp_less(std::size_t{ 1 }, char{ -1 })); - REQUIRE_FALSE(cmp_less(int{ 1 }, std::size_t{ 0 })); - REQUIRE_FALSE(cmp_less(char{ 0 }, std::numeric_limits::min())); - REQUIRE_FALSE(cmp_less(std::size_t{ 0 }, std::numeric_limits::min())); - REQUIRE_FALSE(cmp_less(std::numeric_limits::max(), int{ -1 })); - REQUIRE_FALSE(cmp_less(std::numeric_limits::max(), std::size_t{ 1 })); - } -} diff --git a/libmamba/tests/src/util/test_encoding.cpp b/libmamba/tests/src/util/test_encoding.cpp index 6d7955274..8a2e766b3 100644 --- a/libmamba/tests/src/util/test_encoding.cpp +++ b/libmamba/tests/src/util/test_encoding.cpp @@ -16,7 +16,7 @@ using namespace mamba::util; namespace { - TEST_CASE("Hexadecimal") + TEST_CASE("Hexadecimal", "[mamba::util]") { SECTION("nibble_to_hex") { @@ -107,7 +107,7 @@ namespace } } - TEST_CASE("percent") + TEST_CASE("percent", "[mamba::util]") { SECTION("encode") { @@ -141,7 +141,7 @@ namespace } } - TEST_CASE("base64") + TEST_CASE("base64", "[mamba::util]") { SECTION("encode") { @@ -149,7 +149,7 @@ namespace REQUIRE(encode_base64("Hello World!").value() == "SGVsbG8gV29ybGQh"); REQUIRE(encode_base64("!@#$%^U&I*O").value() == "IUAjJCVeVSZJKk8="); REQUIRE( - encode_base64(u8"_私のにほHelloわへたです").value() + encode_base64(to_utf8_std_string(u8"_私のにほHelloわへたです")).value() == "X+engeOBruOBq+OBu0hlbGxv44KP44G444Gf44Gn44GZ" ); REQUIRE(encode_base64("xyzpass").value() == "eHl6cGFzcw=="); @@ -161,7 +161,7 @@ namespace REQUIRE(decode_base64("SGVsbG8gV29ybGQh").value() == "Hello World!"); REQUIRE(decode_base64("IUAjJCVeVSZJKk8=").value() == "!@#$%^U&I*O"); REQUIRE( - decode_base64(u8"X+engeOBruOBq+OBu0hlbGxv44KP44G444Gf44Gn44GZ").value() + decode_base64(to_utf8_std_string(u8"X+engeOBruOBq+OBu0hlbGxv44KP44G444Gf44Gn44GZ")).value() == "_私のにほHelloわへたです" ); REQUIRE(decode_base64("eHl6cGFzcw==").value() == "xyzpass"); diff --git a/libmamba/tests/src/util/test_environment.cpp b/libmamba/tests/src/util/test_environment.cpp index 4d0fa2cc2..91c901042 100644 --- a/libmamba/tests/src/util/test_environment.cpp +++ b/libmamba/tests/src/util/test_environment.cpp @@ -7,6 +7,7 @@ #include #include "mamba/util/build.hpp" +#include "mamba/util/encoding.hpp" #include "mamba/util/environment.hpp" #include "mambatests.hpp" @@ -15,7 +16,7 @@ using namespace mamba::util; namespace { - TEST_CASE("get_env") + TEST_CASE("get_env", "[mamba::util]") { const auto restore = mambatests::EnvironmentCleaner(); @@ -29,32 +30,32 @@ namespace SECTION("ASCII") { - const auto key = std::string(u8"VAR_THAT_DOES_NOT_EXIST_XYZ"); - const auto value1 = std::string(u8"VALUE"); + const auto key = to_utf8_std_string(u8"VAR_THAT_DOES_NOT_EXIST_XYZ"); + const auto value1 = to_utf8_std_string(u8"VALUE"); set_env(key, value1); REQUIRE(get_env(key) == value1); - const auto value2 = std::string(u8"VALUE_NEW"); + const auto value2 = to_utf8_std_string(u8"VALUE_NEW"); set_env(key, value2); REQUIRE(get_env(key) == value2); } SECTION("UTF-8") { - const auto key = std::string(u8"VAR_私のにほんごわへたです"); - const auto value1 = std::string(u8"😀"); + const auto key = to_utf8_std_string(u8"VAR_私のにほんごわへたです"); + const auto value1 = to_utf8_std_string(u8"😀"); set_env(key, value1); REQUIRE(get_env(key) == value1); - const auto value2 = std::string(u8"🤗"); + const auto value2 = to_utf8_std_string(u8"🤗"); set_env(key, value2); REQUIRE(get_env(key) == value2); } } - TEST_CASE("unset_env") + TEST_CASE("unset_env", "[mamba::util]") { const auto restore = mambatests::EnvironmentCleaner(); - const auto key = std::string(u8"VAR_THAT_DOES_NOT_EXIST_ABC_😀"); + const auto key = to_utf8_std_string(u8"VAR_THAT_DOES_NOT_EXIST_ABC_😀"); REQUIRE_FALSE(get_env(key).has_value()); unset_env(key); REQUIRE_FALSE(get_env(key).has_value()); @@ -64,7 +65,7 @@ namespace REQUIRE_FALSE(get_env(key).has_value()); } - TEST_CASE("get_env_map") + TEST_CASE("get_env_map", "[mamba::util]") { const auto restore = mambatests::EnvironmentCleaner(); @@ -73,64 +74,64 @@ namespace REQUIRE(env.count("VAR_THAT_MUST_NOT_EXIST_XYZ") == 0); REQUIRE(env.count("PATH") == 1); - const auto key = std::string(u8"VAR_私のにほHelloわへたです"); - const auto value = std::string(u8"😀"); + const auto key = to_utf8_std_string(u8"VAR_私のにほHelloわへたです"); + const auto value = to_utf8_std_string(u8"😀"); set_env(key, value); env = get_env_map(); REQUIRE(env.at(key) == value); } - TEST_CASE("update_env_map") + TEST_CASE("update_env_map", "[mamba::util]") { const auto restore = mambatests::EnvironmentCleaner(); - const auto key_inexistent = std::string(u8"CONDA😀"); - const auto key_unchanged = std::string(u8"MAMBA😀"); - const auto key_changed = std::string(u8"PIXI😀"); + const auto key_inexistent = to_utf8_std_string(u8"CONDA😀"); + const auto key_unchanged = to_utf8_std_string(u8"MAMBA😀"); + const auto key_changed = to_utf8_std_string(u8"PIXI😀"); REQUIRE_FALSE(get_env(key_inexistent).has_value()); REQUIRE_FALSE(get_env(key_unchanged).has_value()); REQUIRE_FALSE(get_env(key_changed).has_value()); - const auto val_set_1 = std::string(u8"a😀"); + const auto val_set_1 = to_utf8_std_string(u8"a😀"); update_env_map({ { key_changed, val_set_1 }, { key_unchanged, val_set_1 } }); REQUIRE(get_env(key_inexistent) == std::nullopt); REQUIRE(get_env(key_unchanged) == val_set_1); REQUIRE(get_env(key_changed) == val_set_1); - const auto val_set_2 = std::string(u8"b😀"); + const auto val_set_2 = to_utf8_std_string(u8"b😀"); update_env_map({ { key_changed, val_set_2 } }); REQUIRE(get_env(key_inexistent) == std::nullopt); REQUIRE(get_env(key_unchanged) == val_set_1); REQUIRE(get_env(key_changed) == val_set_2); } - TEST_CASE("set_env_map") + TEST_CASE("set_env_map", "[mamba::util]") { const auto restore = mambatests::EnvironmentCleaner(); - const auto key_inexistent = std::string(u8"CONDA🤗"); - const auto key_unchanged = std::string(u8"MAMBA🤗"); - const auto key_changed = std::string(u8"PIXI🤗"); + const auto key_inexistent = to_utf8_std_string(u8"CONDA🤗"); + const auto key_unchanged = to_utf8_std_string(u8"MAMBA🤗"); + const auto key_changed = to_utf8_std_string(u8"PIXI🤗"); REQUIRE_FALSE(get_env(key_inexistent).has_value()); REQUIRE_FALSE(get_env(key_unchanged).has_value()); REQUIRE_FALSE(get_env(key_changed).has_value()); - const auto val_set_1 = std::string(u8"a😀"); + const auto val_set_1 = to_utf8_std_string(u8"a😀"); set_env_map({ { key_changed, val_set_1 }, { key_unchanged, val_set_1 } }); REQUIRE(get_env(key_inexistent) == std::nullopt); REQUIRE(get_env(key_unchanged) == val_set_1); REQUIRE(get_env(key_changed) == val_set_1); - const auto val_set_2 = std::string(u8"b😀"); + const auto val_set_2 = to_utf8_std_string(u8"b😀"); set_env_map({ { key_changed, val_set_2 } }); REQUIRE(get_env(key_inexistent) == std::nullopt); REQUIRE(get_env(key_unchanged) == std::nullopt); // Difference with update_env_map REQUIRE(get_env(key_changed) == val_set_2); } - TEST_CASE("user_home_dir") + TEST_CASE("user_home_dir", "[mamba::util]") { const auto restore = mambatests::EnvironmentCleaner(); @@ -165,7 +166,7 @@ namespace } } - TEST_CASE("user_xdg") + TEST_CASE("user_xdg", "[mamba::util]") { const auto restore = mambatests::EnvironmentCleaner(); @@ -193,7 +194,7 @@ namespace } } - TEST_CASE("which_in") + TEST_CASE("which_in", "[mamba::util]") { SECTION("Inexistent search dirs") { @@ -224,7 +225,7 @@ namespace } } - TEST_CASE("which") + TEST_CASE("which", "[mamba::util]") { SECTION("echo") { diff --git a/libmamba/tests/src/util/test_os_win.cpp b/libmamba/tests/src/util/test_os_win.cpp index aa3706ffd..e335e4c58 100644 --- a/libmamba/tests/src/util/test_os_win.cpp +++ b/libmamba/tests/src/util/test_os_win.cpp @@ -11,6 +11,7 @@ #include #include "mamba/util/build.hpp" +#include "mamba/util/encoding.hpp" #include "mamba/util/os_win.hpp" using namespace mamba; @@ -25,7 +26,7 @@ namespace SKIP(); } const std::wstring text_utf16 = L"Hello, I am Joël. 私のにほんごわへたです"; - const std::string text_utf8 = u8"Hello, I am Joël. 私のにほんごわへたです"; + const std::string text_utf8 = to_utf8_std_string(u8"Hello, I am Joël. 私のにほんごわへたです"); SECTION("utf8_to_windows_encoding") { diff --git a/libmambapy/CMakeLists.txt b/libmambapy/CMakeLists.txt index 199723cc1..18cff2e27 100644 --- a/libmambapy/CMakeLists.txt +++ b/libmambapy/CMakeLists.txt @@ -50,7 +50,14 @@ target_include_directories(bindings PRIVATE src/libmambapy/bindings) mamba_target_add_compile_warnings(bindings WARNING_AS_ERROR ${MAMBA_WARNING_AS_ERROR}) target_link_libraries(bindings PRIVATE pybind11::pybind11 ${libmamba_target}) -target_compile_features(bindings PRIVATE cxx_std_17) +target_compile_features(bindings PUBLIC cxx_std_20) +set_target_properties( + bindings + PROPERTIES + CXX_STANDARD 20 + CXX_STANDARD_REQUIRED YES + CXX_EXTENSIONS NO +) # Installation diff --git a/mamba_package/CMakeLists.txt b/mamba_package/CMakeLists.txt index cf47433a2..80f2ce1c4 100644 --- a/mamba_package/CMakeLists.txt +++ b/mamba_package/CMakeLists.txt @@ -36,7 +36,14 @@ mamba_target_add_compile_warnings(mamba-package WARNING_AS_ERROR ${MAMBA_WARNING target_link_libraries(mamba-package PRIVATE mamba::libmamba) -set_target_properties(mamba-package PROPERTIES CXX_STANDARD 17) +target_compile_features(mamba-package PUBLIC cxx_std_20) +set_target_properties( + mamba-package + PROPERTIES + CXX_STANDARD 20 + CXX_STANDARD_REQUIRED YES + CXX_EXTENSIONS NO +) install( TARGETS mamba-package diff --git a/micromamba/CMakeLists.txt b/micromamba/CMakeLists.txt index 86e1f2840..7feffbd8e 100644 --- a/micromamba/CMakeLists.txt +++ b/micromamba/CMakeLists.txt @@ -66,7 +66,14 @@ macro(mambaexe_create_target target_name linkage output_name) add_executable(${target_name} ${MICROMAMBA_SRCS} ${MICROMAMBA_HEADERS}) mamba_target_add_compile_warnings(${target_name} WARNING_AS_ERROR ${MAMBA_WARNING_AS_ERROR}) mamba_target_set_lto(${target_name} MODE ${MAMBA_LTO}) - set_property(TARGET ${target_name} PROPERTY CXX_STANDARD 17) + target_compile_features(${target_name} PUBLIC cxx_std_20) + set_target_properties( + ${target_name} + PROPERTIES + CXX_STANDARD 20 + CXX_STANDARD_REQUIRED YES + CXX_EXTENSIONS NO + ) target_link_libraries(${target_name} PRIVATE Threads::Threads reproc reproc++)