diff --git a/libmamba/tests/include/mambatests.hpp b/libmamba/tests/include/mambatests.hpp index 4293ca2da0..3df723993d 100644 --- a/libmamba/tests/include/mambatests.hpp +++ b/libmamba/tests/include/mambatests.hpp @@ -9,11 +9,16 @@ #include #include +#include #include #include #include +#include +#include + #include "mamba/core/context.hpp" +#include "mamba/core/invoke.hpp" #include "mamba/core/output.hpp" #include "mamba/fs/filesystem.hpp" #include "mamba/util/environment.hpp" @@ -91,8 +96,10 @@ namespace mambatests }; // RAII helper for C++ tests that temporarily override fields on the shared Context - // singleton (see context()). Tests often need to point at a temp prefix, tweak channels, - // or flip feature flags; without restoration, later tests inherit stale state. + // singleton (see context()). A future improvement would be to give each test its own + // Context instance instead of mutating the singleton (see singletons() FIXME). Until then, + // tests often need to point at a temp prefix, tweak channels, or flip feature flags; + // without restoration, later tests inherit stale state. // // Save the value of each touched field on first use and restore it when the guard is // destroyed. Repeated calls to the same setter only change the live value — the original @@ -107,7 +114,7 @@ namespace mambatests // mambatests::ScopedContextChange context_change{ ctx }; // context_change.set_channels({ "conda-forge" }).set_offline(false); // - // context_change.preserve(&mamba::Context::use_sharded_repodata); + // context_change.preserve(ctx.use_sharded_repodata); // ctx.use_sharded_repodata = false; // restored to the pre-preserve value at scope end class ScopedContextChange { @@ -120,73 +127,74 @@ namespace mambatests ~ScopedContextChange() { - for (auto it = m_restorers.rbegin(); it != m_restorers.rend(); ++it) + for (auto& restorer : std::ranges::reverse_view(m_restorers)) { - (*it)(); + auto result = mamba::safe_invoke(restorer); + if (!result) + { + INFO(result.error().what()); + FAIL_CHECK("ScopedContextChange restoration failed"); + } } } ScopedContextChange& set_target_prefix(const mamba::fs::u8path& prefix) { - touch( - &mamba::Context::prefix_params, - [&](auto& params) { params.target_prefix = prefix; } - ); + touch(m_ctx.prefix_params, [&](auto& params) { params.target_prefix = prefix; }); return *this; } ScopedContextChange& set_root_prefix(const mamba::fs::u8path& prefix) { - touch(&mamba::Context::prefix_params, [&](auto& params) { params.root_prefix = prefix; }); + touch(m_ctx.prefix_params, [&](auto& params) { params.root_prefix = prefix; }); return *this; } ScopedContextChange& set_envs_dirs(std::vector dirs) { - touch(&mamba::Context::envs_dirs, [&](auto& field) { field = std::move(dirs); }); + touch(m_ctx.envs_dirs, [&](auto& field) { field = std::move(dirs); }); return *this; } ScopedContextChange& set_pkgs_dirs(std::vector dirs) { - touch(&mamba::Context::pkgs_dirs, [&](auto& field) { field = std::move(dirs); }); + touch(m_ctx.pkgs_dirs, [&](auto& field) { field = std::move(dirs); }); return *this; } ScopedContextChange& set_prefix_data_interoperability(bool value) { - touch(&mamba::Context::prefix_data_interoperability, [&](auto& field) { field = value; }); + touch(m_ctx.prefix_data_interoperability, [&](auto& field) { field = value; }); return *this; } ScopedContextChange& set_channels(std::vector channels) { - touch(&mamba::Context::channels, [&](auto& field) { field = std::move(channels); }); + touch(m_ctx.channels, [&](auto& field) { field = std::move(channels); }); return *this; } ScopedContextChange& set_use_sharded_repodata(bool value) { - touch(&mamba::Context::use_sharded_repodata, [&](auto& field) { field = value; }); + touch(m_ctx.use_sharded_repodata, [&](auto& field) { field = value; }); return *this; } ScopedContextChange& set_offline(bool value) { - touch(&mamba::Context::offline, [&](auto& field) { field = value; }); + touch(m_ctx.offline, [&](auto& field) { field = value; }); return *this; } ScopedContextChange& set_platform(std::string platform) { - touch(&mamba::Context::platform, [&](auto& field) { field = std::move(platform); }); + touch(m_ctx.platform, [&](auto& field) { field = std::move(platform); }); return *this; } - // Snapshot member for restoration without assigning a new value. The member pointer - // syntax (e.g. &mamba::Context::platform) selects which Context field to guard. + // Snapshot member for restoration without assigning a new value. template - ScopedContextChange& preserve(T mamba::Context::* member) + ScopedContextChange& preserve(T& member) { touch(member, [](auto&) {}); return *this; @@ -200,15 +208,14 @@ namespace mambatests private: template - void touch(T mamba::Context::* member, F&& mutator) + void touch(T& member, F&& mutator) { - auto& field = m_ctx.*member; - if (m_saved_fields.insert(static_cast(&field)).second) + if (m_saved_fields.insert(static_cast(&member)).second) { - m_restorers.push_back([&field, initial = field]() mutable - { field = std::move(initial); }); + m_restorers.push_back([&member, initial = member]() mutable + { member = std::move(initial); }); } - mutator(field); + std::invoke(std::forward(mutator), member); } mamba::Context& m_ctx; diff --git a/libmamba/tests/src/core/test_channel_loader.cpp b/libmamba/tests/src/core/test_channel_loader.cpp index a623d24307..eb5fac3b32 100644 --- a/libmamba/tests/src/core/test_channel_loader.cpp +++ b/libmamba/tests/src/core/test_channel_loader.cpp @@ -162,12 +162,12 @@ TEST_CASE("load_channels", "[mamba::api][channel_loader]") // Use test singletons so Console/progress bar are initialized (avoids SIGABRT) Context& ctx = mambatests::context(); mambatests::ScopedContextChange context_change{ ctx }; - context_change.preserve(&mamba::Context::channels) - .preserve(&mamba::Context::mirrored_channels) - .preserve(&mamba::Context::pkgs_dirs) - .preserve(&mamba::Context::offline) - .preserve(&mamba::Context::remote_fetch_params) - .preserve(&mamba::Context::channel_alias); + context_change.preserve(ctx.channels) + .preserve(ctx.mirrored_channels) + .preserve(ctx.pkgs_dirs) + .preserve(ctx.offline) + .preserve(ctx.remote_fetch_params) + .preserve(ctx.channel_alias); ctx.channels = {}; ctx.mirrored_channels = {}; diff --git a/libmamba/tests/src/core/test_channels_hook.cpp b/libmamba/tests/src/core/test_channels_hook.cpp index 9ab80763fb..8bfa5214b4 100644 --- a/libmamba/tests/src/core/test_channels_hook.cpp +++ b/libmamba/tests/src/core/test_channels_hook.cpp @@ -43,7 +43,7 @@ namespace mamba::testing ChannelsHookFixture() { - m_context_change.preserve(&mamba::Context::channel_alias).preserve(&mamba::Context::channels); + m_context_change.preserve(ctx.channel_alias).preserve(ctx.channels); } ~ChannelsHookFixture() diff --git a/libmamba/tests/src/core/test_configuration.cpp b/libmamba/tests/src/core/test_configuration.cpp index d1f63168d5..0a35bf1b3a 100644 --- a/libmamba/tests/src/core/test_configuration.cpp +++ b/libmamba/tests/src/core/test_configuration.cpp @@ -39,8 +39,7 @@ namespace mamba Configuration() { - m_context_change.preserve(&mamba::Context::channel_alias) - .preserve(&mamba::Context::remote_fetch_params); + m_context_change.preserve(ctx.channel_alias).preserve(ctx.remote_fetch_params); } ~Configuration() @@ -865,7 +864,7 @@ namespace mamba TEST_CASE_METHOD(Configuration, "platform") { mambatests::ScopedContextChange context_change{ ctx }; - context_change.preserve(&mamba::Context::platform); + context_change.preserve(ctx.platform); REQUIRE(ctx.platform == ctx.host_platform); diff --git a/libmamba/tests/src/core/test_output.cpp b/libmamba/tests/src/core/test_output.cpp index e04f0e509c..aa740cec7d 100644 --- a/libmamba/tests/src/core/test_output.cpp +++ b/libmamba/tests/src/core/test_output.cpp @@ -19,7 +19,7 @@ namespace mamba { auto& ctx = mambatests::context(); mambatests::ScopedContextChange context_change{ ctx }; - context_change.preserve(&mamba::Context::graphics_params); + context_change.preserve(ctx.graphics_params); ctx.graphics_params.no_progress_bars = true; auto proxy = Console::instance().add_progress_bar("conda-forge"); diff --git a/libmamba/tests/src/core/test_sharded_repodata_integration.cpp b/libmamba/tests/src/core/test_sharded_repodata_integration.cpp index 67b517e9ff..bc3aae196b 100644 --- a/libmamba/tests/src/core/test_sharded_repodata_integration.cpp +++ b/libmamba/tests/src/core/test_sharded_repodata_integration.cpp @@ -1290,8 +1290,7 @@ TEST_CASE("Sharded repodata - update scenarios", "[mamba::core][sharded][.integr // For update, we need to create prefix data and use Update request mambatests::ScopedContextChange update_context_change{ ctx }; - update_context_change.preserve(&mamba::Context::use_sharded_repodata) - .preserve(&mamba::Context::validation_params); + update_context_change.preserve(ctx.use_sharded_repodata).preserve(ctx.validation_params); // Test traditional update ctx.use_sharded_repodata = false; @@ -1615,8 +1614,7 @@ TEST_CASE("Sharded repodata - remove scenarios", "[mamba::core][sharded][.integr // For remove, we need to create prefix data and use Remove request mambatests::ScopedContextChange remove_context_change{ ctx }; - remove_context_change.preserve(&mamba::Context::use_sharded_repodata) - .preserve(&mamba::Context::validation_params); + remove_context_change.preserve(ctx.use_sharded_repodata).preserve(ctx.validation_params); // Test traditional remove ctx.use_sharded_repodata = false; diff --git a/libmamba/tests/src/core/test_virtual_packages.cpp b/libmamba/tests/src/core/test_virtual_packages.cpp index cee2483f35..9e82747126 100644 --- a/libmamba/tests/src/core/test_virtual_packages.cpp +++ b/libmamba/tests/src/core/test_virtual_packages.cpp @@ -42,7 +42,7 @@ namespace mamba auto& ctx = mambatests::context(); mambatests::ScopedContextChange context_change{ ctx }; - context_change.preserve(&mamba::Context::platform); + context_change.preserve(ctx.platform); auto pkgs = detail::dist_packages(ctx.platform);