maint: Use Catch2 instead of doctest (#3618)

This commit is contained in:
Ayaz Salikhov 2024-12-06 07:57:33 +00:00 committed by GitHub
parent 633d8d005a
commit c3a2c1c66e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
90 changed files with 6275 additions and 6229 deletions

View File

@ -21,7 +21,7 @@ dependencies:
- yaml-cpp >=0.8.0
- sel(win): winreg
# libmamba test dependencies
- doctest
- catch2
# micromamba dependencies
- cli11 >=2.2
# micromamba test dependencies

View File

@ -30,6 +30,6 @@ dependencies:
- libnghttp2-static
- lz4-c-static
# libmamba test dependencies
- doctest
- catch2
# micromamba dependencies
- cli11 >=2.2,<3

View File

@ -9,6 +9,7 @@ cmake_minimum_required(VERSION 3.16)
add_executable(
test_solv_cpp
src/main.cpp
src/msvc_catch_string_view.cpp
src/pool_data.cpp
src/test_pool.cpp
src/test_queue.cpp
@ -19,7 +20,8 @@ add_executable(
src/test_transaction.cpp
)
target_include_directories(test_solv_cpp PRIVATE src/)
target_compile_definitions(test_solv_cpp PRIVATE DOCTEST_CONFIG_USE_STD_HEADERS)
find_package(doctest REQUIRED)
target_link_libraries(test_solv_cpp PRIVATE doctest::doctest solv::cpp)
find_package(Catch2 REQUIRED)
target_link_libraries(test_solv_cpp PRIVATE Catch2::Catch2WithMain solv::cpp)
set_target_properties(
test_solv_cpp PROPERTIES COMPILE_DEFINITIONS CATCH_CONFIG_ENABLE_ALL_STRINGMAKERS
)

View File

@ -1,3 +1,3 @@
#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
#define CATCH_CONFIG_MAIN
#include <doctest/doctest.h>
#include <catch2/catch_all.hpp>

View File

@ -0,0 +1,22 @@
#ifdef _WIN32
// Catch compiled on `conda-forge` for MSVC doesn't support outputting `string_view`.
// So we have to define StringMaker for it ourselves.
// The declaration is present though, so this only causes link errors.
#include <string>
#include <string_view>
#include <catch2/catch_tostring.hpp>
namespace Catch
{
std::string StringMaker<std::string_view>::convert(std::string_view str)
{
return std::string(str);
}
}
#endif

View File

@ -9,7 +9,7 @@
#include <string_view>
#include <vector>
#include <doctest/doctest.h>
#include <catch2/catch_all.hpp>
#include <solv/pool.h>
#include <solv/solver.h>
@ -18,55 +18,55 @@
using namespace solv;
TEST_SUITE("solv::ObjPool")
namespace
{
TEST_CASE("Construct a pool")
{
auto pool = ObjPool();
SUBCASE("Change distribution type")
SECTION("Change distribution type")
{
pool.set_disttype(DISTTYPE_CONDA);
CHECK_EQ(pool.disttype(), DISTTYPE_CONDA);
REQUIRE(pool.disttype() == DISTTYPE_CONDA);
}
SUBCASE("Error")
SECTION("Error")
{
pool.set_current_error("Some failure");
CHECK_EQ(pool.current_error(), "Some failure");
REQUIRE(pool.current_error() == "Some failure");
}
SUBCASE("Add strings")
SECTION("Add strings")
{
const auto id_hello = pool.add_string("Hello");
const auto maybe_id_hello = pool.find_string("Hello");
REQUIRE(maybe_id_hello.has_value());
CHECK_EQ(maybe_id_hello.value(), id_hello);
CHECK_EQ(pool.get_string(id_hello), "Hello");
REQUIRE(maybe_id_hello.value() == id_hello);
REQUIRE(pool.get_string(id_hello) == "Hello");
SUBCASE("Add another string")
SECTION("Add another string")
{
const auto id_world = pool.add_string("World");
CHECK_NE(id_world, id_hello);
REQUIRE(id_world != id_hello);
const auto maybe_id_world = pool.find_string("World");
REQUIRE(maybe_id_world.has_value());
CHECK_EQ(maybe_id_world.value(), id_world);
CHECK_EQ(pool.get_string(id_world), "World");
REQUIRE(maybe_id_world.value() == id_world);
REQUIRE(pool.get_string(id_world) == "World");
SUBCASE("Add the same one again")
SECTION("Add the same one again")
{
const auto id_world_again = pool.add_string("World");
CHECK_EQ(id_world_again, id_world);
REQUIRE(id_world_again == id_world);
}
}
SUBCASE("Find non-existent string")
SECTION("Find non-existent string")
{
CHECK_FALSE(pool.find_string("Bar").has_value());
REQUIRE_FALSE(pool.find_string("Bar").has_value());
}
}
SUBCASE("Add dependencies")
SECTION("Add dependencies")
{
const auto id_name = pool.add_string("mamba");
const auto id_version_1 = pool.add_string("1.0.0");
@ -74,66 +74,68 @@ TEST_SUITE("solv::ObjPool")
const auto id_rel = pool.add_dependency(id_name, REL_GT, id_version_1);
const auto maybe_id_rel = pool.find_dependency(id_name, REL_GT, id_version_1);
REQUIRE(maybe_id_rel.has_value());
CHECK_EQ(maybe_id_rel.value(), id_rel);
CHECK_EQ(pool.get_dependency_name(id_rel), "mamba");
CHECK_EQ(pool.get_dependency_relation(id_rel), " > ");
CHECK_EQ(pool.get_dependency_version(id_rel), "1.0.0");
CHECK_EQ(pool.dependency_to_string(id_rel), "mamba > 1.0.0");
REQUIRE(maybe_id_rel.value() == id_rel);
REQUIRE(pool.get_dependency_name(id_rel) == "mamba");
REQUIRE(pool.get_dependency_relation(id_rel) == " > ");
REQUIRE(pool.get_dependency_version(id_rel) == "1.0.0");
REQUIRE(pool.dependency_to_string(id_rel) == "mamba > 1.0.0");
SUBCASE("Parse a conda dependency")
SECTION("Parse a conda dependency")
{
const auto id_conda = pool.add_conda_dependency("rattler < 0.1");
CHECK_EQ(pool.get_dependency_name(id_conda), "rattler");
CHECK_EQ(pool.get_dependency_version(id_conda), "<0.1");
REQUIRE(pool.get_dependency_name(id_conda) == "rattler");
REQUIRE(pool.get_dependency_version(id_conda) == "<0.1");
}
}
SUBCASE("Add repo")
SECTION("Add repo")
{
auto [repo1_id, repo1] = pool.add_repo("repo1");
CHECK_EQ(repo1.id(), repo1_id);
REQUIRE(repo1.id() == repo1_id);
REQUIRE(pool.has_repo(repo1_id));
REQUIRE(pool.get_repo(repo1_id).has_value());
CHECK_EQ(pool.get_repo(repo1_id).value().id(), repo1_id);
CHECK_EQ(pool.repo_count(), 1);
REQUIRE(pool.get_repo(repo1_id).value().id() == repo1_id);
REQUIRE(pool.repo_count() == 1);
auto [repo2_id, repo2] = pool.add_repo("repo2");
auto [repo3_id, repo3] = pool.add_repo("repo3");
CHECK_EQ(pool.repo_count(), 3);
REQUIRE(pool.repo_count() == 3);
SUBCASE("Add repo with same name")
SECTION("Add repo with same name")
{
auto [repo1_bis_id, repo1_bis] = pool.add_repo("repo1");
CHECK_EQ(pool.repo_count(), 4);
CHECK_NE(repo1_bis_id, repo1_id);
REQUIRE(pool.repo_count() == 4);
REQUIRE(repo1_bis_id != repo1_id);
}
SUBCASE("Set installed repo")
SECTION("Set installed repo")
{
CHECK_FALSE(pool.installed_repo().has_value());
REQUIRE_FALSE(pool.installed_repo().has_value());
pool.set_installed_repo(repo2_id);
REQUIRE(pool.installed_repo().has_value());
CHECK_EQ(pool.installed_repo()->id(), repo2_id);
REQUIRE(pool.installed_repo()->id() == repo2_id);
}
SUBCASE("Iterate over repos")
SECTION("Iterate over repos")
{
const auto repo_ids = std::array{ repo1_id, repo2_id, repo3_id };
SUBCASE("Over all repos")
SECTION("Over all repos")
{
std::size_t n_repos = 0;
pool.for_each_repo_id(
[&](RepoId id)
{
CHECK_NE(std::find(repo_ids.cbegin(), repo_ids.cend(), id), repo_ids.cend());
REQUIRE(
std::find(repo_ids.cbegin(), repo_ids.cend(), id) != repo_ids.cend()
);
n_repos++;
}
);
CHECK_EQ(n_repos, pool.repo_count());
REQUIRE(n_repos == pool.repo_count());
}
SUBCASE("Over one repo then break")
SECTION("Over one repo then break")
{
std::size_t n_repos = 0;
pool.for_each_repo_id(
@ -143,28 +145,28 @@ TEST_SUITE("solv::ObjPool")
return LoopControl::Break;
}
);
CHECK_EQ(n_repos, 1);
REQUIRE(n_repos == 1);
}
}
SUBCASE("Get inexisting repo")
SECTION("Get inexisting repo")
{
CHECK_FALSE(pool.has_repo(1234));
CHECK_FALSE(pool.get_repo(1234).has_value());
REQUIRE_FALSE(pool.has_repo(1234));
REQUIRE_FALSE(pool.get_repo(1234).has_value());
}
SUBCASE("Remove repo")
SECTION("Remove repo")
{
CHECK(pool.remove_repo(repo2_id, true));
CHECK_FALSE(pool.has_repo(repo2_id));
CHECK(pool.get_repo(repo1_id).has_value());
CHECK_EQ(pool.repo_count(), 2);
REQUIRE(pool.remove_repo(repo2_id, true));
REQUIRE_FALSE(pool.has_repo(repo2_id));
REQUIRE(pool.get_repo(repo1_id).has_value());
REQUIRE(pool.repo_count() == 2);
// Remove invalid repo is a noop
CHECK_FALSE(pool.remove_repo(1234, true));
REQUIRE_FALSE(pool.remove_repo(1234, true));
}
SUBCASE("Manage solvables")
SECTION("Manage solvables")
{
auto [id1, s1] = repo1.add_solvable();
const auto pkg_name_id = pool.add_string("mamba");
@ -178,28 +180,28 @@ TEST_SUITE("solv::ObjPool")
s2.set_version("2.0.0");
s2.add_self_provide();
SUBCASE("Retrieve solvables")
SECTION("Retrieve solvables")
{
CHECK_EQ(pool.solvable_count(), 2);
CHECK(pool.get_solvable(id1).has_value());
CHECK(pool.get_solvable(id2).has_value());
REQUIRE(pool.solvable_count() == 2);
REQUIRE(pool.get_solvable(id1).has_value());
REQUIRE(pool.get_solvable(id2).has_value());
}
SUBCASE("Iterate over solvables")
SECTION("Iterate over solvables")
{
SUBCASE("Iterate over all solvables")
SECTION("Iterate over all solvables")
{
std::vector<SolvableId> ids = {};
pool.for_each_solvable_id([&](SolvableId id) { ids.push_back(id); });
std::sort(ids.begin(), ids.end()); // Ease comparison
CHECK_EQ(ids, decltype(ids){ id1, id2 });
REQUIRE(ids == decltype(ids){ id1, id2 });
pool.for_each_solvable(
[&](ObjSolvableViewConst s)
{ CHECK_NE(std::find(ids.cbegin(), ids.cend(), s.id()), ids.cend()); }
{ REQUIRE(std::find(ids.cbegin(), ids.cend(), s.id()) != ids.cend()); }
);
}
SUBCASE("Over one solvable then break")
SECTION("Over one solvable then break")
{
std::size_t n_solvables = 0;
pool.for_each_solvable_id(
@ -209,40 +211,40 @@ TEST_SUITE("solv::ObjPool")
return LoopControl::Break;
}
);
CHECK_EQ(n_solvables, 1);
REQUIRE(n_solvables == 1);
}
}
SUBCASE("Iterate on installed solvables")
SECTION("Iterate on installed solvables")
{
SUBCASE("No installed repo")
SECTION("No installed repo")
{
pool.for_each_installed_solvable_id([&](SolvableId) { CHECK(false); });
pool.for_each_installed_solvable_id([&](SolvableId) { REQUIRE(false); });
}
SUBCASE("One installed repo")
SECTION("One installed repo")
{
pool.set_installed_repo(repo1_id);
std::vector<SolvableId> ids = {};
pool.for_each_installed_solvable_id([&](auto id) { ids.push_back(id); });
std::sort(ids.begin(), ids.end()); // Ease comparison
CHECK_EQ(ids, decltype(ids){ id1 });
REQUIRE(ids == decltype(ids){ id1 });
}
}
SUBCASE("Iterate through whatprovides")
SECTION("Iterate through whatprovides")
{
const auto dep_id = pool.add_dependency(pkg_name_id, REL_EQ, pkg_version_id);
SUBCASE("Without creating the whatprovides index is an error")
SECTION("Without creating the whatprovides index is an error")
{
CHECK_THROWS_AS(
REQUIRE_THROWS_AS(
pool.for_each_whatprovides_id(dep_id, [&](auto) {}),
std::runtime_error
);
}
SUBCASE("With creation of whatprovides index")
SECTION("With creation of whatprovides index")
{
pool.create_whatprovides();
auto whatprovides_ids = std::vector<SolvableId>();
@ -251,10 +253,10 @@ TEST_SUITE("solv::ObjPool")
[&](auto id) { whatprovides_ids.push_back(id); }
);
// Only one solvable matches
CHECK_EQ(whatprovides_ids, std::vector{ id1 });
REQUIRE(whatprovides_ids == std::vector{ id1 });
}
SUBCASE("Namespace dependencies are not in whatprovies")
SECTION("Namespace dependencies are not in whatprovies")
{
const auto other_dep_id = pool.add_dependency(
pkg_name_id,
@ -264,33 +266,33 @@ TEST_SUITE("solv::ObjPool")
pool.create_whatprovides();
bool called = false;
pool.for_each_whatprovides_id(other_dep_id, [&](auto) { called = true; });
CHECK_FALSE(called);
REQUIRE_FALSE(called);
}
SUBCASE("Namespace names are in whatprovies")
SECTION("Namespace names are in whatprovies")
{
pool.add_dependency(pkg_name_id, REL_NAMESPACE, pkg_version_id);
pool.create_whatprovides();
bool called = false;
// Diff below in other_dep_id > pkg_name_id
pool.for_each_whatprovides_id(pkg_name_id, [&](auto) { called = true; });
CHECK(called);
REQUIRE(called);
}
}
SUBCASE("Manually set whatprovides")
SECTION("Manually set whatprovides")
{
const auto dep_id = pool.add_string("mydep");
SUBCASE("Without creating the whatprovides index is an error")
SECTION("Without creating the whatprovides index is an error")
{
CHECK_THROWS_AS(
REQUIRE_THROWS_AS(
pool.add_to_whatprovides(dep_id, pool.add_to_whatprovides_data({ id1 })),
std::runtime_error
);
}
SUBCASE("With creation of whatprovides index")
SECTION("With creation of whatprovides index")
{
pool.create_whatprovides();
pool.add_to_whatprovides(dep_id, pool.add_to_whatprovides_data({ id1 }));
@ -299,9 +301,9 @@ TEST_SUITE("solv::ObjPool")
dep_id,
[&](auto id) { whatprovides_ids.push_back(id); }
);
CHECK_EQ(whatprovides_ids, std::vector{ id1 });
REQUIRE(whatprovides_ids == std::vector{ id1 });
SUBCASE("Gets cleared when calling create_whatprovides")
SECTION("Gets cleared when calling create_whatprovides")
{
pool.create_whatprovides();
whatprovides_ids.clear();
@ -309,14 +311,14 @@ TEST_SUITE("solv::ObjPool")
dep_id,
[&](auto id) { whatprovides_ids.push_back(id); }
);
CHECK(whatprovides_ids.empty());
REQUIRE(whatprovides_ids.empty());
}
}
}
}
}
SUBCASE("Add a debug callback")
SECTION("Add a debug callback")
{
std::string_view message = "";
int type = 0;
@ -328,11 +330,11 @@ TEST_SUITE("solv::ObjPool")
}
);
pool_debug(pool.raw(), SOLV_DEBUG_RESULT, "Ho no!");
CHECK_EQ(message, "Ho no!");
CHECK_EQ(type, SOLV_DEBUG_RESULT);
REQUIRE(message == "Ho no!");
REQUIRE(type == SOLV_DEBUG_RESULT);
}
SUBCASE("Add a namespace callback")
SECTION("Add a namespace callback")
{
pool.set_namespace_callback(
[&](ObjPoolView /* pool */,
@ -364,9 +366,9 @@ TEST_SUITE("solv::ObjPool")
repo.internalize();
pool.create_whatprovides(); // Required otherwise segfault
SUBCASE("Select Solvables")
SECTION("Select Solvables")
{
SUBCASE("Resolving pkg>1.0.0")
SECTION("Resolving pkg>1.0.0")
{
const auto dep_id = pool.add_dependency(
pool.add_string("pkg"),
@ -374,12 +376,12 @@ TEST_SUITE("solv::ObjPool")
pool.add_string("1.0.0")
);
auto solvs = pool.select_solvables({ SOLVER_SOLVABLE_PROVIDES, dep_id });
CHECK_EQ(solvs.size(), 2);
CHECK(solvs.contains(id1));
CHECK(solvs.contains(id2));
REQUIRE(solvs.size() == 2);
REQUIRE(solvs.contains(id1));
REQUIRE(solvs.contains(id2));
}
SUBCASE("Resolving pkg>2.1")
SECTION("Resolving pkg>2.1")
{
const auto dep_id = pool.add_dependency(
pool.add_string("pkg"),
@ -387,22 +389,22 @@ TEST_SUITE("solv::ObjPool")
pool.add_string("2.1")
);
auto solvs = pool.select_solvables({ SOLVER_SOLVABLE_PROVIDES, dep_id });
CHECK_EQ(solvs.size(), 1);
CHECK(solvs.contains(id2));
REQUIRE(solvs.size() == 1);
REQUIRE(solvs.contains(id2));
}
}
SUBCASE("What matches dep")
SECTION("What matches dep")
{
SUBCASE("Who depends on a foo")
SECTION("Who depends on a foo")
{
auto solvs = pool.what_matches_dep(SOLVABLE_REQUIRES, pool.add_string("foo"));
CHECK_EQ(solvs.size(), 2);
CHECK(solvs.contains(id1));
CHECK(solvs.contains(id2));
REQUIRE(solvs.size() == 2);
REQUIRE(solvs.contains(id1));
REQUIRE(solvs.contains(id2));
}
SUBCASE("Who depends on a foo>4.0")
SECTION("Who depends on a foo>4.0")
{
const auto dep_id = pool.add_dependency(
pool.add_string("foo"),
@ -410,12 +412,12 @@ TEST_SUITE("solv::ObjPool")
pool.add_string("4.0")
);
auto solvs = pool.what_matches_dep(SOLVABLE_REQUIRES, dep_id);
CHECK_EQ(solvs.size(), 2);
CHECK(solvs.contains(id1));
CHECK(solvs.contains(id2));
REQUIRE(solvs.size() == 2);
REQUIRE(solvs.contains(id1));
REQUIRE(solvs.contains(id2));
}
SUBCASE("Who depends on foo<0.5")
SECTION("Who depends on foo<0.5")
{
const auto dep_id = pool.add_dependency(
pool.add_string("foo"),
@ -423,7 +425,7 @@ TEST_SUITE("solv::ObjPool")
pool.add_string("0.5")
);
auto solvs = pool.what_matches_dep(SOLVABLE_REQUIRES, dep_id);
CHECK(solvs.empty());
REQUIRE(solvs.empty());
}
}
}

View File

@ -8,39 +8,39 @@
#include <stdexcept>
#include <vector>
#include <doctest/doctest.h>
#include <catch2/catch_all.hpp>
#include "solv-cpp/queue.hpp"
using namespace solv;
TEST_SUITE("solv::ObjQueue")
namespace
{
TEST_CASE("constructor")
{
auto q1 = ObjQueue();
CHECK_EQ(q1.size(), 0);
CHECK(q1.empty());
REQUIRE(q1.size() == 0);
REQUIRE(q1.empty());
auto q2 = ObjQueue{ 1, 2, 3 };
CHECK_EQ(q2.size(), 3);
CHECK_FALSE(q2.empty());
REQUIRE(q2.size() == 3);
REQUIRE_FALSE(q2.empty());
auto q3 = q2;
CHECK_EQ(q3.size(), q2.size());
CHECK_NE(q2.data(), q3.data());
REQUIRE(q3.size() == q2.size());
REQUIRE(q2.data() != q3.data());
const auto q3_data = q3.data();
const auto q3_size = q3.size();
auto q4 = std::move(q3);
CHECK_EQ(q4.size(), q3_size);
CHECK_EQ(q4.data(), q3_data);
REQUIRE(q4.size() == q3_size);
REQUIRE(q4.data() == q3_data);
const auto q4_data = q4.data();
const auto q4_size = q4.size();
q1 = std::move(q4);
CHECK_EQ(q1.size(), q4_size);
CHECK_EQ(q1.data(), q4_data);
REQUIRE(q1.size() == q4_size);
REQUIRE(q1.data() == q4_data);
}
TEST_CASE("swap")
@ -54,46 +54,46 @@ TEST_SUITE("solv::ObjQueue")
const auto q2_data = q2.data();
swap(q1, q2);
CHECK_EQ(q1.size(), q2_size);
CHECK_EQ(q1.data(), q2_data);
CHECK_EQ(q2.size(), q1_size);
CHECK_EQ(q2.data(), q1_data);
REQUIRE(q1.size() == q2_size);
REQUIRE(q1.data() == q2_data);
REQUIRE(q2.size() == q1_size);
REQUIRE(q2.data() == q1_data);
}
TEST_CASE("push_back")
{
auto q = ObjQueue();
q.push_back(1);
CHECK_EQ(q.front(), 1);
CHECK_EQ(q.back(), 1);
REQUIRE(q.front() == 1);
REQUIRE(q.back() == 1);
q.push_back(3);
CHECK_EQ(q.front(), 1);
CHECK_EQ(q.back(), 3);
REQUIRE(q.front() == 1);
REQUIRE(q.back() == 3);
}
TEST_CASE("element")
{
auto q = ObjQueue{ 3, 2, 1 };
CHECK_EQ(q[0], 3);
CHECK_EQ(q[1], 2);
CHECK_EQ(q[2], 1);
REQUIRE(q[0] == 3);
REQUIRE(q[1] == 2);
REQUIRE(q[2] == 1);
}
TEST_CASE("at")
{
auto q = ObjQueue{ 3, 2, 1 };
CHECK_EQ(q.at(0), q[0]);
CHECK_EQ(q.at(1), q[1]);
CHECK_EQ(q.at(2), q[2]);
REQUIRE(q.at(0) == q[0]);
REQUIRE(q.at(1) == q[1]);
REQUIRE(q.at(2) == q[2]);
auto use_at = [&]() { [[maybe_unused]] const auto& x = q.at(q.size()); };
CHECK_THROWS_AS(use_at(), std::out_of_range);
REQUIRE_THROWS_AS(use_at(), std::out_of_range);
}
TEST_CASE("clear")
{
auto q = ObjQueue{ 3, 2, 1 };
q.clear();
CHECK(q.empty());
REQUIRE(q.empty());
}
TEST_CASE("iterator")
@ -104,11 +104,11 @@ TEST_SUITE("solv::ObjQueue")
{
++n;
}
CHECK_EQ(n, q.size());
REQUIRE(n == q.size());
const auto l = std::list<::Id>(q.begin(), q.end());
const auto l_expected = std::list{ 3, 2, 1 };
CHECK_EQ(l, l_expected);
REQUIRE(l == l_expected);
}
TEST_CASE("reverse_iterator")
@ -116,16 +116,16 @@ TEST_SUITE("solv::ObjQueue")
const auto q = ObjQueue{ 3, 2, 1 };
const auto v = std::vector(q.crbegin(), q.crend());
CHECK_EQ(v.front(), q.back());
CHECK_EQ(v.back(), q.front());
REQUIRE(v.front() == q.back());
REQUIRE(v.back() == q.front());
}
TEST_CASE("insert_one")
{
auto q = ObjQueue();
auto iter = q.insert(q.cbegin(), 4);
CHECK_EQ(*iter, 4);
CHECK_EQ(q.front(), 4);
REQUIRE(*iter == 4);
REQUIRE(q.front() == 4);
}
TEST_CASE("insert_span")
@ -135,21 +135,21 @@ TEST_SUITE("solv::ObjQueue")
const auto r1 = std::vector{ 1, 2, 3 };
// std::vector::iterator is not always a pointer
auto iter = q.insert(q.cend(), r1.data(), r1.data() + r1.size());
CHECK_EQ(*iter, q[0]);
CHECK_EQ(q[0], 1);
CHECK_EQ(q[1], 2);
CHECK_EQ(q[2], 3);
REQUIRE(*iter == q[0]);
REQUIRE(q[0] == 1);
REQUIRE(q[1] == 2);
REQUIRE(q[2] == 3);
const auto r2 = std::vector{ 4, 4 };
iter = q.insert(q.cbegin(), r2.data(), r2.data() + r2.size());
CHECK_EQ(*iter, q[0]);
CHECK_EQ(q[0], 4);
CHECK_EQ(q[1], 4);
REQUIRE(*iter == q[0]);
REQUIRE(q[0] == 4);
REQUIRE(q[1] == 4);
const auto r3 = std::vector<int>{};
iter = q.insert(q.cbegin(), r3.data(), r3.data() + r3.size());
CHECK_EQ(*iter, q[0]);
CHECK_EQ(q[0], 4);
REQUIRE(*iter == q[0]);
REQUIRE(q[0] == 4);
}
TEST_CASE("insert_range")
@ -158,58 +158,58 @@ TEST_SUITE("solv::ObjQueue")
const auto r1 = std::list{ 1, 2, 3 };
auto iter = q.insert(q.cend(), r1.begin(), r1.end());
CHECK_EQ(*iter, q[0]);
CHECK_EQ(q[0], 1);
CHECK_EQ(q[1], 2);
CHECK_EQ(q[2], 3);
REQUIRE(*iter == q[0]);
REQUIRE(q[0] == 1);
REQUIRE(q[1] == 2);
REQUIRE(q[2] == 3);
const auto r2 = std::list{ 4, 4 };
iter = q.insert(q.cbegin(), r2.begin(), r2.end());
CHECK_EQ(*iter, q[0]);
CHECK_EQ(q[0], 4);
CHECK_EQ(q[1], 4);
REQUIRE(*iter == q[0]);
REQUIRE(q[0] == 4);
REQUIRE(q[1] == 4);
const auto r3 = std::list<int>{};
iter = q.insert(q.cbegin(), r3.begin(), r3.end());
CHECK_EQ(*iter, q[0]);
CHECK_EQ(q[0], 4);
REQUIRE(*iter == q[0]);
REQUIRE(q[0] == 4);
}
TEST_CASE("erase")
{
auto q = ObjQueue{ 3, 2, 1 };
const auto iter = q.erase(q.cbegin() + 1);
CHECK_EQ(*iter, 1);
CHECK_EQ(q.size(), 2);
REQUIRE(*iter == 1);
REQUIRE(q.size() == 2);
}
TEST_CASE("capacity")
{
auto q = ObjQueue();
q.reserve(10);
CHECK_EQ(q.size(), 0);
CHECK_GE(q.capacity(), 10);
REQUIRE(q.size() == 0);
REQUIRE(q.capacity() >= 10);
}
TEST_CASE("comparison")
{
CHECK_EQ(ObjQueue{}, ObjQueue{});
REQUIRE(ObjQueue{} == ObjQueue{});
auto q1 = ObjQueue{ 1, 2, 3 };
CHECK_EQ(q1, q1);
CHECK_NE(q1, ObjQueue{});
REQUIRE(q1 == q1);
REQUIRE(q1 != ObjQueue{});
auto q2 = q1;
CHECK_EQ(q1, q2);
REQUIRE(q1 == q2);
q2.reserve(10);
CHECK_EQ(q1, q2);
REQUIRE(q1 == q2);
}
TEST_CASE("contains")
{
const auto q = ObjQueue{ 1, 9, 3 };
CHECK(q.contains(3));
CHECK_FALSE(q.contains(0));
REQUIRE(q.contains(3));
REQUIRE_FALSE(q.contains(0));
}
}

View File

@ -10,7 +10,7 @@
#include <filesystem>
#include <string>
#include <doctest/doctest.h>
#include <catch2/catch_all.hpp>
#include "solv-cpp/pool.hpp"
#include "solv-cpp/repo.hpp"
@ -49,24 +49,24 @@ struct TmpDir
}
};
TEST_SUITE("solv::ObjRepo")
namespace
{
TEST_CASE("Construct a repo")
{
auto pool = ObjPool();
auto [repo_id, repo] = pool.add_repo("test-forge");
CHECK_EQ(repo.id(), repo_id);
CHECK_EQ(repo.name(), "test-forge");
REQUIRE(repo.id() == repo_id);
REQUIRE(repo.name() == "test-forge");
SUBCASE("Fetch the repo")
SECTION("Fetch the repo")
{
REQUIRE(pool.has_repo(repo_id));
auto repo_alt = pool.get_repo(repo_id).value();
CHECK_EQ(repo_alt.name(), repo.name());
CHECK_EQ(repo_alt.id(), repo.id());
REQUIRE(repo_alt.name() == repo.name());
REQUIRE(repo_alt.id() == repo.id());
}
SUBCASE("Set attributes")
SECTION("Set attributes")
{
repo.set_url("https://repo.mamba.pm/conda-forge");
repo.set_etag(R"(etag)W/"8eea3023872b68ef71fd930472a15599"(etag)");
@ -76,73 +76,73 @@ TEST_SUITE("solv::ObjRepo")
repo.set_pip_added(true);
repo.set_tool_version("1.2.3.4");
SUBCASE("Empty without internalize")
SECTION("Empty without internalize")
{
CHECK_EQ(repo.url(), "");
CHECK_EQ(repo.etag(), "");
CHECK_EQ(repo.mod(), "");
CHECK_EQ(repo.channel(), "");
CHECK_EQ(repo.subdir(), "");
CHECK_EQ(repo.pip_added(), false);
CHECK_EQ(repo.tool_version(), "");
REQUIRE(repo.url() == "");
REQUIRE(repo.etag() == "");
REQUIRE(repo.mod() == "");
REQUIRE(repo.channel() == "");
REQUIRE(repo.subdir() == "");
REQUIRE(repo.pip_added() == false);
REQUIRE(repo.tool_version() == "");
}
SUBCASE("Internalize and get attributes")
SECTION("Internalize and get attributes")
{
repo.internalize();
CHECK_EQ(repo.url(), "https://repo.mamba.pm/conda-forge");
CHECK_EQ(repo.channel(), "conda-forge");
CHECK_EQ(repo.subdir(), "noarch");
CHECK_EQ(repo.etag(), R"(etag)W/"8eea3023872b68ef71fd930472a15599"(etag)");
CHECK_EQ(repo.mod(), "Tue, 25 Apr 2023 11:48:37 GMT");
CHECK_EQ(repo.pip_added(), true);
CHECK_EQ(repo.tool_version(), "1.2.3.4");
REQUIRE(repo.url() == "https://repo.mamba.pm/conda-forge");
REQUIRE(repo.channel() == "conda-forge");
REQUIRE(repo.subdir() == "noarch");
REQUIRE(repo.etag() == R"(etag)W/"8eea3023872b68ef71fd930472a15599"(etag)");
REQUIRE(repo.mod() == "Tue, 25 Apr 2023 11:48:37 GMT");
REQUIRE(repo.pip_added() == true);
REQUIRE(repo.tool_version() == "1.2.3.4");
SUBCASE("Override attribute")
SECTION("Override attribute")
{
repo.set_subdir("linux-64");
CHECK_EQ(repo.subdir(), "noarch");
REQUIRE(repo.subdir() == "noarch");
repo.internalize();
CHECK_EQ(repo.subdir(), "linux-64");
REQUIRE(repo.subdir() == "linux-64");
}
}
}
SUBCASE("Add solvables")
SECTION("Add solvables")
{
CHECK_EQ(repo.solvable_count(), 0);
REQUIRE(repo.solvable_count() == 0);
const auto [id1, s1] = repo.add_solvable();
REQUIRE(repo.get_solvable(id1).has_value());
CHECK_EQ(repo.get_solvable(id1)->raw(), s1.raw());
CHECK_EQ(repo.solvable_count(), 1);
CHECK(repo.has_solvable(id1));
REQUIRE(repo.get_solvable(id1)->raw() == s1.raw());
REQUIRE(repo.solvable_count() == 1);
REQUIRE(repo.has_solvable(id1));
const auto [id2, s2] = repo.add_solvable();
CHECK_EQ(repo.solvable_count(), 2);
CHECK(repo.has_solvable(id2));
REQUIRE(repo.solvable_count() == 2);
REQUIRE(repo.has_solvable(id2));
SUBCASE("Retrieve repo from solvable")
SECTION("Retrieve repo from solvable")
{
CHECK_EQ(ObjRepoViewConst::of_solvable(s1).raw(), repo.raw());
REQUIRE(ObjRepoViewConst::of_solvable(s1).raw() == repo.raw());
}
SUBCASE("Iterate over solvables")
SECTION("Iterate over solvables")
{
SUBCASE("Over all solvables")
SECTION("Over all solvables")
{
const auto ids = std::array{ id1, id2 };
std::size_t n_solvables = 0;
repo.for_each_solvable_id(
[&](SolvableId id)
{
CHECK_NE(std::find(ids.cbegin(), ids.cend(), id), ids.cend());
REQUIRE(std::find(ids.cbegin(), ids.cend(), id) != ids.cend());
n_solvables++;
}
);
CHECK_EQ(n_solvables, repo.solvable_count());
REQUIRE(n_solvables == repo.solvable_count());
}
SUBCASE("Over one solvable then break")
SECTION("Over one solvable then break")
{
std::size_t n_solvables = 0;
repo.for_each_solvable(
@ -152,56 +152,56 @@ TEST_SUITE("solv::ObjRepo")
return LoopControl::Break;
}
);
CHECK_EQ(n_solvables, 1);
REQUIRE(n_solvables == 1);
}
}
SUBCASE("Get inexisting solvable")
SECTION("Get inexisting solvable")
{
CHECK_FALSE(repo.has_solvable(1234));
CHECK_FALSE(repo.get_solvable(1234).has_value());
REQUIRE_FALSE(repo.has_solvable(1234));
REQUIRE_FALSE(repo.get_solvable(1234).has_value());
}
SUBCASE("Remove solvable")
SECTION("Remove solvable")
{
CHECK(repo.remove_solvable(id2, true));
CHECK_FALSE(repo.has_solvable(id2));
CHECK(repo.has_solvable(id1));
CHECK_EQ(repo.solvable_count(), 1);
REQUIRE(repo.remove_solvable(id2, true));
REQUIRE_FALSE(repo.has_solvable(id2));
REQUIRE(repo.has_solvable(id1));
REQUIRE(repo.solvable_count() == 1);
}
SUBCASE("Confuse ids from another repo")
SECTION("Confuse ids from another repo")
{
auto [other_repo_id, other_repo] = pool.add_repo("other-repo");
auto [other_id, other_s] = other_repo.add_solvable();
CHECK_FALSE(repo.has_solvable(other_id));
CHECK_FALSE(repo.get_solvable(other_id).has_value());
CHECK_FALSE(repo.remove_solvable(other_id, true));
REQUIRE_FALSE(repo.has_solvable(other_id));
REQUIRE_FALSE(repo.get_solvable(other_id).has_value());
REQUIRE_FALSE(repo.remove_solvable(other_id, true));
}
SUBCASE("Clear solvables")
SECTION("Clear solvables")
{
repo.clear(true);
CHECK_EQ(repo.solvable_count(), 0);
CHECK_FALSE(repo.has_solvable(id1));
CHECK_FALSE(repo.get_solvable(id1).has_value());
REQUIRE(repo.solvable_count() == 0);
REQUIRE_FALSE(repo.has_solvable(id1));
REQUIRE_FALSE(repo.get_solvable(id1).has_value());
}
SUBCASE("Write repo to file")
SECTION("Write repo to file")
{
// Using only C OS encoding API for test.
auto dir = TmpDir();
const auto solv_file = (dir.path / "test-forge.solv").string();
{
std::FILE* fptr = std::fopen(solv_file.c_str(), "wb");
REQUIRE_NE(fptr, nullptr);
REQUIRE(fptr != nullptr);
const auto written = repo.write(fptr);
REQUIRE(written);
REQUIRE_EQ(std::fclose(fptr), 0);
REQUIRE(std::fclose(fptr) == 0);
}
SUBCASE("Read repo from file")
SECTION("Read repo from file")
{
// Delete repo
const auto n_solvables = repo.solvable_count();
@ -210,15 +210,15 @@ TEST_SUITE("solv::ObjRepo")
// Create new repo from file
auto [repo_id2, repo2] = pool.add_repo("test-forge");
std::FILE* fptr = std::fopen(solv_file.c_str(), "rb");
REQUIRE_NE(fptr, nullptr);
REQUIRE(fptr != nullptr);
const auto read = repo2.read(fptr);
REQUIRE(read);
REQUIRE_EQ(std::fclose(fptr), 0);
REQUIRE(std::fclose(fptr) == 0);
CHECK_EQ(repo2.solvable_count(), n_solvables);
REQUIRE(repo2.solvable_count() == n_solvables);
// True because we reused ids
CHECK(repo2.has_solvable(id1));
CHECK(repo2.has_solvable(id2));
REQUIRE(repo2.has_solvable(id1));
REQUIRE(repo2.has_solvable(id2));
}
}
}

View File

@ -4,7 +4,7 @@
//
// The full license is in the file LICENSE, distributed with this software.
#include <doctest/doctest.h>
#include <catch2/catch_all.hpp>
#include <solv/solver.h>
#include "solv-cpp/pool.hpp"
@ -17,7 +17,7 @@
using namespace solv;
using namespace solv::test;
TEST_SUITE("solv::scenariso")
namespace
{
TEST_CASE("Solving")
{
@ -35,65 +35,65 @@ TEST_SUITE("solv::scenariso")
auto [installed_id, repo_installed] = pool.add_repo("installed");
pool.set_installed_repo(installed_id);
SUBCASE(R"(Installed package "a")")
SECTION(R"(Installed package "a")")
{
const auto ia1 = add_simple_package(pool, repo_installed, SimplePkg{ "a", "1.0" });
repo_installed.internalize();
auto solver = ObjSolver(pool);
SUBCASE("Already statifies iteslf")
SECTION("Already statifies iteslf")
{
auto jobs = ObjQueue{
SOLVER_INSTALL | SOLVER_SOLVABLE_PROVIDES,
pool.add_conda_dependency("a"),
};
CHECK(solver.solve(pool, jobs));
REQUIRE(solver.solve(pool, jobs));
auto trans = ObjTransaction::from_solver(pool, solver);
// Outcome: nothing
CHECK(trans.steps().empty());
REQUIRE(trans.steps().empty());
}
SUBCASE("Already satisfies dependency")
SECTION("Already satisfies dependency")
{
auto jobs = ObjQueue{
SOLVER_INSTALL | SOLVER_SOLVABLE_PROVIDES,
pool.add_conda_dependency("b==1.0"),
};
CHECK(solver.solve(pool, jobs));
REQUIRE(solver.solve(pool, jobs));
auto trans = ObjTransaction::from_solver(pool, solver);
// Outcome: install only b 1.0
CHECK_EQ(trans.steps(), ObjQueue{ fb1 });
REQUIRE(trans.steps() == ObjQueue{ fb1 });
}
SUBCASE("Is not removed when not needed even with ALLOW_UNINSTALL")
SECTION("Is not removed when not needed even with ALLOW_UNINSTALL")
{
auto jobs = ObjQueue{
SOLVER_INSTALL | SOLVER_SOLVABLE_PROVIDES,
pool.add_conda_dependency("b==2.0"),
};
solver.set_flag(SOLVER_FLAG_ALLOW_UNINSTALL, true);
CHECK(solver.solve(pool, jobs));
REQUIRE(solver.solve(pool, jobs));
auto trans = ObjTransaction::from_solver(pool, solver);
// Outcome: install b 2.0, leave a
CHECK_EQ(trans.steps(), ObjQueue{ fb2 });
REQUIRE(trans.steps() == ObjQueue{ fb2 });
}
SUBCASE("Gets upgraded as a dependency")
SECTION("Gets upgraded as a dependency")
{
auto jobs = ObjQueue{
SOLVER_INSTALL | SOLVER_SOLVABLE_PROVIDES,
pool.add_conda_dependency("c==1.0"),
};
CHECK(solver.solve(pool, jobs));
REQUIRE(solver.solve(pool, jobs));
auto trans = ObjTransaction::from_solver(pool, solver);
CHECK_EQ(trans.steps().size(), 3);
CHECK(trans.steps().contains(ia1)); // Remove a 1.0
CHECK(trans.steps().contains(fa2)); // Install a 2.0
CHECK(trans.steps().contains(fc1)); // Install c 1.0
REQUIRE(trans.steps().size() == 3);
REQUIRE(trans.steps().contains(ia1)); // Remove a 1.0
REQUIRE(trans.steps().contains(fa2)); // Install a 2.0
REQUIRE(trans.steps().contains(fc1)); // Install c 1.0
}
SUBCASE("Fails to upgrade when lock even with ALLOW_UNINSTALL")
SECTION("Fails to upgrade when lock even with ALLOW_UNINSTALL")
{
auto jobs = ObjQueue{
SOLVER_LOCK | SOLVER_SOLVABLE_PROVIDES,
@ -102,27 +102,27 @@ TEST_SUITE("solv::scenariso")
pool.add_conda_dependency("c==1.0"),
};
solver.set_flag(SOLVER_FLAG_ALLOW_UNINSTALL, true);
CHECK_FALSE(solver.solve(pool, jobs));
REQUIRE_FALSE(solver.solve(pool, jobs));
}
}
SUBCASE(R"(Installed package "a" get downgraded by dependency)")
SECTION(R"(Installed package "a" get downgraded by dependency)")
{
const auto ia2 = add_simple_package(pool, repo_installed, SimplePkg{ "a", "2.0" });
repo_installed.internalize();
auto solver = ObjSolver(pool);
SUBCASE("Fails by default")
SECTION("Fails by default")
{
auto jobs = ObjQueue{
SOLVER_INSTALL | SOLVER_SOLVABLE_PROVIDES,
pool.add_conda_dependency("c==2.0"),
};
CHECK_FALSE(solver.solve(pool, jobs));
REQUIRE_FALSE(solver.solve(pool, jobs));
}
SUBCASE("Succeeds with ALLOW_DOWNGRADE or ALLOW_UNINSTALL")
SECTION("Succeeds with ALLOW_DOWNGRADE or ALLOW_UNINSTALL")
{
for (const auto flag : { SOLVER_FLAG_ALLOW_DOWNGRADE, SOLVER_FLAG_ALLOW_UNINSTALL })
{
@ -131,12 +131,12 @@ TEST_SUITE("solv::scenariso")
SOLVER_INSTALL | SOLVER_SOLVABLE_PROVIDES,
pool.add_conda_dependency("c==2.0"),
};
CHECK(solver.solve(pool, jobs));
REQUIRE(solver.solve(pool, jobs));
auto trans = ObjTransaction::from_solver(pool, solver);
CHECK_EQ(trans.steps().size(), 3);
CHECK(trans.steps().contains(ia2)); // Remove a 2.0
CHECK(trans.steps().contains(fa1)); // Install a 1.0
CHECK(trans.steps().contains(fc2)); // Install c 2.0
REQUIRE(trans.steps().size() == 3);
REQUIRE(trans.steps().contains(ia2)); // Remove a 2.0
REQUIRE(trans.steps().contains(fa1)); // Install a 1.0
REQUIRE(trans.steps().contains(fc2)); // Install c 2.0
}
}
}
@ -154,28 +154,28 @@ TEST_SUITE("solv::scenariso")
const auto a_solv_id = add_simple_package(pool, repo, SimplePkg{ "a", "1.0" });
repo.internalize();
SUBCASE("Direct job namespace dependency")
SECTION("Direct job namespace dependency")
{
SUBCASE("Which resolves to some packages")
SECTION("Which resolves to some packages")
{
bool called = false;
pool.set_namespace_callback(
[&, a_solv_id = a_solv_id](ObjPoolView, StringId name, StringId ver) noexcept -> OffsetId
{
called = true;
CHECK_EQ(name, dep_name_id);
CHECK_EQ(ver, dep_ver_id);
REQUIRE(name == dep_name_id);
REQUIRE(ver == dep_ver_id);
return pool.add_to_whatprovides_data({ a_solv_id });
}
);
auto solver = ObjSolver(pool);
auto solved = solver.solve(pool, { SOLVER_INSTALL, dep_id });
CHECK(solved);
CHECK(called);
REQUIRE(solved);
REQUIRE(called);
}
SUBCASE("Which is unsatisfyable")
SECTION("Which is unsatisfyable")
{
bool called = false;
pool.set_namespace_callback(
@ -188,11 +188,11 @@ TEST_SUITE("solv::scenariso")
auto solver = ObjSolver(pool);
auto solved = solver.solve(pool, { SOLVER_INSTALL, dep_id });
CHECK(called);
CHECK_FALSE(solved);
REQUIRE(called);
REQUIRE_FALSE(solved);
}
SUBCASE("Callback throws")
SECTION("Callback throws")
{
pool.set_namespace_callback(
[](ObjPoolView, StringId, StringId) -> OffsetId
@ -200,14 +200,14 @@ TEST_SUITE("solv::scenariso")
);
auto solver = ObjSolver(pool);
CHECK_THROWS_AS(
REQUIRE_THROWS_AS(
[&] { return solver.solve(pool, { SOLVER_INSTALL, dep_id }); }(),
std::runtime_error
);
}
}
SUBCASE("transitive job dependency")
SECTION("transitive job dependency")
{
// Add a dependency ``job==3.0``
const auto job_name_id = pool.add_string("job");
@ -222,26 +222,26 @@ TEST_SUITE("solv::scenariso")
job_solv.add_self_provide();
repo.internalize();
SUBCASE("Which resolves to some packages")
SECTION("Which resolves to some packages")
{
bool called = false;
pool.set_namespace_callback(
[&, a_solv_id = a_solv_id](ObjPoolView, StringId name, StringId ver) noexcept -> OffsetId
{
called = true;
CHECK_EQ(name, dep_name_id);
CHECK_EQ(ver, dep_ver_id);
REQUIRE(name == dep_name_id);
REQUIRE(ver == dep_ver_id);
return pool.add_to_whatprovides_data({ a_solv_id });
}
);
auto solver = ObjSolver(pool);
auto solved = solver.solve(pool, { SOLVER_INSTALL, job_id });
CHECK(called);
CHECK(solved);
REQUIRE(called);
REQUIRE(solved);
}
SUBCASE("Which is unsatisfyable")
SECTION("Which is unsatisfyable")
{
bool called = false;
pool.set_namespace_callback(
@ -254,11 +254,11 @@ TEST_SUITE("solv::scenariso")
auto solver = ObjSolver(pool);
auto solved = solver.solve(pool, { SOLVER_INSTALL, job_id });
CHECK(called);
CHECK_FALSE(solved);
REQUIRE(called);
REQUIRE_FALSE(solved);
}
SUBCASE("Callback throws")
SECTION("Callback throws")
{
pool.set_namespace_callback(
[](ObjPoolView, StringId, StringId) -> OffsetId
@ -266,7 +266,7 @@ TEST_SUITE("solv::scenariso")
);
auto solver = ObjSolver(pool);
CHECK_THROWS_AS(
REQUIRE_THROWS_AS(
[&] { return solver.solve(pool, { SOLVER_INSTALL, job_id }); }(),
std::runtime_error
);

View File

@ -4,7 +4,7 @@
//
// The full license is in the file LICENSE, distributed with this software.
#include <doctest/doctest.h>
#include <catch2/catch_all.hpp>
#include "solv-cpp/pool.hpp"
#include "solv-cpp/repo.hpp"
@ -12,32 +12,32 @@
using namespace solv;
TEST_SUITE("solv::ObjSolvable")
namespace
{
TEST_CASE("Create a solvable")
{
auto pool = ObjPool();
auto [repo_id, repo] = pool.add_repo("test-forge");
const auto [solv_id, solv] = repo.add_solvable();
CHECK_EQ(solv_id, solv.id());
REQUIRE(solv_id == solv.id());
SUBCASE("Set name and version")
SECTION("Set name and version")
{
solv.set_name("my-package");
solv.set_version("0.1.1");
CHECK_EQ(solv.name(), "my-package");
CHECK_EQ(solv.version(), "0.1.1");
REQUIRE(solv.name() == "my-package");
REQUIRE(solv.version() == "0.1.1");
SUBCASE("Change name version")
SECTION("Change name version")
{
solv.set_name("other-package");
solv.set_version("0.2.2");
CHECK_EQ(solv.name(), "other-package");
CHECK_EQ(solv.version(), "0.2.2");
REQUIRE(solv.name() == "other-package");
REQUIRE(solv.version() == "0.2.2");
}
}
SUBCASE("Set attributes")
SECTION("Set attributes")
{
solv.set_build_number(33);
solv.set_build_string("build");
@ -56,229 +56,228 @@ TEST_SUITE("solv::ObjSolvable")
solv.set_platform("linux-64");
solv.set_type(SolvableType::Virtualpackage);
SUBCASE("Empty without internalize")
SECTION("Empty without internalize")
{
CHECK_EQ(solv.build_number(), 0);
CHECK_EQ(solv.build_string(), "");
CHECK_EQ(solv.file_name(), "");
CHECK_EQ(solv.license(), "");
CHECK_EQ(solv.md5(), "");
CHECK_EQ(solv.sha256(), "");
CHECK_EQ(solv.signatures(), "");
CHECK_EQ(solv.noarch(), "");
CHECK_EQ(solv.size(), 0);
CHECK_EQ(solv.timestamp(), 0);
CHECK_EQ(solv.url(), "");
CHECK_EQ(solv.channel(), "");
CHECK_EQ(solv.platform(), "");
CHECK_EQ(solv.type(), SolvableType::Package);
REQUIRE(solv.build_number() == 0);
REQUIRE(solv.build_string() == "");
REQUIRE(solv.file_name() == "");
REQUIRE(solv.license() == "");
REQUIRE(solv.md5() == "");
REQUIRE(solv.sha256() == "");
REQUIRE(solv.signatures() == "");
REQUIRE(solv.noarch() == "");
REQUIRE(solv.size() == 0);
REQUIRE(solv.timestamp() == 0);
REQUIRE(solv.url() == "");
REQUIRE(solv.channel() == "");
REQUIRE(solv.platform() == "");
REQUIRE(solv.type() == SolvableType::Package);
}
SUBCASE("Internalize and get attributes")
SECTION("Internalize and get attributes")
{
repo.internalize();
CHECK_EQ(solv.build_string(), "build");
CHECK_EQ(solv.build_number(), 33);
CHECK_EQ(solv.build_string(), "build");
CHECK_EQ(solv.file_name(), "file.tar.gz");
CHECK_EQ(solv.license(), "MIT");
CHECK_EQ(solv.md5(), "6f29ba77e8b03b191c9d667f331bf2a0");
CHECK_EQ(
solv.sha256(),
"ecde63af23e0d49c0ece19ec539d873ea408a6f966d3126994c6d33ae1b9d3f7"
REQUIRE(solv.build_string() == "build");
REQUIRE(solv.build_number() == 33);
REQUIRE(solv.build_string() == "build");
REQUIRE(solv.file_name() == "file.tar.gz");
REQUIRE(solv.license() == "MIT");
REQUIRE(solv.md5() == "6f29ba77e8b03b191c9d667f331bf2a0");
REQUIRE(
solv.sha256() == "ecde63af23e0d49c0ece19ec539d873ea408a6f966d3126994c6d33ae1b9d3f7"
);
CHECK_EQ(
solv.signatures(),
R"("signatures": { "some_file.tar.bz2": { "a133184c9c7a651f55db194031a6c1240b798333923dc9319d1fe2c94a1242d": { "signature": "7a67a875d0454c14671d960a02858e059d154876dab6b3873304a27102063c9c25"}}})"
REQUIRE(
solv.signatures()
== R"("signatures": { "some_file.tar.bz2": { "a133184c9c7a651f55db194031a6c1240b798333923dc9319d1fe2c94a1242d": { "signature": "7a67a875d0454c14671d960a02858e059d154876dab6b3873304a27102063c9c25"}}})"
);
CHECK_EQ(solv.noarch(), "python");
CHECK_EQ(solv.size(), 2345);
CHECK_EQ(solv.timestamp(), 4110596167);
CHECK_EQ(solv.url(), "https://conda.anaconda.org/conda-forge/linux-64");
CHECK_EQ(solv.channel(), "conda-forge");
CHECK_EQ(solv.platform(), "linux-64");
CHECK_EQ(solv.type(), SolvableType::Virtualpackage);
REQUIRE(solv.noarch() == "python");
REQUIRE(solv.size() == 2345);
REQUIRE(solv.timestamp() == 4110596167);
REQUIRE(solv.url() == "https://conda.anaconda.org/conda-forge/linux-64");
REQUIRE(solv.channel() == "conda-forge");
REQUIRE(solv.platform() == "linux-64");
REQUIRE(solv.type() == SolvableType::Virtualpackage);
SUBCASE("Override attribute")
SECTION("Override attribute")
{
solv.set_license("GPL");
CHECK_EQ(solv.license(), "MIT");
REQUIRE(solv.license() == "MIT");
repo.internalize();
CHECK_EQ(solv.license(), "GPL");
REQUIRE(solv.license() == "GPL");
}
}
}
SUBCASE("Get unset attributes")
SECTION("Get unset attributes")
{
CHECK_EQ(solv.name(), "");
CHECK_EQ(solv.version(), "");
CHECK_EQ(solv.build_number(), 0);
CHECK_EQ(solv.build_string(), "");
CHECK_EQ(solv.file_name(), "");
CHECK_EQ(solv.license(), "");
CHECK_EQ(solv.md5(), "");
CHECK_EQ(solv.sha256(), "");
CHECK_EQ(solv.signatures(), "");
CHECK_EQ(solv.noarch(), "");
CHECK_EQ(solv.size(), 0);
CHECK_EQ(solv.timestamp(), 0);
CHECK_EQ(solv.url(), "");
CHECK_EQ(solv.channel(), "");
CHECK_EQ(solv.platform(), "");
CHECK_EQ(solv.type(), SolvableType::Package);
REQUIRE(solv.name() == "");
REQUIRE(solv.version() == "");
REQUIRE(solv.build_number() == 0);
REQUIRE(solv.build_string() == "");
REQUIRE(solv.file_name() == "");
REQUIRE(solv.license() == "");
REQUIRE(solv.md5() == "");
REQUIRE(solv.sha256() == "");
REQUIRE(solv.signatures() == "");
REQUIRE(solv.noarch() == "");
REQUIRE(solv.size() == 0);
REQUIRE(solv.timestamp() == 0);
REQUIRE(solv.url() == "");
REQUIRE(solv.channel() == "");
REQUIRE(solv.platform() == "");
REQUIRE(solv.type() == SolvableType::Package);
}
SUBCASE("Add dependency")
SECTION("Add dependency")
{
solv.add_dependency(33);
CHECK_EQ(solv.dependencies(), ObjQueue{ 33 });
REQUIRE(solv.dependencies() == ObjQueue{ 33 });
SUBCASE("Add more dependencies")
SECTION("Add more dependencies")
{
solv.add_dependencies(ObjQueue{ 44, 22 });
CHECK_EQ(solv.dependencies(), ObjQueue{ 33, 44, 22 });
REQUIRE(solv.dependencies() == ObjQueue{ 33, 44, 22 });
}
SUBCASE("Reset dependencies")
SECTION("Reset dependencies")
{
solv.set_dependencies({});
CHECK(solv.dependencies().empty());
REQUIRE(solv.dependencies().empty());
}
SUBCASE("Dependencies with markers")
SECTION("Dependencies with markers")
{
solv.add_dependency(34);
solv.add_dependency(11, SOLVABLE_PREREQMARKER);
solv.add_dependency(35);
CHECK_EQ(solv.dependencies(-1), ObjQueue{ 33, 34 });
CHECK_EQ(solv.dependencies(0), ObjQueue{ 33, 34, SOLVABLE_PREREQMARKER, 11, 35 });
CHECK_EQ(solv.dependencies(1), ObjQueue{ 11, 35 });
CHECK_EQ(solv.dependencies(SOLVABLE_PREREQMARKER), ObjQueue{ 11, 35 });
REQUIRE(solv.dependencies(-1) == ObjQueue{ 33, 34 });
REQUIRE(solv.dependencies(0) == ObjQueue{ 33, 34, SOLVABLE_PREREQMARKER, 11, 35 });
REQUIRE(solv.dependencies(1) == ObjQueue{ 11, 35 });
REQUIRE(solv.dependencies(SOLVABLE_PREREQMARKER) == ObjQueue{ 11, 35 });
}
}
SUBCASE("Add provide")
SECTION("Add provide")
{
solv.add_provide(33);
CHECK_EQ(solv.provides(), ObjQueue{ 33 });
REQUIRE(solv.provides() == ObjQueue{ 33 });
SUBCASE("Add self provide")
SECTION("Add self provide")
{
solv.add_self_provide();
CHECK_EQ(solv.provides().size(), 2);
REQUIRE(solv.provides().size() == 2);
}
SUBCASE("Add more provides")
SECTION("Add more provides")
{
solv.add_provides(ObjQueue{ 44, 22 });
CHECK_EQ(solv.provides(), ObjQueue{ 33, 44, 22 });
REQUIRE(solv.provides() == ObjQueue{ 33, 44, 22 });
}
SUBCASE("Reset provides")
SECTION("Reset provides")
{
solv.set_provides({});
CHECK(solv.provides().empty());
REQUIRE(solv.provides().empty());
}
}
SUBCASE("Add constraint")
SECTION("Add constraint")
{
solv.add_constraint(33);
SUBCASE("Internalize and get constraint")
SECTION("Internalize and get constraint")
{
repo.internalize();
CHECK_EQ(solv.constraints(), ObjQueue{ 33 });
REQUIRE(solv.constraints() == ObjQueue{ 33 });
SUBCASE("Fail to add more constraint")
SECTION("Fail to add more constraint")
{
solv.add_constraint(44);
CHECK_EQ(solv.constraints(), ObjQueue{ 33 });
REQUIRE(solv.constraints() == ObjQueue{ 33 });
SUBCASE("Override when internalizing again")
SECTION("Override when internalizing again")
{
repo.internalize();
CHECK_EQ(solv.constraints(), ObjQueue{ 44 });
REQUIRE(solv.constraints() == ObjQueue{ 44 });
}
}
SUBCASE("Fail to set constraints")
SECTION("Fail to set constraints")
{
solv.set_constraints({ 22 });
CHECK_EQ(solv.constraints(), ObjQueue{ 33 });
REQUIRE(solv.constraints() == ObjQueue{ 33 });
SUBCASE("Override when internalizing again")
SECTION("Override when internalizing again")
{
repo.internalize();
CHECK_EQ(solv.constraints(), ObjQueue{ 22 });
REQUIRE(solv.constraints() == ObjQueue{ 22 });
}
}
}
SUBCASE("Add more constraints")
SECTION("Add more constraints")
{
solv.add_constraints(ObjQueue{ 44, 22 });
repo.internalize();
CHECK_EQ(solv.constraints(), ObjQueue{ 33, 44, 22 });
REQUIRE(solv.constraints() == ObjQueue{ 33, 44, 22 });
}
SUBCASE("Reset constraints")
SECTION("Reset constraints")
{
solv.set_constraints({});
repo.internalize();
CHECK(solv.constraints().empty());
REQUIRE(solv.constraints().empty());
}
}
SUBCASE("Track feature")
SECTION("Track feature")
{
const StringId feat1_id = solv.add_track_feature("feature1");
SUBCASE("Internalize and get tracked features")
SECTION("Internalize and get tracked features")
{
repo.internalize();
CHECK_EQ(solv.track_features(), ObjQueue{ feat1_id });
REQUIRE(solv.track_features() == ObjQueue{ feat1_id });
SUBCASE("Fail to track more features")
SECTION("Fail to track more features")
{
const StringId feat2_id = solv.add_track_feature("feature2");
CHECK_EQ(solv.track_features(), ObjQueue{ feat1_id });
REQUIRE(solv.track_features() == ObjQueue{ feat1_id });
SUBCASE("Override when internalizing again")
SECTION("Override when internalizing again")
{
repo.internalize();
CHECK_EQ(solv.track_features(), ObjQueue{ feat2_id });
REQUIRE(solv.track_features() == ObjQueue{ feat2_id });
}
}
SUBCASE("Fail to set tracked features")
SECTION("Fail to set tracked features")
{
solv.set_track_features({ 22 });
CHECK_EQ(solv.track_features(), ObjQueue{ feat1_id });
REQUIRE(solv.track_features() == ObjQueue{ feat1_id });
SUBCASE("Override when internalizing again")
SECTION("Override when internalizing again")
{
repo.internalize();
CHECK_EQ(solv.track_features(), ObjQueue{ 22 });
REQUIRE(solv.track_features() == ObjQueue{ 22 });
}
}
}
SUBCASE("Track more features")
SECTION("Track more features")
{
solv.add_track_features(ObjQueue{ 44, 11 });
repo.internalize();
CHECK_EQ(solv.track_features(), ObjQueue{ feat1_id, 44, 11 });
REQUIRE(solv.track_features() == ObjQueue{ feat1_id, 44, 11 });
}
SUBCASE("Reset tracked features")
SECTION("Reset tracked features")
{
solv.set_track_features({});
repo.internalize();
CHECK(solv.track_features().empty());
REQUIRE(solv.track_features().empty());
}
}
}

View File

@ -4,7 +4,7 @@
//
// The full license is in the file LICENSE, distributed with this software.
#include <doctest/doctest.h>
#include <catch2/catch_all.hpp>
#include <solv/solver.h>
#include "solv-cpp/pool.hpp"
@ -15,7 +15,7 @@
using namespace solv;
using namespace solv::test;
TEST_SUITE("solv::ObjSolver")
namespace
{
TEST_CASE("Create a solver")
{
@ -26,20 +26,20 @@ TEST_SUITE("solv::ObjSolver")
auto solver = ObjSolver(pool);
CHECK_EQ(solver.problem_count(), 0);
REQUIRE(solver.problem_count() == 0);
SUBCASE("Flag default value")
SECTION("Flag default value")
{
CHECK_FALSE(solver.get_flag(SOLVER_FLAG_ALLOW_DOWNGRADE));
REQUIRE_FALSE(solver.get_flag(SOLVER_FLAG_ALLOW_DOWNGRADE));
}
SUBCASE("Set flag")
SECTION("Set flag")
{
solver.set_flag(SOLVER_FLAG_ALLOW_DOWNGRADE, true);
CHECK(solver.get_flag(SOLVER_FLAG_ALLOW_DOWNGRADE));
REQUIRE(solver.get_flag(SOLVER_FLAG_ALLOW_DOWNGRADE));
}
SUBCASE("Solve successfully")
SECTION("Solve successfully")
{
// The job is matched with the ``provides`` field of the solvable
auto jobs = ObjQueue{
@ -48,11 +48,11 @@ TEST_SUITE("solv::ObjSolver")
SOLVER_INSTALL | SOLVER_SOLVABLE_PROVIDES,
pool.add_conda_dependency("icons=2.*"),
};
CHECK(solver.solve(pool, jobs));
CHECK_EQ(solver.problem_count(), 0);
REQUIRE(solver.solve(pool, jobs));
REQUIRE(solver.problem_count() == 0);
}
SUBCASE("Solve unsuccessfully with conflict")
SECTION("Solve unsuccessfully with conflict")
{
// The job is matched with the ``provides`` field of the solvable
auto jobs = ObjQueue{
@ -61,8 +61,8 @@ TEST_SUITE("solv::ObjSolver")
SOLVER_INSTALL | SOLVER_SOLVABLE_PROVIDES, pool.add_conda_dependency("intl=5.*"),
};
CHECK_FALSE(solver.solve(pool, jobs));
CHECK_NE(solver.problem_count(), 0);
REQUIRE_FALSE(solver.solve(pool, jobs));
REQUIRE(solver.problem_count() != 0);
auto all_rules = ObjQueue{};
solver.for_each_problem_id(
@ -72,10 +72,10 @@ TEST_SUITE("solv::ObjSolver")
all_rules.insert(all_rules.end(), pb_rules.cbegin(), pb_rules.cend());
}
);
CHECK_FALSE(all_rules.empty());
REQUIRE_FALSE(all_rules.empty());
}
SUBCASE("Solve unsuccessfully with missing package")
SECTION("Solve unsuccessfully with missing package")
{
// The job is matched with the ``provides`` field of the solvable
auto jobs = ObjQueue{
@ -83,8 +83,8 @@ TEST_SUITE("solv::ObjSolver")
pool.add_conda_dependency("does-not-exists"),
};
CHECK_FALSE(solver.solve(pool, jobs));
CHECK_NE(solver.problem_count(), 0);
REQUIRE_FALSE(solver.solve(pool, jobs));
REQUIRE(solver.problem_count() != 0);
auto all_rules = ObjQueue{};
solver.for_each_problem_id(
@ -94,7 +94,7 @@ TEST_SUITE("solv::ObjSolver")
all_rules.insert(all_rules.end(), pb_rules.cbegin(), pb_rules.cend());
}
);
CHECK_FALSE(all_rules.empty());
REQUIRE_FALSE(all_rules.empty());
}
}
}

View File

@ -6,7 +6,7 @@
#include <algorithm>
#include <doctest/doctest.h>
#include <catch2/catch_all.hpp>
#include <solv/solver.h>
#include <solv/transaction.h>
@ -20,7 +20,7 @@
using namespace solv;
using namespace solv::test;
TEST_SUITE("solv::ObjTransaction")
namespace
{
TEST_CASE("Create a transaction")
{
@ -29,50 +29,50 @@ TEST_SUITE("solv::ObjTransaction")
const auto pkg_to_id = add_simple_packages(pool, repo, make_packages());
repo.internalize();
SUBCASE("From single packages")
SECTION("From single packages")
{
SUBCASE("Add not installed package")
SECTION("Add not installed package")
{
pool.create_whatprovides();
const auto id = pkg_to_id.at({ "menu", "1.5.0", { "dropdown=2.*" } });
auto trans = ObjTransaction::from_solvables(pool, { id });
CHECK_EQ(trans.steps(), ObjQueue{ id });
CHECK_EQ(trans.step_type(pool, id), SOLVER_TRANSACTION_INSTALL);
REQUIRE(trans.steps() == ObjQueue{ id });
REQUIRE(trans.step_type(pool, id) == SOLVER_TRANSACTION_INSTALL);
}
SUBCASE("Ignore removing not installed package")
SECTION("Ignore removing not installed package")
{
pool.create_whatprovides();
const auto id = pkg_to_id.at({ "menu", "1.5.0", { "dropdown=2.*" } });
// Negative id means remove
auto trans = ObjTransaction::from_solvables(pool, { -id });
CHECK(trans.empty());
CHECK_EQ(trans.step_type(pool, id), SOLVER_TRANSACTION_IGNORE);
REQUIRE(trans.empty());
REQUIRE(trans.step_type(pool, id) == SOLVER_TRANSACTION_IGNORE);
}
SUBCASE("Ignore adding installed package")
SECTION("Ignore adding installed package")
{
const auto id = pkg_to_id.at({ "menu", "1.5.0", { "dropdown=2.*" } });
pool.set_installed_repo(repo_id);
pool.create_whatprovides();
auto trans = ObjTransaction::from_solvables(pool, { id });
CHECK(trans.empty());
CHECK_EQ(trans.step_type(pool, id), SOLVER_TRANSACTION_IGNORE);
REQUIRE(trans.empty());
REQUIRE(trans.step_type(pool, id) == SOLVER_TRANSACTION_IGNORE);
}
SUBCASE("Remove installed package")
SECTION("Remove installed package")
{
const auto id = pkg_to_id.at({ "menu", "1.5.0", { "dropdown=2.*" } });
pool.set_installed_repo(repo_id);
pool.create_whatprovides();
// Negative id means remove
auto trans = ObjTransaction::from_solvables(pool, { -id });
CHECK_EQ(trans.steps(), ObjQueue{ id });
CHECK_EQ(trans.step_type(pool, id), SOLVER_TRANSACTION_ERASE);
REQUIRE(trans.steps() == ObjQueue{ id });
REQUIRE(trans.step_type(pool, id) == SOLVER_TRANSACTION_ERASE);
}
}
SUBCASE("From a list of package to install")
SECTION("From a list of package to install")
{
pool.create_whatprovides();
const auto solvables = ObjQueue{
@ -82,24 +82,24 @@ TEST_SUITE("solv::ObjTransaction")
};
auto trans = ObjTransaction::from_solvables(pool, solvables);
CHECK_FALSE(trans.empty());
CHECK_EQ(trans.size(), solvables.size());
CHECK_EQ(trans.steps(), solvables);
REQUIRE_FALSE(trans.empty());
REQUIRE(trans.size() == solvables.size());
REQUIRE(trans.steps() == solvables);
SUBCASE("Copy transaction")
SECTION("Copy transaction")
{
const auto copy = trans;
CHECK_EQ(copy.steps(), solvables);
REQUIRE(copy.steps() == solvables);
}
SUBCASE("Order the solvables")
SECTION("Order the solvables")
{
trans.order(pool);
CHECK_EQ(trans.steps(), ObjQueue{ solvables.crbegin(), solvables.crend() });
REQUIRE(trans.steps() == ObjQueue{ solvables.crbegin(), solvables.crend() });
}
}
SUBCASE("From a solver run")
SECTION("From a solver run")
{
auto [installed_id, installed] = pool.add_repo("installed");
const auto icons_id = add_simple_package(pool, installed, { "icons", "1.0.0" });
@ -110,22 +110,22 @@ TEST_SUITE("solv::ObjTransaction")
auto solver = ObjSolver(pool);
REQUIRE(solver.solve(pool, { SOLVER_INSTALL, pool.add_conda_dependency("menu>=1.4") }));
auto trans = ObjTransaction::from_solver(pool, solver);
CHECK_FALSE(trans.empty());
CHECK_EQ(trans.size(), 4);
REQUIRE_FALSE(trans.empty());
REQUIRE(trans.size() == 4);
SUBCASE("Outdated installed package is updated")
SECTION("Outdated installed package is updated")
{
CHECK(trans.steps().contains(icons_id));
CHECK_EQ(trans.step_type(pool, icons_id), SOLVER_TRANSACTION_UPGRADED);
REQUIRE(trans.steps().contains(icons_id));
REQUIRE(trans.step_type(pool, icons_id) == SOLVER_TRANSACTION_UPGRADED);
// The solvable id that upgrades ``icons_id``
const auto maybe_icons_update_id = trans.step_newer(pool, icons_id);
REQUIRE(maybe_icons_update_id.has_value());
CHECK(trans.steps().contains(maybe_icons_update_id.value()));
REQUIRE(trans.steps().contains(maybe_icons_update_id.value()));
// The solvable id that isupgraded by ``icons_id``
CHECK_EQ(trans.step_olders(pool, maybe_icons_update_id.value()), ObjQueue{ icons_id });
REQUIRE(trans.step_olders(pool, maybe_icons_update_id.value()) == ObjQueue{ icons_id });
}
SUBCASE("Classify the transaction elements")
SECTION("Classify the transaction elements")
{
auto solvables = ObjQueue();
@ -150,7 +150,7 @@ TEST_SUITE("solv::ObjTransaction")
std::sort(solvables.begin(), solvables.end());
auto steps = trans.steps();
std::sort(steps.begin(), steps.end());
CHECK_EQ(solvables, steps);
REQUIRE(solvables == steps);
}
}
}

View File

@ -12,6 +12,10 @@ set(
LIBMAMBA_TEST_SRCS
include/mambatests.hpp
src/test_main.cpp
# Catch utils
src/catch-utils/conda_url.hpp
src/catch-utils/msvc_catch_byte.cpp
src/catch-utils/msvc_catch_string_view.cpp
# Utility library
src/util/test_cast.cpp
src/util/test_compare.cpp
@ -27,14 +31,14 @@ set(
src/util/test_os_osx.cpp
src/util/test_os_unix.cpp
src/util/test_os_win.cpp
src/util/test_path_manip.cpp
src/util/test_parsers.cpp
src/util/test_path_manip.cpp
src/util/test_random.cpp
src/util/test_string.cpp
src/util/test_tuple_hash.cpp
src/util/test_type_traits.cpp
src/util/test_url.cpp
src/util/test_url_manip.cpp
src/util/test_url.cpp
src/util/test_weakening_map.cpp
# Implementation of version and matching specs
src/specs/test_archive.cpp
@ -103,13 +107,16 @@ target_include_directories(
"${CMAKE_SOURCE_DIR}/libmamba/src"
)
find_package(doctest REQUIRED)
find_package(Catch2 REQUIRED)
find_package(Threads REQUIRED)
target_link_libraries(
test_libmamba
PUBLIC mamba::libmamba reproc reproc++
PRIVATE doctest::doctest Threads::Threads
PRIVATE Catch2::Catch2WithMain Threads::Threads
)
set_target_properties(
test_libmamba PROPERTIES COMPILE_DEFINITIONS CATCH_CONFIG_ENABLE_ALL_STRINGMAKERS
)
# Copy data directory into binary dir to avoid modifications
@ -126,10 +133,8 @@ add_dependencies(test_libmamba test_libmamba_data)
target_compile_definitions(
test_libmamba
PRIVATE
DOCTEST_CONFIG_USE_STD_HEADERS
MAMBA_TEST_DATA_DIR="${CMAKE_CURRENT_BINARY_DIR}/data"
MAMBA_TEST_LOCK_EXE="$<TARGET_FILE:testing_libmamba_lock>"
PRIVATE MAMBA_TEST_DATA_DIR="${CMAKE_CURRENT_BINARY_DIR}/data"
MAMBA_TEST_LOCK_EXE="$<TARGET_FILE:testing_libmamba_lock>"
)
target_compile_features(test_libmamba PUBLIC cxx_std_17)

View File

@ -3,19 +3,22 @@
// Distributed under the terms of the BSD 3-Clause License.
//
// The full license is in the file LICENSE, distributed with this software.
#pragma once
#include <doctest/doctest.h>
#include <string>
#include <catch2/catch_tostring.hpp>
#include "mamba/specs/conda_url.hpp"
namespace doctest
namespace Catch
{
template <>
struct StringMaker<mamba::specs::CondaURL>
{
static auto convert(const mamba::specs::CondaURL& value) -> String
static std::string convert(const mamba::specs::CondaURL& value)
{
return { value.str().c_str() };
return value.str();
}
};
}

View File

@ -0,0 +1,22 @@
#ifdef _WIN32
// Catch compiled on `conda-forge` for MSVC doesn't support outputting `std::byte`.
// So we have to define StringMaker for it ourselves.
// The declaration is present though, so this only causes link errors.
#include <string>
#include <catch2/catch_tostring.hpp>
#include <fmt/format.h>
namespace Catch
{
std::string StringMaker<std::byte>::convert(std::byte value)
{
return fmt::format("{}", value);
}
}
#endif

View File

@ -0,0 +1,22 @@
#ifdef _WIN32
// Catch compiled on `conda-forge` for MSVC doesn't support outputting `string_view`.
// So we have to define StringMaker for it ourselves.
// The declaration is present though, so this only causes link errors.
#include <string>
#include <string_view>
#include <catch2/catch_tostring.hpp>
namespace Catch
{
std::string StringMaker<std::string_view>::convert(std::string_view str)
{
return std::string(str);
}
}
#endif

View File

@ -1,4 +1,4 @@
#include <doctest/doctest.h>
#include <catch2/catch_all.hpp>
#include "mamba/core/activation.hpp"
#include "mamba/core/context.hpp"
@ -7,7 +7,7 @@
namespace mamba
{
TEST_SUITE("activation")
namespace
{
TEST_CASE("activation")
{

View File

@ -4,7 +4,7 @@
//
// The full license is in the file LICENSE, distributed with this software.
#include <doctest/doctest.h>
#include <catch2/catch_all.hpp>
#include "mamba/core/channel_context.hpp"
#include "mamba/core/context.hpp"
@ -13,12 +13,11 @@
#include "mamba/util/flat_set.hpp"
#include "mamba/util/url_manip.hpp"
#include "doctest-printer/conda_url.hpp"
#include "doctest-printer/flat_set.hpp"
#include "catch-utils/conda_url.hpp"
#include "mambatests.hpp"
TEST_SUITE("ChannelContext")
namespace
{
using namespace mamba;
@ -33,29 +32,29 @@ TEST_SUITE("ChannelContext")
auto ctx = Context();
auto chan_ctx = ChannelContext::make_conda_compatible(ctx);
SUBCASE("Channel alias")
SECTION("Channel alias")
{
CHECK_EQ(chan_ctx.params().channel_alias.str(), "https://conda.anaconda.org/");
REQUIRE(chan_ctx.params().channel_alias.str() == "https://conda.anaconda.org/");
}
SUBCASE("Conda pkgs channels")
SECTION("Conda pkgs channels")
{
const auto& custom = chan_ctx.params().custom_channels;
const auto& main = custom.at("pkgs/main");
CHECK_EQ(main.url(), CondaURL::parse("https://repo.anaconda.com/pkgs/main"));
CHECK_EQ(main.display_name(), "pkgs/main");
REQUIRE(main.url() == CondaURL::parse("https://repo.anaconda.com/pkgs/main"));
REQUIRE(main.display_name() == "pkgs/main");
const auto& pro = custom.at("pkgs/pro");
CHECK_EQ(pro.url(), CondaURL::parse("https://repo.anaconda.com/pkgs/pro"));
CHECK_EQ(pro.display_name(), "pkgs/pro");
REQUIRE(pro.url() == CondaURL::parse("https://repo.anaconda.com/pkgs/pro"));
REQUIRE(pro.display_name() == "pkgs/pro");
const auto& r = custom.at("pkgs/r");
CHECK_EQ(r.url(), CondaURL::parse("https://repo.anaconda.com/pkgs/r"));
CHECK_EQ(r.display_name(), "pkgs/r");
REQUIRE(r.url() == CondaURL::parse("https://repo.anaconda.com/pkgs/r"));
REQUIRE(r.display_name() == "pkgs/r");
}
SUBCASE("Defaults")
SECTION("Defaults")
{
const auto& defaults = chan_ctx.params().custom_multichannels.at("defaults");
@ -68,12 +67,11 @@ TEST_SUITE("ChannelContext")
}
if (util::on_win)
{
CHECK_EQ(
found_names,
util::flat_set<std::string>{ "pkgs/main", "pkgs/r", "pkgs/msys2" }
REQUIRE(
found_names == util::flat_set<std::string>{ "pkgs/main", "pkgs/r", "pkgs/msys2" }
);
CHECK_EQ(
found_urls,
REQUIRE(
found_urls ==
util::flat_set<std::string>{
"https://repo.anaconda.com/pkgs/main",
"https://repo.anaconda.com/pkgs/r",
@ -83,9 +81,9 @@ TEST_SUITE("ChannelContext")
}
else
{
CHECK_EQ(found_names, util::flat_set<std::string>{ "pkgs/main", "pkgs/r" });
CHECK_EQ(
found_urls,
REQUIRE(found_names == util::flat_set<std::string>{ "pkgs/main", "pkgs/r" });
REQUIRE(
found_urls ==
util::flat_set<std::string>{
"https://repo.anaconda.com/pkgs/main",
"https://repo.anaconda.com/pkgs/r",
@ -94,11 +92,11 @@ TEST_SUITE("ChannelContext")
}
}
SUBCASE("Has zst")
SECTION("Has zst")
{
const auto& chans = chan_ctx.make_channel("https://conda.anaconda.org/conda-forge");
REQUIRE_EQ(chans.size(), 1);
CHECK(chan_ctx.has_zst(chans.at(0)));
REQUIRE(chans.size() == 1);
REQUIRE(chan_ctx.has_zst(chans.at(0)));
}
}
@ -106,14 +104,14 @@ TEST_SUITE("ChannelContext")
{
auto ctx = Context();
SUBCASE("Channel alias override")
SECTION("Channel alias override")
{
ctx.channel_alias = "https://ali.as";
auto chan_ctx = ChannelContext::make_conda_compatible(ctx);
CHECK_EQ(chan_ctx.params().channel_alias.str(), "https://ali.as/");
REQUIRE(chan_ctx.params().channel_alias.str() == "https://ali.as/");
}
SUBCASE("Custom channels")
SECTION("Custom channels")
{
ctx.custom_channels = {
{ "chan1", "https://repo.mamba.pm/chan1" },
@ -124,21 +122,21 @@ TEST_SUITE("ChannelContext")
const auto& custom = chan_ctx.params().custom_channels;
const auto& chan1 = custom.at("chan1");
CHECK_EQ(chan1.url(), CondaURL::parse("https://repo.mamba.pm/chan1"));
CHECK_EQ(chan1.display_name(), "chan1");
REQUIRE(chan1.url() == CondaURL::parse("https://repo.mamba.pm/chan1"));
REQUIRE(chan1.display_name() == "chan1");
// Conda behaviour that URL ending must match name
const auto& chan2 = custom.at("chan2");
CHECK_EQ(chan2.url(), CondaURL::parse("https://repo.mamba.pm/chan2"));
CHECK_EQ(chan2.display_name(), "chan2");
REQUIRE(chan2.url() == CondaURL::parse("https://repo.mamba.pm/chan2"));
REQUIRE(chan2.display_name() == "chan2");
// Explicit override
const auto& main = custom.at("pkgs/main");
CHECK_EQ(main.url(), CondaURL::parse("https://repo.mamba.pm/pkgs/main"));
CHECK_EQ(main.display_name(), "pkgs/main");
REQUIRE(main.url() == CondaURL::parse("https://repo.mamba.pm/pkgs/main"));
REQUIRE(main.display_name() == "pkgs/main");
}
SUBCASE("Custom defaults")
SECTION("Custom defaults")
{
ctx.default_channels = {
"https://mamba.com/test/channel",
@ -152,8 +150,8 @@ TEST_SUITE("ChannelContext")
{
found_urls.insert(chan.url().str());
}
CHECK_EQ(
found_urls,
REQUIRE(
found_urls ==
util::flat_set<std::string>{
"https://mamba.com/test/channel",
"https://mamba.com/stable/channel",
@ -161,13 +159,13 @@ TEST_SUITE("ChannelContext")
);
}
SUBCASE("Local")
SECTION("Local")
{
const auto tmp_dir = TemporaryDirectory();
const auto conda_bld = tmp_dir.path() / "conda-bld";
fs::create_directory(conda_bld);
SUBCASE("HOME")
SECTION("HOME")
{
const auto restore = mambatests::EnvironmentCleaner();
util::set_env("HOME", tmp_dir.path()); // Unix
@ -176,32 +174,32 @@ TEST_SUITE("ChannelContext")
auto chan_ctx = ChannelContext::make_conda_compatible(ctx);
const auto& local = chan_ctx.params().custom_multichannels.at("local");
REQUIRE_EQ(local.size(), 1);
CHECK_EQ(local.front().url(), CondaURL::parse(util::path_to_url(conda_bld.string())));
REQUIRE(local.size() == 1);
REQUIRE(local.front().url() == CondaURL::parse(util::path_to_url(conda_bld.string())));
}
SUBCASE("Root prefix")
SECTION("Root prefix")
{
ctx.prefix_params.root_prefix = tmp_dir.path();
auto chan_ctx = ChannelContext::make_conda_compatible(ctx);
const auto& local = chan_ctx.params().custom_multichannels.at("local");
REQUIRE_EQ(local.size(), 1);
CHECK_EQ(local.front().url(), CondaURL::parse(util::path_to_url(conda_bld.string())));
REQUIRE(local.size() == 1);
REQUIRE(local.front().url() == CondaURL::parse(util::path_to_url(conda_bld.string())));
}
SUBCASE("Target prefix")
SECTION("Target prefix")
{
ctx.prefix_params.root_prefix = tmp_dir.path();
auto chan_ctx = ChannelContext::make_conda_compatible(ctx);
const auto& local = chan_ctx.params().custom_multichannels.at("local");
REQUIRE_EQ(local.size(), 1);
CHECK_EQ(local.front().url(), CondaURL::parse(util::path_to_url(conda_bld.string())));
REQUIRE(local.size() == 1);
REQUIRE(local.front().url() == CondaURL::parse(util::path_to_url(conda_bld.string())));
}
}
SUBCASE("Custom multi channels")
SECTION("Custom multi channels")
{
ctx.channel_alias = "https://ali.as";
ctx.custom_multichannels["mymulti"] = std::vector<std::string>{
@ -227,16 +225,16 @@ TEST_SUITE("ChannelContext")
found_names.insert(chan.display_name());
found_urls.insert(chan.url().str());
}
CHECK_EQ(
found_names,
REQUIRE(
found_names ==
util::flat_set<std::string>{
"conda-forge",
"https://mydomain.com/bioconda",
"https://mydomain.com/snakepit",
}
);
CHECK_EQ(
found_urls,
REQUIRE(
found_urls ==
util::flat_set<std::string>{
"https://ali.as/conda-forge",
"https://mydomain.com/bioconda",
@ -256,16 +254,16 @@ TEST_SUITE("ChannelContext")
found_names.insert(chan.display_name());
found_urls.insert(chan.url().str());
}
CHECK_EQ(
found_names,
REQUIRE(
found_names ==
util::flat_set<std::string>{
"https://otherdomain.com/conda-forge",
"bioconda",
"https://otherdomain.com/snakepit",
}
);
CHECK_EQ(
found_urls,
REQUIRE(
found_urls ==
util::flat_set<std::string>{
"https://otherdomain.com/conda-forge",
"https://ali.as/bioconda",
@ -280,14 +278,14 @@ TEST_SUITE("ChannelContext")
{
auto ctx = Context();
SUBCASE("Channel alias")
SECTION("Channel alias")
{
ctx.channel_alias = "https://ali.as";
auto chan_ctx = ChannelContext::make_simple(ctx);
CHECK_EQ(chan_ctx.params().channel_alias.str(), "https://ali.as/");
REQUIRE(chan_ctx.params().channel_alias.str() == "https://ali.as/");
}
SUBCASE("Custom channels")
SECTION("Custom channels")
{
ctx.custom_channels = {
{ "chan1", "https://repo.mamba.pm/chan1" },
@ -298,36 +296,36 @@ TEST_SUITE("ChannelContext")
const auto& custom = chan_ctx.params().custom_channels;
const auto& chan1 = custom.at("chan1");
CHECK_EQ(chan1.url(), CondaURL::parse("https://repo.mamba.pm/chan1"));
CHECK_EQ(chan1.display_name(), "chan1");
REQUIRE(chan1.url() == CondaURL::parse("https://repo.mamba.pm/chan1"));
REQUIRE(chan1.display_name() == "chan1");
// Different from Conda behaviour
const auto& chan2 = custom.at("chan2");
CHECK_EQ(chan2.url(), CondaURL::parse("https://repo.mamba.pm/"));
CHECK_EQ(chan2.display_name(), "chan2");
REQUIRE(chan2.url() == CondaURL::parse("https://repo.mamba.pm/"));
REQUIRE(chan2.display_name() == "chan2");
// Explicitly created
const auto& main = custom.at("pkgs/main");
CHECK_EQ(main.url(), CondaURL::parse("https://repo.mamba.pm/pkgs/main"));
CHECK_EQ(main.display_name(), "pkgs/main");
REQUIRE(main.url() == CondaURL::parse("https://repo.mamba.pm/pkgs/main"));
REQUIRE(main.display_name() == "pkgs/main");
}
SUBCASE("No hard coded names")
SECTION("No hard coded names")
{
auto chan_ctx = ChannelContext::make_simple(ctx);
const auto& custom = chan_ctx.params().custom_multichannels;
CHECK_EQ(custom.find("pkgs/main"), custom.cend());
CHECK_EQ(custom.find("pkgs/r"), custom.cend());
CHECK_EQ(custom.find("pkgs/pro"), custom.cend());
CHECK_EQ(custom.find("pkgs/msys2"), custom.cend());
REQUIRE(custom.find("pkgs/main") == custom.cend());
REQUIRE(custom.find("pkgs/r") == custom.cend());
REQUIRE(custom.find("pkgs/pro") == custom.cend());
REQUIRE(custom.find("pkgs/msys2") == custom.cend());
const auto& custom_multi = chan_ctx.params().custom_multichannels;
CHECK_EQ(custom_multi.find("defaults"), custom_multi.cend());
CHECK_EQ(custom_multi.find("local"), custom_multi.cend());
REQUIRE(custom_multi.find("defaults") == custom_multi.cend());
REQUIRE(custom_multi.find("local") == custom_multi.cend());
}
SUBCASE("Custom multi channels")
SECTION("Custom multi channels")
{
ctx.channel_alias = "https://ali.as";
ctx.custom_multichannels["mymulti"] = std::vector<std::string>{
@ -353,16 +351,16 @@ TEST_SUITE("ChannelContext")
found_names.insert(chan.display_name());
found_urls.insert(chan.url().str());
}
CHECK_EQ(
found_names,
REQUIRE(
found_names ==
util::flat_set<std::string>{
"conda-forge",
"https://mydomain.com/bioconda",
"https://mydomain.com/snakepit",
}
);
CHECK_EQ(
found_urls,
REQUIRE(
found_urls ==
util::flat_set<std::string>{
"https://ali.as/conda-forge",
"https://mydomain.com/bioconda",
@ -382,16 +380,16 @@ TEST_SUITE("ChannelContext")
found_names.insert(chan.display_name());
found_urls.insert(chan.url().str());
}
CHECK_EQ(
found_names,
REQUIRE(
found_names ==
util::flat_set<std::string>{
"https://otherdomain.com/conda-forge",
"bioconda",
"https://otherdomain.com/snakepit",
}
);
CHECK_EQ(
found_urls,
REQUIRE(
found_urls ==
util::flat_set<std::string>{
"https://otherdomain.com/conda-forge",
"https://ali.as/bioconda",
@ -401,11 +399,11 @@ TEST_SUITE("ChannelContext")
}
}
SUBCASE("Has zst")
SECTION("Has zst")
{
ctx.repodata_has_zst = { "https://otherdomain.com/conda-forge[noarch,linux-64]" };
SUBCASE("enabled")
SECTION("enabled")
{
ctx.repodata_use_zst = true;
auto chan_ctx = ChannelContext::make_simple(ctx);
@ -414,32 +412,32 @@ TEST_SUITE("ChannelContext")
const auto& chans = chan_ctx.make_channel(
"https://otherdomain.com/conda-forge[noarch]"
);
REQUIRE_EQ(chans.size(), 1);
CHECK(chan_ctx.has_zst(chans.at(0)));
REQUIRE(chans.size() == 1);
REQUIRE(chan_ctx.has_zst(chans.at(0)));
}
{
const auto& chans = chan_ctx.make_channel(
"https://otherdomain.com/conda-forge[win-64]"
);
REQUIRE_EQ(chans.size(), 1);
CHECK_FALSE(chan_ctx.has_zst(chans.at(0)));
REQUIRE(chans.size() == 1);
REQUIRE_FALSE(chan_ctx.has_zst(chans.at(0)));
}
{
const auto& chans = chan_ctx.make_channel("https://conda.anaconda.org/conda-forge"
);
REQUIRE_EQ(chans.size(), 1);
CHECK_FALSE(chan_ctx.has_zst(chans.at(0)));
REQUIRE(chans.size() == 1);
REQUIRE_FALSE(chan_ctx.has_zst(chans.at(0)));
}
}
SUBCASE("disabled")
SECTION("disabled")
{
ctx.repodata_use_zst = false;
auto chan_ctx = ChannelContext::make_simple(ctx);
const auto& chans = chan_ctx.make_channel("https://otherdomain.com/conda-forge");
REQUIRE_EQ(chans.size(), 1);
CHECK_FALSE(chan_ctx.has_zst(chans.at(0)));
REQUIRE(chans.size() == 1);
REQUIRE_FALSE(chan_ctx.has_zst(chans.at(0)));
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -8,7 +8,7 @@
#include <sstream>
#include <tuple>
#include <doctest/doctest.h>
#include <catch2/catch_all.hpp>
#include "mamba/core/channel_context.hpp"
#include "mamba/core/context.hpp"
@ -27,9 +27,9 @@ namespace mamba
TEST_CASE("cache_name_from_url")
{
CHECK_EQ(cache_name_from_url("http://test.com/1234/"), "302f0a61");
CHECK_EQ(cache_name_from_url("http://test.com/1234/repodata.json"), "302f0a61");
CHECK_EQ(cache_name_from_url("http://test.com/1234/current_repodata.json"), "78a8cce9");
REQUIRE(cache_name_from_url("http://test.com/1234/") == "302f0a61");
REQUIRE(cache_name_from_url("http://test.com/1234/repodata.json") == "302f0a61");
REQUIRE(cache_name_from_url("http://test.com/1234/current_repodata.json") == "78a8cce9");
}
// TEST(cpp_install, install)
@ -46,45 +46,46 @@ namespace mamba
// lp.execute();
// }
TEST_SUITE("history")
namespace
{
TEST_CASE("user_request")
{
auto u = History::UserRequest::prefilled(mambatests::context());
// update in 100 years!
CHECK_EQ(u.date[0], '2');
CHECK_EQ(u.date[1], '0');
REQUIRE(u.date[0] == '2');
REQUIRE(u.date[1] == '0');
}
}
TEST_SUITE("output")
namespace
{
TEST_CASE("hide_secrets")
{
auto res = Console::instance().hide_secrets("http://myweb.com/t/my-12345-token/test.repo");
CHECK_EQ(res, "http://myweb.com/t/*****/test.repo");
REQUIRE(res == "http://myweb.com/t/*****/test.repo");
res = Console::instance().hide_secrets("http://root:secretpassword@myweb.com/test.repo");
CHECK_EQ(res, "http://root:*****@myweb.com/test.repo");
REQUIRE(res == "http://root:*****@myweb.com/test.repo");
res = Console::instance().hide_secrets(
"http://root:secretpassword@myweb.com/test.repo http://root:secretpassword@myweb.com/test.repo"
);
CHECK_EQ(res, "http://root:*****@myweb.com/test.repo http://root:*****@myweb.com/test.repo");
REQUIRE(
res == "http://root:*****@myweb.com/test.repo http://root:*****@myweb.com/test.repo"
);
res = Console::instance().hide_secrets(
"http://root:secretpassword@myweb.com/test.repo\nhttp://myweb.com/t/my-12345-token/test.repo http://myweb.com/t/my-12345-token/test.repo http://root:secretpassword@myweb.com/test.repo"
);
CHECK_EQ(
res,
"http://root:*****@myweb.com/test.repo\nhttp://myweb.com/t/*****/test.repo http://myweb.com/t/*****/test.repo http://root:*****@myweb.com/test.repo"
REQUIRE(
res == "http://root:*****@myweb.com/test.repo\nhttp://myweb.com/t/*****/test.repo http://myweb.com/t/*****/test.repo http://root:*****@myweb.com/test.repo"
);
res = Console::instance().hide_secrets("myweb.com/t/my-12345-token/test.repo");
CHECK_EQ(res, "myweb.com/t/*****/test.repo");
REQUIRE(res == "myweb.com/t/*****/test.repo");
res = Console::instance().hide_secrets("root:secretpassword@myweb.com/test.repo");
CHECK_EQ(res, "root:*****@myweb.com/test.repo");
REQUIRE(res == "root:*****@myweb.com/test.repo");
}
// Note: this was initially a value-parametrized test; unfortunately,
@ -111,15 +112,15 @@ namespace mamba
CAPTURE(p);
std::stringstream test_stream;
test_stream << std::get<0>(p) << std::endl;
CHECK_EQ(
Console::instance().prompt("Test prompt", std::get<1>(p), test_stream),
std::get<2>(p)
REQUIRE(
Console::instance().prompt("Test prompt", std::get<1>(p), test_stream)
== std::get<2>(p)
);
}
}
}
TEST_SUITE("context")
namespace
{
TEST_CASE("env_name")
{
@ -130,29 +131,29 @@ namespace mamba
ctx.envs_dirs = { ctx.prefix_params.root_prefix / "envs" };
fs::u8path prefix = "/home/user/micromamba/envs/testprefix";
CHECK_EQ(env_name(ctx, prefix), "testprefix");
REQUIRE(env_name(ctx, prefix) == "testprefix");
prefix = "/home/user/micromamba/envs/a.txt";
CHECK_EQ(env_name(ctx, prefix), "a.txt");
REQUIRE(env_name(ctx, prefix) == "a.txt");
prefix = "/home/user/micromamba/envs/a.txt";
CHECK_EQ(env_name(ctx, prefix), "a.txt");
REQUIRE(env_name(ctx, prefix) == "a.txt");
prefix = "/home/user/micromamba/envs/abc/a.txt";
CHECK_EQ(env_name(ctx, prefix), "/home/user/micromamba/envs/abc/a.txt");
REQUIRE(env_name(ctx, prefix) == "/home/user/micromamba/envs/abc/a.txt");
prefix = "/home/user/env";
CHECK_EQ(env_name(ctx, prefix), "/home/user/env");
REQUIRE(env_name(ctx, prefix) == "/home/user/env");
}
}
}
TEST_SUITE("fsutil")
namespace
{
TEST_CASE("starts_with_home")
{
if (util::on_linux)
{
auto home = fs::u8path(util::expand_home("~"));
CHECK_EQ(path::starts_with_home(home / "test" / "file.txt"), true);
CHECK_EQ(path::starts_with_home("~"), true);
CHECK_EQ(path::starts_with_home("/opt/bin"), false);
REQUIRE(path::starts_with_home(home / "test" / "file.txt") == true);
REQUIRE(path::starts_with_home("~") == true);
REQUIRE(path::starts_with_home("/opt/bin") == false);
}
}
@ -161,12 +162,12 @@ namespace mamba
if (util::on_linux)
{
path::touch("/tmp/dir/file.txt", true);
CHECK(fs::exists("/tmp/dir/file.txt"));
REQUIRE(fs::exists("/tmp/dir/file.txt"));
}
}
}
TEST_SUITE("link")
namespace
{
TEST_CASE("replace_long_shebang")
{
@ -177,13 +178,12 @@ namespace mamba
);
if (util::on_linux)
{
CHECK_EQ(res, "#!/usr/bin/env python -o test -x");
REQUIRE(res == "#!/usr/bin/env python -o test -x");
}
else
{
CHECK_EQ(
res,
"#!/this/is/loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong/python -o test -x"
REQUIRE(
res == "#!/this/is/loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong/python -o test -x"
);
}
@ -192,23 +192,23 @@ namespace mamba
res = replace_long_shebang(
"#!/this/is/loooooooooooooooooooooooooooooooooooooooooooooooooooo\\ oooooo\\ oooooo\\ oooooooooooooooooooooooooooooooooooong/python -o test -x"
);
CHECK_EQ(res, "#!/usr/bin/env python -o test -x");
REQUIRE(res == "#!/usr/bin/env python -o test -x");
res = replace_long_shebang(
"#!/this/is/loooooooooooooooooooooooooooooooooooooooooooooooooooo\\ oooooo\\ oooooo\\ oooooooooooooooooooooooooooooooooooong/pyt hon -o test -x"
);
CHECK_EQ(res, "#!/usr/bin/env pyt hon -o test -x");
REQUIRE(res == "#!/usr/bin/env pyt hon -o test -x");
res = replace_long_shebang(
"#!/this/is/loooooooooooooooooooooooooooooooooooooooooooooooooooo\\ oooooo\\ oooooo\\ oooooooooooooooooooooooooooooooooooong/pyt\\ hon -o test -x"
);
CHECK_EQ(res, "#!/usr/bin/env pyt\\ hon -o test -x");
REQUIRE(res == "#!/usr/bin/env pyt\\ hon -o test -x");
res = replace_long_shebang(
"#! /this/is/loooooooooooooooooooooooooooooooooooooooooooooooooooo\\ oooooo\\ oooooo\\ oooooooooooooooooooooooooooooooooooong/pyt\\ hon -o test -x"
);
CHECK_EQ(res, "#!/usr/bin/env pyt\\ hon -o test -x");
REQUIRE(res == "#!/usr/bin/env pyt\\ hon -o test -x");
res = replace_long_shebang(
"#! /this/is/looooooooooooooooooooooooooooooooooooooooooooo\\ \\ ooooooo\\ oooooo\\ oooooo\\ ooooooooooooooooo\\ ooooooooooooooooooong/pyt\\ hon -o \"te st\" -x"
);
CHECK_EQ(res, "#!/usr/bin/env pyt\\ hon -o \"te st\" -x");
REQUIRE(res == "#!/usr/bin/env pyt\\ hon -o \"te st\" -x");
}
std::string shebang = fmt::format(
@ -216,21 +216,21 @@ namespace mamba
std::string(500, 'a')
);
res = replace_long_shebang(shebang);
CHECK_EQ(res, "#!/usr/bin/env python -o test 123 -x");
REQUIRE(res == "#!/usr/bin/env python -o test 123 -x");
shebang = fmt::format("#!/{}/bin/python -o test 123 -x", std::string(500, 'a'));
shebang[299] = '\\';
shebang[300] = ' ';
res = replace_long_shebang(shebang);
CHECK_EQ(res, "#!/usr/bin/env python -o test 123 -x");
REQUIRE(res == "#!/usr/bin/env python -o test 123 -x");
}
}
TEST_CASE("python_shebang")
{
auto res = python_shebang("/usr/bin/python");
CHECK_EQ(res, "#!/usr/bin/python");
REQUIRE(res == "#!/usr/bin/python");
res = python_shebang("/usr/bin/pyth on with spaces");
CHECK_EQ(res, "#!/bin/sh\n'''exec' \"/usr/bin/pyth on with spaces\" \"$0\" \"$@\" #'''");
REQUIRE(res == "#!/bin/sh\n'''exec' \"/usr/bin/pyth on with spaces\" \"$0\" \"$@\" #'''");
}
TEST_CASE("shebang_regex_matches")
@ -238,99 +238,99 @@ namespace mamba
std::string shebang = "#!/simple/shebang";
std::smatch s;
auto match = std::regex_match(shebang, s, shebang_regex);
CHECK(match);
CHECK_EQ(s[0].str(), "#!/simple/shebang");
CHECK_EQ(s[1].str(), "#!/simple/shebang");
CHECK_EQ(s[2].str(), "/simple/shebang");
CHECK_EQ(s[3].str(), "");
REQUIRE(match);
REQUIRE(s[0].str() == "#!/simple/shebang");
REQUIRE(s[1].str() == "#!/simple/shebang");
REQUIRE(s[2].str() == "/simple/shebang");
REQUIRE(s[3].str() == "");
// // with spaces
shebang = "#! /simple/shebang";
match = std::regex_match(shebang, s, shebang_regex);
CHECK(match);
CHECK_EQ(s[0].str(), "#! /simple/shebang");
CHECK_EQ(s[1].str(), "#! /simple/shebang");
CHECK_EQ(s[2].str(), "/simple/shebang");
CHECK_EQ(s[3].str(), "");
REQUIRE(match);
REQUIRE(s[0].str() == "#! /simple/shebang");
REQUIRE(s[1].str() == "#! /simple/shebang");
REQUIRE(s[2].str() == "/simple/shebang");
REQUIRE(s[3].str() == "");
// with escaped spaces and flags
shebang = "#!/simple/shebang/escaped\\ space --and --flags -x";
match = std::regex_match(shebang, s, shebang_regex);
CHECK(match);
CHECK_EQ(s[0].str(), "#!/simple/shebang/escaped\\ space --and --flags -x");
CHECK_EQ(s[1].str(), "#!/simple/shebang/escaped\\ space --and --flags -x");
CHECK_EQ(s[2].str(), "/simple/shebang/escaped\\ space");
CHECK_EQ(s[3].str(), " --and --flags -x");
REQUIRE(match);
REQUIRE(s[0].str() == "#!/simple/shebang/escaped\\ space --and --flags -x");
REQUIRE(s[1].str() == "#!/simple/shebang/escaped\\ space --and --flags -x");
REQUIRE(s[2].str() == "/simple/shebang/escaped\\ space");
REQUIRE(s[3].str() == " --and --flags -x");
}
}
TEST_SUITE("utils")
namespace
{
TEST_CASE("quote_for_shell")
{
if (!util::on_win)
{
std::vector<std::string> args1 = { "python", "-c", "print('is\ngreat')" };
CHECK_EQ(quote_for_shell(args1), "python -c 'print('\"'\"'is\ngreat'\"'\"')'");
REQUIRE(quote_for_shell(args1) == "python -c 'print('\"'\"'is\ngreat'\"'\"')'");
std::vector<std::string> args2 = { "python", "-c", "print(\"is great\")" };
CHECK_EQ(quote_for_shell(args2), "python -c 'print(\"is great\")'");
REQUIRE(quote_for_shell(args2) == "python -c 'print(\"is great\")'");
std::vector<std::string> args3 = { "python", "very nice", "print(\"is great\")" };
CHECK_EQ(quote_for_shell(args3), "python 'very nice' 'print(\"is great\")'");
REQUIRE(quote_for_shell(args3) == "python 'very nice' 'print(\"is great\")'");
std::vector<std::string> args4 = { "pyt \t tab", "very nice", "print(\"is great\")" };
CHECK_EQ(quote_for_shell(args4), "'pyt \t tab' 'very nice' 'print(\"is great\")'");
REQUIRE(quote_for_shell(args4) == "'pyt \t tab' 'very nice' 'print(\"is great\")'");
std::vector<std::string> args5 = { "echo", "(" };
CHECK_EQ(quote_for_shell(args5), "echo '('");
REQUIRE(quote_for_shell(args5) == "echo '('");
std::vector<std::string> args6 = { "echo", "foo'bar\nspam" };
CHECK_EQ(quote_for_shell(args6), "echo 'foo'\"'\"'bar\nspam'");
REQUIRE(quote_for_shell(args6) == "echo 'foo'\"'\"'bar\nspam'");
}
std::vector<std::string> args1 = { "a b c", "d", "e" };
CHECK_EQ(quote_for_shell(args1, "cmdexe"), "\"a b c\" d e");
REQUIRE(quote_for_shell(args1, "cmdexe") == "\"a b c\" d e");
std::vector<std::string> args2 = { "ab\"c", "\\", "d" };
CHECK_EQ(quote_for_shell(args2, "cmdexe"), "ab\\\"c \\ d");
REQUIRE(quote_for_shell(args2, "cmdexe") == "ab\\\"c \\ d");
std::vector<std::string> args3 = { "ab\"c", " \\", "d" };
CHECK_EQ(quote_for_shell(args3, "cmdexe"), "ab\\\"c \" \\\\\" d");
REQUIRE(quote_for_shell(args3, "cmdexe") == "ab\\\"c \" \\\\\" d");
std::vector<std::string> args4 = { "a\\\\\\b", "de fg", "h" };
CHECK_EQ(quote_for_shell(args4, "cmdexe"), "a\\\\\\b \"de fg\" h");
REQUIRE(quote_for_shell(args4, "cmdexe") == "a\\\\\\b \"de fg\" h");
std::vector<std::string> args5 = { "a\\\"b", "c", "d" };
CHECK_EQ(quote_for_shell(args5, "cmdexe"), "a\\\\\\\"b c d");
REQUIRE(quote_for_shell(args5, "cmdexe") == "a\\\\\\\"b c d");
std::vector<std::string> args6 = { "a\\\\b c", "d", "e" };
CHECK_EQ(quote_for_shell(args6, "cmdexe"), "\"a\\\\b c\" d e");
REQUIRE(quote_for_shell(args6, "cmdexe") == "\"a\\\\b c\" d e");
std::vector<std::string> args7 = { "a\\\\b\\ c", "d", "e" };
CHECK_EQ(quote_for_shell(args7, "cmdexe"), "\"a\\\\b\\ c\" d e");
REQUIRE(quote_for_shell(args7, "cmdexe") == "\"a\\\\b\\ c\" d e");
std::vector<std::string> args8 = { "ab", "" };
CHECK_EQ(quote_for_shell(args8, "cmdexe"), "ab \"\"");
REQUIRE(quote_for_shell(args8, "cmdexe") == "ab \"\"");
}
TEST_CASE("lexists")
{
fs::create_symlink("empty_target", "nonexistinglink");
CHECK_FALSE(fs::exists("nonexistinglink"));
CHECK(lexists("nonexistinglink"));
REQUIRE_FALSE(fs::exists("nonexistinglink"));
REQUIRE(lexists("nonexistinglink"));
fs::remove("nonexistinglink");
CHECK_FALSE(fs::exists("nonexistinglink"));
CHECK_FALSE(lexists("nonexistinglink"));
REQUIRE_FALSE(fs::exists("nonexistinglink"));
REQUIRE_FALSE(lexists("nonexistinglink"));
path::touch("emptytestfile");
CHECK(fs::exists("emptytestfile"));
CHECK(lexists("emptytestfile"));
REQUIRE(fs::exists("emptytestfile"));
REQUIRE(lexists("emptytestfile"));
fs::create_symlink("emptytestfile", "existinglink");
CHECK(fs::exists("existinglink"));
CHECK(lexists("existinglink"));
REQUIRE(fs::exists("existinglink"));
REQUIRE(lexists("existinglink"));
fs::remove("existinglink");
CHECK_FALSE(fs::exists("existinglink"));
CHECK_FALSE(lexists("existinglink"));
REQUIRE_FALSE(fs::exists("existinglink"));
REQUIRE_FALSE(lexists("existinglink"));
fs::remove("emptytestfile");
CHECK_FALSE(fs::exists("emptytestfile"));
CHECK_FALSE(lexists("emptytestfile"));
REQUIRE_FALSE(fs::exists("emptytestfile"));
REQUIRE_FALSE(lexists("emptytestfile"));
std::error_code ec;
CHECK_FALSE(lexists("completelyinexistent", ec));
CHECK_FALSE(ec);
REQUIRE_FALSE(lexists("completelyinexistent", ec));
REQUIRE_FALSE(ec);
CHECK_FALSE(fs::exists("completelyinexistent", ec));
CHECK_FALSE(ec);
REQUIRE_FALSE(fs::exists("completelyinexistent", ec));
REQUIRE_FALSE(ec);
}
}
@ -347,49 +347,49 @@ namespace mamba
}
#endif
TEST_SUITE("subdirdata")
namespace
{
TEST_CASE("parse_last_modified_etag")
{
fs::u8path cache_folder = fs::u8path{ mambatests::test_data_dir / "repodata_json_cache" };
auto mq = SubdirMetadata::read(cache_folder / "test_1.json");
CHECK(mq.has_value());
REQUIRE(mq.has_value());
auto j = mq.value();
CHECK_EQ(j.last_modified(), "Fri, 11 Feb 2022 13:52:44 GMT");
CHECK_EQ(
j.url(),
"file:///Users/wolfvollprecht/Programs/mamba/mamba/tests/channel_a/linux-64/repodata.json"
REQUIRE(j.last_modified() == "Fri, 11 Feb 2022 13:52:44 GMT");
REQUIRE(
j.url()
== "file:///Users/wolfvollprecht/Programs/mamba/mamba/tests/channel_a/linux-64/repodata.json"
);
j = SubdirMetadata::read(cache_folder / "test_2.json").value();
CHECK_EQ(j.last_modified(), "Fri, 11 Feb 2022 13:52:44 GMT");
CHECK_EQ(
j.url(),
"file:///Users/wolfvollprecht/Programs/mamba/mamba/tests/channel_a/linux-64/repodata.json"
REQUIRE(j.last_modified() == "Fri, 11 Feb 2022 13:52:44 GMT");
REQUIRE(
j.url()
== "file:///Users/wolfvollprecht/Programs/mamba/mamba/tests/channel_a/linux-64/repodata.json"
);
j = SubdirMetadata::read(cache_folder / "test_5.json").value();
CHECK_EQ(j.last_modified(), "Fri, 11 Feb 2022 13:52:44 GMT");
CHECK_EQ(
j.url(),
"file:///Users/wolfvollprecht/Programs/mamba/mamba/tests/channel_a/linux-64/repodata.json"
REQUIRE(j.last_modified() == "Fri, 11 Feb 2022 13:52:44 GMT");
REQUIRE(
j.url()
== "file:///Users/wolfvollprecht/Programs/mamba/mamba/tests/channel_a/linux-64/repodata.json"
);
j = SubdirMetadata::read(cache_folder / "test_4.json").value();
CHECK_EQ(j.cache_control(), "{{}}\",,,\"");
CHECK_EQ(j.etag(), "\n\n\"\"randome ecx,,ssd\n,,\"");
CHECK_EQ(j.last_modified(), "Fri, 11 Feb 2022 13:52:44 GMT");
CHECK_EQ(
j.url(),
"file:///Users/wolfvollprecht/Programs/mamba/mamba/tests/channel_a/linux-64/repodata.json"
REQUIRE(j.cache_control() == "{{}}\",,,\"");
REQUIRE(j.etag() == "\n\n\"\"randome ecx,,ssd\n,,\"");
REQUIRE(j.last_modified() == "Fri, 11 Feb 2022 13:52:44 GMT");
REQUIRE(
j.url()
== "file:///Users/wolfvollprecht/Programs/mamba/mamba/tests/channel_a/linux-64/repodata.json"
);
mq = SubdirMetadata::read(cache_folder / "test_3.json");
CHECK(mq.has_value() == false);
REQUIRE(mq.has_value() == false);
j = SubdirMetadata::read(cache_folder / "test_6.json").value();
CHECK_EQ(j.last_modified(), "Thu, 02 Apr 2020 20:21:27 GMT");
CHECK_EQ(j.url(), "https://conda.anaconda.org/intake/osx-arm64");
REQUIRE(j.last_modified() == "Thu, 02 Apr 2020 20:21:27 GMT");
REQUIRE(j.url() == "https://conda.anaconda.org/intake/osx-arm64");
auto state_file = cache_folder / "test_7.state.json";
// set file_mtime
@ -421,11 +421,11 @@ namespace mamba
}
j = SubdirMetadata::read(cache_folder / "test_7.json").value();
CHECK_EQ(j.cache_control(), "something");
CHECK_EQ(j.etag(), "something else");
CHECK_EQ(j.last_modified(), "Fri, 11 Feb 2022 13:52:44 GMT");
CHECK_EQ(j.url(), "https://conda.anaconda.org/conda-forge/noarch/repodata.json.zst");
CHECK_EQ(j.has_zst(), false);
REQUIRE(j.cache_control() == "something");
REQUIRE(j.etag() == "something else");
REQUIRE(j.last_modified() == "Fri, 11 Feb 2022 13:52:44 GMT");
REQUIRE(j.url() == "https://conda.anaconda.org/conda-forge/noarch/repodata.json.zst");
REQUIRE(j.has_zst() == false);
}
}
} // namespace mamba

View File

@ -4,7 +4,7 @@
//
// The full license is in the file LICENSE, distributed with this software.
#include <doctest/doctest.h>
#include <catch2/catch_all.hpp>
#include "mamba/api/install.hpp"
#include "mamba/util/build.hpp"
@ -13,7 +13,7 @@
namespace mamba
{
TEST_SUITE("env_file_reading")
namespace
{
TEST_CASE("selector")
{
@ -21,25 +21,25 @@ namespace mamba
using namespace detail;
if constexpr (util::on_linux || util::on_mac)
{
CHECK(eval_selector("sel(unix)", context.platform));
REQUIRE(eval_selector("sel(unix)", context.platform));
if (util::on_mac)
{
CHECK(eval_selector("sel(osx)", context.platform));
CHECK_FALSE(eval_selector("sel(linux)", context.platform));
CHECK_FALSE(eval_selector("sel(win)", context.platform));
REQUIRE(eval_selector("sel(osx)", context.platform));
REQUIRE_FALSE(eval_selector("sel(linux)", context.platform));
REQUIRE_FALSE(eval_selector("sel(win)", context.platform));
}
else
{
CHECK(eval_selector("sel(linux)", context.platform));
CHECK_FALSE(eval_selector("sel(osx)", context.platform));
CHECK_FALSE(eval_selector("sel(win)", context.platform));
REQUIRE(eval_selector("sel(linux)", context.platform));
REQUIRE_FALSE(eval_selector("sel(osx)", context.platform));
REQUIRE_FALSE(eval_selector("sel(win)", context.platform));
}
}
else if (util::on_win)
{
CHECK(eval_selector("sel(win)", context.platform));
CHECK_FALSE(eval_selector("sel(osx)", context.platform));
CHECK_FALSE(eval_selector("sel(linux)", context.platform));
REQUIRE(eval_selector("sel(win)", context.platform));
REQUIRE_FALSE(eval_selector("sel(osx)", context.platform));
REQUIRE_FALSE(eval_selector("sel(linux)", context.platform));
}
}
@ -51,25 +51,25 @@ namespace mamba
mambatests::test_data_dir / "env_file/env_1.yaml",
context.platform
);
CHECK_EQ(res.name, "env_1");
CHECK_EQ(res.channels, V({ "conda-forge", "bioconda" }));
CHECK_EQ(res.dependencies, V({ "test1", "test2", "test3" }));
CHECK_FALSE(res.others_pkg_mgrs_specs.size());
REQUIRE(res.name == "env_1");
REQUIRE(res.channels == V({ "conda-forge", "bioconda" }));
REQUIRE(res.dependencies == V({ "test1", "test2", "test3" }));
REQUIRE_FALSE(res.others_pkg_mgrs_specs.size());
auto res2 = detail::read_yaml_file(
mambatests::test_data_dir / "env_file/env_2.yaml",
context.platform
);
CHECK_EQ(res2.name, "env_2");
CHECK_EQ(res2.channels, V({ "conda-forge", "bioconda" }));
REQUIRE(res2.name == "env_2");
REQUIRE(res2.channels == V({ "conda-forge", "bioconda" }));
#ifdef __linux__
CHECK_EQ(res2.dependencies, V({ "test1-unix", "test1-linux", "test2-linux", "test4" }));
REQUIRE(res2.dependencies == V({ "test1-unix", "test1-linux", "test2-linux", "test4" }));
#elif __APPLE__
CHECK_EQ(res2.dependencies, V({ "test1-unix", "test1-osx", "test4" }));
REQUIRE(res2.dependencies == V({ "test1-unix", "test1-osx", "test4" }));
#elif _WIN32
CHECK_EQ(res2.dependencies, V({ "test1-win", "test4" }));
REQUIRE(res2.dependencies == V({ "test1-win", "test4" }));
#endif
CHECK_FALSE(res2.others_pkg_mgrs_specs.size());
REQUIRE_FALSE(res2.others_pkg_mgrs_specs.size());
}
TEST_CASE("external_pkg_mgrs")
@ -80,15 +80,15 @@ namespace mamba
mambatests::test_data_dir / "env_file/env_3.yaml",
context.platform
);
CHECK_EQ(res.name, "env_3");
CHECK_EQ(res.channels, V({ "conda-forge", "bioconda" }));
CHECK_EQ(res.dependencies, V({ "test1", "test2", "test3", "pip" }));
REQUIRE(res.name == "env_3");
REQUIRE(res.channels == V({ "conda-forge", "bioconda" }));
REQUIRE(res.dependencies == V({ "test1", "test2", "test3", "pip" }));
CHECK_EQ(res.others_pkg_mgrs_specs.size(), 1);
REQUIRE(res.others_pkg_mgrs_specs.size() == 1);
auto o = res.others_pkg_mgrs_specs[0];
CHECK_EQ(o.pkg_mgr, "pip");
CHECK_EQ(o.deps, V({ "pytest", "numpy" }));
CHECK_EQ(o.cwd, fs::absolute(mambatests::test_data_dir / "env_file"));
REQUIRE(o.pkg_mgr == "pip");
REQUIRE(o.deps == V({ "pytest", "numpy" }));
REQUIRE(o.cwd == fs::absolute(mambatests::test_data_dir / "env_file"));
}
}

View File

@ -4,7 +4,7 @@
//
// The full license is in the file LICENSE, distributed with this software.
#include <doctest/doctest.h>
#include <catch2/catch_all.hpp>
#include <yaml-cpp/exceptions.h>
#include "mamba/core/channel_context.hpp"
@ -18,20 +18,20 @@
namespace mamba
{
TEST_SUITE("env_lockfile")
namespace
{
TEST_CASE("absent_file_fails")
{
const auto maybe_lockfile = read_environment_lockfile("this/file/does/not/exists");
REQUIRE_FALSE(maybe_lockfile);
const auto error = maybe_lockfile.error();
REQUIRE_EQ(mamba_error_code::env_lockfile_parsing_failed, error.error_code());
REQUIRE(mamba_error_code::env_lockfile_parsing_failed == error.error_code());
const auto& error_details = EnvLockFileError::get_details(error);
CHECK_EQ(file_parsing_error_code::parsing_failure, error_details.parsing_error_code);
REQUIRE(file_parsing_error_code::parsing_failure == error_details.parsing_error_code);
REQUIRE(error_details.yaml_error_type);
const std::type_index bad_file_error_id{ typeid(YAML::BadFile) };
CHECK_EQ(bad_file_error_id, error_details.yaml_error_type.value());
REQUIRE(bad_file_error_id == error_details.yaml_error_type.value());
// NOTE: one could attempt to check if opening a file which is not an YAML file
// would fail. Unfortunately YAML parsers will accept any kind of file,
@ -46,9 +46,9 @@ namespace mamba
const auto maybe_lockfile = read_environment_lockfile(invalid_version_lockfile_path);
REQUIRE_FALSE(maybe_lockfile);
const auto error = maybe_lockfile.error();
REQUIRE_EQ(mamba_error_code::env_lockfile_parsing_failed, error.error_code());
REQUIRE(mamba_error_code::env_lockfile_parsing_failed == error.error_code());
const auto& error_details = EnvLockFileError::get_details(error);
CHECK_EQ(file_parsing_error_code::unsupported_version, error_details.parsing_error_code);
REQUIRE(file_parsing_error_code::unsupported_version == error_details.parsing_error_code);
}
TEST_CASE("valid_no_package_succeed")
@ -56,9 +56,13 @@ namespace mamba
const fs::u8path lockfile_path{ mambatests::test_data_dir
/ "env_lockfile/good_no_package-lock.yaml" };
const auto maybe_lockfile = read_environment_lockfile(lockfile_path);
REQUIRE_MESSAGE(maybe_lockfile, maybe_lockfile.error().what());
if (!maybe_lockfile)
{
INFO(maybe_lockfile.error().what());
FAIL();
}
const auto lockfile = maybe_lockfile.value();
CHECK(lockfile.get_all_packages().empty());
REQUIRE(lockfile.get_all_packages().empty());
}
TEST_CASE("invalid_package_fails")
@ -68,9 +72,9 @@ namespace mamba
const auto maybe_lockfile = read_environment_lockfile(lockfile_path);
REQUIRE_FALSE(maybe_lockfile);
const auto error = maybe_lockfile.error();
REQUIRE_EQ(mamba_error_code::env_lockfile_parsing_failed, error.error_code());
REQUIRE(mamba_error_code::env_lockfile_parsing_failed == error.error_code());
const auto& error_details = EnvLockFileError::get_details(error);
CHECK_EQ(file_parsing_error_code::parsing_failure, error_details.parsing_error_code);
REQUIRE(file_parsing_error_code::parsing_failure == error_details.parsing_error_code);
}
TEST_CASE("valid_one_package_succeed")
@ -78,9 +82,13 @@ namespace mamba
const fs::u8path lockfile_path{ mambatests::test_data_dir
/ "env_lockfile/good_one_package-lock.yaml" };
const auto maybe_lockfile = read_environment_lockfile(lockfile_path);
REQUIRE_MESSAGE(maybe_lockfile, maybe_lockfile.error().what());
if (!maybe_lockfile)
{
INFO(maybe_lockfile.error().what());
FAIL();
}
const auto lockfile = maybe_lockfile.value();
CHECK_EQ(lockfile.get_all_packages().size(), 1);
REQUIRE(lockfile.get_all_packages().size() == 1);
}
TEST_CASE("valid_one_package_implicit_category")
@ -89,9 +97,13 @@ namespace mamba
mambatests::test_data_dir / "env_lockfile/good_one_package_missing_category-lock.yaml"
};
const auto maybe_lockfile = read_environment_lockfile(lockfile_path);
REQUIRE_MESSAGE(maybe_lockfile, maybe_lockfile.error().what());
if (!maybe_lockfile)
{
INFO(maybe_lockfile.error().what());
FAIL();
}
const auto lockfile = maybe_lockfile.value();
CHECK_EQ(lockfile.get_all_packages().size(), 1);
REQUIRE(lockfile.get_all_packages().size() == 1);
}
TEST_CASE("valid_multiple_packages_succeed")
@ -99,9 +111,13 @@ namespace mamba
const fs::u8path lockfile_path{ mambatests::test_data_dir
/ "env_lockfile/good_multiple_packages-lock.yaml" };
const auto maybe_lockfile = read_environment_lockfile(lockfile_path);
REQUIRE_MESSAGE(maybe_lockfile, maybe_lockfile.error().what());
if (!maybe_lockfile)
{
INFO(maybe_lockfile.error().what());
FAIL();
}
const auto lockfile = maybe_lockfile.value();
CHECK_GT(lockfile.get_all_packages().size(), 1);
REQUIRE(lockfile.get_all_packages().size() > 1);
}
TEST_CASE("get_specific_packages")
@ -109,16 +125,16 @@ namespace mamba
const fs::u8path lockfile_path{ mambatests::test_data_dir
/ "env_lockfile/good_multiple_packages-lock.yaml" };
const auto lockfile = read_environment_lockfile(lockfile_path).value();
CHECK(lockfile.get_packages_for("", "", "").empty());
REQUIRE(lockfile.get_packages_for("", "", "").empty());
{
const auto packages = lockfile.get_packages_for("main", "linux-64", "conda");
CHECK_FALSE(packages.empty());
CHECK_GT(packages.size(), 4);
REQUIRE_FALSE(packages.empty());
REQUIRE(packages.size() > 4);
}
{
const auto packages = lockfile.get_packages_for("main", "linux-64", "pip");
CHECK_FALSE(packages.empty());
CHECK_EQ(packages.size(), 2);
REQUIRE_FALSE(packages.empty());
REQUIRE(packages.size() == 2);
}
}
@ -147,15 +163,15 @@ namespace mamba
other_specs
);
auto to_install = std::get<1>(transaction.to_conda());
CHECK_EQ(to_install.size(), num_conda);
REQUIRE(to_install.size() == num_conda);
if (num_pip == 0)
{
CHECK_EQ(other_specs.size(), 0);
REQUIRE(other_specs.size() == 0);
}
else
{
CHECK_EQ(other_specs.size(), 1);
CHECK_EQ(other_specs.at(0).deps.size(), num_pip);
REQUIRE(other_specs.size() == 1);
REQUIRE(other_specs.at(0).deps.size() == num_pip);
}
};
@ -168,40 +184,40 @@ namespace mamba
}
}
TEST_SUITE("is_env_lockfile_name")
namespace
{
TEST_CASE("basics")
TEST_CASE("is_env_lockfile_name")
{
CHECK(is_env_lockfile_name("something-lock.yaml"));
CHECK(is_env_lockfile_name("something-lock.yml"));
CHECK(is_env_lockfile_name("/some/dir/something-lock.yaml"));
CHECK(is_env_lockfile_name("/some/dir/something-lock.yml"));
CHECK(is_env_lockfile_name("../../some/dir/something-lock.yaml"));
CHECK(is_env_lockfile_name("../../some/dir/something-lock.yml"));
REQUIRE(is_env_lockfile_name("something-lock.yaml"));
REQUIRE(is_env_lockfile_name("something-lock.yml"));
REQUIRE(is_env_lockfile_name("/some/dir/something-lock.yaml"));
REQUIRE(is_env_lockfile_name("/some/dir/something-lock.yml"));
REQUIRE(is_env_lockfile_name("../../some/dir/something-lock.yaml"));
REQUIRE(is_env_lockfile_name("../../some/dir/something-lock.yml"));
CHECK(is_env_lockfile_name(fs::u8path{ "something-lock.yaml" }.string()));
CHECK(is_env_lockfile_name(fs::u8path{ "something-lock.yml" }.string()));
CHECK(is_env_lockfile_name(fs::u8path{ "/some/dir/something-lock.yaml" }.string()));
CHECK(is_env_lockfile_name(fs::u8path{ "/some/dir/something-lock.yml" }.string()));
CHECK(is_env_lockfile_name(fs::u8path{ "../../some/dir/something-lock.yaml" }.string()));
CHECK(is_env_lockfile_name(fs::u8path{ "../../some/dir/something-lock.yml" }.string()));
REQUIRE(is_env_lockfile_name(fs::u8path{ "something-lock.yaml" }.string()));
REQUIRE(is_env_lockfile_name(fs::u8path{ "something-lock.yml" }.string()));
REQUIRE(is_env_lockfile_name(fs::u8path{ "/some/dir/something-lock.yaml" }.string()));
REQUIRE(is_env_lockfile_name(fs::u8path{ "/some/dir/something-lock.yml" }.string()));
REQUIRE(is_env_lockfile_name(fs::u8path{ "../../some/dir/something-lock.yaml" }.string()));
REQUIRE(is_env_lockfile_name(fs::u8path{ "../../some/dir/something-lock.yml" }.string()));
CHECK_FALSE(is_env_lockfile_name("something"));
CHECK_FALSE(is_env_lockfile_name("something-lock"));
CHECK_FALSE(is_env_lockfile_name("/some/dir/something"));
CHECK_FALSE(is_env_lockfile_name("../../some/dir/something"));
REQUIRE_FALSE(is_env_lockfile_name("something"));
REQUIRE_FALSE(is_env_lockfile_name("something-lock"));
REQUIRE_FALSE(is_env_lockfile_name("/some/dir/something"));
REQUIRE_FALSE(is_env_lockfile_name("../../some/dir/something"));
CHECK_FALSE(is_env_lockfile_name("something.yaml"));
CHECK_FALSE(is_env_lockfile_name("something.yml"));
CHECK_FALSE(is_env_lockfile_name("/some/dir/something.yaml"));
CHECK_FALSE(is_env_lockfile_name("/some/dir/something.yml"));
CHECK_FALSE(is_env_lockfile_name("../../some/dir/something.yaml"));
CHECK_FALSE(is_env_lockfile_name("../../some/dir/something.yml"));
REQUIRE_FALSE(is_env_lockfile_name("something.yaml"));
REQUIRE_FALSE(is_env_lockfile_name("something.yml"));
REQUIRE_FALSE(is_env_lockfile_name("/some/dir/something.yaml"));
REQUIRE_FALSE(is_env_lockfile_name("/some/dir/something.yml"));
REQUIRE_FALSE(is_env_lockfile_name("../../some/dir/something.yaml"));
REQUIRE_FALSE(is_env_lockfile_name("../../some/dir/something.yml"));
CHECK_FALSE(is_env_lockfile_name(fs::u8path{ "something" }.string()));
CHECK_FALSE(is_env_lockfile_name(fs::u8path{ "something-lock" }.string()));
CHECK_FALSE(is_env_lockfile_name(fs::u8path{ "/some/dir/something" }.string()));
CHECK_FALSE(is_env_lockfile_name(fs::u8path{ "../../some/dir/something" }.string()));
REQUIRE_FALSE(is_env_lockfile_name(fs::u8path{ "something" }.string()));
REQUIRE_FALSE(is_env_lockfile_name(fs::u8path{ "something-lock" }.string()));
REQUIRE_FALSE(is_env_lockfile_name(fs::u8path{ "/some/dir/something" }.string()));
REQUIRE_FALSE(is_env_lockfile_name(fs::u8path{ "../../some/dir/something" }.string()));
}
}

View File

@ -4,7 +4,7 @@
//
// The full license is in the file LICENSE, distributed with this software.
#include <doctest/doctest.h>
#include <catch2/catch_all.hpp>
#include "mamba/core/environments_manager.hpp"
#include "mamba/fs/filesystem.hpp"
@ -14,7 +14,7 @@
namespace mamba
{
TEST_SUITE("env_manager")
namespace
{
TEST_CASE("all_envs")
{
@ -25,7 +25,7 @@ namespace mamba
auto new_prefixes = e.list_all_known_prefixes();
// the prefix should be cleaned out, because it doesn't have the
// `conda-meta/history` file
CHECK_EQ(new_prefixes.size(), prefixes.size());
REQUIRE(new_prefixes.size() == prefixes.size());
// Create an env containing `conda-meta/history` file
// and test register/unregister
@ -34,11 +34,11 @@ namespace mamba
e.register_env(prefix);
new_prefixes = e.list_all_known_prefixes();
CHECK_EQ(new_prefixes.size(), prefixes.size() + 1);
REQUIRE(new_prefixes.size() == prefixes.size() + 1);
e.unregister_env(prefix);
new_prefixes = e.list_all_known_prefixes();
CHECK_EQ(new_prefixes.size(), prefixes.size());
REQUIRE(new_prefixes.size() == prefixes.size());
// Add another file in addition to `conda-meta/history`
// and test register/unregister
@ -46,13 +46,13 @@ namespace mamba
e.register_env(prefix);
new_prefixes = e.list_all_known_prefixes();
CHECK_EQ(new_prefixes.size(), prefixes.size() + 1);
REQUIRE(new_prefixes.size() == prefixes.size() + 1);
e.unregister_env(prefix);
new_prefixes = e.list_all_known_prefixes();
// Shouldn't unregister because `conda-meta/other_file`
// is there
CHECK_EQ(new_prefixes.size(), prefixes.size() + 1);
REQUIRE(new_prefixes.size() == prefixes.size() + 1);
// Remove test directory
fs::remove_all(util::expand_home("~/some_test_folder"));

View File

@ -4,7 +4,7 @@
//
// The full license is in the file LICENSE, distributed with this software.
#include <doctest/doctest.h>
#include <catch2/catch_all.hpp>
#include "mamba/core/execution.hpp"
@ -49,7 +49,7 @@ namespace mamba
}
}
TEST_SUITE("execution")
namespace
{
TEST_CASE("stop_default_always_succeeds")
{
@ -86,7 +86,7 @@ namespace mamba
[&] { executor.schedule([&] { ++counter; }); }
);
} // All threads from the executor must have been joined here.
CHECK_EQ(counter, arbitrary_task_count);
REQUIRE(counter == arbitrary_task_count);
}
TEST_CASE("closed_prevents_more_scheduling_and_joins")
@ -104,7 +104,7 @@ namespace mamba
);
executor.close();
CHECK_EQ(counter, arbitrary_task_count);
REQUIRE(counter == arbitrary_task_count);
execute_tasks_from_concurrent_threads(
arbitrary_task_count,
@ -112,11 +112,9 @@ namespace mamba
[&] { executor.schedule([&] { throw "this code must never be executed"; }); }
);
}
CHECK_EQ(
counter,
arbitrary_task_count
); // We re-check to make sure no thread are executed anymore
// as soon as `.close()` was called.
REQUIRE(counter == arbitrary_task_count); // We re-check to make sure no thread are
// executed anymore as soon as `.close()` was
// called.
}
}

View File

@ -6,7 +6,7 @@
#include <vector>
#include <doctest/doctest.h>
#include <catch2/catch_all.hpp>
#include "mamba/core/util.hpp"
#include "mamba/core/util_scope.hpp"
@ -14,7 +14,7 @@
namespace mamba
{
TEST_SUITE("u8path")
namespace
{
TEST_CASE("normalized_separators")
{
@ -22,9 +22,9 @@ namespace mamba
std::filesystem::path x{ value };
const auto y = fs::normalized_separators(x);
#if defined(_WIN32)
REQUIRE_EQ(y.u8string(), u8R"(a\b\c)");
REQUIRE(y.u8string() == u8R"(a\b\c)");
#else
REQUIRE_EQ(y.u8string(), value);
REQUIRE(y.u8string() == value);
#endif
}
@ -32,9 +32,9 @@ namespace mamba
{
static constexpr auto value = u8"日本語";
const std::filesystem::path x = fs::from_utf8(value);
REQUIRE_EQ(x.u8string(), u8"日本語"); // check assumption
REQUIRE(x.u8string() == u8"日本語"); // check assumption
const auto y = fs::normalized_separators(x);
REQUIRE_EQ(y.u8string(), u8"日本語");
REQUIRE(y.u8string() == u8"日本語");
}
TEST_CASE("consistent_encoding")
@ -42,13 +42,13 @@ namespace mamba
const auto utf8_string = u8"日本語";
const fs::u8path filename(utf8_string);
const auto str = filename.string();
CHECK_EQ(str, utf8_string);
REQUIRE(str == utf8_string);
const fs::u8path file_path = fs::temp_directory_path() / filename;
CHECK_EQ(file_path.filename().string(), utf8_string);
REQUIRE(file_path.filename().string() == utf8_string);
const auto std_path = file_path.std_path();
CHECK_EQ(std_path.filename().u8string(), utf8_string);
REQUIRE(std_path.filename().u8string() == utf8_string);
}
TEST_CASE("string_stream_encoding")
@ -59,12 +59,12 @@ namespace mamba
const fs::u8path filename(utf8_string);
std::stringstream stream;
stream << filename;
CHECK_EQ(stream.str(), quoted_utf8_string);
REQUIRE(stream.str() == quoted_utf8_string);
fs::u8path path_read;
stream.seekg(0);
stream >> path_read;
CHECK_EQ(path_read.string(), utf8_string);
REQUIRE(path_read.string() == utf8_string);
}
TEST_CASE("directory_iteration")
@ -86,9 +86,9 @@ namespace mamba
const auto path_to_search_from = file_dir.parent_path();
fs::recursive_directory_iterator it{ path_to_search_from };
auto first_entry = *it;
CHECK_EQ(first_entry.path(), file_path.parent_path());
REQUIRE(first_entry.path() == file_path.parent_path());
auto secibd_entry = *(++it);
CHECK_EQ(secibd_entry.path(), file_path);
REQUIRE(secibd_entry.path() == file_path);
}
{
@ -105,7 +105,7 @@ namespace mamba
static_assert(std::is_same_v<decltype(entry.path()), fs::u8path>);
entries_found.push_back(entry.path());
}
CHECK_EQ(entries_found, expected_entries);
REQUIRE(entries_found == expected_entries);
}
{
@ -122,7 +122,7 @@ namespace mamba
static_assert(std::is_same_v<decltype(entry.path()), fs::u8path>);
entries_found.push_back(entry.path().string());
}
CHECK_EQ(entries_found, expected_entries);
REQUIRE(entries_found == expected_entries);
}
{
@ -136,7 +136,7 @@ namespace mamba
static_assert(std::is_same_v<decltype(entry.path()), fs::u8path>);
entries_found.push_back(entry.path());
}
CHECK_EQ(entries_found, expected_entries);
REQUIRE(entries_found == expected_entries);
}
{
@ -150,7 +150,7 @@ namespace mamba
static_assert(std::is_same_v<decltype(entry.path()), fs::u8path>);
entries_found.push_back(entry.path().string());
}
CHECK_EQ(entries_found, expected_entries);
REQUIRE(entries_found == expected_entries);
}
}
@ -173,12 +173,12 @@ namespace mamba
{
const fs::u8path path = u8R"(a/b/c/d)";
const auto path_1 = path / u8R"(e\f\g)";
CHECK_EQ(path_1.string(), u8R"(a\b\c\d\e\f\g)");
REQUIRE(path_1.string() == u8R"(a\b\c\d\e\f\g)");
}
#endif
}
TEST_SUITE("filesystem")
namespace
{
TEST_CASE("remove_readonly_file")
{
@ -201,19 +201,19 @@ namespace mamba
fs::perms::owner_read | fs::perms::group_read,
fs::perm_options::replace
);
CHECK_EQ(
(fs::status(readonly_file_path).permissions() & fs::perms::owner_write),
fs::perms::none
REQUIRE(
(fs::status(readonly_file_path).permissions() & fs::perms::owner_write)
== fs::perms::none
);
CHECK_EQ(
(fs::status(readonly_file_path).permissions() & fs::perms::group_write),
fs::perms::none
REQUIRE(
(fs::status(readonly_file_path).permissions() & fs::perms::group_write)
== fs::perms::none
);
// removing should still work.
CHECK(fs::exists(readonly_file_path));
REQUIRE(fs::exists(readonly_file_path));
fs::remove(readonly_file_path);
CHECK_FALSE(fs::exists(readonly_file_path));
REQUIRE_FALSE(fs::exists(readonly_file_path));
}
TEST_CASE("remove_all_readonly_files")
@ -247,13 +247,13 @@ namespace mamba
fs::perms::owner_read | fs::perms::group_read,
fs::perm_options::replace
);
CHECK_EQ(
(fs::status(readonly_file_path).permissions() & fs::perms::owner_write),
fs::perms::none
REQUIRE(
(fs::status(readonly_file_path).permissions() & fs::perms::owner_write)
== fs::perms::none
);
CHECK_EQ(
(fs::status(readonly_file_path).permissions() & fs::perms::group_write),
fs::perms::none
REQUIRE(
(fs::status(readonly_file_path).permissions() & fs::perms::group_write)
== fs::perms::none
);
}
};
@ -283,9 +283,9 @@ namespace mamba
create_readonly_files(dir_path);
}
CHECK(fs::exists(tmp_dir));
REQUIRE(fs::exists(tmp_dir));
fs::remove_all(tmp_dir);
CHECK_FALSE(fs::exists(tmp_dir));
REQUIRE_FALSE(fs::exists(tmp_dir));
}
}

View File

@ -9,7 +9,7 @@
#include <sstream>
#include <string>
#include <doctest/doctest.h>
#include <catch2/catch_all.hpp>
#include "mambatests.hpp"
@ -26,9 +26,9 @@
namespace mamba
{
TEST_SUITE("history")
namespace
{
TEST_CASE("parse")
TEST_CASE("History parse")
{
static const auto history_file_path = fs::absolute(
mambatests::test_data_dir / "history/parse/conda-meta/history"
@ -90,7 +90,7 @@ namespace mamba
}
history_file.close();
REQUIRE_EQ(updated_history_buffer.str(), check_buffer.str());
REQUIRE(updated_history_buffer.str() == check_buffer.str());
}
TEST_CASE("parse_metadata")

View File

@ -6,40 +6,45 @@
#include <exception>
#include <doctest/doctest.h>
#include <catch2/catch_all.hpp>
#include "mamba/core/invoke.hpp"
#include "mamba/util/string.hpp"
namespace mamba
{
TEST_SUITE("safe_invoke")
namespace
{
TEST_CASE("executes_with_success")
{
bool was_called = false;
auto result = safe_invoke([&] { was_called = true; });
CHECK(result);
CHECK(was_called);
REQUIRE(result);
REQUIRE(was_called);
}
TEST_CASE("catches_std_exceptions")
{
const auto message = "expected failure";
auto result = safe_invoke([&] { throw std::runtime_error(message); });
CHECK_FALSE(result);
CHECK_MESSAGE(util::ends_with(result.error().what(), message), result.error().what());
REQUIRE_FALSE(result);
if (!util::ends_with(result.error().what(), message))
{
INFO(result.error().what());
FAIL();
}
}
TEST_CASE("catches_any_exceptions")
{
const auto message = "expected failure";
auto result = safe_invoke([&] { throw message; });
CHECK_FALSE(result);
CHECK_MESSAGE(
util::ends_with(result.error().what(), "unknown error"),
result.error().what()
);
REQUIRE_FALSE(result);
if (!util::ends_with(result.error().what(), "unknown error"))
{
INFO(result.error().what());
FAIL();
}
}
TEST_CASE("safely_catch_moved_callable_destructor_exception")
@ -86,12 +91,13 @@ namespace mamba
};
auto result = safe_invoke(DoNotDoThisAtHome{ did_move_happened });
CHECK_FALSE(result);
CHECK_MESSAGE(
util::ends_with(result.error().what(), "unknown error"),
result.error().what()
);
CHECK(did_move_happened);
REQUIRE_FALSE(result);
if (!util::ends_with(result.error().what(), "unknown error"))
{
INFO(result.error().what());
FAIL();
}
REQUIRE(did_move_happened);
}
}

View File

@ -7,7 +7,7 @@
#include <iostream>
#include <string>
#include <doctest/doctest.h>
#include <catch2/catch_all.hpp>
#include <reproc++/run.hpp>
#include "mamba/core/context.hpp"
@ -56,66 +56,66 @@ namespace mamba
}
};
TEST_SUITE("LockDirTest")
namespace
{
TEST_CASE_FIXTURE(LockDirTest, "basics")
TEST_CASE_METHOD(LockDirTest, "basics")
{
mamba::LockFile lock{ tempdir_path };
CHECK(lock);
REQUIRE(lock);
{
auto new_lock = std::move(lock);
CHECK_FALSE(lock);
CHECK(new_lock);
REQUIRE_FALSE(lock);
REQUIRE(new_lock);
}
CHECK_FALSE(lock);
REQUIRE_FALSE(lock);
}
TEST_CASE_FIXTURE(LockDirTest, "disable_locking")
TEST_CASE_METHOD(LockDirTest, "disable_locking")
{
{
auto _ = on_scope_exit([] { mamba::allow_file_locking(true); });
mamba::allow_file_locking(false);
auto lock = LockFile(tempdir_path);
CHECK_FALSE(lock);
REQUIRE_FALSE(lock);
}
REQUIRE(mamba::is_file_locking_allowed());
{
REQUIRE(mamba::is_file_locking_allowed());
auto lock = LockFile(tempdir_path);
CHECK(lock);
REQUIRE(lock);
}
}
TEST_CASE_FIXTURE(LockDirTest, "same_pid")
TEST_CASE_METHOD(LockDirTest, "same_pid")
{
{
auto lock = LockFile(tempdir_path);
CHECK(lock.is_locked());
CHECK_EQ(lock.count_lock_owners(), 1);
CHECK(fs::exists(lock.lockfile_path()));
REQUIRE(lock.is_locked());
REQUIRE(lock.count_lock_owners() == 1);
REQUIRE(fs::exists(lock.lockfile_path()));
{
auto other_lock = LockFile(tempdir_path);
CHECK(other_lock.is_locked());
CHECK_EQ(other_lock.count_lock_owners(), 2);
CHECK_EQ(lock.count_lock_owners(), 2);
REQUIRE(other_lock.is_locked());
REQUIRE(other_lock.count_lock_owners() == 2);
REQUIRE(lock.count_lock_owners() == 2);
}
CHECK_EQ(lock.count_lock_owners(), 1);
REQUIRE(lock.count_lock_owners() == 1);
// check the first lock is still locked
CHECK(fs::exists(lock.lockfile_path()));
REQUIRE(fs::exists(lock.lockfile_path()));
}
CHECK_FALSE(fs::exists(tempdir_path / (tempdir_path.filename().string() + ".lock")));
REQUIRE_FALSE(fs::exists(tempdir_path / (tempdir_path.filename().string() + ".lock")));
// we can still re-lock afterwards
{
auto lock = LockFile(tempdir_path);
CHECK(fs::exists(lock.lockfile_path()));
REQUIRE(fs::exists(lock.lockfile_path()));
}
}
TEST_CASE_FIXTURE(LockDirTest, "different_pid")
TEST_CASE_METHOD(LockDirTest, "different_pid")
{
const std::string lock_exe = mambatests::testing_libmamba_lock_exe.string();
std::string out, err;
@ -123,10 +123,10 @@ namespace mamba
{
auto lock = LockFile(tempdir_path);
CHECK(fs::exists(lock.lockfile_path()));
REQUIRE(fs::exists(lock.lockfile_path()));
// Check lock status
CHECK(mamba::LockFile::is_locked(lock));
REQUIRE(mamba::LockFile::is_locked(lock));
// Check lock status from another process
args = { lock_exe, "is-locked", lock.lockfile_path().string() };
@ -148,7 +148,7 @@ namespace mamba
{
std::cout << "conversion error" << std::endl;
}
CHECK(is_locked);
REQUIRE(is_locked);
// Try to lock from another process
args = { lock_exe, "lock", "--timeout=1", tempdir_path.string() };
@ -170,11 +170,11 @@ namespace mamba
{
std::cout << "conversion error" << std::endl;
}
CHECK_FALSE(new_lock_created);
REQUIRE_FALSE(new_lock_created);
}
fs::u8path lock_path = tempdir_path / (tempdir_path.filename().string() + ".lock");
CHECK_FALSE(fs::exists(lock_path));
REQUIRE_FALSE(fs::exists(lock_path));
args = { lock_exe, "is-locked", lock_path.string() };
out.clear();
@ -189,7 +189,7 @@ namespace mamba
catch (...)
{
}
CHECK_FALSE(is_locked);
REQUIRE_FALSE(is_locked);
}
}
@ -214,32 +214,32 @@ namespace mamba
}
};
TEST_SUITE("LockFileTest")
namespace
{
TEST_CASE_FIXTURE(LockFileTest, "same_pid")
TEST_CASE_METHOD(LockFileTest, "same_pid")
{
{
LockFile lock{ tempfile_path };
CHECK(lock.is_locked());
CHECK(fs::exists(lock.lockfile_path()));
CHECK_EQ(lock.count_lock_owners(), 1);
REQUIRE(lock.is_locked());
REQUIRE(fs::exists(lock.lockfile_path()));
REQUIRE(lock.count_lock_owners() == 1);
{
LockFile other_lock{ tempfile_path };
CHECK(other_lock.is_locked());
CHECK_EQ(other_lock.count_lock_owners(), 2);
CHECK_EQ(lock.count_lock_owners(), 2);
REQUIRE(other_lock.is_locked());
REQUIRE(other_lock.count_lock_owners() == 2);
REQUIRE(lock.count_lock_owners() == 2);
}
CHECK_EQ(lock.count_lock_owners(), 1);
REQUIRE(lock.count_lock_owners() == 1);
// check the first lock is still locked
CHECK(fs::exists(lock.lockfile_path()));
REQUIRE(fs::exists(lock.lockfile_path()));
}
CHECK_FALSE(fs::exists(tempfile_path.string() + ".lock"));
REQUIRE_FALSE(fs::exists(tempfile_path.string() + ".lock"));
}
TEST_CASE_FIXTURE(LockFileTest, "different_pid")
TEST_CASE_METHOD(LockFileTest, "different_pid")
{
const std::string lock_exe = mambatests::testing_libmamba_lock_exe.string();
std::string out, err;
@ -247,10 +247,10 @@ namespace mamba
{
// Create a lock
auto lock = LockFile(tempfile_path);
CHECK(fs::exists(lock.lockfile_path()));
REQUIRE(fs::exists(lock.lockfile_path()));
// Check lock status from current PID
CHECK(mamba::LockFile::is_locked(lock));
REQUIRE(mamba::LockFile::is_locked(lock));
// Check lock status from another process
args = { lock_exe, "is-locked", lock.lockfile_path().string() };
@ -272,7 +272,7 @@ namespace mamba
{
std::cout << "conversion error" << std::endl;
}
CHECK(is_locked);
REQUIRE(is_locked);
// Try to lock from another process
args = { lock_exe, "lock", "--timeout=1", tempfile_path.string() };
@ -294,11 +294,11 @@ namespace mamba
{
std::cout << "conversion error" << std::endl;
}
CHECK_FALSE(new_lock_created);
REQUIRE_FALSE(new_lock_created);
}
fs::u8path lock_path = tempfile_path.string() + ".lock";
CHECK_FALSE(fs::exists(lock_path));
REQUIRE_FALSE(fs::exists(lock_path));
args = { lock_exe, "is-locked", lock_path.string() };
out.clear();
@ -313,7 +313,7 @@ namespace mamba
catch (...)
{
}
CHECK_FALSE(is_locked);
REQUIRE_FALSE(is_locked);
}
}
}

View File

@ -4,7 +4,7 @@
//
// The full license is in the file LICENSE, distributed with this software.
#include <doctest/doctest.h>
#include <catch2/catch_all.hpp>
#include "mamba/core/context.hpp"
#include "mamba/core/output.hpp"
@ -13,19 +13,19 @@
namespace mamba
{
TEST_SUITE("output")
namespace
{
TEST_CASE("no_progress_bars")
{
mambatests::context().graphics_params.no_progress_bars = true;
auto proxy = Console::instance().add_progress_bar("conda-forge");
CHECK_FALSE(proxy.defined());
CHECK_FALSE(proxy);
REQUIRE_FALSE(proxy.defined());
REQUIRE_FALSE(proxy);
mambatests::context().graphics_params.no_progress_bars = false;
proxy = Console::instance().add_progress_bar("conda-forge");
CHECK(proxy.defined());
CHECK(proxy);
REQUIRE(proxy.defined());
REQUIRE(proxy);
}
}
} // namespace mamba

View File

@ -4,7 +4,7 @@
//
// The full license is in the file LICENSE, distributed with this software.
#include <doctest/doctest.h>
#include <catch2/catch_all.hpp>
#include "mamba/core/channel_context.hpp"
#include "mamba/core/pinning.hpp"
@ -17,7 +17,7 @@ namespace mamba
{
namespace testing
{
TEST_SUITE("pinning")
namespace
{
TEST_CASE("python_pin")
{
@ -32,67 +32,67 @@ namespace mamba
throw std::runtime_error("could not load prefix data");
}
PrefixData& prefix_data = sprefix_data.value();
REQUIRE_EQ(prefix_data.records().size(), 0);
REQUIRE(prefix_data.records().size() == 0);
specs = { "python" };
pin = python_pin(prefix_data, specs);
CHECK_EQ(pin, "");
REQUIRE(pin == "");
specs = { "python-test" };
pin = python_pin(prefix_data, specs);
CHECK_EQ(pin, "");
REQUIRE(pin == "");
specs = { "python=3" };
pin = python_pin(prefix_data, specs);
CHECK_EQ(pin, "");
REQUIRE(pin == "");
specs = { "python==3.8" };
pin = python_pin(prefix_data, specs);
CHECK_EQ(pin, "");
REQUIRE(pin == "");
specs = { "python==3.8.3" };
pin = python_pin(prefix_data, specs);
CHECK_EQ(pin, "");
REQUIRE(pin == "");
specs = { "numpy" };
pin = python_pin(prefix_data, specs);
CHECK_EQ(pin, "");
REQUIRE(pin == "");
specs::PackageInfo pkg_info("python", "3.7.10", "abcde", 0);
prefix_data.add_packages({ pkg_info });
REQUIRE_EQ(prefix_data.records().size(), 1);
REQUIRE(prefix_data.records().size() == 1);
specs = { "python" };
pin = python_pin(prefix_data, specs);
CHECK_EQ(pin, "");
REQUIRE(pin == "");
specs = { "numpy" };
pin = python_pin(prefix_data, specs);
CHECK_EQ(pin, "python 3.7.*");
REQUIRE(pin == "python 3.7.*");
specs = { "python-test" };
pin = python_pin(prefix_data, specs);
CHECK_EQ(pin, "python 3.7.*");
REQUIRE(pin == "python 3.7.*");
specs = { "python==3" };
pin = python_pin(prefix_data, specs);
CHECK_EQ(pin, "");
REQUIRE(pin == "");
specs = { "python=3.*" };
pin = python_pin(prefix_data, specs);
CHECK_EQ(pin, "");
REQUIRE(pin == "");
specs = { "python=3.8" };
pin = python_pin(prefix_data, specs);
CHECK_EQ(pin, "");
REQUIRE(pin == "");
specs = { "python=3.8.3" };
pin = python_pin(prefix_data, specs);
CHECK_EQ(pin, "");
REQUIRE(pin == "");
specs = { "numpy", "python" };
pin = python_pin(prefix_data, specs);
CHECK_EQ(pin, "");
REQUIRE(pin == "");
}
TEST_CASE("file_pins")
@ -106,18 +106,18 @@ namespace mamba
out_file.close();
pins = file_pins(path);
REQUIRE_EQ(pins.size(), 2);
CHECK_EQ(pins[0], "numpy=1.13");
CHECK_EQ(pins[1], "jupyterlab=3");
REQUIRE(pins.size() == 2);
REQUIRE(pins[0] == "numpy=1.13");
REQUIRE(pins[1] == "jupyterlab=3");
out_file.open(path.std_path(), std::ofstream::out | std::ofstream::trunc);
out_file << "numpy=1.13\npython=3.7.5";
out_file.close();
pins = file_pins(path);
REQUIRE_EQ(pins.size(), 2);
CHECK_EQ(pins[0], "numpy=1.13");
CHECK_EQ(pins[1], "python=3.7.5");
REQUIRE(pins.size() == 2);
REQUIRE(pins[0] == "numpy=1.13");
REQUIRE(pins[1] == "python=3.7.5");
}
}
} // namespace testing

View File

@ -6,7 +6,7 @@
#include <sstream>
#include <doctest/doctest.h>
#include <catch2/catch_all.hpp>
#include "mamba/core/progress_bar.hpp"
@ -46,354 +46,354 @@ namespace mamba
std::ostringstream ostream;
};
TEST_SUITE("progress_bar")
namespace
{
TEST_CASE_FIXTURE(progress_bar, "print")
TEST_CASE_METHOD(progress_bar, "print")
{
auto& r = proxy.repr();
CHECK(r.prefix.active());
CHECK_EQ(r.prefix.value(), "conda-forge");
CHECK_EQ(r.prefix.width(), 11);
REQUIRE(r.prefix.active());
REQUIRE(r.prefix.value() == "conda-forge");
REQUIRE(r.prefix.width() == 11);
CHECK(r.progress);
CHECK_EQ(r.progress.value(), "??");
CHECK_EQ(r.progress.width(), 2);
REQUIRE(r.progress);
REQUIRE(r.progress.value() == "??");
REQUIRE(r.progress.width() == 2);
CHECK(r.separator);
CHECK_EQ(r.separator.value(), "-");
CHECK_EQ(r.separator.width(), 1);
REQUIRE(r.separator);
REQUIRE(r.separator.value() == "-");
REQUIRE(r.separator.width() == 1);
CHECK(r.total);
CHECK_EQ(r.total.value(), "bar");
CHECK_EQ(r.total.width(), 3);
REQUIRE(r.total);
REQUIRE(r.total.value() == "bar");
REQUIRE(r.total.width() == 3);
CHECK(r.speed);
CHECK_EQ(r.speed.value(), "@10");
CHECK_EQ(r.speed.width(), 3);
REQUIRE(r.speed);
REQUIRE(r.speed.value() == "@10");
REQUIRE(r.speed.width() == 3);
CHECK(r.postfix.active());
CHECK_EQ(r.postfix.value(), "downloading");
CHECK_EQ(r.postfix.width(), 11);
REQUIRE(r.postfix.active());
REQUIRE(r.postfix.value() == "downloading");
REQUIRE(r.postfix.width() == 11);
CHECK(r.elapsed.active());
CHECK_EQ(r.elapsed.value(), "0.1s");
CHECK_EQ(r.elapsed.width(), 4);
REQUIRE(r.elapsed.active());
REQUIRE(r.elapsed.value() == "0.1s");
REQUIRE(r.elapsed.width() == 4);
proxy.print(ostream, 0, false);
CHECK_EQ(ostream.str(), "conda-forge ?? foo - bar @10 downloading 0.1s");
REQUIRE(ostream.str() == "conda-forge ?? foo - bar @10 downloading 0.1s");
ostream.str("");
r.set_width(21); // no impact if 'update_repr' not called
proxy.print(ostream, 0, false);
CHECK_EQ(ostream.str(), "conda-forge ?? foo - bar @10 downloading 0.1s");
REQUIRE(ostream.str() == "conda-forge ?? foo - bar @10 downloading 0.1s");
ostream.str("");
}
TEST_CASE_FIXTURE(progress_bar, "print_no_resize")
TEST_CASE_METHOD(progress_bar, "print_no_resize")
{
auto& r = proxy.repr();
r.set_width(150);
proxy.update_repr();
CHECK(r.prefix);
CHECK(r.progress);
CHECK(r.current);
CHECK(r.separator);
CHECK(r.total);
CHECK(r.speed);
CHECK(r.postfix);
CHECK(r.elapsed);
CHECK_EQ(r.prefix.width(), 11);
CHECK_EQ(r.progress.width(), 106);
CHECK_EQ(r.current.width(), 3);
CHECK_EQ(r.separator.width(), 1);
CHECK_EQ(r.total.width(), 3);
CHECK_EQ(r.speed.width(), 3);
CHECK_EQ(r.postfix.width(), 11);
CHECK_EQ(r.elapsed.width(), 5);
REQUIRE(r.prefix);
REQUIRE(r.progress);
REQUIRE(r.current);
REQUIRE(r.separator);
REQUIRE(r.total);
REQUIRE(r.speed);
REQUIRE(r.postfix);
REQUIRE(r.elapsed);
REQUIRE(r.prefix.width() == 11);
REQUIRE(r.progress.width() == 106);
REQUIRE(r.current.width() == 3);
REQUIRE(r.separator.width() == 1);
REQUIRE(r.total.width() == 3);
REQUIRE(r.speed.width() == 3);
REQUIRE(r.postfix.width() == 11);
REQUIRE(r.elapsed.width() == 5);
}
TEST_CASE_FIXTURE(progress_bar, "print_reduce_bar")
TEST_CASE_METHOD(progress_bar, "print_reduce_bar")
{
auto& r = proxy.repr();
r.set_width(84);
proxy.update_repr();
CHECK(r.prefix);
CHECK(r.progress);
CHECK(r.current);
CHECK(r.separator);
CHECK(r.total);
CHECK(r.speed);
CHECK(r.postfix);
CHECK(r.elapsed);
CHECK_EQ(r.prefix.width(), 11);
CHECK_EQ(r.progress.width(), 40);
CHECK_EQ(r.current.width(), 3);
CHECK_EQ(r.separator.width(), 1);
CHECK_EQ(r.total.width(), 3);
CHECK_EQ(r.speed.width(), 3);
CHECK_EQ(r.postfix.width(), 11);
CHECK_EQ(r.elapsed.width(), 5);
REQUIRE(r.prefix);
REQUIRE(r.progress);
REQUIRE(r.current);
REQUIRE(r.separator);
REQUIRE(r.total);
REQUIRE(r.speed);
REQUIRE(r.postfix);
REQUIRE(r.elapsed);
REQUIRE(r.prefix.width() == 11);
REQUIRE(r.progress.width() == 40);
REQUIRE(r.current.width() == 3);
REQUIRE(r.separator.width() == 1);
REQUIRE(r.total.width() == 3);
REQUIRE(r.speed.width() == 3);
REQUIRE(r.postfix.width() == 11);
REQUIRE(r.elapsed.width() == 5);
// 1: reduce bar width
// available space redistributed to the bar
r.set_width(83);
proxy.update_repr();
CHECK(r.prefix);
CHECK(r.progress);
CHECK(r.current);
CHECK(r.separator);
CHECK(r.total);
CHECK(r.speed);
CHECK(r.postfix);
CHECK(r.elapsed);
CHECK_EQ(r.prefix.width(), 11);
CHECK_EQ(r.progress.width(), 39);
CHECK_EQ(r.current.width(), 3);
CHECK_EQ(r.separator.width(), 1);
CHECK_EQ(r.total.width(), 3);
CHECK_EQ(r.speed.width(), 3);
CHECK_EQ(r.postfix.width(), 11);
CHECK_EQ(r.elapsed.width(), 5);
REQUIRE(r.prefix);
REQUIRE(r.progress);
REQUIRE(r.current);
REQUIRE(r.separator);
REQUIRE(r.total);
REQUIRE(r.speed);
REQUIRE(r.postfix);
REQUIRE(r.elapsed);
REQUIRE(r.prefix.width() == 11);
REQUIRE(r.progress.width() == 39);
REQUIRE(r.current.width() == 3);
REQUIRE(r.separator.width() == 1);
REQUIRE(r.total.width() == 3);
REQUIRE(r.speed.width() == 3);
REQUIRE(r.postfix.width() == 11);
REQUIRE(r.elapsed.width() == 5);
}
TEST_CASE_FIXTURE(progress_bar, "print_remove_total_sep")
TEST_CASE_METHOD(progress_bar, "print_remove_total_sep")
{
auto& r = proxy.repr();
r.set_width(59);
proxy.update_repr();
CHECK(r.prefix);
CHECK(r.progress);
CHECK(r.current);
CHECK(r.separator);
CHECK(r.total);
CHECK(r.speed);
CHECK(r.postfix);
CHECK(r.elapsed);
CHECK_EQ(r.prefix.width(), 11);
CHECK_EQ(r.progress.width(), 15);
CHECK_EQ(r.current.width(), 3);
CHECK_EQ(r.separator.width(), 1);
CHECK_EQ(r.total.width(), 3);
CHECK_EQ(r.speed.width(), 3);
CHECK_EQ(r.postfix.width(), 11);
CHECK_EQ(r.elapsed.width(), 5);
REQUIRE(r.prefix);
REQUIRE(r.progress);
REQUIRE(r.current);
REQUIRE(r.separator);
REQUIRE(r.total);
REQUIRE(r.speed);
REQUIRE(r.postfix);
REQUIRE(r.elapsed);
REQUIRE(r.prefix.width() == 11);
REQUIRE(r.progress.width() == 15);
REQUIRE(r.current.width() == 3);
REQUIRE(r.separator.width() == 1);
REQUIRE(r.total.width() == 3);
REQUIRE(r.speed.width() == 3);
REQUIRE(r.postfix.width() == 11);
REQUIRE(r.elapsed.width() == 5);
// 2: remove the total value and the separator
// available space redistributed to the bar
r.set_width(58);
proxy.update_repr();
CHECK(r.prefix);
CHECK(r.progress);
CHECK(r.current);
CHECK_FALSE(r.separator);
CHECK_FALSE(r.total);
CHECK(r.speed);
CHECK(r.postfix);
CHECK(r.elapsed);
CHECK_EQ(r.prefix.width(), 11);
CHECK_EQ(r.progress.width(), 20);
CHECK_EQ(r.current.width(), 3);
CHECK_EQ(r.speed.width(), 3);
CHECK_EQ(r.postfix.width(), 11);
CHECK_EQ(r.elapsed.width(), 5);
REQUIRE(r.prefix);
REQUIRE(r.progress);
REQUIRE(r.current);
REQUIRE_FALSE(r.separator);
REQUIRE_FALSE(r.total);
REQUIRE(r.speed);
REQUIRE(r.postfix);
REQUIRE(r.elapsed);
REQUIRE(r.prefix.width() == 11);
REQUIRE(r.progress.width() == 20);
REQUIRE(r.current.width() == 3);
REQUIRE(r.speed.width() == 3);
REQUIRE(r.postfix.width() == 11);
REQUIRE(r.elapsed.width() == 5);
}
TEST_CASE_FIXTURE(progress_bar, "print_remove_speed")
TEST_CASE_METHOD(progress_bar, "print_remove_speed")
{
auto& r = proxy.repr();
r.set_width(53);
proxy.update_repr();
CHECK(r.prefix);
CHECK(r.progress);
CHECK(r.current);
CHECK_FALSE(r.separator);
CHECK_FALSE(r.total);
CHECK(r.speed);
CHECK(r.postfix);
CHECK(r.elapsed);
CHECK_EQ(r.prefix.width(), 11);
CHECK_EQ(r.progress.width(), 15);
CHECK_EQ(r.current.width(), 3);
CHECK_EQ(r.speed.width(), 3);
CHECK_EQ(r.postfix.width(), 11);
CHECK_EQ(r.elapsed.width(), 5);
REQUIRE(r.prefix);
REQUIRE(r.progress);
REQUIRE(r.current);
REQUIRE_FALSE(r.separator);
REQUIRE_FALSE(r.total);
REQUIRE(r.speed);
REQUIRE(r.postfix);
REQUIRE(r.elapsed);
REQUIRE(r.prefix.width() == 11);
REQUIRE(r.progress.width() == 15);
REQUIRE(r.current.width() == 3);
REQUIRE(r.speed.width() == 3);
REQUIRE(r.postfix.width() == 11);
REQUIRE(r.elapsed.width() == 5);
// 3: remove the speed
// available space redistributed to the bar
r.set_width(52);
proxy.update_repr();
CHECK(r.prefix);
CHECK(r.progress);
CHECK(r.current);
CHECK_FALSE(r.separator);
CHECK_FALSE(r.total);
CHECK_FALSE(r.speed);
CHECK(r.postfix);
CHECK(r.elapsed);
CHECK_EQ(r.prefix.width(), 11);
CHECK_EQ(r.progress.width(), 18);
CHECK_EQ(r.current.width(), 3);
CHECK_EQ(r.postfix.width(), 11);
CHECK_EQ(r.elapsed.width(), 5);
REQUIRE(r.prefix);
REQUIRE(r.progress);
REQUIRE(r.current);
REQUIRE_FALSE(r.separator);
REQUIRE_FALSE(r.total);
REQUIRE_FALSE(r.speed);
REQUIRE(r.postfix);
REQUIRE(r.elapsed);
REQUIRE(r.prefix.width() == 11);
REQUIRE(r.progress.width() == 18);
REQUIRE(r.current.width() == 3);
REQUIRE(r.postfix.width() == 11);
REQUIRE(r.elapsed.width() == 5);
}
TEST_CASE_FIXTURE(progress_bar, "print_remove_postfix")
TEST_CASE_METHOD(progress_bar, "print_remove_postfix")
{
auto& r = proxy.repr();
r.set_width(49);
proxy.update_repr();
CHECK(r.prefix);
CHECK(r.progress);
CHECK(r.current);
CHECK_FALSE(r.separator);
CHECK_FALSE(r.total);
CHECK_FALSE(r.speed);
CHECK(r.postfix);
CHECK(r.elapsed);
CHECK_EQ(r.prefix.width(), 11);
CHECK_EQ(r.progress.width(), 15);
CHECK_EQ(r.current.width(), 3);
CHECK_EQ(r.postfix.width(), 11);
CHECK_EQ(r.elapsed.width(), 5);
REQUIRE(r.prefix);
REQUIRE(r.progress);
REQUIRE(r.current);
REQUIRE_FALSE(r.separator);
REQUIRE_FALSE(r.total);
REQUIRE_FALSE(r.speed);
REQUIRE(r.postfix);
REQUIRE(r.elapsed);
REQUIRE(r.prefix.width() == 11);
REQUIRE(r.progress.width() == 15);
REQUIRE(r.current.width() == 3);
REQUIRE(r.postfix.width() == 11);
REQUIRE(r.elapsed.width() == 5);
// 4: remove the postfix
// available space redistributed to the bar
r.set_width(48);
proxy.update_repr();
CHECK(r.prefix);
CHECK(r.progress);
CHECK(r.current);
CHECK_FALSE(r.separator);
CHECK_FALSE(r.total);
CHECK_FALSE(r.speed);
CHECK_FALSE(r.postfix);
CHECK(r.elapsed);
CHECK_EQ(r.prefix.width(), 11);
CHECK_EQ(r.progress.width(), 26);
CHECK_EQ(r.current.width(), 3);
CHECK_EQ(r.elapsed.width(), 5);
REQUIRE(r.prefix);
REQUIRE(r.progress);
REQUIRE(r.current);
REQUIRE_FALSE(r.separator);
REQUIRE_FALSE(r.total);
REQUIRE_FALSE(r.speed);
REQUIRE_FALSE(r.postfix);
REQUIRE(r.elapsed);
REQUIRE(r.prefix.width() == 11);
REQUIRE(r.progress.width() == 26);
REQUIRE(r.current.width() == 3);
REQUIRE(r.elapsed.width() == 5);
}
TEST_CASE_FIXTURE(progress_bar, "print_truncate_prefix")
TEST_CASE_METHOD(progress_bar, "print_truncate_prefix")
{
auto& r = proxy.repr();
proxy.set_prefix("some_very_very_long_prefix");
r.set_width(52);
proxy.update_repr();
CHECK(r.prefix);
CHECK(r.progress);
CHECK(r.current);
CHECK_FALSE(r.separator);
CHECK_FALSE(r.total);
CHECK_FALSE(r.speed);
CHECK_FALSE(r.postfix);
CHECK(r.elapsed);
CHECK_EQ(r.prefix.width(), 26);
CHECK_EQ(r.progress.width(), 15);
CHECK_EQ(r.current.width(), 3);
CHECK_EQ(r.elapsed.width(), 5);
REQUIRE(r.prefix);
REQUIRE(r.progress);
REQUIRE(r.current);
REQUIRE_FALSE(r.separator);
REQUIRE_FALSE(r.total);
REQUIRE_FALSE(r.speed);
REQUIRE_FALSE(r.postfix);
REQUIRE(r.elapsed);
REQUIRE(r.prefix.width() == 26);
REQUIRE(r.progress.width() == 15);
REQUIRE(r.current.width() == 3);
REQUIRE(r.elapsed.width() == 5);
// 5: truncate the prefix if too long
// available space redistributed to the prefix
r.set_width(51);
proxy.update_repr();
CHECK(r.prefix);
CHECK(r.progress);
CHECK(r.current);
CHECK_FALSE(r.separator);
CHECK_FALSE(r.total);
CHECK_FALSE(r.speed);
CHECK_FALSE(r.postfix);
CHECK(r.elapsed);
CHECK_EQ(r.prefix.width(), 25);
CHECK_EQ(r.progress.width(), 15);
CHECK_EQ(r.current.width(), 3);
CHECK_EQ(r.elapsed.width(), 5);
REQUIRE(r.prefix);
REQUIRE(r.progress);
REQUIRE(r.current);
REQUIRE_FALSE(r.separator);
REQUIRE_FALSE(r.total);
REQUIRE_FALSE(r.speed);
REQUIRE_FALSE(r.postfix);
REQUIRE(r.elapsed);
REQUIRE(r.prefix.width() == 25);
REQUIRE(r.progress.width() == 15);
REQUIRE(r.current.width() == 3);
REQUIRE(r.elapsed.width() == 5);
}
TEST_CASE_FIXTURE(progress_bar, "print_without_bar")
TEST_CASE_METHOD(progress_bar, "print_without_bar")
{
auto& r = proxy.repr();
r.set_width(34).reset_fields();
proxy.update_repr();
CHECK(r.prefix);
CHECK(r.progress);
CHECK(r.current);
CHECK_FALSE(r.separator);
CHECK_FALSE(r.total);
CHECK_FALSE(r.speed);
CHECK_FALSE(r.postfix);
CHECK(r.elapsed);
CHECK_EQ(r.prefix.width(), 11);
CHECK_EQ(r.progress.width(), 12);
CHECK_EQ(r.current.width(), 3);
REQUIRE(r.prefix);
REQUIRE(r.progress);
REQUIRE(r.current);
REQUIRE_FALSE(r.separator);
REQUIRE_FALSE(r.total);
REQUIRE_FALSE(r.speed);
REQUIRE_FALSE(r.postfix);
REQUIRE(r.elapsed);
REQUIRE(r.prefix.width() == 11);
REQUIRE(r.progress.width() == 12);
REQUIRE(r.current.width() == 3);
// This fails because of invisible ANSI escape codes introduced with
// https://github.com/mamba-org/mamba/pull/2085/
// CHECK(r.progress.overflow());
CHECK_EQ(r.elapsed.width(), 5);
// REQUIRE(r.progress.overflow());
REQUIRE(r.elapsed.width() == 5);
// 6: display progress without a bar
r.set_width(33);
proxy.update_repr();
proxy.print(ostream, 0, false);
CHECK_EQ(ostream.str(), "conda-forge 0% foo --");
REQUIRE(ostream.str() == "conda-forge 0% foo --");
ostream.str("");
}
TEST_CASE_FIXTURE(progress_bar, "print_remove_current")
TEST_CASE_METHOD(progress_bar, "print_remove_current")
{
auto& r = proxy.repr();
r.set_width(26).reset_fields();
proxy.update_repr();
proxy.print(ostream, 0, false);
CHECK_EQ(ostream.str(), "conda-forge 0% foo --");
REQUIRE(ostream.str() == "conda-forge 0% foo --");
ostream.str("");
// 7: remove the current value
r.set_width(25).reset_fields();
proxy.update_repr();
proxy.print(ostream, 0, false);
CHECK_EQ(ostream.str(), "conda-forge 0% --");
REQUIRE(ostream.str() == "conda-forge 0% --");
ostream.str("");
}
TEST_CASE_FIXTURE(progress_bar, "print_remove_elapsed")
TEST_CASE_METHOD(progress_bar, "print_remove_elapsed")
{
auto& r = proxy.repr();
r.set_width(22).reset_fields();
proxy.update_repr();
CHECK(r.prefix);
CHECK(r.progress);
CHECK_FALSE(r.current);
CHECK_FALSE(r.separator);
CHECK_FALSE(r.total);
CHECK_FALSE(r.speed);
CHECK_FALSE(r.postfix);
CHECK(r.elapsed);
REQUIRE(r.prefix);
REQUIRE(r.progress);
REQUIRE_FALSE(r.current);
REQUIRE_FALSE(r.separator);
REQUIRE_FALSE(r.total);
REQUIRE_FALSE(r.speed);
REQUIRE_FALSE(r.postfix);
REQUIRE(r.elapsed);
proxy.print(ostream, 0, false);
CHECK_EQ(r.prefix.width(), 11);
CHECK_EQ(r.progress.width(), 4);
CHECK_EQ(r.elapsed.width(), 5);
CHECK_EQ(ostream.str(), "conda-forge 0% --");
REQUIRE(r.prefix.width() == 11);
REQUIRE(r.progress.width() == 4);
REQUIRE(r.elapsed.width() == 5);
REQUIRE(ostream.str() == "conda-forge 0% --");
ostream.str("");
// 8: remove the elapsed time
r.set_width(21);
proxy.update_repr();
proxy.print(ostream, 0, false);
CHECK_EQ(r.prefix.width(), 11);
CHECK_EQ(r.progress.width(), 9);
CHECK_EQ(ostream.str(), "conda-forge 0%");
REQUIRE(r.prefix.width() == 11);
REQUIRE(r.progress.width() == 9);
REQUIRE(ostream.str() == "conda-forge 0%");
ostream.str("");
}
}

View File

@ -4,11 +4,11 @@
//
// The full license is in the file LICENSE, distributed with this software.
#include <doctest/doctest.h>
#include <catch2/catch_all.hpp>
namespace mamba
{
TEST_SUITE("shell_init")
namespace
{
TEST_CASE("init")
{

View File

@ -9,7 +9,7 @@
#include <thread>
#include <type_traits>
#include <doctest/doctest.h>
#include <catch2/catch_all.hpp>
#include "mamba/core/tasksync.hpp"
@ -38,7 +38,7 @@ namespace mamba
}
}
TEST_SUITE("task_synchronizer")
namespace
{
TEST_CASE("sync_types_never_move")
{
@ -57,26 +57,26 @@ namespace mamba
TEST_CASE("tasks_are_joined_after_join_not_after_reset")
{
TaskSynchronizer task_sync;
CHECK_FALSE(task_sync.is_joined());
REQUIRE_FALSE(task_sync.is_joined());
task_sync.join_tasks();
CHECK(task_sync.is_joined());
REQUIRE(task_sync.is_joined());
task_sync.reset();
CHECK_FALSE(task_sync.is_joined());
REQUIRE_FALSE(task_sync.is_joined());
task_sync.join_tasks();
CHECK(task_sync.is_joined());
REQUIRE(task_sync.is_joined());
}
TEST_CASE("once_joined_tasks_are_noop")
{
TaskSynchronizer task_sync;
task_sync.join_tasks();
CHECK(task_sync.is_joined());
REQUIRE(task_sync.is_joined());
task_sync.join_tasks(); // nothing happen if we call it twice
CHECK(task_sync.is_joined());
REQUIRE(task_sync.is_joined());
auto no_op = task_sync.synchronized([] { fail_now(); });
no_op();
@ -95,16 +95,16 @@ namespace mamba
int execution_count = 0;
TaskSynchronizer task_sync;
auto synched_task = task_sync.synchronized([&] { ++execution_count; });
CHECK_EQ(execution_count, 0);
REQUIRE(execution_count == 0);
synched_task();
CHECK_EQ(execution_count, 1);
REQUIRE(execution_count == 1);
task_sync.join_tasks();
CHECK_EQ(execution_count, 1);
REQUIRE(execution_count == 1);
synched_task();
CHECK_EQ(execution_count, 1);
REQUIRE(execution_count == 1);
}
TEST_CASE("executed_synched_task_never_blocks_join")
@ -120,7 +120,7 @@ namespace mamba
synched_task();
CHECK_EQ(execution_count, 1);
REQUIRE(execution_count == 1);
}
TEST_CASE("executing_synched_task_always_block_join")
@ -148,7 +148,7 @@ namespace mamba
);
wait_condition([&] { return task_started.load(); });
CHECK_EQ(sequence, "A");
REQUIRE(sequence == "A");
auto ft_unlocker = std::async(
std::launch::async,
@ -169,7 +169,7 @@ namespace mamba
);
wait_condition([&] { return unlocker_ready.load(); });
CHECK_EQ(sequence, "AB");
REQUIRE(sequence == "AB");
sequence.push_back('C');
@ -184,8 +184,8 @@ namespace mamba
// reordering
const auto end_time = std::chrono::high_resolution_clock::now();
CHECK_EQ(sequence, "ABCDEF");
REQUIRE_GE(end_time - begin_time, unlock_duration);
REQUIRE(sequence == "ABCDEF");
REQUIRE(end_time - begin_time >= unlock_duration);
}
TEST_CASE("throwing_task_never_block_join")
@ -200,7 +200,7 @@ namespace mamba
synched_task();
CHECK_THROWS_AS(task_future.get(), int);
REQUIRE_THROWS_AS(task_future.get(), int);
}
}

View File

@ -6,7 +6,7 @@
#include <iostream>
#include <doctest/doctest.h>
#include <catch2/catch_all.hpp>
#include "mamba/core/context.hpp"
#include "mamba/core/execution.hpp"
@ -27,7 +27,7 @@ namespace mamba
int res = 0;
// Ensures the compiler doe snot optimize away mambatests::context()
std::string current_command = mambatests::context().command_params.current_command;
CHECK_EQ(current_command, "mamba");
REQUIRE(current_command == "mamba");
Console::instance().init_progress_bar_manager(ProgressBarMode::multi);
{
interruption_guard g(
@ -65,34 +65,34 @@ namespace mamba
return res;
}
TEST_SUITE("thread_utils")
namespace
{
TEST_CASE("interrupt")
{
int res = test_interruption_guard(true);
CHECK_EQ(res, -95);
REQUIRE(res == -95);
}
TEST_CASE("no_interrupt")
{
int res = test_interruption_guard(false);
CHECK_EQ(res, 5);
REQUIRE(res == 5);
}
TEST_CASE("no_interrupt_then_interrupt")
{
int res = test_interruption_guard(false);
CHECK_EQ(res, 5);
REQUIRE(res == 5);
int res2 = test_interruption_guard(true);
CHECK_EQ(res2, -95);
REQUIRE(res2 == -95);
}
TEST_CASE("no_interrupt_sequence")
{
int res = test_interruption_guard(false);
CHECK_EQ(res, 5);
REQUIRE(res == 5);
int res2 = test_interruption_guard(false);
CHECK_EQ(res2, 5);
REQUIRE(res2 == 5);
}
}
#endif

View File

@ -4,7 +4,7 @@
//
// The full license is in the file LICENSE, distributed with this software.
#include <doctest/doctest.h>
#include <catch2/catch_all.hpp>
#include "mamba/core/context.hpp"
#include "mamba/core/fsutil.hpp"
@ -17,54 +17,54 @@
namespace mamba
{
TEST_SUITE("on_scope_exit")
namespace
{
TEST_CASE("basics")
{
bool executed = false;
{
on_scope_exit _{ [&] { executed = true; } };
CHECK_FALSE(executed);
REQUIRE_FALSE(executed);
}
CHECK(executed);
REQUIRE(executed);
}
}
TEST_SUITE("is_yaml_file_name")
namespace
{
TEST_CASE("basics")
TEST_CASE("is_yaml_file_name")
{
CHECK(is_yaml_file_name("something.yaml"));
CHECK(is_yaml_file_name("something.yml"));
CHECK(is_yaml_file_name("something-lock.yaml"));
CHECK(is_yaml_file_name("something-lock.yml"));
CHECK(is_yaml_file_name("/some/dir/something.yaml"));
CHECK(is_yaml_file_name("/some/dir/something.yaml"));
CHECK(is_yaml_file_name("../../some/dir/something.yml"));
CHECK(is_yaml_file_name("../../some/dir/something.yml"));
REQUIRE(is_yaml_file_name("something.yaml"));
REQUIRE(is_yaml_file_name("something.yml"));
REQUIRE(is_yaml_file_name("something-lock.yaml"));
REQUIRE(is_yaml_file_name("something-lock.yml"));
REQUIRE(is_yaml_file_name("/some/dir/something.yaml"));
REQUIRE(is_yaml_file_name("/some/dir/something.yaml"));
REQUIRE(is_yaml_file_name("../../some/dir/something.yml"));
REQUIRE(is_yaml_file_name("../../some/dir/something.yml"));
CHECK(is_yaml_file_name(fs::u8path{ "something.yaml" }.string()));
CHECK(is_yaml_file_name(fs::u8path{ "something.yml" }.string()));
CHECK(is_yaml_file_name(fs::u8path{ "something-lock.yaml" }.string()));
CHECK(is_yaml_file_name(fs::u8path{ "something-lock.yml" }.string()));
CHECK(is_yaml_file_name(fs::u8path{ "/some/dir/something.yaml" }.string()));
CHECK(is_yaml_file_name(fs::u8path{ "/some/dir/something.yml" }.string()));
CHECK(is_yaml_file_name(fs::u8path{ "../../some/dir/something.yaml" }.string()));
CHECK(is_yaml_file_name(fs::u8path{ "../../some/dir/something.yml" }.string()));
REQUIRE(is_yaml_file_name(fs::u8path{ "something.yaml" }.string()));
REQUIRE(is_yaml_file_name(fs::u8path{ "something.yml" }.string()));
REQUIRE(is_yaml_file_name(fs::u8path{ "something-lock.yaml" }.string()));
REQUIRE(is_yaml_file_name(fs::u8path{ "something-lock.yml" }.string()));
REQUIRE(is_yaml_file_name(fs::u8path{ "/some/dir/something.yaml" }.string()));
REQUIRE(is_yaml_file_name(fs::u8path{ "/some/dir/something.yml" }.string()));
REQUIRE(is_yaml_file_name(fs::u8path{ "../../some/dir/something.yaml" }.string()));
REQUIRE(is_yaml_file_name(fs::u8path{ "../../some/dir/something.yml" }.string()));
CHECK_FALSE(is_yaml_file_name("something"));
CHECK_FALSE(is_yaml_file_name("something-lock"));
CHECK_FALSE(is_yaml_file_name("/some/dir/something"));
CHECK_FALSE(is_yaml_file_name("../../some/dir/something"));
REQUIRE_FALSE(is_yaml_file_name("something"));
REQUIRE_FALSE(is_yaml_file_name("something-lock"));
REQUIRE_FALSE(is_yaml_file_name("/some/dir/something"));
REQUIRE_FALSE(is_yaml_file_name("../../some/dir/something"));
CHECK_FALSE(is_yaml_file_name(fs::u8path{ "something" }.string()));
CHECK_FALSE(is_yaml_file_name(fs::u8path{ "something-lock" }.string()));
CHECK_FALSE(is_yaml_file_name(fs::u8path{ "/some/dir/something" }.string()));
CHECK_FALSE(is_yaml_file_name(fs::u8path{ "../../some/dir/something" }.string()));
REQUIRE_FALSE(is_yaml_file_name(fs::u8path{ "something" }.string()));
REQUIRE_FALSE(is_yaml_file_name(fs::u8path{ "something-lock" }.string()));
REQUIRE_FALSE(is_yaml_file_name(fs::u8path{ "/some/dir/something" }.string()));
REQUIRE_FALSE(is_yaml_file_name(fs::u8path{ "../../some/dir/something" }.string()));
}
}
TEST_SUITE("fsutils")
namespace
{
TEST_CASE("is_writable")
{
@ -76,19 +76,19 @@ namespace mamba
fs::remove_all(test_dir_path);
} };
CHECK(path::is_writable(test_dir_path));
REQUIRE(path::is_writable(test_dir_path));
fs::permissions(test_dir_path, fs::perms::none);
CHECK_FALSE(path::is_writable(test_dir_path));
REQUIRE_FALSE(path::is_writable(test_dir_path));
fs::permissions(test_dir_path, fs::perms::all);
CHECK(path::is_writable(test_dir_path));
REQUIRE(path::is_writable(test_dir_path));
CHECK(path::is_writable(test_dir_path / "non-existing-writable-test-delete-me.txt"));
CHECK(path::is_writable(
REQUIRE(path::is_writable(test_dir_path / "non-existing-writable-test-delete-me.txt"));
REQUIRE(path::is_writable(
util::expand_home("~/.libmamba-non-existing-writable-test-delete-me.txt")
));
CHECK(path::is_writable(test_dir_path / "non-existing-subfolder"));
CHECK_FALSE(fs::exists(test_dir_path / "non-existing-subfolder"));
REQUIRE(path::is_writable(test_dir_path / "non-existing-subfolder"));
REQUIRE_FALSE(fs::exists(test_dir_path / "non-existing-subfolder"));
{
const auto existing_file_path = test_dir_path
@ -98,16 +98,16 @@ namespace mamba
REQUIRE(temp_file.is_open());
temp_file << "delete me" << std::endl;
}
CHECK(path::is_writable(existing_file_path));
REQUIRE(path::is_writable(existing_file_path));
fs::permissions(existing_file_path, fs::perms::none);
CHECK_FALSE(path::is_writable(existing_file_path));
REQUIRE_FALSE(path::is_writable(existing_file_path));
fs::permissions(existing_file_path, fs::perms::all);
CHECK(path::is_writable(existing_file_path));
REQUIRE(path::is_writable(existing_file_path));
}
}
}
TEST_SUITE("utils")
namespace
{
TEST_CASE("proxy_match")
{
@ -121,24 +121,24 @@ namespace mamba
auto proxy_match_with_context = [&](const char* url)
{ return proxy_match(url, context.remote_fetch_params.proxy_servers); };
CHECK_EQ(*proxy_match_with_context("http://example.com/channel"), "foo");
CHECK_EQ(*proxy_match_with_context("http://example.net/channel"), "foo");
CHECK_EQ(*proxy_match_with_context("https://example.com/channel"), "bar");
CHECK_EQ(*proxy_match_with_context("https://example.com:8080/channel"), "bar");
CHECK_EQ(*proxy_match_with_context("https://example.net/channel"), "foobar");
CHECK_EQ(*proxy_match_with_context("ftp://example.net/channel"), "baz");
CHECK_EQ(*proxy_match_with_context("ftp://example.org"), "other");
REQUIRE(*proxy_match_with_context("http://example.com/channel") == "foo");
REQUIRE(*proxy_match_with_context("http://example.net/channel") == "foo");
REQUIRE(*proxy_match_with_context("https://example.com/channel") == "bar");
REQUIRE(*proxy_match_with_context("https://example.com:8080/channel") == "bar");
REQUIRE(*proxy_match_with_context("https://example.net/channel") == "foobar");
REQUIRE(*proxy_match_with_context("ftp://example.net/channel") == "baz");
REQUIRE(*proxy_match_with_context("ftp://example.org") == "other");
context.remote_fetch_params.proxy_servers = { { "http", "foo" },
{ "https", "bar" },
{ "https://example.net", "foobar" },
{ "all://example.net", "baz" } };
CHECK_FALSE(proxy_match_with_context("ftp://example.org").has_value());
REQUIRE_FALSE(proxy_match_with_context("ftp://example.org").has_value());
context.remote_fetch_params.proxy_servers = {};
CHECK_FALSE(proxy_match_with_context("http://example.com/channel").has_value());
REQUIRE_FALSE(proxy_match_with_context("http://example.com/channel").has_value());
}
}
}

View File

@ -4,7 +4,7 @@
//
// The full license is in the file LICENSE, distributed with this software.
#include <doctest/doctest.h>
#include <catch2/catch_all.hpp>
#include "mamba/core/context.hpp"
#include "mamba/core/virtual_packages.hpp"
@ -30,21 +30,21 @@ namespace mamba
}
};
TEST_SUITE("virtual_packages")
namespace
{
TEST_CASE("make_virtual_package")
{
const auto& context = mambatests::context();
const auto pkg = detail::make_virtual_package("test", context.platform, "0.1.5", "abcd");
CHECK_EQ(pkg.name, "test");
CHECK_EQ(pkg.version, "0.1.5");
CHECK_EQ(pkg.build_string, "abcd");
CHECK_EQ(pkg.build_number, 0);
CHECK_EQ(pkg.channel, "@");
CHECK_EQ(pkg.platform, context.platform);
CHECK_EQ(pkg.md5, "12345678901234567890123456789012");
CHECK_EQ(pkg.filename, pkg.name);
REQUIRE(pkg.name == "test");
REQUIRE(pkg.version == "0.1.5");
REQUIRE(pkg.build_string == "abcd");
REQUIRE(pkg.build_number == 0);
REQUIRE(pkg.channel == "@");
REQUIRE(pkg.platform == context.platform);
REQUIRE(pkg.md5 == "12345678901234567890123456789012");
REQUIRE(pkg.filename == pkg.name);
}
TEST_CASE("dist_packages")
@ -56,29 +56,29 @@ namespace mamba
if (util::on_win)
{
REQUIRE_EQ(pkgs.size(), 2);
CHECK_EQ(pkgs[0].name, "__win");
CHECK_GT(Version::parse(pkgs[0].version).value(), Version());
REQUIRE(pkgs.size() == 2);
REQUIRE(pkgs[0].name == "__win");
REQUIRE(Version::parse(pkgs[0].version).value() > Version());
}
if (util::on_linux)
{
REQUIRE_EQ(pkgs.size(), 4);
CHECK_EQ(pkgs[0].name, "__unix");
CHECK_EQ(pkgs[1].name, "__linux");
CHECK_GT(Version::parse(pkgs[1].version).value(), Version());
CHECK_EQ(pkgs[2].name, "__glibc");
CHECK_GT(Version::parse(pkgs[2].version).value(), Version());
REQUIRE(pkgs.size() == 4);
REQUIRE(pkgs[0].name == "__unix");
REQUIRE(pkgs[1].name == "__linux");
REQUIRE(Version::parse(pkgs[1].version).value() > Version());
REQUIRE(pkgs[2].name == "__glibc");
REQUIRE(Version::parse(pkgs[2].version).value() > Version());
}
if (util::on_mac)
{
REQUIRE_EQ(pkgs.size(), 3);
CHECK_EQ(pkgs[0].name, "__unix");
CHECK_EQ(pkgs[1].name, "__osx");
CHECK_GT(Version::parse(pkgs[1].version).value(), Version());
REQUIRE(pkgs.size() == 3);
REQUIRE(pkgs[0].name == "__unix");
REQUIRE(pkgs[1].name == "__osx");
CHECK(Version::parse(pkgs[1].version).value() > Version());
}
#if __x86_64__ || defined(_WIN64)
CHECK_EQ(pkgs.back().name, "__archspec");
CHECK_EQ(pkgs.back().build_string.find("x86_64"), 0);
REQUIRE(pkgs.back().name == "__archspec");
REQUIRE(pkgs.back().build_string.find("x86_64") == 0);
#endif
// This is bad design, tests should not interfere
@ -88,36 +88,36 @@ namespace mamba
util::set_env("CONDA_OVERRIDE_OSX", "12.1");
pkgs = detail::dist_packages("osx-arm");
REQUIRE_EQ(pkgs.size(), 3);
CHECK_EQ(pkgs[0].name, "__unix");
CHECK_EQ(pkgs[1].name, "__osx");
CHECK_EQ(pkgs[1].version, "12.1");
CHECK_EQ(pkgs[2].name, "__archspec");
CHECK_EQ(pkgs[2].build_string, "arm");
REQUIRE(pkgs.size() == 3);
REQUIRE(pkgs[0].name == "__unix");
REQUIRE(pkgs[1].name == "__osx");
REQUIRE(pkgs[1].version == "12.1");
REQUIRE(pkgs[2].name == "__archspec");
REQUIRE(pkgs[2].build_string == "arm");
util::unset_env("CONDA_OVERRIDE_OSX");
util::set_env("CONDA_OVERRIDE_LINUX", "5.7");
util::set_env("CONDA_OVERRIDE_GLIBC", "2.15");
pkgs = detail::dist_packages("linux-32");
REQUIRE_EQ(pkgs.size(), 4);
CHECK_EQ(pkgs[0].name, "__unix");
CHECK_EQ(pkgs[1].name, "__linux");
CHECK_EQ(pkgs[1].version, "5.7");
CHECK_EQ(pkgs[2].name, "__glibc");
CHECK_EQ(pkgs[2].version, "2.15");
CHECK_EQ(pkgs[3].name, "__archspec");
CHECK_EQ(pkgs[3].build_string, "x86");
REQUIRE(pkgs.size() == 4);
REQUIRE(pkgs[0].name == "__unix");
REQUIRE(pkgs[1].name == "__linux");
REQUIRE(pkgs[1].version == "5.7");
REQUIRE(pkgs[2].name == "__glibc");
REQUIRE(pkgs[2].version == "2.15");
REQUIRE(pkgs[3].name == "__archspec");
REQUIRE(pkgs[3].build_string == "x86");
util::unset_env("CONDA_OVERRIDE_GLIBC");
util::unset_env("CONDA_OVERRIDE_LINUX");
pkgs = detail::dist_packages("lin-850");
REQUIRE_EQ(pkgs.size(), 1);
CHECK_EQ(pkgs[0].name, "__archspec");
CHECK_EQ(pkgs[0].build_string, "850");
REQUIRE(pkgs.size() == 1);
REQUIRE(pkgs[0].name == "__archspec");
REQUIRE(pkgs[0].build_string == "850");
util::unset_env("CONDA_SUBDIR");
pkgs = detail::dist_packages("linux");
REQUIRE_EQ(pkgs.size(), 0);
REQUIRE(pkgs.size() == 0);
ctx.platform = ctx.host_platform;
}
@ -127,7 +127,7 @@ namespace mamba
util::set_env("CONDA_OVERRIDE_CUDA", "9.0");
const auto& context = mambatests::context();
auto pkgs = get_virtual_packages(context.platform);
int pkgs_count;
size_t pkgs_count;
if (util::on_win)
{
@ -143,20 +143,20 @@ namespace mamba
}
++pkgs_count;
REQUIRE_EQ(pkgs.size(), pkgs_count);
CHECK_EQ(pkgs.back().name, "__cuda");
CHECK_EQ(pkgs.back().version, "9.0");
REQUIRE(pkgs.size() == pkgs_count);
REQUIRE(pkgs.back().name == "__cuda");
REQUIRE(pkgs.back().version == "9.0");
util::unset_env("CONDA_OVERRIDE_CUDA");
pkgs = get_virtual_packages(context.platform);
if (!detail::cuda_version().empty())
{
REQUIRE_EQ(pkgs.size(), pkgs_count);
REQUIRE(pkgs.size() == pkgs_count);
}
else
{
REQUIRE_EQ(pkgs.size(), pkgs_count - 1);
REQUIRE(pkgs.size() == pkgs_count - 1);
}
}
}

View File

@ -1,23 +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 <array>
#include <doctest/doctest.h>
#include <fmt/format.h>
#include <fmt/ranges.h>
namespace doctest
{
template <typename T, std::size_t N>
struct StringMaker<std::array<T, N>>
{
static auto convert(const std::array<T, N>& value) -> String
{
return { fmt::format("std::array{{{}}}", fmt::join(value, ", ")).c_str() };
}
};
}

View File

@ -1,23 +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 <doctest/doctest.h>
#include <fmt/format.h>
#include <fmt/ranges.h>
#include "mamba/util/flat_set.hpp"
namespace doctest
{
template <typename K, typename C, typename A>
struct StringMaker<mamba::util::flat_set<K, C, A>>
{
static auto convert(const mamba::util::flat_set<K, C, A>& value) -> String
{
return { fmt::format("mamba::util::flat_set{{{}}}", fmt::join(value, ", ")).c_str() };
}
};
}

View File

@ -1,26 +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 <optional>
#include <doctest/doctest.h>
#include <fmt/format.h>
namespace doctest
{
template <typename T>
struct StringMaker<std::optional<T>>
{
static auto convert(const std::optional<T>& value) -> String
{
if (value.has_value())
{
return { fmt::format("Some({})", value.value()).c_str() };
}
return "None";
}
};
}

View File

@ -1,22 +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 <utility>
#include <doctest/doctest.h>
#include <fmt/format.h>
namespace doctest
{
template <typename T, typename U>
struct StringMaker<std::pair<T, U>>
{
static auto convert(const std::pair<T, U>& value) -> String
{
return { fmt::format("std::pair{{{}, {}}}", value.first, value.second).c_str() };
}
};
}

View File

@ -1,23 +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 <vector>
#include <doctest/doctest.h>
#include <fmt/format.h>
#include <fmt/ranges.h>
namespace doctest
{
template <typename T, typename A>
struct StringMaker<std::vector<T, A>>
{
static auto convert(const std::vector<T, A>& value) -> String
{
return { fmt::format("std::vector{{{}}}", fmt::join(value, ", ")).c_str() };
}
};
}

View File

@ -4,7 +4,7 @@
//
// The full license is in the file LICENSE, distributed with this software.
#include <doctest/doctest.h>
#include <catch2/catch_all.hpp>
#include "mamba/download/downloader.hpp"
@ -12,7 +12,7 @@
namespace mamba
{
TEST_SUITE("downloader")
namespace
{
TEST_CASE("file_does_not_exist")
{
@ -31,9 +31,9 @@ namespace mamba
download::MultiRequest dl_request{ std::vector{ std::move(request) } };
context.output_params.quiet = true;
download::MultiResult res = download::download(dl_request, context.mirrors, context);
CHECK_EQ(res.size(), std::size_t(1));
CHECK(!res[0]);
CHECK_EQ(res[0].error().attempt_number, std::size_t(1));
REQUIRE(res.size() == std::size_t(1));
REQUIRE(!res[0]);
REQUIRE(res[0].error().attempt_number == std::size_t(1));
}
TEST_CASE("file_does_not_exist_throw")
@ -49,7 +49,10 @@ namespace mamba
const auto previous_quiet = context.output_params.quiet;
auto _ = on_scope_exit([&] { context.output_params.quiet = previous_quiet; });
context.output_params.quiet = true;
CHECK_THROWS_AS(download::download(dl_request, context.mirrors, context), std::runtime_error);
REQUIRE_THROWS_AS(
download::download(dl_request, context.mirrors, context),
std::runtime_error
);
}
}
}

View File

@ -6,7 +6,7 @@
#include <typeinfo>
#include <doctest/doctest.h>
#include <catch2/catch_all.hpp>
#include "../src/download/mirror_impl.hpp"
@ -16,44 +16,44 @@ namespace mamba::download
{
std::pair<std::string, std::string> split_path_tag(const std::string& path);
TEST_SUITE("split_path_tag")
namespace
{
TEST_CASE("tar_bz2_extension")
{
auto [split_path, split_tag] = split_path_tag("xtensor-0.23.10-h2acdbc0_0.tar.bz2");
CHECK_EQ(split_path, "xtensor");
CHECK_EQ(split_tag, "0.23.10-h2acdbc0-0");
REQUIRE(split_path == "xtensor");
REQUIRE(split_tag == "0.23.10-h2acdbc0-0");
}
TEST_CASE("multiple_parts")
{
auto [split_path, split_tag] = split_path_tag("x-tensor-10.23.10-h2acdbc0_0.tar.bz2");
CHECK_EQ(split_path, "x-tensor");
CHECK_EQ(split_tag, "10.23.10-h2acdbc0-0");
REQUIRE(split_path == "x-tensor");
REQUIRE(split_tag == "10.23.10-h2acdbc0-0");
}
TEST_CASE("more_multiple_parts")
{
auto [split_path, split_tag] = split_path_tag("x-tens-or-10.23.10-h2acdbc0_0.tar.bz2");
CHECK_EQ(split_path, "x-tens-or");
CHECK_EQ(split_tag, "10.23.10-h2acdbc0-0");
REQUIRE(split_path == "x-tens-or");
REQUIRE(split_tag == "10.23.10-h2acdbc0-0");
}
TEST_CASE("json_extension")
{
auto [split_path, split_tag] = split_path_tag("xtensor-0.23.10-h2acdbc0_0.json");
CHECK_EQ(split_path, "xtensor-0.23.10-h2acdbc0_0.json");
CHECK_EQ(split_tag, "latest");
REQUIRE(split_path == "xtensor-0.23.10-h2acdbc0_0.json");
REQUIRE(split_tag == "latest");
}
TEST_CASE("not_enough_parts")
{
CHECK_THROWS_AS(split_path_tag("xtensor.tar.bz2"), std::runtime_error);
REQUIRE_THROWS_AS(split_path_tag("xtensor.tar.bz2"), std::runtime_error);
}
}
}
TEST_SUITE("mirrors")
namespace
{
TEST_CASE("PassThroughMirror")
{
@ -61,30 +61,30 @@ namespace mamba::download
// `mir_ref` is used here to provide an explicit expression to `typeid`
// and avoid expression with side effects evaluation warning
auto& mir_ref = *mir;
CHECK_EQ(typeid(mir_ref), typeid(PassThroughMirror));
REQUIRE(typeid(mir_ref) == typeid(PassThroughMirror));
Mirror::request_generator_list req_gen = mir->get_request_generators("", "");
CHECK_EQ(req_gen.size(), 1);
REQUIRE(req_gen.size() == 1);
Request req_repodata("some_request_name", MirrorName("mirror_name"), "linux-64/repodata.json");
MirrorRequest mir_req = req_gen[0](req_repodata, nullptr);
CHECK_EQ(mir_req.name, "some_request_name");
CHECK_EQ(mir_req.url, "linux-64/repodata.json");
REQUIRE(mir_req.name == "some_request_name");
REQUIRE(mir_req.url == "linux-64/repodata.json");
}
TEST_CASE("HTTPMirror")
{
SUBCASE("https")
SECTION("https")
{
std::unique_ptr<Mirror> mir = make_mirror("https://conda.anaconda.org/conda-forge");
// `mir_ref` is used here to provide an explicit expression to `typeid`
// and avoid expression with side effects evaluation warning
auto& mir_ref = *mir;
CHECK_EQ(typeid(mir_ref), typeid(HTTPMirror));
REQUIRE(typeid(mir_ref) == typeid(HTTPMirror));
Mirror::request_generator_list req_gen = mir->get_request_generators("", "");
CHECK_EQ(req_gen.size(), 1);
REQUIRE(req_gen.size() == 1);
Request req_repodata(
"repodata_request",
@ -93,20 +93,20 @@ namespace mamba::download
);
MirrorRequest mir_req = req_gen[0](req_repodata, nullptr);
CHECK_EQ(mir_req.name, "repodata_request");
CHECK_EQ(mir_req.url, "https://conda.anaconda.org/conda-forge/linux-64/repodata.json");
REQUIRE(mir_req.name == "repodata_request");
REQUIRE(mir_req.url == "https://conda.anaconda.org/conda-forge/linux-64/repodata.json");
}
SUBCASE("http")
SECTION("http")
{
std::unique_ptr<Mirror> mir = make_mirror("http://conda.anaconda.org/conda-forge");
// `mir_ref` is used here to provide an explicit expression to `typeid`
// and avoid expression with side effects evaluation warning
auto& mir_ref = *mir;
CHECK_EQ(typeid(mir_ref), typeid(HTTPMirror));
REQUIRE(typeid(mir_ref) == typeid(HTTPMirror));
Mirror::request_generator_list req_gen = mir->get_request_generators("", "");
CHECK_EQ(req_gen.size(), 1);
REQUIRE(req_gen.size() == 1);
Request req_repodata(
"repodata_request",
@ -115,20 +115,20 @@ namespace mamba::download
);
MirrorRequest mir_req = req_gen[0](req_repodata, nullptr);
CHECK_EQ(mir_req.name, "repodata_request");
CHECK_EQ(mir_req.url, "http://conda.anaconda.org/conda-forge/linux-64/repodata.json");
REQUIRE(mir_req.name == "repodata_request");
REQUIRE(mir_req.url == "http://conda.anaconda.org/conda-forge/linux-64/repodata.json");
}
SUBCASE("file")
SECTION("file")
{
std::unique_ptr<Mirror> mir = make_mirror("file://channel_path");
// `mir_ref` is used here to provide an explicit expression to `typeid`
// and avoid expression with side effects evaluation warning
auto& mir_ref = *mir;
CHECK_EQ(typeid(mir_ref), typeid(HTTPMirror));
REQUIRE(typeid(mir_ref) == typeid(HTTPMirror));
Mirror::request_generator_list req_gen = mir->get_request_generators("", "");
CHECK_EQ(req_gen.size(), 1);
REQUIRE(req_gen.size() == 1);
Request req_repodata(
"repodata_request",
@ -137,26 +137,26 @@ namespace mamba::download
);
MirrorRequest mir_req = req_gen[0](req_repodata, nullptr);
CHECK_EQ(mir_req.name, "repodata_request");
CHECK_EQ(mir_req.url, "file://channel_path/linux-64/repodata.json");
REQUIRE(mir_req.name == "repodata_request");
REQUIRE(mir_req.url == "file://channel_path/linux-64/repodata.json");
}
}
TEST_CASE("OCIMirror")
{
SUBCASE("Request repodata.json")
SECTION("Request repodata.json")
{
std::unique_ptr<Mirror> mir = make_mirror("oci://ghcr.io/channel-mirrors/conda-forge");
// `mir_ref` is used here to provide an explicit expression to `typeid`
// and avoid expression with side effects evaluation warning
auto& mir_ref = *mir;
CHECK_EQ(typeid(mir_ref), typeid(OCIMirror));
REQUIRE(typeid(mir_ref) == typeid(OCIMirror));
Mirror::request_generator_list req_gen = mir->get_request_generators(
"linux-64/repodata.json",
""
);
CHECK_EQ(req_gen.size(), 3);
REQUIRE(req_gen.size() == 3);
Request req_repodata(
"repodata_request",
@ -165,30 +165,30 @@ namespace mamba::download
);
MirrorRequest mir_req = req_gen[0](req_repodata, nullptr);
CHECK_EQ(mir_req.name, "repodata_request");
CHECK_EQ(
mir_req.url,
"https://ghcr.io/token?scope=repository:channel-mirrors/conda-forge/linux-64/repodata.json:pull"
REQUIRE(mir_req.name == "repodata_request");
REQUIRE(
mir_req.url
== "https://ghcr.io/token?scope=repository:channel-mirrors/conda-forge/linux-64/repodata.json:pull"
);
// Empty token leads to throwing an exception
CHECK_THROWS_AS(req_gen[1](req_repodata, nullptr), std::invalid_argument);
CHECK_THROWS_AS(req_gen[2](req_repodata, nullptr), std::invalid_argument);
REQUIRE_THROWS_AS(req_gen[1](req_repodata, nullptr), std::invalid_argument);
REQUIRE_THROWS_AS(req_gen[2](req_repodata, nullptr), std::invalid_argument);
}
SUBCASE("Request spec with sha")
SECTION("Request spec with sha")
{
std::unique_ptr<Mirror> mir = make_mirror("oci://ghcr.io/channel-mirrors/conda-forge");
// `mir_ref` is used here to provide an explicit expression to `typeid`
// and avoid expression with side effects evaluation warning
auto& mir_ref = *mir;
CHECK_EQ(typeid(mir_ref), typeid(OCIMirror));
REQUIRE(typeid(mir_ref) == typeid(OCIMirror));
Mirror::request_generator_list req_gen = mir->get_request_generators(
"linux-64/pandoc-3.2-ha770c72_0.conda",
"418348076c1a39170efb0bdc8a584ddd11e9ed0ff58ccd905488d3f165ca98ba"
);
CHECK_EQ(req_gen.size(), 2);
REQUIRE(req_gen.size() == 2);
Request req_spec(
"pandoc_request",
@ -197,21 +197,21 @@ namespace mamba::download
);
MirrorRequest mir_req = req_gen[0](req_spec, nullptr);
CHECK_EQ(mir_req.name, "pandoc_request");
CHECK_EQ(
mir_req.url,
"https://ghcr.io/token?scope=repository:channel-mirrors/conda-forge/linux-64/pandoc:pull"
REQUIRE(mir_req.name == "pandoc_request");
REQUIRE(
mir_req.url
== "https://ghcr.io/token?scope=repository:channel-mirrors/conda-forge/linux-64/pandoc:pull"
);
// Empty token leads to throwing an exception
CHECK_THROWS_AS(req_gen[1](req_spec, nullptr), std::invalid_argument);
REQUIRE_THROWS_AS(req_gen[1](req_spec, nullptr), std::invalid_argument);
}
}
TEST_CASE("nullptr")
{
std::unique_ptr<Mirror> mir = make_mirror("ghcr.io/channel-mirrors/conda-forge");
CHECK_EQ(mir, nullptr);
REQUIRE(mir == nullptr);
}
}
}

View File

@ -7,7 +7,7 @@
#include <array>
#include <functional>
#include <doctest/doctest.h>
#include <catch2/catch_all.hpp>
#include "mamba/core/util.hpp"
#include "mamba/solver/libsolv/database.hpp"
@ -33,17 +33,17 @@ namespace
}
}
TEST_SUITE("solver::libsolv::database")
namespace
{
using PackageInfo = specs::PackageInfo;
TEST_CASE("Create a database")
{
auto db = libsolv::Database({});
CHECK(std::is_move_constructible_v<libsolv::Database>);
CHECK_EQ(db.repo_count(), 0);
REQUIRE(std::is_move_constructible_v<libsolv::Database>);
REQUIRE(db.repo_count() == 0);
SUBCASE("Add repo from packages")
SECTION("Add repo from packages")
{
auto pkgs = std::array{
mkpkg("x", "1.0"),
@ -51,26 +51,26 @@ TEST_SUITE("solver::libsolv::database")
mkpkg("z", "1.0", { "x>=1.0" }),
};
auto repo1 = db.add_repo_from_packages(pkgs, "repo1");
CHECK_EQ(db.repo_count(), 1);
CHECK_EQ(db.package_count(), 3);
CHECK_EQ(repo1.package_count(), 3);
REQUIRE(db.repo_count() == 1);
REQUIRE(db.package_count() == 3);
REQUIRE(repo1.package_count() == 3);
SUBCASE("Mark as installed repo")
SECTION("Mark as installed repo")
{
CHECK_FALSE(db.installed_repo().has_value());
REQUIRE_FALSE(db.installed_repo().has_value());
db.set_installed_repo(repo1);
CHECK_EQ(db.installed_repo().value(), repo1);
REQUIRE(db.installed_repo().value() == repo1);
SUBCASE("Remove repo")
SECTION("Remove repo")
{
db.remove_repo(repo1);
CHECK_EQ(db.repo_count(), 0);
CHECK_FALSE(db.installed_repo().has_value());
CHECK_EQ(db.package_count(), 0);
REQUIRE(db.repo_count() == 0);
REQUIRE_FALSE(db.installed_repo().has_value());
REQUIRE(db.package_count() == 0);
}
}
SUBCASE("Serialize repo")
SECTION("Serialize repo")
{
auto tmp_dir = TemporaryDirectory();
auto solv_file = tmp_dir.path() / "repo1.solv";
@ -81,19 +81,19 @@ TEST_SUITE("solver::libsolv::database")
/* .mod= */ "Fri, 11 Feb 2022 13:52:44 GMT",
};
auto repo1_copy = db.native_serialize_repo(repo1, solv_file, origin);
CHECK_EQ(repo1_copy, repo1);
REQUIRE(repo1_copy == repo1);
SUBCASE("Read serialized repo")
SECTION("Read serialized repo")
{
auto repo2 = db.add_repo_from_native_serialization(solv_file, origin, "conda-forge")
.value();
CHECK_EQ(repo2.name(), origin.url);
CHECK_EQ(repo2.package_count(), repo1.package_count());
CHECK_NE(repo2, repo1);
CHECK_EQ(db.package_count(), repo1.package_count() + repo2.package_count());
REQUIRE(repo2.name() == origin.url);
REQUIRE(repo2.package_count() == repo1.package_count());
REQUIRE(repo2 != repo1);
REQUIRE(db.package_count() == repo1.package_count() + repo2.package_count());
}
SUBCASE("Fail reading outdated repo")
SECTION("Fail reading outdated repo")
{
for (auto attr : {
&libsolv::RepodataOrigin::url,
@ -108,16 +108,16 @@ TEST_SUITE("solver::libsolv::database")
expected,
"conda-forge"
);
CHECK_FALSE(maybe.has_value());
REQUIRE_FALSE(maybe.has_value());
}
}
}
SUBCASE("Iterate over packages")
SECTION("Iterate over packages")
{
auto repo2 = db.add_repo_from_packages(std::array{ mkpkg("z", "2.0") }, "repo1");
SUBCASE("In a given repo")
SECTION("In a given repo")
{
std::size_t count = 0;
db.for_each_package_in_repo(
@ -125,14 +125,14 @@ TEST_SUITE("solver::libsolv::database")
[&](const auto& p)
{
count++;
CHECK_EQ(p.name, "z");
CHECK_EQ(p.version, "2.0");
REQUIRE(p.name == "z");
REQUIRE(p.version == "2.0");
}
);
CHECK_EQ(count, 1);
REQUIRE(count == 1);
}
SUBCASE("Matching a MatchSpec in multiple repos")
SECTION("Matching a MatchSpec in multiple repos")
{
std::size_t count = 0;
db.for_each_package_matching(
@ -140,13 +140,13 @@ TEST_SUITE("solver::libsolv::database")
[&](const auto& p)
{
count++;
CHECK_EQ(p.name, "z");
REQUIRE(p.name == "z");
}
);
CHECK_EQ(count, 2);
REQUIRE(count == 2);
}
SUBCASE("Matching a strict MatchSpec")
SECTION("Matching a strict MatchSpec")
{
std::size_t count = 0;
db.for_each_package_matching(
@ -154,13 +154,13 @@ TEST_SUITE("solver::libsolv::database")
[&](const auto& p)
{
count++;
CHECK_EQ(p.name, "z");
REQUIRE(p.name == "z");
}
);
CHECK_EQ(count, 1);
REQUIRE(count == 1);
}
SUBCASE("Depending on a given dependency")
SECTION("Depending on a given dependency")
{
std::size_t count = 0;
db.for_each_package_depending_on(
@ -168,15 +168,15 @@ TEST_SUITE("solver::libsolv::database")
[&](const auto& p)
{
count++;
CHECK(util::any_starts_with(p.dependencies, "x"));
REQUIRE(util::any_starts_with(p.dependencies, "x"));
}
);
CHECK_EQ(count, 1);
REQUIRE(count == 1);
}
}
}
SUBCASE("Add repo from repodata with no extra pip")
SECTION("Add repo from repodata with no extra pip")
{
const auto repodata = mambatests::test_data_dir
/ "repodata/conda-forge-numpy-linux-64.json";
@ -188,7 +188,7 @@ TEST_SUITE("solver::libsolv::database")
);
REQUIRE(repo1.has_value());
CHECK_EQ(repo1->package_count(), 33);
REQUIRE(repo1->package_count() == 33);
auto found_python = false;
db.for_each_package_matching(
@ -198,14 +198,14 @@ TEST_SUITE("solver::libsolv::database")
found_python = true;
for (const auto& dep : pkg.dependencies)
{
CHECK_FALSE(util::contains(dep, "pip"));
REQUIRE_FALSE(util::contains(dep, "pip"));
}
}
);
CHECK(found_python);
REQUIRE(found_python);
}
SUBCASE("Add repo from repodata with extra pip")
SECTION("Add repo from repodata with extra pip")
{
const auto repodata = mambatests::test_data_dir
/ "repodata/conda-forge-numpy-linux-64.json";
@ -217,7 +217,7 @@ TEST_SUITE("solver::libsolv::database")
);
REQUIRE(repo1.has_value());
CHECK_EQ(repo1->package_count(), 33);
REQUIRE(repo1->package_count() == 33);
auto found_python = false;
db.for_each_package_matching(
@ -230,13 +230,13 @@ TEST_SUITE("solver::libsolv::database")
{
found_pip |= util::contains(dep, "pip");
}
CHECK(found_pip);
REQUIRE(found_pip);
}
);
CHECK(found_python);
REQUIRE(found_python);
}
SUBCASE("Add repo from repodata only .tar.bz2")
SECTION("Add repo from repodata only .tar.bz2")
{
const auto repodata = mambatests::test_data_dir
/ "repodata/conda-forge-numpy-linux-64.json";
@ -248,10 +248,10 @@ TEST_SUITE("solver::libsolv::database")
libsolv::PackageTypes::TarBz2Only
);
REQUIRE(repo1.has_value());
CHECK_EQ(repo1->package_count(), 4);
REQUIRE(repo1->package_count() == 4);
}
SUBCASE("Add repo from repodata only .conda")
SECTION("Add repo from repodata only .conda")
{
const auto repodata = mambatests::test_data_dir
/ "repodata/conda-forge-numpy-linux-64.json";
@ -263,10 +263,10 @@ TEST_SUITE("solver::libsolv::database")
libsolv::PackageTypes::CondaOnly
);
REQUIRE(repo1.has_value());
CHECK_EQ(repo1->package_count(), 30);
REQUIRE(repo1->package_count() == 30);
}
SUBCASE("Add repo from repodata .conda and .tar.bz2")
SECTION("Add repo from repodata .conda and .tar.bz2")
{
const auto repodata = mambatests::test_data_dir
/ "repodata/conda-forge-numpy-linux-64.json";
@ -278,10 +278,10 @@ TEST_SUITE("solver::libsolv::database")
libsolv::PackageTypes::CondaAndTarBz2
);
REQUIRE(repo1.has_value());
CHECK_EQ(repo1->package_count(), 34);
REQUIRE(repo1->package_count() == 34);
}
SUBCASE("Add repo from repodata .conda or else .tar.bz2")
SECTION("Add repo from repodata .conda or else .tar.bz2")
{
const auto repodata = mambatests::test_data_dir
/ "repodata/conda-forge-numpy-linux-64.json";
@ -293,14 +293,14 @@ TEST_SUITE("solver::libsolv::database")
libsolv::PackageTypes::CondaOrElseTarBz2
);
REQUIRE(repo1.has_value());
CHECK_EQ(repo1->package_count(), 33);
REQUIRE(repo1->package_count() == 33);
}
SUBCASE("Add repo from repodata with verifying packages signatures")
SECTION("Add repo from repodata with verifying packages signatures")
{
const auto repodata = mambatests::test_data_dir
/ "repodata/conda-forge-numpy-linux-64.json";
SUBCASE("Using mamba parser")
SECTION("Using mamba parser")
{
auto repo1 = db.add_repo_from_repodata_json(
repodata,
@ -312,7 +312,7 @@ TEST_SUITE("solver::libsolv::database")
libsolv::RepodataParser::Mamba
);
REQUIRE(repo1.has_value());
CHECK_EQ(repo1->package_count(), 33);
REQUIRE(repo1->package_count() == 33);
db.for_each_package_in_repo(
repo1.value(),
@ -320,27 +320,27 @@ TEST_SUITE("solver::libsolv::database")
{
if (p.name == "_libgcc_mutex")
{
CHECK_EQ(
p.signatures,
R"({"signatures":{"0b7a133184c9c98333923dhfdg86031adc5db1fds54kfga941fe2c94a12fdjg8":{"signature":"0b83c91ddd8b81bbc7a67a586bde4a271bd8f97069c25306870e314f3664ab02083c91ddd8b0dfjsg763jbd0jh14671d960bb303d1eb787307c04c414ediz95a"}}})"
REQUIRE(
p.signatures
== R"({"signatures":{"0b7a133184c9c98333923dhfdg86031adc5db1fds54kfga941fe2c94a12fdjg8":{"signature":"0b83c91ddd8b81bbc7a67a586bde4a271bd8f97069c25306870e314f3664ab02083c91ddd8b0dfjsg763jbd0jh14671d960bb303d1eb787307c04c414ediz95a"}}})"
);
}
else if (p.name == "bzip2")
{
CHECK_EQ(
p.signatures,
R"({"signatures":{"f7a651f55db194031a6c1240b7a133184c9c98333923dc9319d1fe2c94a1242d":{"signature":"058bf4b5d5cb738736870e314f3664b83c91ddd8b81bbc7a67a875d0454c14671d960a02858e059d154876dab6bde853d763c1a3bd8f97069c25304a2710200d"}}})"
REQUIRE(
p.signatures
== R"({"signatures":{"f7a651f55db194031a6c1240b7a133184c9c98333923dc9319d1fe2c94a1242d":{"signature":"058bf4b5d5cb738736870e314f3664b83c91ddd8b81bbc7a67a875d0454c14671d960a02858e059d154876dab6bde853d763c1a3bd8f97069c25304a2710200d"}}})"
);
}
else
{
CHECK_EQ(p.signatures, "");
REQUIRE(p.signatures == "");
}
}
);
}
SUBCASE("Using libsolv parser")
SECTION("Using libsolv parser")
{
auto repo1 = db.add_repo_from_repodata_json(
repodata,
@ -352,7 +352,7 @@ TEST_SUITE("solver::libsolv::database")
libsolv::RepodataParser::Libsolv
);
REQUIRE(repo1.has_value());
CHECK_EQ(repo1->package_count(), 33);
REQUIRE(repo1->package_count() == 33);
db.for_each_package_in_repo(
repo1.value(),
@ -360,36 +360,36 @@ TEST_SUITE("solver::libsolv::database")
{
if (p.name == "_libgcc_mutex")
{
CHECK(
p.signatures.c_str()
== doctest::Contains(
REQUIRE_THAT(
p.signatures.c_str(),
Catch::Matchers::ContainsSubstring(
R"("signatures":{"0b7a133184c9c98333923dhfdg86031adc5db1fds54kfga941fe2c94a12fdjg8":{"signature":"0b83c91ddd8b81bbc7a67a586bde4a271bd8f97069c25306870e314f3664ab02083c91ddd8b0dfjsg763jbd0jh14671d960bb303d1eb787307c04c414ediz95a"}})"
)
);
}
else if (p.name == "bzip2")
{
CHECK(
p.signatures.c_str()
== doctest::Contains(
REQUIRE_THAT(
p.signatures.c_str(),
Catch::Matchers::ContainsSubstring(
R"("signatures":{"f7a651f55db194031a6c1240b7a133184c9c98333923dc9319d1fe2c94a1242d":{"signature":"058bf4b5d5cb738736870e314f3664b83c91ddd8b81bbc7a67a875d0454c14671d960a02858e059d154876dab6bde853d763c1a3bd8f97069c25304a2710200d"}})"
)
);
}
else
{
CHECK_EQ(p.signatures, "");
REQUIRE(p.signatures == "");
}
}
);
}
}
SUBCASE("Add repo from repodata without verifying packages signatures")
SECTION("Add repo from repodata without verifying packages signatures")
{
const auto repodata = mambatests::test_data_dir
/ "repodata/conda-forge-numpy-linux-64.json";
SUBCASE("Using mamba parser")
SECTION("Using mamba parser")
{
auto repo1 = db.add_repo_from_repodata_json(
repodata,
@ -401,15 +401,15 @@ TEST_SUITE("solver::libsolv::database")
libsolv::RepodataParser::Mamba
);
REQUIRE(repo1.has_value());
CHECK_EQ(repo1->package_count(), 33);
REQUIRE(repo1->package_count() == 33);
db.for_each_package_in_repo(
repo1.value(),
[&](const auto& p) { CHECK_EQ(p.signatures, ""); }
[&](const auto& p) { REQUIRE(p.signatures == ""); }
);
}
SUBCASE("Using libsolv parser")
SECTION("Using libsolv parser")
{
auto repo1 = db.add_repo_from_repodata_json(
repodata,
@ -421,16 +421,16 @@ TEST_SUITE("solver::libsolv::database")
libsolv::RepodataParser::Libsolv
);
REQUIRE(repo1.has_value());
CHECK_EQ(repo1->package_count(), 33);
REQUIRE(repo1->package_count() == 33);
db.for_each_package_in_repo(
repo1.value(),
[&](const auto& p) { CHECK_EQ(p.signatures, ""); }
[&](const auto& p) { REQUIRE(p.signatures == ""); }
);
}
}
SUBCASE("Add repo from repodata with repodata_version 2")
SECTION("Add repo from repodata with repodata_version 2")
{
const auto repodata = mambatests::test_data_dir
/ "repodata/conda-forge-repodata-version-2.json";
@ -442,7 +442,7 @@ TEST_SUITE("solver::libsolv::database")
libsolv::PackageTypes::CondaOrElseTarBz2
);
REQUIRE(repo1.has_value());
CHECK_EQ(repo1->package_count(), 2);
REQUIRE(repo1->package_count() == 2);
db.for_each_package_in_repo(
repo1.value(),
@ -450,23 +450,23 @@ TEST_SUITE("solver::libsolv::database")
{
if (p.name == "_libgcc_mutex")
{
CHECK_EQ(
p.package_url,
"https://repo.anaconda.com/repo/main/linux-64/_libgcc_mutex-0.1-conda_forge.tar.bz2"
REQUIRE(
p.package_url
== "https://repo.anaconda.com/repo/main/linux-64/_libgcc_mutex-0.1-conda_forge.tar.bz2"
);
}
else if (p.name == "bzip2")
{
CHECK_EQ(
p.package_url,
"https://repo.anaconda.com/repo/main/linux-64/bzip2-1.0.8-hd590300_5.conda"
REQUIRE(
p.package_url
== "https://repo.anaconda.com/repo/main/linux-64/bzip2-1.0.8-hd590300_5.conda"
);
}
}
);
}
SUBCASE("Add repo from repodata with repodata_version 2 with missing base_url")
SECTION("Add repo from repodata with repodata_version 2 with missing base_url")
{
const auto repodata = mambatests::test_data_dir
/ "repodata/conda-forge-repodata-version-2-missing-base_url.json";
@ -478,7 +478,7 @@ TEST_SUITE("solver::libsolv::database")
libsolv::PackageTypes::CondaOrElseTarBz2
);
REQUIRE(repo1.has_value());
CHECK_EQ(repo1->package_count(), 2);
REQUIRE(repo1->package_count() == 2);
db.for_each_package_in_repo(
repo1.value(),
@ -486,16 +486,16 @@ TEST_SUITE("solver::libsolv::database")
{
if (p.name == "_libgcc_mutex")
{
CHECK_EQ(
p.package_url,
"https://conda.anaconda.org/conda-forge/linux-64/_libgcc_mutex-0.1-conda_forge.tar.bz2"
REQUIRE(
p.package_url
== "https://conda.anaconda.org/conda-forge/linux-64/_libgcc_mutex-0.1-conda_forge.tar.bz2"
);
}
else if (p.name == "bzip2")
{
CHECK_EQ(
p.package_url,
"https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hd590300_5.conda"
REQUIRE(
p.package_url
== "https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-hd590300_5.conda"
);
}
}

View File

@ -9,7 +9,7 @@
#include <variant>
#include <vector>
#include <doctest/doctest.h>
#include <catch2/catch_all.hpp>
#include "mamba/fs/filesystem.hpp"
#include "mamba/solver/libsolv/database.hpp"
@ -63,7 +63,7 @@ find_actions_with_name(const Solution& solution, std::string_view name)
return out;
}
TEST_SUITE("solver::libsolv::solver")
namespace
{
using namespace specs::match_spec_literals;
@ -80,7 +80,7 @@ TEST_SUITE("solver::libsolv::solver")
);
REQUIRE(repo.has_value());
SUBCASE("Install numpy")
SECTION("Install numpy")
{
const auto request = Request{
/* .flags= */ {},
@ -94,16 +94,16 @@ TEST_SUITE("solver::libsolv::solver")
REQUIRE_FALSE(solution.actions.empty());
// Numpy is last because of topological sort
CHECK(std::holds_alternative<Solution::Install>(solution.actions.back()));
CHECK_EQ(std::get<Solution::Install>(solution.actions.back()).install.name, "numpy");
REQUIRE_EQ(find_actions_with_name(solution, "numpy").size(), 1);
REQUIRE(std::holds_alternative<Solution::Install>(solution.actions.back()));
REQUIRE(std::get<Solution::Install>(solution.actions.back()).install.name == "numpy");
REQUIRE(find_actions_with_name(solution, "numpy").size() == 1);
const auto python_actions = find_actions_with_name(solution, "python");
REQUIRE_EQ(python_actions.size(), 1);
CHECK(std::holds_alternative<Solution::Install>(python_actions.front()));
REQUIRE(python_actions.size() == 1);
REQUIRE(std::holds_alternative<Solution::Install>(python_actions.front()));
}
SUBCASE("Force reinstall not installed numpy")
SECTION("Force reinstall not installed numpy")
{
auto flags = Request::Flags();
flags.force_reinstall = true;
@ -119,16 +119,16 @@ TEST_SUITE("solver::libsolv::solver")
REQUIRE_FALSE(solution.actions.empty());
// Numpy is last because of topological sort
CHECK(std::holds_alternative<Solution::Install>(solution.actions.back()));
CHECK_EQ(std::get<Solution::Install>(solution.actions.back()).install.name, "numpy");
REQUIRE_EQ(find_actions_with_name(solution, "numpy").size(), 1);
REQUIRE(std::holds_alternative<Solution::Install>(solution.actions.back()));
REQUIRE(std::get<Solution::Install>(solution.actions.back()).install.name == "numpy");
REQUIRE(find_actions_with_name(solution, "numpy").size() == 1);
const auto python_actions = find_actions_with_name(solution, "python");
REQUIRE_EQ(python_actions.size(), 1);
CHECK(std::holds_alternative<Solution::Install>(python_actions.front()));
REQUIRE(python_actions.size() == 1);
REQUIRE(std::holds_alternative<Solution::Install>(python_actions.front()));
}
SUBCASE("Install numpy without dependencies")
SECTION("Install numpy without dependencies")
{
const auto request = Request{
/* .flags= */ {
@ -145,16 +145,16 @@ TEST_SUITE("solver::libsolv::solver")
REQUIRE_FALSE(solution.actions.empty());
// Numpy is last because of topological sort
CHECK(std::holds_alternative<Solution::Install>(solution.actions.back()));
CHECK_EQ(std::get<Solution::Install>(solution.actions.back()).install.name, "numpy");
REQUIRE_EQ(find_actions_with_name(solution, "numpy").size(), 1);
REQUIRE(std::holds_alternative<Solution::Install>(solution.actions.back()));
REQUIRE(std::get<Solution::Install>(solution.actions.back()).install.name == "numpy");
REQUIRE(find_actions_with_name(solution, "numpy").size() == 1);
const auto python_actions = find_actions_with_name(solution, "python");
REQUIRE_EQ(python_actions.size(), 1);
CHECK(std::holds_alternative<Solution::Omit>(python_actions.front()));
REQUIRE(python_actions.size() == 1);
REQUIRE(std::holds_alternative<Solution::Omit>(python_actions.front()));
}
SUBCASE("Install numpy dependencies only")
SECTION("Install numpy dependencies only")
{
const auto request = Request{
/* .flags= */ {
@ -171,19 +171,19 @@ TEST_SUITE("solver::libsolv::solver")
REQUIRE_FALSE(solution.actions.empty());
// Numpy is last because of topological sort
CHECK(std::holds_alternative<Solution::Omit>(solution.actions.back()));
CHECK_EQ(std::get<Solution::Omit>(solution.actions.back()).what.name, "numpy");
REQUIRE_EQ(find_actions_with_name(solution, "numpy").size(), 1);
REQUIRE(std::holds_alternative<Solution::Omit>(solution.actions.back()));
REQUIRE(std::get<Solution::Omit>(solution.actions.back()).what.name == "numpy");
REQUIRE(find_actions_with_name(solution, "numpy").size() == 1);
const auto python_actions = find_actions_with_name(solution, "python");
REQUIRE_EQ(python_actions.size(), 1);
CHECK(std::holds_alternative<Solution::Install>(python_actions.front()));
REQUIRE(python_actions.size() == 1);
REQUIRE(std::holds_alternative<Solution::Install>(python_actions.front()));
// Pip is not a dependency of numpy (or python here)
CHECK(find_actions_with_name(solution, "pip").empty());
REQUIRE(find_actions_with_name(solution, "pip").empty());
}
SUBCASE("Fail to install missing package")
SECTION("Fail to install missing package")
{
const auto request = Request{
/* .flags= */ {},
@ -196,7 +196,7 @@ TEST_SUITE("solver::libsolv::solver")
}
SUBCASE("Fail to install conflicting dependencies")
SECTION("Fail to install conflicting dependencies")
{
const auto request = Request{
/* .flags= */ {
@ -225,7 +225,7 @@ TEST_SUITE("solver::libsolv::solver")
REQUIRE(repo.has_value());
db.set_installed_repo(repo.value());
SUBCASE("Remove numpy and dependencies")
SECTION("Remove numpy and dependencies")
{
const auto request = Request{
/* .flags= */ {},
@ -239,15 +239,15 @@ TEST_SUITE("solver::libsolv::solver")
REQUIRE_FALSE(solution.actions.empty());
// Numpy is first because of topological sort
CHECK(std::holds_alternative<Solution::Remove>(solution.actions.front()));
CHECK_EQ(std::get<Solution::Remove>(solution.actions.front()).remove.name, "numpy");
REQUIRE_EQ(find_actions_with_name(solution, "numpy").size(), 1);
REQUIRE(std::holds_alternative<Solution::Remove>(solution.actions.front()));
REQUIRE(std::get<Solution::Remove>(solution.actions.front()).remove.name == "numpy");
REQUIRE(find_actions_with_name(solution, "numpy").size() == 1);
// Python is not removed because it is needed by pip which is installed
CHECK(find_actions_with_name(solution, "pip").empty());
REQUIRE(find_actions_with_name(solution, "pip").empty());
}
SUBCASE("Remove numpy and pip and dependencies")
SECTION("Remove numpy and pip and dependencies")
{
const auto request = Request{
/* .flags= */ {},
@ -260,19 +260,19 @@ TEST_SUITE("solver::libsolv::solver")
const auto& solution = std::get<Solution>(outcome.value());
const auto numpy_actions = find_actions_with_name(solution, "numpy");
REQUIRE_EQ(numpy_actions.size(), 1);
CHECK(std::holds_alternative<Solution::Remove>(numpy_actions.front()));
REQUIRE(numpy_actions.size() == 1);
REQUIRE(std::holds_alternative<Solution::Remove>(numpy_actions.front()));
const auto pip_actions = find_actions_with_name(solution, "pip");
REQUIRE_EQ(pip_actions.size(), 1);
CHECK(std::holds_alternative<Solution::Remove>(pip_actions.front()));
REQUIRE(pip_actions.size() == 1);
REQUIRE(std::holds_alternative<Solution::Remove>(pip_actions.front()));
const auto python_actions = find_actions_with_name(solution, "python");
REQUIRE_EQ(python_actions.size(), 1);
CHECK(std::holds_alternative<Solution::Remove>(python_actions.front()));
REQUIRE(python_actions.size() == 1);
REQUIRE(std::holds_alternative<Solution::Remove>(python_actions.front()));
}
SUBCASE("Remove numpy without dependencies")
SECTION("Remove numpy without dependencies")
{
const auto request = Request{
/* .flags= */ {},
@ -284,13 +284,13 @@ TEST_SUITE("solver::libsolv::solver")
REQUIRE(std::holds_alternative<Solution>(outcome.value()));
const auto& solution = std::get<Solution>(outcome.value());
REQUIRE_EQ(solution.actions.size(), 1);
CHECK(std::holds_alternative<Solution::Remove>(solution.actions.front()));
CHECK_EQ(std::get<Solution::Remove>(solution.actions.front()).remove.name, "numpy");
REQUIRE_EQ(find_actions_with_name(solution, "numpy").size(), 1);
REQUIRE(solution.actions.size() == 1);
REQUIRE(std::holds_alternative<Solution::Remove>(solution.actions.front()));
REQUIRE(std::get<Solution::Remove>(solution.actions.front()).remove.name == "numpy");
REQUIRE(find_actions_with_name(solution, "numpy").size() == 1);
}
SUBCASE("Removing non-existing package is a no-op")
SECTION("Removing non-existing package is a no-op")
{
const auto request = Request{
/* .flags= */ {},
@ -302,7 +302,7 @@ TEST_SUITE("solver::libsolv::solver")
REQUIRE(std::holds_alternative<Solution>(outcome.value()));
const auto& solution = std::get<Solution>(outcome.value());
CHECK(solution.actions.empty());
REQUIRE(solution.actions.empty());
}
}
@ -325,7 +325,7 @@ TEST_SUITE("solver::libsolv::solver")
);
REQUIRE(repo.has_value());
SUBCASE("Force reinstall numpy resinstalls it")
SECTION("Force reinstall numpy resinstalls it")
{
auto flags = Request::Flags();
flags.force_reinstall = true;
@ -339,9 +339,9 @@ TEST_SUITE("solver::libsolv::solver")
REQUIRE(std::holds_alternative<Solution>(outcome.value()));
const auto& solution = std::get<Solution>(outcome.value());
REQUIRE_EQ(solution.actions.size(), 1);
CHECK(std::holds_alternative<Solution::Reinstall>(solution.actions.front()));
CHECK_EQ(std::get<Solution::Reinstall>(solution.actions.front()).what.name, "numpy");
REQUIRE(solution.actions.size() == 1);
REQUIRE(std::holds_alternative<Solution::Reinstall>(solution.actions.front()));
REQUIRE(std::get<Solution::Reinstall>(solution.actions.front()).what.name == "numpy");
}
}
@ -358,14 +358,14 @@ TEST_SUITE("solver::libsolv::solver")
);
REQUIRE(repo.has_value());
SUBCASE("numpy 1.0 is installed")
SECTION("numpy 1.0 is installed")
{
const auto installed = db.add_repo_from_packages(std::array{
specs::PackageInfo("numpy", "1.0.0", "phony", 0),
});
db.set_installed_repo(installed);
SUBCASE("Installing numpy does not upgrade")
SECTION("Installing numpy does not upgrade")
{
const auto request = Request{
/* .flags= */ {},
@ -376,10 +376,10 @@ TEST_SUITE("solver::libsolv::solver")
REQUIRE(outcome.has_value());
REQUIRE(std::holds_alternative<Solution>(outcome.value()));
const auto& solution = std::get<Solution>(outcome.value());
CHECK(solution.actions.empty());
REQUIRE(solution.actions.empty());
}
SUBCASE("Upgrade numpy")
SECTION("Upgrade numpy")
{
const auto request = Request{
/* .flags= */ {},
@ -393,19 +393,21 @@ TEST_SUITE("solver::libsolv::solver")
REQUIRE_FALSE(solution.actions.empty());
// Numpy is last because of topological sort
CHECK(std::holds_alternative<Solution::Upgrade>(solution.actions.back()));
CHECK_EQ(std::get<Solution::Upgrade>(solution.actions.back()).install.name, "numpy");
CHECK_EQ(std::get<Solution::Upgrade>(solution.actions.back()).install.version, "1.26.4");
CHECK_EQ(std::get<Solution::Upgrade>(solution.actions.back()).remove.version, "1.0.0");
REQUIRE_EQ(find_actions_with_name(solution, "numpy").size(), 1);
REQUIRE(std::holds_alternative<Solution::Upgrade>(solution.actions.back()));
REQUIRE(std::get<Solution::Upgrade>(solution.actions.back()).install.name == "numpy");
REQUIRE(
std::get<Solution::Upgrade>(solution.actions.back()).install.version == "1.26.4"
);
REQUIRE(std::get<Solution::Upgrade>(solution.actions.back()).remove.version == "1.0.0");
REQUIRE(find_actions_with_name(solution, "numpy").size() == 1);
// Python needs to be installed
const auto python_actions = find_actions_with_name(solution, "python");
REQUIRE_EQ(python_actions.size(), 1);
CHECK(std::holds_alternative<Solution::Install>(python_actions.front()));
REQUIRE(python_actions.size() == 1);
REQUIRE(std::holds_alternative<Solution::Install>(python_actions.front()));
}
SUBCASE("Update numpy to no better solution is a no-op")
SECTION("Update numpy to no better solution is a no-op")
{
const auto request = Request{
/* .flags= */ {},
@ -416,11 +418,11 @@ TEST_SUITE("solver::libsolv::solver")
REQUIRE(outcome.has_value());
REQUIRE(std::holds_alternative<Solution>(outcome.value()));
const auto& solution = std::get<Solution>(outcome.value());
CHECK(solution.actions.empty());
REQUIRE(solution.actions.empty());
}
}
SUBCASE("numpy 1.0 is installed with python 2.0 and foo")
SECTION("numpy 1.0 is installed with python 2.0 and foo")
{
auto pkg_numpy = specs::PackageInfo("numpy", "1.0.0", "phony", 0);
pkg_numpy.dependencies = { "python=2.0", "foo" };
@ -431,7 +433,7 @@ TEST_SUITE("solver::libsolv::solver")
});
db.set_installed_repo(installed);
SUBCASE("numpy is upgraded with cleaning dependencies")
SECTION("numpy is upgraded with cleaning dependencies")
{
const auto request = Request{
/* .flags= */ {},
@ -444,23 +446,25 @@ TEST_SUITE("solver::libsolv::solver")
const auto& solution = std::get<Solution>(outcome.value());
const auto numpy_actions = find_actions_with_name(solution, "numpy");
REQUIRE_EQ(numpy_actions.size(), 1);
CHECK(std::holds_alternative<Solution::Upgrade>(numpy_actions.front()));
CHECK_EQ(std::get<Solution::Upgrade>(numpy_actions.front()).install.version, "1.26.4");
CHECK_EQ(std::get<Solution::Upgrade>(numpy_actions.front()).remove.version, "1.0.0");
REQUIRE(numpy_actions.size() == 1);
REQUIRE(std::holds_alternative<Solution::Upgrade>(numpy_actions.front()));
REQUIRE(std::get<Solution::Upgrade>(numpy_actions.front()).install.version == "1.26.4");
REQUIRE(std::get<Solution::Upgrade>(numpy_actions.front()).remove.version == "1.0.0");
const auto python_actions = find_actions_with_name(solution, "python");
REQUIRE_EQ(python_actions.size(), 1);
CHECK(std::holds_alternative<Solution::Upgrade>(python_actions.front()));
CHECK_EQ(std::get<Solution::Upgrade>(python_actions.front()).install.version, "3.12.1");
CHECK_EQ(std::get<Solution::Upgrade>(python_actions.front()).remove.version, "2.0.0");
REQUIRE(python_actions.size() == 1);
REQUIRE(std::holds_alternative<Solution::Upgrade>(python_actions.front()));
REQUIRE(
std::get<Solution::Upgrade>(python_actions.front()).install.version == "3.12.1"
);
REQUIRE(std::get<Solution::Upgrade>(python_actions.front()).remove.version == "2.0.0");
const auto foo_actions = find_actions_with_name(solution, "foo");
REQUIRE_EQ(foo_actions.size(), 1);
CHECK(std::holds_alternative<Solution::Remove>(foo_actions.front()));
REQUIRE(foo_actions.size() == 1);
REQUIRE(std::holds_alternative<Solution::Remove>(foo_actions.front()));
}
SUBCASE("numpy is upgraded with cleaning dependencies and a user keep")
SECTION("numpy is upgraded with cleaning dependencies and a user keep")
{
const auto request = Request{
/* .flags= */ {},
@ -473,22 +477,24 @@ TEST_SUITE("solver::libsolv::solver")
const auto& solution = std::get<Solution>(outcome.value());
const auto numpy_actions = find_actions_with_name(solution, "numpy");
REQUIRE_EQ(numpy_actions.size(), 1);
CHECK(std::holds_alternative<Solution::Upgrade>(numpy_actions.front()));
CHECK_EQ(std::get<Solution::Upgrade>(numpy_actions.front()).install.version, "1.26.4");
CHECK_EQ(std::get<Solution::Upgrade>(numpy_actions.front()).remove.version, "1.0.0");
REQUIRE(numpy_actions.size() == 1);
REQUIRE(std::holds_alternative<Solution::Upgrade>(numpy_actions.front()));
REQUIRE(std::get<Solution::Upgrade>(numpy_actions.front()).install.version == "1.26.4");
REQUIRE(std::get<Solution::Upgrade>(numpy_actions.front()).remove.version == "1.0.0");
const auto python_actions = find_actions_with_name(solution, "python");
REQUIRE_EQ(python_actions.size(), 1);
CHECK(std::holds_alternative<Solution::Upgrade>(python_actions.front()));
CHECK_EQ(std::get<Solution::Upgrade>(python_actions.front()).install.version, "3.12.1");
CHECK_EQ(std::get<Solution::Upgrade>(python_actions.front()).remove.version, "2.0.0");
REQUIRE(python_actions.size() == 1);
REQUIRE(std::holds_alternative<Solution::Upgrade>(python_actions.front()));
REQUIRE(
std::get<Solution::Upgrade>(python_actions.front()).install.version == "3.12.1"
);
REQUIRE(std::get<Solution::Upgrade>(python_actions.front()).remove.version == "2.0.0");
// foo is left unchanged in the installed repository because of Keep job
CHECK(find_actions_with_name(solution, "foo").empty());
REQUIRE(find_actions_with_name(solution, "foo").empty());
}
SUBCASE("numpy is upgraded without cleaning dependencies")
SECTION("numpy is upgraded without cleaning dependencies")
{
const auto request = Request{
/* .flags= */ {},
@ -501,21 +507,23 @@ TEST_SUITE("solver::libsolv::solver")
const auto& solution = std::get<Solution>(outcome.value());
const auto numpy_actions = find_actions_with_name(solution, "numpy");
REQUIRE_EQ(numpy_actions.size(), 1);
CHECK(std::holds_alternative<Solution::Upgrade>(numpy_actions.front()));
CHECK_EQ(std::get<Solution::Upgrade>(numpy_actions.front()).install.version, "1.26.4");
CHECK_EQ(std::get<Solution::Upgrade>(numpy_actions.front()).remove.version, "1.0.0");
REQUIRE(numpy_actions.size() == 1);
REQUIRE(std::holds_alternative<Solution::Upgrade>(numpy_actions.front()));
REQUIRE(std::get<Solution::Upgrade>(numpy_actions.front()).install.version == "1.26.4");
REQUIRE(std::get<Solution::Upgrade>(numpy_actions.front()).remove.version == "1.0.0");
const auto python_actions = find_actions_with_name(solution, "python");
REQUIRE_EQ(python_actions.size(), 1);
CHECK(std::holds_alternative<Solution::Upgrade>(python_actions.front()));
CHECK_EQ(std::get<Solution::Upgrade>(python_actions.front()).install.version, "3.12.1");
CHECK_EQ(std::get<Solution::Upgrade>(python_actions.front()).remove.version, "2.0.0");
REQUIRE(python_actions.size() == 1);
REQUIRE(std::holds_alternative<Solution::Upgrade>(python_actions.front()));
REQUIRE(
std::get<Solution::Upgrade>(python_actions.front()).install.version == "3.12.1"
);
REQUIRE(std::get<Solution::Upgrade>(python_actions.front()).remove.version == "2.0.0");
CHECK(find_actions_with_name(solution, "foo").empty());
REQUIRE(find_actions_with_name(solution, "foo").empty());
}
SUBCASE("python upgrade leads to numpy upgrade")
SECTION("python upgrade leads to numpy upgrade")
{
const auto request = Request{
/* .flags= */ {},
@ -528,22 +536,24 @@ TEST_SUITE("solver::libsolv::solver")
const auto& solution = std::get<Solution>(outcome.value());
const auto numpy_actions = find_actions_with_name(solution, "numpy");
REQUIRE_EQ(numpy_actions.size(), 1);
CHECK(std::holds_alternative<Solution::Upgrade>(numpy_actions.front()));
CHECK_EQ(std::get<Solution::Upgrade>(numpy_actions.front()).install.version, "1.26.4");
CHECK_EQ(std::get<Solution::Upgrade>(numpy_actions.front()).remove.version, "1.0.0");
REQUIRE(numpy_actions.size() == 1);
REQUIRE(std::holds_alternative<Solution::Upgrade>(numpy_actions.front()));
REQUIRE(std::get<Solution::Upgrade>(numpy_actions.front()).install.version == "1.26.4");
REQUIRE(std::get<Solution::Upgrade>(numpy_actions.front()).remove.version == "1.0.0");
const auto python_actions = find_actions_with_name(solution, "python");
REQUIRE_EQ(python_actions.size(), 1);
CHECK(std::holds_alternative<Solution::Upgrade>(python_actions.front()));
CHECK_EQ(std::get<Solution::Upgrade>(python_actions.front()).install.version, "3.12.1");
CHECK_EQ(std::get<Solution::Upgrade>(python_actions.front()).remove.version, "2.0.0");
REQUIRE(python_actions.size() == 1);
REQUIRE(std::holds_alternative<Solution::Upgrade>(python_actions.front()));
REQUIRE(
std::get<Solution::Upgrade>(python_actions.front()).install.version == "3.12.1"
);
REQUIRE(std::get<Solution::Upgrade>(python_actions.front()).remove.version == "2.0.0");
CHECK(find_actions_with_name(solution, "foo").empty());
REQUIRE(find_actions_with_name(solution, "foo").empty());
}
}
SUBCASE("numpy 1.0 is installed with python 4.0 and constrained foo")
SECTION("numpy 1.0 is installed with python 4.0 and constrained foo")
{
auto pkg_numpy = specs::PackageInfo("numpy", "1.0.0", "phony", 0);
pkg_numpy.dependencies = { "python=4.0", "foo" };
@ -556,7 +566,7 @@ TEST_SUITE("solver::libsolv::solver")
});
db.set_installed_repo(installed);
SUBCASE("numpy upgrade lead to allowed python downgrade")
SECTION("numpy upgrade lead to allowed python downgrade")
{
const auto request = Request{
/* .flags= */ {
@ -575,19 +585,23 @@ TEST_SUITE("solver::libsolv::solver")
const auto& solution = std::get<Solution>(outcome.value());
const auto numpy_actions = find_actions_with_name(solution, "numpy");
REQUIRE_EQ(numpy_actions.size(), 1);
CHECK(std::holds_alternative<Solution::Upgrade>(numpy_actions.front()));
CHECK_EQ(std::get<Solution::Upgrade>(numpy_actions.front()).install.version, "1.26.4");
CHECK_EQ(std::get<Solution::Upgrade>(numpy_actions.front()).remove.version, "1.0.0");
REQUIRE(numpy_actions.size() == 1);
REQUIRE(std::holds_alternative<Solution::Upgrade>(numpy_actions.front()));
REQUIRE(std::get<Solution::Upgrade>(numpy_actions.front()).install.version == "1.26.4");
REQUIRE(std::get<Solution::Upgrade>(numpy_actions.front()).remove.version == "1.0.0");
const auto python_actions = find_actions_with_name(solution, "python");
REQUIRE_EQ(python_actions.size(), 1);
CHECK(std::holds_alternative<Solution::Downgrade>(python_actions.front()));
CHECK_EQ(std::get<Solution::Downgrade>(python_actions.front()).install.version, "3.12.1");
CHECK_EQ(std::get<Solution::Downgrade>(python_actions.front()).remove.version, "4.0.0");
REQUIRE(python_actions.size() == 1);
REQUIRE(std::holds_alternative<Solution::Downgrade>(python_actions.front()));
REQUIRE(
std::get<Solution::Downgrade>(python_actions.front()).install.version == "3.12.1"
);
REQUIRE(
std::get<Solution::Downgrade>(python_actions.front()).remove.version == "4.0.0"
);
}
SUBCASE("no numpy upgrade without allowing downgrading other packages")
SECTION("no numpy upgrade without allowing downgrading other packages")
{
const auto request = Request{
/* .flags= */ {
@ -606,7 +620,7 @@ TEST_SUITE("solver::libsolv::solver")
const auto& solution = std::get<Solution>(outcome.value());
// No possible changes
CHECK(solution.actions.empty());
REQUIRE(solution.actions.empty());
}
}
}
@ -624,7 +638,7 @@ TEST_SUITE("solver::libsolv::solver")
db.set_repo_priority(repo1, { 2, 0 });
db.set_repo_priority(repo2, { 1, 0 });
SUBCASE("All repos considered without strict repo priority")
SECTION("All repos considered without strict repo priority")
{
auto request = Request{
/* .flags= */ {},
@ -638,12 +652,12 @@ TEST_SUITE("solver::libsolv::solver")
const auto& solution = std::get<Solution>(outcome.value());
const auto numpy_actions = find_actions_with_name(solution, "numpy");
REQUIRE_EQ(numpy_actions.size(), 1);
CHECK(std::holds_alternative<Solution::Install>(numpy_actions.front()));
CHECK_EQ(std::get<Solution::Install>(numpy_actions.front()).install.version, "2.0.0");
REQUIRE(numpy_actions.size() == 1);
REQUIRE(std::holds_alternative<Solution::Install>(numpy_actions.front()));
REQUIRE(std::get<Solution::Install>(numpy_actions.front()).install.version == "2.0.0");
}
SUBCASE("Fail to get package from non priority repo with strict repo priority")
SECTION("Fail to get package from non priority repo with strict repo priority")
{
auto request = Request{
/* .flags= */ {},
@ -653,7 +667,7 @@ TEST_SUITE("solver::libsolv::solver")
const auto outcome = libsolv::Solver().solve(db, request);
REQUIRE(outcome.has_value());
CHECK(std::holds_alternative<libsolv::UnSolvable>(outcome.value()));
REQUIRE(std::holds_alternative<libsolv::UnSolvable>(outcome.value()));
}
}
@ -674,7 +688,7 @@ TEST_SUITE("solver::libsolv::solver")
return out;
};
SUBCASE("Pins are respected")
SECTION("Pins are respected")
{
db.add_repo_from_packages(std::array{
mkfoo("1.0.0", 0, { "feat" }, 0),
@ -692,12 +706,12 @@ TEST_SUITE("solver::libsolv::solver")
const auto& solution = std::get<Solution>(outcome.value());
const auto actions = find_actions_with_name(solution, "foo");
REQUIRE_EQ(actions.size(), 1);
CHECK(std::holds_alternative<Solution::Install>(actions.front()));
CHECK_EQ(std::get<Solution::Install>(actions.front()).install.version, "1.0.0");
REQUIRE(actions.size() == 1);
REQUIRE(std::holds_alternative<Solution::Install>(actions.front()));
REQUIRE(std::get<Solution::Install>(actions.front()).install.version == "1.0.0");
}
SUBCASE("Track features has highest priority")
SECTION("Track features has highest priority")
{
db.add_repo_from_packages(std::array{
mkfoo("1.0.0", 0, {}, 0),
@ -714,12 +728,12 @@ TEST_SUITE("solver::libsolv::solver")
const auto& solution = std::get<Solution>(outcome.value());
const auto actions = find_actions_with_name(solution, "foo");
REQUIRE_EQ(actions.size(), 1);
CHECK(std::holds_alternative<Solution::Install>(actions.front()));
CHECK_EQ(std::get<Solution::Install>(actions.front()).install.version, "1.0.0");
REQUIRE(actions.size() == 1);
REQUIRE(std::holds_alternative<Solution::Install>(actions.front()));
REQUIRE(std::get<Solution::Install>(actions.front()).install.version == "1.0.0");
}
SUBCASE("Version has second highest priority")
SECTION("Version has second highest priority")
{
db.add_repo_from_packages(std::array{
mkfoo("2.0.0", 0, {}, 0),
@ -736,12 +750,12 @@ TEST_SUITE("solver::libsolv::solver")
const auto& solution = std::get<Solution>(outcome.value());
const auto actions = find_actions_with_name(solution, "foo");
REQUIRE_EQ(actions.size(), 1);
CHECK(std::holds_alternative<Solution::Install>(actions.front()));
CHECK_EQ(std::get<Solution::Install>(actions.front()).install.version, "2.0.0");
REQUIRE(actions.size() == 1);
REQUIRE(std::holds_alternative<Solution::Install>(actions.front()));
REQUIRE(std::get<Solution::Install>(actions.front()).install.version == "2.0.0");
}
SUBCASE("Build number has third highest priority")
SECTION("Build number has third highest priority")
{
db.add_repo_from_packages(std::array{
mkfoo("2.0.0", 1, {}, 0),
@ -758,12 +772,12 @@ TEST_SUITE("solver::libsolv::solver")
const auto& solution = std::get<Solution>(outcome.value());
const auto actions = find_actions_with_name(solution, "foo");
REQUIRE_EQ(actions.size(), 1);
CHECK(std::holds_alternative<Solution::Install>(actions.front()));
CHECK_EQ(std::get<Solution::Install>(actions.front()).install.build_number, 1);
REQUIRE(actions.size() == 1);
REQUIRE(std::holds_alternative<Solution::Install>(actions.front()));
REQUIRE(std::get<Solution::Install>(actions.front()).install.build_number == 1);
}
SUBCASE("Timestamp has lowest priority")
SECTION("Timestamp has lowest priority")
{
db.add_repo_from_packages(std::array{
mkfoo("2.0.0", 0, {}, 0),
@ -780,9 +794,9 @@ TEST_SUITE("solver::libsolv::solver")
const auto& solution = std::get<Solution>(outcome.value());
const auto actions = find_actions_with_name(solution, "foo");
REQUIRE_EQ(actions.size(), 1);
CHECK(std::holds_alternative<Solution::Install>(actions.front()));
CHECK_EQ(std::get<Solution::Install>(actions.front()).install.timestamp, 1);
REQUIRE(actions.size() == 1);
REQUIRE(std::holds_alternative<Solution::Install>(actions.front()));
REQUIRE(std::get<Solution::Install>(actions.front()).install.timestamp == 1);
}
}
@ -793,7 +807,7 @@ TEST_SUITE("solver::libsolv::solver")
/* .channel_alias= */ specs::CondaURL::parse("https://conda.anaconda.org/").value(),
});
SUBCASE("Different channels")
SECTION("Different channels")
{
auto pkg1 = specs::PackageInfo("foo", "1.0.0", "conda", 0);
pkg1.package_url = "https://conda.anaconda.org/conda-forge/linux-64/foo-1.0.0-phony.conda";
@ -802,7 +816,7 @@ TEST_SUITE("solver::libsolv::solver")
pkg2.package_url = "https://conda.anaconda.org/mamba-forge/linux-64/foo-1.0.0-phony.conda";
db.add_repo_from_packages(std::array{ pkg2 });
SUBCASE("conda-forge::foo")
SECTION("conda-forge::foo")
{
auto request = Request{
/* .flags= */ {},
@ -815,12 +829,12 @@ TEST_SUITE("solver::libsolv::solver")
const auto& solution = std::get<Solution>(outcome.value());
const auto actions = find_actions_with_name(solution, "foo");
REQUIRE_EQ(actions.size(), 1);
CHECK(std::holds_alternative<Solution::Install>(actions.front()));
CHECK_EQ(std::get<Solution::Install>(actions.front()).install.build_string, "conda");
REQUIRE(actions.size() == 1);
REQUIRE(std::holds_alternative<Solution::Install>(actions.front()));
REQUIRE(std::get<Solution::Install>(actions.front()).install.build_string == "conda");
}
SUBCASE("mamba-forge::foo")
SECTION("mamba-forge::foo")
{
auto request = Request{
/* .flags= */ {},
@ -833,12 +847,12 @@ TEST_SUITE("solver::libsolv::solver")
const auto& solution = std::get<Solution>(outcome.value());
const auto actions = find_actions_with_name(solution, "foo");
REQUIRE_EQ(actions.size(), 1);
CHECK(std::holds_alternative<Solution::Install>(actions.front()));
CHECK_EQ(std::get<Solution::Install>(actions.front()).install.build_string, "mamba");
REQUIRE(actions.size() == 1);
REQUIRE(std::holds_alternative<Solution::Install>(actions.front()));
REQUIRE(std::get<Solution::Install>(actions.front()).install.build_string == "mamba");
}
SUBCASE("pixi-forge::foo")
SECTION("pixi-forge::foo")
{
auto request = Request{
/* .flags= */ {},
@ -848,10 +862,10 @@ TEST_SUITE("solver::libsolv::solver")
const auto outcome = libsolv::Solver().solve(db, request);
REQUIRE(outcome.has_value());
CHECK(std::holds_alternative<libsolv::UnSolvable>(outcome.value()));
REQUIRE(std::holds_alternative<libsolv::UnSolvable>(outcome.value()));
}
SUBCASE("https://conda.anaconda.org/mamba-forge::foo")
SECTION("https://conda.anaconda.org/mamba-forge::foo")
{
auto request = Request{
/* .flags= */ {},
@ -864,13 +878,13 @@ TEST_SUITE("solver::libsolv::solver")
const auto& solution = std::get<Solution>(outcome.value());
const auto actions = find_actions_with_name(solution, "foo");
REQUIRE_EQ(actions.size(), 1);
CHECK(std::holds_alternative<Solution::Install>(actions.front()));
CHECK_EQ(std::get<Solution::Install>(actions.front()).install.build_string, "mamba");
REQUIRE(actions.size() == 1);
REQUIRE(std::holds_alternative<Solution::Install>(actions.front()));
REQUIRE(std::get<Solution::Install>(actions.front()).install.build_string == "mamba");
}
}
SUBCASE("Different subdirs")
SECTION("Different subdirs")
{
const auto repo_linux = db.add_repo_from_repodata_json(
mambatests::test_data_dir / "repodata/conda-forge-numpy-linux-64.json",
@ -891,7 +905,7 @@ TEST_SUITE("solver::libsolv::solver")
);
REQUIRE(repo_noarch.has_value());
SUBCASE("conda-forge/win-64::numpy")
SECTION("conda-forge/win-64::numpy")
{
auto request = Request{
/* .flags= */ {},
@ -903,7 +917,7 @@ TEST_SUITE("solver::libsolv::solver")
REQUIRE(std::holds_alternative<libsolv::UnSolvable>(outcome.value()));
}
SUBCASE("conda-forge::numpy[subdir=linux-64]")
SECTION("conda-forge::numpy[subdir=linux-64]")
{
auto request = Request{
/* .flags= */ {},
@ -916,9 +930,9 @@ TEST_SUITE("solver::libsolv::solver")
const auto& solution = std::get<Solution>(outcome.value());
const auto actions = find_actions_with_name(solution, "numpy");
REQUIRE_EQ(actions.size(), 1);
CHECK(std::holds_alternative<Solution::Install>(actions.front()));
CHECK(util::contains(
REQUIRE(actions.size() == 1);
REQUIRE(std::holds_alternative<Solution::Install>(actions.front()));
REQUIRE(util::contains(
std::get<Solution::Install>(actions.front()).install.package_url,
"linux-64"
));
@ -932,7 +946,7 @@ TEST_SUITE("solver::libsolv::solver")
auto db = libsolv::Database({});
SUBCASE("Respect pins through direct dependencies")
SECTION("Respect pins through direct dependencies")
{
auto pkg1 = PackageInfo("foo");
pkg1.version = "1.0";
@ -952,12 +966,12 @@ TEST_SUITE("solver::libsolv::solver")
const auto& solution = std::get<Solution>(outcome.value());
const auto foo_actions = find_actions_with_name(solution, "foo");
REQUIRE_EQ(foo_actions.size(), 1);
CHECK(std::holds_alternative<Solution::Install>(foo_actions.front()));
CHECK_EQ(std::get<Solution::Install>(foo_actions.front()).install.version, "1.0");
REQUIRE(foo_actions.size() == 1);
REQUIRE(std::holds_alternative<Solution::Install>(foo_actions.front()));
REQUIRE(std::get<Solution::Install>(foo_actions.front()).install.version == "1.0");
}
SUBCASE("Respect pins through indirect dependencies")
SECTION("Respect pins through indirect dependencies")
{
auto pkg1 = PackageInfo("foo");
pkg1.version = "1.0";
@ -983,14 +997,14 @@ TEST_SUITE("solver::libsolv::solver")
const auto& solution = std::get<Solution>(outcome.value());
const auto foo_actions = find_actions_with_name(solution, "foo");
REQUIRE_EQ(foo_actions.size(), 1);
CHECK(std::holds_alternative<Solution::Install>(foo_actions.front()));
CHECK_EQ(std::get<Solution::Install>(foo_actions.front()).install.version, "1.0");
REQUIRE(foo_actions.size() == 1);
REQUIRE(std::holds_alternative<Solution::Install>(foo_actions.front()));
REQUIRE(std::get<Solution::Install>(foo_actions.front()).install.version == "1.0");
const auto bar_actions = find_actions_with_name(solution, "bar");
REQUIRE_EQ(bar_actions.size(), 1);
CHECK(std::holds_alternative<Solution::Install>(bar_actions.front()));
CHECK_EQ(std::get<Solution::Install>(bar_actions.front()).install.version, "1.0");
REQUIRE(bar_actions.size() == 1);
REQUIRE(std::holds_alternative<Solution::Install>(bar_actions.front()));
REQUIRE(std::get<Solution::Install>(bar_actions.front()).install.version == "1.0");
}
}
@ -1000,7 +1014,7 @@ TEST_SUITE("solver::libsolv::solver")
auto db = libsolv::Database({});
SUBCASE("*[md5=0bab699354cbd66959550eb9b9866620]")
SECTION("*[md5=0bab699354cbd66959550eb9b9866620]")
{
auto pkg1 = PackageInfo("foo");
pkg1.md5 = "0bab699354cbd66959550eb9b9866620";
@ -1019,15 +1033,15 @@ TEST_SUITE("solver::libsolv::solver")
REQUIRE(std::holds_alternative<Solution>(outcome.value()));
const auto& solution = std::get<Solution>(outcome.value());
REQUIRE_EQ(solution.actions.size(), 1);
CHECK(std::holds_alternative<Solution::Install>(solution.actions.front()));
CHECK_EQ(
std::get<Solution::Install>(solution.actions.front()).install.md5,
"0bab699354cbd66959550eb9b9866620"
REQUIRE(solution.actions.size() == 1);
REQUIRE(std::holds_alternative<Solution::Install>(solution.actions.front()));
REQUIRE(
std::get<Solution::Install>(solution.actions.front()).install.md5
== "0bab699354cbd66959550eb9b9866620"
);
}
SUBCASE("foo[md5=notreallymd5]")
SECTION("foo[md5=notreallymd5]")
{
auto pkg1 = PackageInfo("foo");
pkg1.md5 = "0bab699354cbd66959550eb9b9866620";
@ -1044,7 +1058,7 @@ TEST_SUITE("solver::libsolv::solver")
REQUIRE(std::holds_alternative<libsolv::UnSolvable>(outcome.value()));
}
SUBCASE("foo[build_string=bld]")
SECTION("foo[build_string=bld]")
{
auto pkg1 = PackageInfo("foo");
pkg1.build_string = "bad";
@ -1063,12 +1077,14 @@ TEST_SUITE("solver::libsolv::solver")
REQUIRE(std::holds_alternative<Solution>(outcome.value()));
const auto& solution = std::get<Solution>(outcome.value());
REQUIRE_EQ(solution.actions.size(), 1);
CHECK(std::holds_alternative<Solution::Install>(solution.actions.front()));
CHECK_EQ(std::get<Solution::Install>(solution.actions.front()).install.build_string, "bld");
REQUIRE(solution.actions.size() == 1);
REQUIRE(std::holds_alternative<Solution::Install>(solution.actions.front()));
REQUIRE(
std::get<Solution::Install>(solution.actions.front()).install.build_string == "bld"
);
}
SUBCASE("foo[build_string=bld, build_number='>2']")
SECTION("foo[build_string=bld, build_number='>2']")
{
auto pkg1 = PackageInfo("foo");
pkg1.build_string = "bad";
@ -1092,13 +1108,15 @@ TEST_SUITE("solver::libsolv::solver")
REQUIRE(std::holds_alternative<Solution>(outcome.value()));
const auto& solution = std::get<Solution>(outcome.value());
REQUIRE_EQ(solution.actions.size(), 1);
CHECK(std::holds_alternative<Solution::Install>(solution.actions.front()));
CHECK_EQ(std::get<Solution::Install>(solution.actions.front()).install.build_string, "bld");
CHECK_EQ(std::get<Solution::Install>(solution.actions.front()).install.build_number, 4);
REQUIRE(solution.actions.size() == 1);
REQUIRE(std::holds_alternative<Solution::Install>(solution.actions.front()));
REQUIRE(
std::get<Solution::Install>(solution.actions.front()).install.build_string == "bld"
);
REQUIRE(std::get<Solution::Install>(solution.actions.front()).install.build_number == 4);
}
SUBCASE("foo[version='=*,=*', build='pyhd*']")
SECTION("foo[version='=*,=*', build='pyhd*']")
{
auto pkg = PackageInfo("foo");
pkg.version = "=*,=*";
@ -1119,8 +1137,8 @@ TEST_SUITE("solver::libsolv::solver")
const auto problems_explained = unsolvable.explain_problems(db, {});
// To avoid mismatch due to color formatting, we perform the check by splitting the
// output following the format
CHECK(util::contains(problems_explained, "foo =*,=* pyhd*"));
CHECK(util::contains(
REQUIRE(util::contains(problems_explained, "foo =*,=* pyhd*"));
REQUIRE(util::contains(
problems_explained,
"does not exist (perhaps a typo or a missing channel)."
));

View File

@ -9,7 +9,7 @@
#include <utility>
#include <vector>
#include <doctest/doctest.h>
#include <catch2/catch_all.hpp>
#include <fmt/format.h>
#include <fmt/ranges.h>
#include <nlohmann/json.hpp>
@ -33,53 +33,51 @@
using namespace mamba;
using namespace mamba::solver;
TEST_SUITE("solver::conflict_map")
namespace
{
TEST_CASE("symmetric")
{
auto c = conflict_map<std::size_t>();
CHECK_EQ(c.size(), 0);
CHECK_FALSE(c.has_conflict(0));
CHECK_FALSE(c.in_conflict(0, 1));
CHECK(c.add(0, 1));
CHECK(c.add(1, 2));
CHECK_FALSE(c.add(1, 2));
CHECK(c.has_conflict(0));
CHECK(c.in_conflict(0, 1));
CHECK(c.in_conflict(1, 2));
CHECK(c.has_conflict(2));
CHECK_FALSE(c.in_conflict(0, 2));
REQUIRE(c.size() == 0);
REQUIRE_FALSE(c.has_conflict(0));
REQUIRE_FALSE(c.in_conflict(0, 1));
REQUIRE(c.add(0, 1));
REQUIRE(c.add(1, 2));
REQUIRE_FALSE(c.add(1, 2));
REQUIRE(c.has_conflict(0));
REQUIRE(c.in_conflict(0, 1));
REQUIRE(c.in_conflict(1, 2));
REQUIRE(c.has_conflict(2));
REQUIRE_FALSE(c.in_conflict(0, 2));
// With same
CHECK(c.add(5, 5));
CHECK(c.has_conflict(5));
CHECK(c.in_conflict(5, 5));
REQUIRE(c.add(5, 5));
REQUIRE(c.has_conflict(5));
REQUIRE(c.in_conflict(5, 5));
}
TEST_CASE("remove")
{
auto c = conflict_map<std::size_t>({ { 1, 1 }, { 1, 2 }, { 1, 3 }, { 2, 4 } });
REQUIRE_EQ(c.size(), 4);
REQUIRE(c.size() == 4);
REQUIRE(c.in_conflict(2, 4));
REQUIRE(c.in_conflict(4, 2));
CHECK(c.remove(2, 4));
CHECK_FALSE(c.in_conflict(4, 2));
CHECK_FALSE(c.in_conflict(2, 4));
CHECK(c.has_conflict(2));
CHECK_FALSE(c.has_conflict(4));
REQUIRE(c.remove(2, 4));
REQUIRE_FALSE(c.in_conflict(4, 2));
REQUIRE_FALSE(c.in_conflict(2, 4));
REQUIRE(c.has_conflict(2));
REQUIRE_FALSE(c.has_conflict(4));
CHECK_FALSE(c.remove(2, 4));
REQUIRE_FALSE(c.remove(2, 4));
CHECK(c.remove(1));
CHECK_FALSE(c.has_conflict(1));
CHECK_FALSE(c.in_conflict(1, 1));
CHECK_FALSE(c.in_conflict(1, 2));
CHECK_FALSE(c.in_conflict(3, 1));
REQUIRE(c.remove(1));
REQUIRE_FALSE(c.has_conflict(1));
REQUIRE_FALSE(c.in_conflict(1, 1));
REQUIRE_FALSE(c.in_conflict(1, 2));
REQUIRE_FALSE(c.in_conflict(3, 1));
}
}
TEST_SUITE_BEGIN("solver::problems_graph");
namespace
{
using namespace mamba::specs::match_spec_literals;
@ -570,27 +568,27 @@ TEST_CASE("NamedList")
{
l.insert({ mkpkg("pkg", fmt::format("0.{}.0", minor)) });
}
CHECK_EQ(l.size(), n_packages);
CHECK_EQ(l.name(), "pkg");
REQUIRE(l.size() == n_packages);
REQUIRE(l.name() == "pkg");
{
auto [str, size] = l.versions_trunc(", ", "...", 5);
CHECK_EQ(size, 9);
CHECK_EQ(str, "0.1.0, 0.2.0, ..., 0.9.0");
REQUIRE(size == 9);
REQUIRE(str == "0.1.0, 0.2.0, ..., 0.9.0");
}
{
auto [str, size] = l.build_strings_trunc(", ", "...", 5, false);
CHECK_EQ(size, 9);
CHECK_EQ(str, "bld, bld, ..., bld");
REQUIRE(size == 9);
REQUIRE(str == "bld, bld, ..., bld");
}
{
auto [str, size] = l.build_strings_trunc(", ", "...", 5, true);
CHECK_EQ(size, 1);
CHECK_EQ(str, "bld");
REQUIRE(size == 1);
REQUIRE(str == "bld");
}
{
auto [str, size] = l.versions_and_build_strings_trunc("|", "---", 5);
CHECK_EQ(size, 9);
CHECK_EQ(str, "0.1.0 bld|0.2.0 bld|---|0.9.0 bld");
REQUIRE(size == 9);
REQUIRE(str == "0.1.0 bld|0.2.0 bld|---|0.9.0 bld");
}
}
@ -630,7 +628,7 @@ TEST_CASE("Create problem graph")
const auto pbs_init = unsolvable.problems_graph(db);
const auto& graph_init = pbs_init.graph();
REQUIRE_GE(graph_init.number_of_nodes(), 1);
REQUIRE(graph_init.number_of_nodes() >= 1);
graph_init.for_each_node_id(
[&](auto id)
{
@ -643,19 +641,19 @@ TEST_CASE("Create problem graph")
if (graph_init.in_degree(id) == 0)
{
// Only one root node
CHECK_EQ(id, pbs_init.root_node());
CHECK(std::holds_alternative<PbGr::RootNode>(node));
REQUIRE(id == pbs_init.root_node());
REQUIRE(std::holds_alternative<PbGr::RootNode>(node));
}
else if (graph_init.out_degree(id) == 0)
{
CHECK_FALSE(std::holds_alternative<PbGr::RootNode>(node));
REQUIRE_FALSE(std::holds_alternative<PbGr::RootNode>(node));
}
else
{
CHECK(std::holds_alternative<PbGr::PackageNode>(node));
REQUIRE(std::holds_alternative<PbGr::PackageNode>(node));
}
// All nodes reachable from the root
CHECK(is_reachable(pbs_init.graph(), pbs_init.root_node(), id));
REQUIRE(is_reachable(pbs_init.graph(), pbs_init.root_node(), id));
}
}
);
@ -665,16 +663,16 @@ TEST_CASE("Create problem graph")
{
bool tmp = std::holds_alternative<PbGr::PackageNode>(graph_init.node(n))
|| std::holds_alternative<PbGr::ConstraintNode>(graph_init.node(n));
CHECK(tmp);
REQUIRE(tmp);
}
SUBCASE("Simplify conflicts")
SECTION("Simplify conflicts")
{
const auto& pbs_simplified = simplify_conflicts(pbs_init);
const auto& graph_simplified = pbs_simplified.graph();
REQUIRE_GE(graph_simplified.number_of_nodes(), 1);
REQUIRE_LE(graph_simplified.number_of_nodes(), pbs_init.graph().number_of_nodes());
REQUIRE(graph_simplified.number_of_nodes() >= 1);
REQUIRE(graph_simplified.number_of_nodes() <= pbs_init.graph().number_of_nodes());
for (const auto& [id, _] : pbs_simplified.conflicts())
{
@ -684,20 +682,20 @@ TEST_CASE("Create problem graph")
// practice
if (!is_virtual_package(node))
{
CHECK(graph_simplified.has_node(id));
REQUIRE(graph_simplified.has_node(id));
// Unfortunately not all conflicts are on leaves
// CHECK_EQ(graph_simplified.out_degree(id), 0);
CHECK(is_reachable(graph_simplified, pbs_simplified.root_node(), id));
// REQUIRE(graph_simplified.out_degree(id) == 0);
REQUIRE(is_reachable(graph_simplified, pbs_simplified.root_node(), id));
}
}
SUBCASE("Compress graph")
SECTION("Compress graph")
{
const auto pbs_comp = CpPbGr::from_problems_graph(pbs_simplified);
const auto& graph_comp = pbs_comp.graph();
REQUIRE_GE(pbs_init.graph().number_of_nodes(), graph_comp.number_of_nodes());
REQUIRE_GE(graph_comp.number_of_nodes(), 1);
REQUIRE(pbs_init.graph().number_of_nodes() >= graph_comp.number_of_nodes());
REQUIRE(graph_comp.number_of_nodes() >= 1);
graph_comp.for_each_node_id(
[&](auto id)
{
@ -710,19 +708,19 @@ TEST_CASE("Create problem graph")
if (graph_comp.in_degree(id) == 0)
{
// Only one root node
CHECK_EQ(id, pbs_init.root_node());
CHECK(std::holds_alternative<CpPbGr::RootNode>(node));
REQUIRE(id == pbs_init.root_node());
REQUIRE(std::holds_alternative<CpPbGr::RootNode>(node));
}
else if (graph_comp.out_degree(id) == 0)
{
CHECK_FALSE(std::holds_alternative<CpPbGr::RootNode>(node));
REQUIRE_FALSE(std::holds_alternative<CpPbGr::RootNode>(node));
}
else
{
CHECK(std::holds_alternative<CpPbGr::PackageListNode>(node));
REQUIRE(std::holds_alternative<CpPbGr::PackageListNode>(node));
}
// All nodes reachable from the root
CHECK(is_reachable(graph_comp, pbs_comp.root_node(), id));
REQUIRE(is_reachable(graph_comp, pbs_comp.root_node(), id));
}
}
);
@ -733,10 +731,10 @@ TEST_CASE("Create problem graph")
bool tmp = std::holds_alternative<CpPbGr::PackageListNode>(graph_comp.node(n))
|| std::holds_alternative<CpPbGr::ConstraintListNode>(graph_comp.node(n
));
CHECK(tmp);
REQUIRE(tmp);
}
SUBCASE("Compose error message")
SECTION("Compose error message")
{
const auto message = problem_tree_msg(pbs_comp);
@ -745,7 +743,7 @@ TEST_CASE("Create problem graph")
using Node = std::remove_cv_t<std::remove_reference_t<decltype(node)>>;
if constexpr (!std::is_same_v<Node, CpPbGr::RootNode>)
{
CHECK(util::contains(message, node.name()));
REQUIRE(util::contains(message, node.name()));
}
};
@ -760,5 +758,3 @@ TEST_CASE("Create problem graph")
}
}
}
TEST_SUITE_END();

View File

@ -6,7 +6,7 @@
#include <type_traits>
#include <doctest/doctest.h>
#include <catch2/catch_all.hpp>
#include "mamba/solver/request.hpp"
#include "mamba/specs/match_spec.hpp"
@ -14,7 +14,7 @@
using namespace mamba;
using namespace mamba::solver;
TEST_SUITE("solver::request")
namespace
{
using namespace specs::match_spec_literals;
@ -32,14 +32,14 @@ TEST_SUITE("solver::request")
},
};
SUBCASE("Iterate over same elements")
SECTION("Iterate over same elements")
{
auto count_install = std::size_t(0);
for_each_of<Request::Install>(request, [&](const Request::Install&) { count_install++; });
CHECK_EQ(count_install, 2);
REQUIRE(count_install == 2);
}
SUBCASE("Iterate over different elements")
SECTION("Iterate over different elements")
{
auto count_install = std::size_t(0);
auto count_remove = std::size_t(0);
@ -59,11 +59,11 @@ TEST_SUITE("solver::request")
}
);
CHECK_EQ(count_install, 2);
CHECK_EQ(count_remove, 1);
REQUIRE(count_install == 2);
REQUIRE(count_remove == 1);
}
SUBCASE("Iterate over elements and break loop")
SECTION("Iterate over elements and break loop")
{
auto count_install = std::size_t(0);
for_each_of<Request::Install>(
@ -74,7 +74,7 @@ TEST_SUITE("solver::request")
return util::LoopControl::Break;
}
);
CHECK_EQ(count_install, 1);
REQUIRE(count_install == 1);
}
}
}

View File

@ -4,7 +4,7 @@
//
// The full license is in the file LICENSE, distributed with this software.
#include <doctest/doctest.h>
#include <catch2/catch_all.hpp>
#include "mamba/solver/solution.hpp"
#include "mamba/specs/package_info.hpp"
@ -13,7 +13,7 @@
using namespace mamba;
using namespace mamba::solver;
TEST_SUITE("solver::solution")
namespace
{
using PackageInfo = specs::PackageInfo;
@ -29,7 +29,7 @@ TEST_SUITE("solver::solution")
Solution::Install{ PackageInfo("install") },
} };
SUBCASE("Iterate over packages")
SECTION("Iterate over packages")
{
auto remove_count = std::size_t(0);
for_each_to_remove(
@ -39,10 +39,10 @@ TEST_SUITE("solver::solution")
remove_count++;
const auto has_remove = util::ends_with(pkg.name, "remove")
|| (pkg.name == "reinstall");
CHECK(has_remove);
REQUIRE(has_remove);
}
);
CHECK_EQ(remove_count, 5);
REQUIRE(remove_count == 5);
auto install_count = std::size_t(0);
for_each_to_install(
@ -52,10 +52,10 @@ TEST_SUITE("solver::solution")
install_count++;
const auto has_install = util::ends_with(pkg.name, "install")
|| (pkg.name == "reinstall");
CHECK(has_install);
REQUIRE(has_install);
}
);
CHECK_EQ(install_count, 5);
REQUIRE(install_count == 5);
auto omit_count = std::size_t(0);
for_each_to_omit(
@ -63,13 +63,13 @@ TEST_SUITE("solver::solution")
[&](const PackageInfo& pkg)
{
omit_count++;
CHECK(util::ends_with(pkg.name, "omit"));
REQUIRE(util::ends_with(pkg.name, "omit"));
}
);
CHECK_EQ(omit_count, 1);
REQUIRE(omit_count == 1);
}
SUBCASE("Iterate over packages and break")
SECTION("Iterate over packages and break")
{
auto remove_count = std::size_t(0);
for_each_to_remove(
@ -80,7 +80,7 @@ TEST_SUITE("solver::solution")
return util::LoopControl::Break;
}
);
CHECK_EQ(remove_count, 1);
REQUIRE(remove_count == 1);
auto install_count = std::size_t(0);
for_each_to_install(
@ -91,7 +91,7 @@ TEST_SUITE("solver::solution")
return util::LoopControl::Break;
}
);
CHECK_EQ(install_count, 1);
REQUIRE(install_count == 1);
auto omit_count = std::size_t(0);
for_each_to_omit(
@ -102,7 +102,7 @@ TEST_SUITE("solver::solution")
return util::LoopControl::Break;
}
);
CHECK_EQ(omit_count, 1);
REQUIRE(omit_count == 1);
}
}
}

View File

@ -4,14 +4,14 @@
//
// The full license is in the file LICENSE, distributed with this software.
#include <doctest/doctest.h>
#include <catch2/catch_all.hpp>
#include "mamba/specs/archive.hpp"
using namespace mamba;
using namespace mamba::specs;
TEST_SUITE("specs::archive")
namespace
{
TEST_CASE("has_archive_extension")
{
@ -24,8 +24,8 @@ TEST_SUITE("specs::archive")
})
{
CAPTURE(std::string_view(no_ext_path));
CHECK_FALSE(has_archive_extension(no_ext_path));
CHECK_FALSE(has_archive_extension(fs::u8path(no_ext_path)));
REQUIRE_FALSE(has_archive_extension(no_ext_path));
REQUIRE_FALSE(has_archive_extension(fs::u8path(no_ext_path)));
}
for (const auto& ext_path : {
@ -34,8 +34,8 @@ TEST_SUITE("specs::archive")
})
{
CAPTURE(std::string_view(ext_path));
CHECK(has_archive_extension(ext_path));
CHECK(has_archive_extension(fs::u8path(ext_path)));
REQUIRE(has_archive_extension(ext_path));
REQUIRE(has_archive_extension(fs::u8path(ext_path)));
}
}
@ -50,26 +50,26 @@ TEST_SUITE("specs::archive")
})
{
CAPTURE(std::string_view(no_ext_path));
CHECK_EQ(strip_archive_extension(no_ext_path), no_ext_path);
CHECK_EQ(strip_archive_extension(fs::u8path(no_ext_path)), no_ext_path);
REQUIRE(strip_archive_extension(no_ext_path) == no_ext_path);
REQUIRE(strip_archive_extension(fs::u8path(no_ext_path)) == no_ext_path);
}
CHECK_EQ(
strip_archive_extension("soupsieve-2.3.2.post1-pyhd8ed1ab_0.tar.bz2"),
"soupsieve-2.3.2.post1-pyhd8ed1ab_0"
REQUIRE(
strip_archive_extension("soupsieve-2.3.2.post1-pyhd8ed1ab_0.tar.bz2")
== "soupsieve-2.3.2.post1-pyhd8ed1ab_0"
);
CHECK_EQ(
strip_archive_extension("folder/soupsieve-2.3.2.post1-pyhd8ed1ab_0.tar.bz2"),
"folder/soupsieve-2.3.2.post1-pyhd8ed1ab_0"
REQUIRE(
strip_archive_extension("folder/soupsieve-2.3.2.post1-pyhd8ed1ab_0.tar.bz2")
== "folder/soupsieve-2.3.2.post1-pyhd8ed1ab_0"
);
CHECK_EQ(
strip_archive_extension(fs::u8path("soupsieve-2.3.2.post1-pyhd8ed1ab_0.tar.bz2")),
"soupsieve-2.3.2.post1-pyhd8ed1ab_0"
REQUIRE(
strip_archive_extension(fs::u8path("soupsieve-2.3.2.post1-pyhd8ed1ab_0.tar.bz2"))
== "soupsieve-2.3.2.post1-pyhd8ed1ab_0"
);
CHECK_EQ(
strip_archive_extension(fs::u8path("folder/soupsieve-2.3.2.post1-pyhd8ed1ab_0.tar.bz2")),
"folder/soupsieve-2.3.2.post1-pyhd8ed1ab_0"
REQUIRE(
strip_archive_extension(fs::u8path("folder/soupsieve-2.3.2.post1-pyhd8ed1ab_0.tar.bz2"))
== "folder/soupsieve-2.3.2.post1-pyhd8ed1ab_0"
);
}
}

View File

@ -4,84 +4,84 @@
//
// The full license is in the file LICENSE, distributed with this software.
#include <doctest/doctest.h>
#include <catch2/catch_all.hpp>
#include "mamba/specs/authentication_info.hpp"
using namespace mamba::specs;
TEST_SUITE("specs::authentication_info")
namespace
{
TEST_CASE("URLWeakener")
{
const auto weakener = URLWeakener();
SUBCASE("mamba.org/private/chan")
SECTION("mamba.org/private/chan")
{
CHECK_EQ(weakener.make_first_key("mamba.org/private/chan"), "mamba.org/private/chan/");
REQUIRE(weakener.make_first_key("mamba.org/private/chan") == "mamba.org/private/chan/");
auto maybe_key = weakener.weaken_key("mamba.org/private/chan/");
CHECK_EQ(maybe_key, "mamba.org/private/chan");
REQUIRE(maybe_key == "mamba.org/private/chan");
maybe_key = weakener.weaken_key(maybe_key.value());
CHECK_EQ(maybe_key, "mamba.org/private/");
REQUIRE(maybe_key == "mamba.org/private/");
maybe_key = weakener.weaken_key(maybe_key.value());
CHECK_EQ(maybe_key, "mamba.org/private");
REQUIRE(maybe_key == "mamba.org/private");
maybe_key = weakener.weaken_key(maybe_key.value());
CHECK_EQ(maybe_key, "mamba.org/");
REQUIRE(maybe_key == "mamba.org/");
maybe_key = weakener.weaken_key(maybe_key.value());
CHECK_EQ(maybe_key, "mamba.org");
REQUIRE(maybe_key == "mamba.org");
maybe_key = weakener.weaken_key(maybe_key.value());
CHECK_EQ(maybe_key, std::nullopt);
REQUIRE(maybe_key == std::nullopt);
}
SUBCASE("mamba.org/private/chan/")
SECTION("mamba.org/private/chan/")
{
CHECK_EQ(weakener.make_first_key("mamba.org/private/chan"), "mamba.org/private/chan/");
REQUIRE(weakener.make_first_key("mamba.org/private/chan") == "mamba.org/private/chan/");
}
}
TEST_CASE("AuthticationDataBase")
{
SUBCASE("mamba.org")
SECTION("mamba.org")
{
auto db = AuthenticationDataBase{ { "mamba.org", BearerToken{ "mytoken" } } };
CHECK(db.contains("mamba.org"));
CHECK_FALSE(db.contains("mamba.org/"));
REQUIRE(db.contains("mamba.org"));
REQUIRE_FALSE(db.contains("mamba.org/"));
CHECK(db.contains_weaken("mamba.org"));
CHECK(db.contains_weaken("mamba.org/"));
CHECK(db.contains_weaken("mamba.org/channel"));
CHECK_FALSE(db.contains_weaken("repo.mamba.org"));
CHECK_FALSE(db.contains_weaken("/folder"));
REQUIRE(db.contains_weaken("mamba.org"));
REQUIRE(db.contains_weaken("mamba.org/"));
REQUIRE(db.contains_weaken("mamba.org/channel"));
REQUIRE_FALSE(db.contains_weaken("repo.mamba.org"));
REQUIRE_FALSE(db.contains_weaken("/folder"));
}
SUBCASE("mamba.org/")
SECTION("mamba.org/")
{
auto db = AuthenticationDataBase{ { "mamba.org/", BearerToken{ "mytoken" } } };
CHECK(db.contains("mamba.org/"));
CHECK_FALSE(db.contains("mamba.org"));
REQUIRE(db.contains("mamba.org/"));
REQUIRE_FALSE(db.contains("mamba.org"));
CHECK(db.contains_weaken("mamba.org"));
CHECK(db.contains_weaken("mamba.org/"));
CHECK(db.contains_weaken("mamba.org/channel"));
CHECK_FALSE(db.contains_weaken("repo.mamba.org/"));
CHECK_FALSE(db.contains_weaken("/folder"));
REQUIRE(db.contains_weaken("mamba.org"));
REQUIRE(db.contains_weaken("mamba.org/"));
REQUIRE(db.contains_weaken("mamba.org/channel"));
REQUIRE_FALSE(db.contains_weaken("repo.mamba.org/"));
REQUIRE_FALSE(db.contains_weaken("/folder"));
}
SUBCASE("mamba.org/channel")
SECTION("mamba.org/channel")
{
auto db = AuthenticationDataBase{ { "mamba.org/channel", BearerToken{ "mytoken" } } };
CHECK(db.contains("mamba.org/channel"));
CHECK_FALSE(db.contains("mamba.org"));
REQUIRE(db.contains("mamba.org/channel"));
REQUIRE_FALSE(db.contains("mamba.org"));
CHECK_FALSE(db.contains_weaken("mamba.org"));
CHECK_FALSE(db.contains_weaken("mamba.org/"));
CHECK(db.contains_weaken("mamba.org/channel"));
CHECK_FALSE(db.contains_weaken("repo.mamba.org/"));
CHECK_FALSE(db.contains_weaken("/folder"));
REQUIRE_FALSE(db.contains_weaken("mamba.org"));
REQUIRE_FALSE(db.contains_weaken("mamba.org/"));
REQUIRE(db.contains_weaken("mamba.org/channel"));
REQUIRE_FALSE(db.contains_weaken("repo.mamba.org/"));
REQUIRE_FALSE(db.contains_weaken("/folder"));
}
}
}

View File

@ -6,65 +6,65 @@
#include <array>
#include <doctest/doctest.h>
#include <catch2/catch_all.hpp>
#include "mamba/specs/build_number_spec.hpp"
using namespace mamba::specs;
TEST_SUITE("specs::build_number_spec")
namespace
{
TEST_CASE("BuildNumberPredicate")
{
const auto free = BuildNumberPredicate::make_free();
CHECK(free.contains(0));
CHECK(free.contains(1));
CHECK(free.contains(2));
CHECK_EQ(free.str(), "=*");
REQUIRE(free.contains(0));
REQUIRE(free.contains(1));
REQUIRE(free.contains(2));
REQUIRE(free.str() == "=*");
const auto eq = BuildNumberPredicate::make_equal_to(1);
CHECK_FALSE(eq.contains(0));
CHECK(eq.contains(1));
CHECK_FALSE(eq.contains(2));
CHECK_EQ(eq.str(), "=1");
REQUIRE_FALSE(eq.contains(0));
REQUIRE(eq.contains(1));
REQUIRE_FALSE(eq.contains(2));
REQUIRE(eq.str() == "=1");
const auto ne = BuildNumberPredicate::make_not_equal_to(1);
CHECK(ne.contains(0));
CHECK_FALSE(ne.contains(1));
CHECK(ne.contains(2));
CHECK_EQ(ne.str(), "!=1");
REQUIRE(ne.contains(0));
REQUIRE_FALSE(ne.contains(1));
REQUIRE(ne.contains(2));
REQUIRE(ne.str() == "!=1");
const auto gt = BuildNumberPredicate::make_greater(1);
CHECK_FALSE(gt.contains(0));
CHECK_FALSE(gt.contains(1));
CHECK(gt.contains(2));
CHECK_EQ(gt.str(), ">1");
REQUIRE_FALSE(gt.contains(0));
REQUIRE_FALSE(gt.contains(1));
REQUIRE(gt.contains(2));
REQUIRE(gt.str() == ">1");
const auto ge = BuildNumberPredicate::make_greater_equal(1);
CHECK_FALSE(ge.contains(0));
CHECK(ge.contains(1));
CHECK(ge.contains(2));
CHECK_EQ(ge.str(), ">=1");
REQUIRE_FALSE(ge.contains(0));
REQUIRE(ge.contains(1));
REQUIRE(ge.contains(2));
REQUIRE(ge.str() == ">=1");
const auto lt = BuildNumberPredicate::make_less(1);
CHECK(lt.contains(0));
CHECK_FALSE(lt.contains(1));
CHECK_FALSE(lt.contains(2));
CHECK_EQ(lt.str(), "<1");
REQUIRE(lt.contains(0));
REQUIRE_FALSE(lt.contains(1));
REQUIRE_FALSE(lt.contains(2));
REQUIRE(lt.str() == "<1");
const auto le = BuildNumberPredicate::make_less_equal(1);
CHECK(le.contains(0));
CHECK(le.contains(1));
CHECK_FALSE(le.contains(2));
CHECK_EQ(le.str(), "<=1");
REQUIRE(le.contains(0));
REQUIRE(le.contains(1));
REQUIRE_FALSE(le.contains(2));
REQUIRE(le.str() == "<=1");
const auto predicates = std::array{ free, eq, ne, lt, le, gt, ge };
for (std::size_t i = 0; i < predicates.size(); ++i)
{
CHECK_EQ(predicates[i], predicates[i]);
REQUIRE(predicates[i] == predicates[i]);
for (std::size_t j = i + 1; j < predicates.size(); ++j)
{
CHECK_NE(predicates[i], predicates[j]);
REQUIRE(predicates[i] != predicates[j]);
}
}
}
@ -73,42 +73,42 @@ TEST_SUITE("specs::build_number_spec")
{
using namespace mamba::specs::build_number_spec_literals;
SUBCASE("Successful")
SECTION("Successful")
{
CHECK(""_bs.contains(0));
CHECK(""_bs.contains(1));
CHECK("*"_bs.contains(1));
CHECK("=*"_bs.contains(1));
REQUIRE(""_bs.contains(0));
REQUIRE(""_bs.contains(1));
REQUIRE("*"_bs.contains(1));
REQUIRE("=*"_bs.contains(1));
CHECK("1"_bs.contains(1));
CHECK("=1"_bs.contains(1));
CHECK_FALSE("1"_bs.contains(2));
CHECK_FALSE("=1"_bs.contains(2));
REQUIRE("1"_bs.contains(1));
REQUIRE("=1"_bs.contains(1));
REQUIRE_FALSE("1"_bs.contains(2));
REQUIRE_FALSE("=1"_bs.contains(2));
CHECK("!=1"_bs.contains(0));
CHECK_FALSE("!=1"_bs.contains(1));
CHECK("!=1"_bs.contains(2));
REQUIRE("!=1"_bs.contains(0));
REQUIRE_FALSE("!=1"_bs.contains(1));
REQUIRE("!=1"_bs.contains(2));
CHECK_FALSE(">1"_bs.contains(0));
CHECK_FALSE(">1"_bs.contains(1));
CHECK(">1"_bs.contains(2));
REQUIRE_FALSE(">1"_bs.contains(0));
REQUIRE_FALSE(">1"_bs.contains(1));
REQUIRE(">1"_bs.contains(2));
CHECK_FALSE(">=1"_bs.contains(0));
CHECK(">=1"_bs.contains(1));
CHECK(">=1"_bs.contains(2));
REQUIRE_FALSE(">=1"_bs.contains(0));
REQUIRE(">=1"_bs.contains(1));
REQUIRE(">=1"_bs.contains(2));
CHECK("<1"_bs.contains(0));
CHECK_FALSE("<1"_bs.contains(1));
CHECK_FALSE("<1"_bs.contains(2));
REQUIRE("<1"_bs.contains(0));
REQUIRE_FALSE("<1"_bs.contains(1));
REQUIRE_FALSE("<1"_bs.contains(2));
CHECK("<=1"_bs.contains(0));
CHECK("<=1"_bs.contains(1));
CHECK_FALSE("<=1"_bs.contains(2));
REQUIRE("<=1"_bs.contains(0));
REQUIRE("<=1"_bs.contains(1));
REQUIRE_FALSE("<=1"_bs.contains(2));
CHECK(" <= 1 "_bs.contains(0));
REQUIRE(" <= 1 "_bs.contains(0));
}
SUBCASE("Unsuccessful")
SECTION("Unsuccessful")
{
using namespace std::literals::string_view_literals;
@ -119,40 +119,40 @@ TEST_SUITE("specs::build_number_spec")
for (const auto& spec : bad_specs)
{
CAPTURE(spec);
CHECK_FALSE(BuildNumberSpec::parse(spec).has_value());
REQUIRE_FALSE(BuildNumberSpec::parse(spec).has_value());
}
}
}
TEST_CASE("BuildNumberSepc::str")
{
CHECK_EQ(BuildNumberSpec::parse("=3").value().str(), "=3");
CHECK_EQ(BuildNumberSpec::parse("<2").value().str(), "<2");
CHECK_EQ(BuildNumberSpec::parse("*").value().str(), "=*");
REQUIRE(BuildNumberSpec::parse("=3").value().str() == "=3");
REQUIRE(BuildNumberSpec::parse("<2").value().str() == "<2");
REQUIRE(BuildNumberSpec::parse("*").value().str() == "=*");
}
TEST_CASE("BuildNumberSepc::is_explicitly_free")
{
CHECK(BuildNumberSpec::parse("*").value().is_explicitly_free());
CHECK_FALSE(BuildNumberSpec::parse("=3").value().is_explicitly_free());
CHECK_FALSE(BuildNumberSpec::parse("<2").value().is_explicitly_free());
REQUIRE(BuildNumberSpec::parse("*").value().is_explicitly_free());
REQUIRE_FALSE(BuildNumberSpec::parse("=3").value().is_explicitly_free());
REQUIRE_FALSE(BuildNumberSpec::parse("<2").value().is_explicitly_free());
}
TEST_CASE("Comparability and hashability")
TEST_CASE("BuildNumberSpec Comparability and hashability")
{
auto bn1 = BuildNumberSpec::parse("=3").value();
auto bn2 = BuildNumberSpec::parse("3").value();
auto bn3 = BuildNumberSpec::parse("*").value();
CHECK_EQ(bn1, bn2);
CHECK_NE(bn1, bn3);
REQUIRE(bn1 == bn2);
REQUIRE(bn1 != bn3);
auto hash_fn = std::hash<BuildNumberSpec>{};
auto bn1_hash = hash_fn(bn1);
auto bn2_hash = hash_fn(bn2);
auto bn3_hash = hash_fn(bn3);
CHECK_EQ(bn1_hash, bn2_hash);
CHECK_NE(bn1_hash, bn3_hash);
REQUIRE(bn1_hash == bn2_hash);
REQUIRE(bn1_hash != bn3_hash);
}
}

View File

@ -4,7 +4,7 @@
//
// The full license is in the file LICENSE, distributed with this software.
#include <doctest/doctest.h>
#include <catch2/catch_all.hpp>
#include "mamba/specs/channel.hpp"
#include "mamba/specs/conda_url.hpp"
@ -12,10 +12,9 @@
#include "mamba/util/path_manip.hpp"
#include "mamba/util/string.hpp"
#include "doctest-printer/conda_url.hpp"
#include "doctest-printer/flat_set.hpp"
#include "catch-utils/conda_url.hpp"
TEST_SUITE("specs::channel")
namespace
{
using namespace mamba;
using namespace mamba::specs;
@ -24,7 +23,7 @@ TEST_SUITE("specs::channel")
TEST_CASE("Channel")
{
SUBCASE("Constructor railing slash")
SECTION("Constructor railing slash")
{
// Leading slash for empty paths
for (auto url : {
@ -34,7 +33,7 @@ TEST_SUITE("specs::channel")
{
CAPTURE(url);
auto chan = Channel(CondaURL::parse(url).value(), "somename");
CHECK_NE(chan.url().str(), mamba::util::rstrip(url, '/'));
REQUIRE(chan.url().str() != mamba::util::rstrip(url, '/'));
}
// No trailing slash for paths
@ -46,11 +45,11 @@ TEST_SUITE("specs::channel")
{
CAPTURE(url);
auto chan = Channel(CondaURL::parse(url).value(), "somename");
CHECK_EQ(chan.url().str(), mamba::util::rstrip(url, '/'));
REQUIRE(chan.url().str() == mamba::util::rstrip(url, '/'));
}
}
SUBCASE("Equality")
SECTION("Equality")
{
for (auto raw_url : {
"https://repo.mamba.pm/"sv,
@ -63,23 +62,23 @@ TEST_SUITE("specs::channel")
CAPTURE(raw_url);
auto chan_a = Channel(CondaURL::parse(raw_url).value(), "somename", { "linux-64" });
CHECK_EQ(chan_a, chan_a);
REQUIRE(chan_a == chan_a);
auto chan_b = chan_a;
CHECK_EQ(chan_b, chan_a);
CHECK_EQ(chan_a, chan_b);
REQUIRE(chan_b == chan_a);
REQUIRE(chan_a == chan_b);
chan_b = Channel(chan_a.url(), chan_a.display_name(), { "linux-64", "noarch" });
CHECK_NE(chan_b, chan_a);
REQUIRE(chan_b != chan_a);
chan_b = Channel(chan_a.url(), "othername", chan_a.platforms());
CHECK_NE(chan_b, chan_a);
REQUIRE(chan_b != chan_a);
}
}
SUBCASE("Equivalence")
SECTION("Equivalence")
{
SUBCASE("Same platforms")
SECTION("Same platforms")
{
for (auto raw_url : {
"https://repo.mamba.pm/"sv,
@ -100,20 +99,20 @@ TEST_SUITE("specs::channel")
auto chan_b = Channel(url_b, "somename", { "linux-64" });
// Channel::url_equivalent_with
CHECK(chan_a.url_equivalent_with(chan_a));
CHECK(chan_b.url_equivalent_with(chan_b));
CHECK(chan_a.url_equivalent_with(chan_b));
CHECK(chan_b.url_equivalent_with(chan_a));
REQUIRE(chan_a.url_equivalent_with(chan_a));
REQUIRE(chan_b.url_equivalent_with(chan_b));
REQUIRE(chan_a.url_equivalent_with(chan_b));
REQUIRE(chan_b.url_equivalent_with(chan_a));
// Channel::contains_equivalent
CHECK(chan_a.contains_equivalent(chan_a));
CHECK(chan_b.contains_equivalent(chan_b));
CHECK(chan_a.contains_equivalent(chan_b));
CHECK(chan_b.contains_equivalent(chan_a));
REQUIRE(chan_a.contains_equivalent(chan_a));
REQUIRE(chan_b.contains_equivalent(chan_b));
REQUIRE(chan_a.contains_equivalent(chan_b));
REQUIRE(chan_b.contains_equivalent(chan_a));
}
}
SUBCASE("Platforms superset")
SECTION("Platforms superset")
{
for (auto raw_url : {
"https://repo.mamba.pm/"sv,
@ -133,13 +132,13 @@ TEST_SUITE("specs::channel")
auto chan_a = Channel(url_a, "somename", { "noarch", "linux-64" });
auto chan_b = Channel(url_b, "somename", { "linux-64" });
CHECK(chan_a.contains_equivalent(chan_a));
CHECK(chan_a.contains_equivalent(chan_b));
CHECK_FALSE(chan_b.contains_equivalent(chan_a));
REQUIRE(chan_a.contains_equivalent(chan_a));
REQUIRE(chan_a.contains_equivalent(chan_b));
REQUIRE_FALSE(chan_b.contains_equivalent(chan_a));
}
}
SUBCASE("Different platforms")
SECTION("Different platforms")
{
for (auto raw_url : {
"https://repo.mamba.pm/"sv,
@ -156,74 +155,75 @@ TEST_SUITE("specs::channel")
auto chan_a = Channel(url_a, "somename", { "noarch", "linux-64" });
auto chan_b = Channel(url_b, "somename", { "osx-64" });
CHECK_FALSE(chan_a.contains_equivalent(chan_b));
CHECK_FALSE(chan_b.contains_equivalent(chan_a));
REQUIRE_FALSE(chan_a.contains_equivalent(chan_b));
REQUIRE_FALSE(chan_b.contains_equivalent(chan_a));
}
}
SUBCASE("Packages")
SECTION("Packages")
{
using namespace conda_url_literals;
const auto chan = Channel("https://repo.mamba.pm/"_cu, "conda-forge", { "linux-64" });
CHECK(chan.contains_equivalent(Channel(chan.url() / "linux-64/pkg.conda", "", {})));
CHECK_FALSE(chan.contains_equivalent(Channel(chan.url() / "osx-64/pkg.conda", "", {}))
REQUIRE(chan.contains_equivalent(Channel(chan.url() / "linux-64/pkg.conda", "", {})));
REQUIRE_FALSE(
chan.contains_equivalent(Channel(chan.url() / "osx-64/pkg.conda", "", {}))
);
const auto pkg_chan = Channel(chan.url() / "linux-64/foo.tar.bz2", "", {});
CHECK(pkg_chan.contains_equivalent(pkg_chan));
CHECK_FALSE(pkg_chan.contains_equivalent(chan));
CHECK_FALSE(
REQUIRE(pkg_chan.contains_equivalent(pkg_chan));
REQUIRE_FALSE(pkg_chan.contains_equivalent(chan));
REQUIRE_FALSE(
pkg_chan.contains_equivalent(Channel(chan.url() / "osx-64/pkg.conda", "", {}))
);
}
}
SUBCASE("Contains package")
SECTION("Contains package")
{
using namespace conda_url_literals;
using Match = Channel::Match;
SUBCASE("https://repo.mamba.pm/")
SECTION("https://repo.mamba.pm/")
{
auto chan = Channel("https://repo.mamba.pm/"_cu, "conda-forge", { "linux-64" });
CHECK_EQ(
chan.contains_package("https://repo.mamba.pm/linux-64/pkg.conda"_cu),
Match::Full
REQUIRE(
chan.contains_package("https://repo.mamba.pm/linux-64/pkg.conda"_cu) == Match::Full
);
CHECK_EQ(
chan.contains_package("https://repo.mamba.pm/win-64/pkg.conda"_cu),
Match::InOtherPlatform
REQUIRE(
chan.contains_package("https://repo.mamba.pm/win-64/pkg.conda"_cu)
== Match::InOtherPlatform
);
CHECK_EQ(
chan.contains_package("https://repo.mamba.pm/pkg.conda"_cu),
Match::InOtherPlatform
REQUIRE(
chan.contains_package("https://repo.mamba.pm/pkg.conda"_cu) == Match::InOtherPlatform
);
}
SUBCASE("https://repo.mamba.pm/osx-64/foo.tar.gz")
SECTION("https://repo.mamba.pm/osx-64/foo.tar.gz")
{
auto chan = Channel("https://repo.mamba.pm/osx-64/foo.tar.bz2"_cu, "", {});
CHECK_EQ(chan.contains_package(chan.url()), Match::Full);
CHECK_EQ(chan.contains_package("https://repo.mamba.pm/win-64/pkg.conda"_cu), Match::No);
CHECK_EQ(chan.contains_package("https://repo.mamba.pm/pkg.conda"_cu), Match::No);
REQUIRE(chan.contains_package(chan.url()) == Match::Full);
REQUIRE(
chan.contains_package("https://repo.mamba.pm/win-64/pkg.conda"_cu) == Match::No
);
REQUIRE(chan.contains_package("https://repo.mamba.pm/pkg.conda"_cu) == Match::No);
}
SUBCASE("https://user:pass@repo.mamba.pm/conda-forge/")
SECTION("https://user:pass@repo.mamba.pm/conda-forge/")
{
auto chan = Channel(
"https://user:pass@repo.mamba.pm/conda-forge/"_cu,
"conda-forge",
{ "win-64" }
);
CHECK_EQ(chan.contains_package(chan.url() / "win-64/pkg.conda"), Match::Full);
CHECK_EQ(
chan.contains_package("https://repo.mamba.pm/conda-forge/win-64/pkg.conda"_cu),
Match::Full
REQUIRE(chan.contains_package(chan.url() / "win-64/pkg.conda") == Match::Full);
REQUIRE(
chan.contains_package("https://repo.mamba.pm/conda-forge/win-64/pkg.conda"_cu)
== Match::Full
);
CHECK_EQ(
chan.contains_package("https://repo.mamba.pm/conda-forge/osx-64/pkg.conda"_cu),
Match::InOtherPlatform
REQUIRE(
chan.contains_package("https://repo.mamba.pm/conda-forge/osx-64/pkg.conda"_cu)
== Match::InOtherPlatform
);
}
}
@ -262,42 +262,42 @@ TEST_SUITE("specs::channel")
return params;
};
SUBCASE("/path/to/libmamba-1.4.2-hcea66bb_0.conda")
SECTION("/path/to/libmamba-1.4.2-hcea66bb_0.conda")
{
const auto path = "/path/to/libmamba-1.4.2-hcea66bb_0.conda"sv;
auto uc = UnresolvedChannel(std::string(path), {}, UnresolvedChannel::Type::PackagePath);
SUBCASE("Typical parameters")
SECTION("Typical parameters")
{
auto params = make_typical_params();
auto channels = Channel::resolve(uc, params).value();
REQUIRE_EQ(channels.size(), 1);
REQUIRE(channels.size() == 1);
const auto& chan = channels.front();
const auto url = "file:///path/to/libmamba-1.4.2-hcea66bb_0.conda"sv;
CHECK_EQ(chan.url(), CondaURL::parse(url).value());
CHECK_EQ(chan.platforms(), platform_list()); // Empty because package
CHECK_EQ(chan.display_name(), url);
REQUIRE(chan.url() == CondaURL::parse(url).value());
REQUIRE(chan.platforms() == platform_list()); // Empty because package
REQUIRE(chan.display_name() == url);
}
}
SUBCASE("~/conda-bld/win-64/libmamba-1.4.2-hcea66bb_0.conda")
SECTION("~/conda-bld/win-64/libmamba-1.4.2-hcea66bb_0.conda")
{
const auto path = "~/conda-bld/win-64/libmamba-1.4.2-hcea66bb_0.conda"sv;
auto uc = UnresolvedChannel(std::string(path), {}, UnresolvedChannel::Type::PackagePath);
SUBCASE("Typical parameters")
SECTION("Typical parameters")
{
auto params = make_typical_params();
auto channels = Channel::resolve(uc, params).value();
REQUIRE_EQ(channels.size(), 1);
REQUIRE(channels.size() == 1);
const auto& chan = channels.front();
const auto url = "file:///home/conda-bld/win-64/libmamba-1.4.2-hcea66bb_0.conda"sv;
CHECK_EQ(chan.url(), CondaURL::parse(url).value());
CHECK_EQ(chan.platforms(), platform_list()); // Empty because package
CHECK_EQ(chan.display_name(), url);
REQUIRE(chan.url() == CondaURL::parse(url).value());
REQUIRE(chan.platforms() == platform_list()); // Empty because package
REQUIRE(chan.display_name() == url);
}
SUBCASE("Matching channel alias")
SECTION("Matching channel alias")
{
auto params = ChannelResolveParams{
/* .platform= */ {},
@ -307,13 +307,13 @@ TEST_SUITE("specs::channel")
/* .authentication_db= */ {},
/* .home_dir= */ "/home",
};
CHECK_EQ(
Channel::resolve(uc, params).value().at(0).display_name(),
"win-64/libmamba-1.4.2-hcea66bb_0.conda"
REQUIRE(
Channel::resolve(uc, params).value().at(0).display_name()
== "win-64/libmamba-1.4.2-hcea66bb_0.conda"
);
}
SUBCASE("Custom channel")
SECTION("Custom channel")
{
auto params = ChannelResolveParams{
/* .platform= */ {},
@ -329,113 +329,113 @@ TEST_SUITE("specs::channel")
.value()
.at(0)
);
CHECK_EQ(Channel::resolve(uc, params).value().at(0).display_name(), "mychan");
REQUIRE(Channel::resolve(uc, params).value().at(0).display_name() == "mychan");
}
}
SUBCASE("./path/to/libmamba-1.4.2-hcea66bb_0.conda")
SECTION("./path/to/libmamba-1.4.2-hcea66bb_0.conda")
{
const auto path = "./path/to/libmamba-1.4.2-hcea66bb_0.conda"sv;
auto uc = UnresolvedChannel(std::string(path), {}, UnresolvedChannel::Type::PackagePath);
SUBCASE("Typical parameters")
SECTION("Typical parameters")
{
auto params = make_typical_params();
auto channels = Channel::resolve(uc, params).value();
REQUIRE_EQ(channels.size(), 1);
REQUIRE(channels.size() == 1);
const auto& chan = channels.front();
const auto url = "file:///cwd/path/to/libmamba-1.4.2-hcea66bb_0.conda"sv;
CHECK_EQ(chan.url(), CondaURL::parse(url).value());
CHECK_EQ(chan.platforms(), platform_list()); // Empty because package
CHECK_EQ(chan.display_name(), url);
REQUIRE(chan.url() == CondaURL::parse(url).value());
REQUIRE(chan.platforms() == platform_list()); // Empty because package
REQUIRE(chan.display_name() == url);
}
}
SUBCASE("/some/folder")
SECTION("/some/folder")
{
const auto path = "/some/folder"sv;
auto uc = UnresolvedChannel(std::string(path), {}, UnresolvedChannel::Type::Path);
SUBCASE("Typical parameters")
SECTION("Typical parameters")
{
auto params = make_typical_params();
auto channels = Channel::resolve(uc, params).value();
REQUIRE_EQ(channels.size(), 1);
REQUIRE(channels.size() == 1);
const auto& chan = channels.front();
const auto url = "file:///some/folder"sv;
CHECK_EQ(chan.url(), CondaURL::parse(url).value());
CHECK_EQ(chan.platforms(), params.platforms);
CHECK_EQ(chan.display_name(), url);
REQUIRE(chan.url() == CondaURL::parse(url).value());
REQUIRE(chan.platforms() == params.platforms);
REQUIRE(chan.display_name() == url);
}
SUBCASE("With platform filers")
SECTION("With platform filers")
{
auto other_specs = UnresolvedChannel(
std::string(path),
{ "foo-56" },
UnresolvedChannel::Type::Path
);
CHECK_EQ(
Channel::resolve(other_specs, ChannelResolveParams{}).value().at(0).platforms(),
other_specs.platform_filters()
REQUIRE(
Channel::resolve(other_specs, ChannelResolveParams{}).value().at(0).platforms()
== other_specs.platform_filters()
);
}
}
SUBCASE("~/folder")
SECTION("~/folder")
{
const auto path = "~/folder"sv;
auto uc = UnresolvedChannel(std::string(path), {}, UnresolvedChannel::Type::Path);
SUBCASE("Typical parameters")
SECTION("Typical parameters")
{
auto params = make_typical_params();
auto channels = Channel::resolve(uc, params).value();
REQUIRE_EQ(channels.size(), 1);
REQUIRE(channels.size() == 1);
const auto& chan = channels.front();
const auto url = "file:///home/folder"sv;
CHECK_EQ(chan.url(), CondaURL::parse(url).value());
CHECK_EQ(chan.platforms(), params.platforms);
CHECK_EQ(chan.display_name(), url);
REQUIRE(chan.url() == CondaURL::parse(url).value());
REQUIRE(chan.platforms() == params.platforms);
REQUIRE(chan.display_name() == url);
}
}
SUBCASE("./other/folder")
SECTION("./other/folder")
{
const auto path = "./other/folder"sv;
auto uc = UnresolvedChannel(std::string(path), {}, UnresolvedChannel::Type::Path);
SUBCASE("Typical parameters")
SECTION("Typical parameters")
{
auto params = make_typical_params();
auto channels = Channel::resolve(uc, params).value();
REQUIRE_EQ(channels.size(), 1);
REQUIRE(channels.size() == 1);
const auto& chan = channels.front();
const auto url = "file:///cwd/other/folder"sv;
CHECK_EQ(chan.url(), CondaURL::parse(url));
CHECK_EQ(chan.platforms(), params.platforms);
CHECK_EQ(chan.display_name(), url);
REQUIRE(chan.url() == CondaURL::parse(url));
REQUIRE(chan.platforms() == params.platforms);
REQUIRE(chan.display_name() == url);
}
}
SUBCASE("https://repo.mamba.pm/conda-forge/linux-64/libmamba-1.4.2-hcea66bb_0.conda")
SECTION("https://repo.mamba.pm/conda-forge/linux-64/libmamba-1.4.2-hcea66bb_0.conda")
{
const auto url = "https://repo.mamba.pm/conda-forge/linux-64/libmamba-1.4.2-hcea66bb_0.conda"sv;
auto uc = UnresolvedChannel(std::string(url), {}, UnresolvedChannel::Type::PackageURL);
SUBCASE("Typical parameters")
SECTION("Typical parameters")
{
auto params = make_typical_params();
auto channels = Channel::resolve(uc, params).value();
REQUIRE_EQ(channels.size(), 1);
REQUIRE(channels.size() == 1);
const auto& chan = channels.front();
CHECK_EQ(chan.url(), CondaURL::parse(url));
CHECK_EQ(chan.platforms(), platform_list()); // Empty because package
CHECK_EQ(chan.display_name(), url);
REQUIRE(chan.url() == CondaURL::parse(url));
REQUIRE(chan.platforms() == platform_list()); // Empty because package
REQUIRE(chan.display_name() == url);
}
}
SUBCASE("https://repo.mamba.pm")
SECTION("https://repo.mamba.pm")
{
const auto url = "https://repo.mamba.pm"sv;
auto uc = UnresolvedChannel(
@ -444,29 +444,29 @@ TEST_SUITE("specs::channel")
UnresolvedChannel::Type::URL
);
SUBCASE("Empty params")
SECTION("Empty params")
{
auto channels = Channel::resolve(uc, ChannelResolveParams{}).value();
REQUIRE_EQ(channels.size(), 1);
REQUIRE(channels.size() == 1);
const auto& chan = channels.front();
CHECK_EQ(chan.url(), CondaURL::parse(url));
CHECK_EQ(chan.platforms(), uc.platform_filters());
CHECK_EQ(chan.display_name(), url);
REQUIRE(chan.url() == CondaURL::parse(url));
REQUIRE(chan.platforms() == uc.platform_filters());
REQUIRE(chan.display_name() == url);
}
SUBCASE("Typical parameters")
SECTION("Typical parameters")
{
auto params = make_typical_params();
auto channels = Channel::resolve(uc, params).value();
REQUIRE_EQ(channels.size(), 1);
REQUIRE(channels.size() == 1);
const auto& chan = channels.front();
CHECK_EQ(chan.url(), CondaURL::parse(url));
CHECK_EQ(chan.platforms(), uc.platform_filters());
CHECK_EQ(chan.display_name(), url);
REQUIRE(chan.url() == CondaURL::parse(url));
REQUIRE(chan.platforms() == uc.platform_filters());
REQUIRE(chan.display_name() == url);
}
}
SUBCASE("https://repo.mamba.pm/conda-forge")
SECTION("https://repo.mamba.pm/conda-forge")
{
const auto url = "https://repo.mamba.pm/conda-forge"sv;
auto uc = UnresolvedChannel(
@ -475,37 +475,39 @@ TEST_SUITE("specs::channel")
UnresolvedChannel::Type::URL
);
SUBCASE("Empty params")
SECTION("Empty params")
{
auto channels = Channel::resolve(uc, ChannelResolveParams{}).value();
REQUIRE_EQ(channels.size(), 1);
REQUIRE(channels.size() == 1);
const auto& chan = channels.front();
CHECK_EQ(chan.url(), CondaURL::parse(url));
CHECK_EQ(chan.platforms(), uc.platform_filters());
CHECK_EQ(chan.display_name(), url);
REQUIRE(chan.url() == CondaURL::parse(url));
REQUIRE(chan.platforms() == uc.platform_filters());
REQUIRE(chan.display_name() == url);
}
SUBCASE("Typical parameters")
SECTION("Typical parameters")
{
auto params = make_typical_params();
auto channels = Channel::resolve(uc, params).value();
REQUIRE_EQ(channels.size(), 1);
REQUIRE(channels.size() == 1);
const auto& chan = channels.front();
CHECK_EQ(chan.url(), CondaURL::parse(url));
CHECK_EQ(chan.platforms(), uc.platform_filters());
CHECK_EQ(chan.display_name(), url);
REQUIRE(chan.url() == CondaURL::parse(url));
REQUIRE(chan.platforms() == uc.platform_filters());
REQUIRE(chan.display_name() == url);
}
SUBCASE("Default platforms")
SECTION("Default platforms")
{
auto params = ChannelResolveParams{ /* .platform= */ { "rainbow-37", "noarch" } };
CHECK_EQ(Channel::resolve(uc, params).value().at(0).platforms(), uc.platform_filters());
REQUIRE(
Channel::resolve(uc, params).value().at(0).platforms() == uc.platform_filters()
);
uc.clear_platform_filters();
CHECK_EQ(Channel::resolve(uc, params).value().at(0).platforms(), params.platforms);
REQUIRE(Channel::resolve(uc, params).value().at(0).platforms() == params.platforms);
}
SUBCASE("Matching channel alias")
SECTION("Matching channel alias")
{
for (auto alias : {
"https://repo.mamba.pm/"sv,
@ -518,11 +520,11 @@ TEST_SUITE("specs::channel")
/* .platform= */ {},
/* .channel_alias= */ CondaURL::parse(alias).value(),
};
CHECK_EQ(Channel::resolve(uc, params).value().at(0).display_name(), "conda-forge");
REQUIRE(Channel::resolve(uc, params).value().at(0).display_name() == "conda-forge");
}
}
SUBCASE("Not matching channel alias")
SECTION("Not matching channel alias")
{
for (auto alias : {
"repo.anaconda.com"sv,
@ -533,11 +535,11 @@ TEST_SUITE("specs::channel")
/* .platform= */ {},
/* .channel_alias= */ CondaURL::parse(alias).value(),
};
CHECK_EQ(Channel::resolve(uc, params).value().at(0).display_name(), url);
REQUIRE(Channel::resolve(uc, params).value().at(0).display_name() == url);
}
}
SUBCASE("Custom channel")
SECTION("Custom channel")
{
auto params = ChannelResolveParams{
/* .platform= */ {},
@ -546,13 +548,13 @@ TEST_SUITE("specs::channel")
{ { "mychan", Channel::resolve(uc, ChannelResolveParams{}).value().at(0) } }
};
auto channels = Channel::resolve(uc, params).value();
REQUIRE_EQ(channels.size(), 1);
REQUIRE(channels.size() == 1);
const auto& chan = channels.front();
CHECK_EQ(chan.url(), CondaURL::parse(url).value());
CHECK_EQ(chan.display_name(), "mychan");
REQUIRE(chan.url() == CondaURL::parse(url).value());
REQUIRE(chan.display_name() == "mychan");
}
SUBCASE("Authentication info")
SECTION("Authentication info")
{
auto params = ChannelResolveParams{
/* .platform= */ {},
@ -563,16 +565,16 @@ TEST_SUITE("specs::channel")
};
auto channels = Channel::resolve(uc, params).value();
REQUIRE_EQ(channels.size(), 1);
REQUIRE(channels.size() == 1);
const auto& chan = channels.front();
CHECK_EQ(
chan.url(),
CondaURL::parse("https://repo.mamba.pm/t/mytoken/conda-forge").value()
REQUIRE(
chan.url()
== CondaURL::parse("https://repo.mamba.pm/t/mytoken/conda-forge").value()
);
CHECK_EQ(chan.display_name(), "https://repo.mamba.pm/conda-forge");
REQUIRE(chan.display_name() == "https://repo.mamba.pm/conda-forge");
}
SUBCASE("Authentication info multiple tokens")
SECTION("Authentication info multiple tokens")
{
auto params = ChannelResolveParams{
/* .platform= */ {},
@ -587,22 +589,22 @@ TEST_SUITE("specs::channel")
};
auto channels = Channel::resolve(uc, params).value();
REQUIRE_EQ(channels.size(), 1);
REQUIRE(channels.size() == 1);
const auto& chan = channels.front();
CHECK_EQ(
chan.url(),
CondaURL::parse("https://repo.mamba.pm/t/forge-token/conda-forge").value()
REQUIRE(
chan.url()
== CondaURL::parse("https://repo.mamba.pm/t/forge-token/conda-forge").value()
);
CHECK_EQ(chan.display_name(), "https://repo.mamba.pm/conda-forge");
REQUIRE(chan.display_name() == "https://repo.mamba.pm/conda-forge");
}
}
SUBCASE("https://user:pass@repo.mamba.pm/conda-forge")
SECTION("https://user:pass@repo.mamba.pm/conda-forge")
{
const auto url = "https://user:pass@repo.mamba.pm/conda-forge"sv;
auto uc = UnresolvedChannel(std::string(url), {}, UnresolvedChannel::Type::URL);
SUBCASE("Authentication info token")
SECTION("Authentication info token")
{
auto params = ChannelResolveParams{
/* .platform= */ {},
@ -613,16 +615,16 @@ TEST_SUITE("specs::channel")
};
auto channels = Channel::resolve(uc, params).value();
REQUIRE_EQ(channels.size(), 1);
REQUIRE(channels.size() == 1);
const auto& chan = channels.front();
CHECK_EQ(
chan.url(),
CondaURL::parse("https://user:pass@repo.mamba.pm/t/mytoken/conda-forge")
REQUIRE(
chan.url()
== CondaURL::parse("https://user:pass@repo.mamba.pm/t/mytoken/conda-forge")
);
CHECK_EQ(chan.display_name(), "https://repo.mamba.pm/conda-forge");
REQUIRE(chan.display_name() == "https://repo.mamba.pm/conda-forge");
}
SUBCASE("Authentication info user password")
SECTION("Authentication info user password")
{
auto params = ChannelResolveParams{
/* .platform= */ {},
@ -634,31 +636,31 @@ TEST_SUITE("specs::channel")
};
auto channels = Channel::resolve(uc, params).value();
REQUIRE_EQ(channels.size(), 1);
REQUIRE(channels.size() == 1);
const auto& chan = channels.front();
// Higher precedence
CHECK_EQ(chan.url(), CondaURL::parse("https://user:pass@repo.mamba.pm/conda-forge"));
CHECK_EQ(chan.display_name(), "https://repo.mamba.pm/conda-forge");
REQUIRE(chan.url() == CondaURL::parse("https://user:pass@repo.mamba.pm/conda-forge"));
REQUIRE(chan.display_name() == "https://repo.mamba.pm/conda-forge");
}
}
SUBCASE("https://repo.anaconda.com/pkgs/main")
SECTION("https://repo.anaconda.com/pkgs/main")
{
const auto url = "https://repo.anaconda.com/pkgs/main"sv;
auto uc = UnresolvedChannel(std::string(url), {}, UnresolvedChannel::Type::URL);
SUBCASE("Typical parameters")
SECTION("Typical parameters")
{
auto params = make_typical_params();
auto channels = Channel::resolve(uc, params).value();
REQUIRE_EQ(channels.size(), 1);
REQUIRE(channels.size() == 1);
const auto& chan = channels.front();
CHECK_EQ(chan.url(), CondaURL::parse(url));
CHECK_EQ(chan.platforms(), params.platforms);
CHECK_EQ(chan.display_name(), "pkgs/main");
REQUIRE(chan.url() == CondaURL::parse(url));
REQUIRE(chan.platforms() == params.platforms);
REQUIRE(chan.display_name() == "pkgs/main");
}
SUBCASE("Matching channel alias")
SECTION("Matching channel alias")
{
auto params = ChannelResolveParams{
/* .platform= */ {},
@ -666,33 +668,33 @@ TEST_SUITE("specs::channel")
};
auto channels = Channel::resolve(uc, params).value();
REQUIRE_EQ(channels.size(), 1);
REQUIRE(channels.size() == 1);
const auto& chan = channels.front();
CHECK_EQ(chan.url(), CondaURL::parse(url));
CHECK_EQ(chan.display_name(), "pkgs/main");
REQUIRE(chan.url() == CondaURL::parse(url));
REQUIRE(chan.display_name() == "pkgs/main");
}
}
SUBCASE("conda-forge")
SECTION("conda-forge")
{
const auto name = "conda-forge"sv;
auto uc = UnresolvedChannel(std::string(name), {}, UnresolvedChannel::Type::Name);
SUBCASE("Typical parameters")
SECTION("Typical parameters")
{
auto params = make_typical_params();
auto channels = Channel::resolve(uc, params).value();
REQUIRE_EQ(channels.size(), 1);
REQUIRE(channels.size() == 1);
const auto& chan = channels.front();
CHECK_EQ(
chan.url(),
CondaURL::parse(util::path_concat(params.channel_alias.str(), name)).value()
REQUIRE(
chan.url()
== CondaURL::parse(util::path_concat(params.channel_alias.str(), name)).value()
);
CHECK_EQ(chan.platforms(), params.platforms);
CHECK_EQ(chan.display_name(), name);
REQUIRE(chan.platforms() == params.platforms);
REQUIRE(chan.display_name() == name);
}
SUBCASE("Authentication info user password")
SECTION("Authentication info user password")
{
auto params = ChannelResolveParams{
/* .platform= */ {},
@ -704,17 +706,16 @@ TEST_SUITE("specs::channel")
};
auto channels = Channel::resolve(uc, params).value();
REQUIRE_EQ(channels.size(), 1);
REQUIRE(channels.size() == 1);
const auto& chan = channels.front();
CHECK_EQ(
chan.url(),
CondaURL::parse("https://user:pass@mydomain.com/private/conda-forge")
REQUIRE(
chan.url() == CondaURL::parse("https://user:pass@mydomain.com/private/conda-forge")
);
CHECK_EQ(chan.display_name(), name);
CHECK_EQ(chan.platforms(), params.platforms);
REQUIRE(chan.display_name() == name);
REQUIRE(chan.platforms() == params.platforms);
}
SUBCASE("Custom channel")
SECTION("Custom channel")
{
auto params = make_typical_params();
params.custom_channels.emplace(
@ -725,69 +726,68 @@ TEST_SUITE("specs::channel")
);
auto channels = Channel::resolve(uc, params).value();
REQUIRE_EQ(channels.size(), 1);
REQUIRE(channels.size() == 1);
const auto& chan = channels.front();
// Higher precedence.
CHECK_EQ(chan.url(), CondaURL::parse("ftp://mydomain.net/conda"));
CHECK_EQ(chan.display_name(), name);
CHECK_EQ(chan.platforms(), params.platforms);
REQUIRE(chan.url() == CondaURL::parse("ftp://mydomain.net/conda"));
REQUIRE(chan.display_name() == name);
REQUIRE(chan.platforms() == params.platforms);
}
}
SUBCASE("pkgs/main")
SECTION("pkgs/main")
{
const auto name = "pkgs/main"sv;
auto uc = UnresolvedChannel(std::string(name), {}, UnresolvedChannel::Type::Name);
SUBCASE("Typical parameters")
SECTION("Typical parameters")
{
auto params = make_typical_params();
auto channels = Channel::resolve(uc, params).value();
REQUIRE_EQ(channels.size(), 1);
REQUIRE(channels.size() == 1);
const auto& chan = channels.front();
CHECK_EQ(chan.url(), CondaURL::parse("https://repo.anaconda.com/pkgs/main"));
CHECK_EQ(chan.platforms(), params.platforms);
CHECK_EQ(chan.display_name(), name);
REQUIRE(chan.url() == CondaURL::parse("https://repo.anaconda.com/pkgs/main"));
REQUIRE(chan.platforms() == params.platforms);
REQUIRE(chan.display_name() == name);
}
}
SUBCASE("pkgs/main/label/dev")
SECTION("pkgs/main/label/dev")
{
const auto name = "pkgs/main/label/dev"sv;
auto specs = UnresolvedChannel(std::string(name), {}, UnresolvedChannel::Type::Name);
SUBCASE("Typical parameters")
SECTION("Typical parameters")
{
auto params = make_typical_params();
auto channels = Channel::resolve(specs, params).value();
REQUIRE_EQ(channels.size(), 1);
REQUIRE(channels.size() == 1);
const auto& chan = channels.front();
CHECK_EQ(chan.url(), CondaURL::parse("https://repo.anaconda.com/pkgs/main/label/dev"));
CHECK_EQ(chan.platforms(), params.platforms);
CHECK_EQ(chan.display_name(), name);
REQUIRE(chan.url() == CondaURL::parse("https://repo.anaconda.com/pkgs/main/label/dev"));
REQUIRE(chan.platforms() == params.platforms);
REQUIRE(chan.display_name() == name);
}
}
SUBCASE("testchannel/mylabel/xyz")
SECTION("testchannel/mylabel/xyz")
{
const auto name = "testchannel/mylabel/xyz"sv;
auto uc = UnresolvedChannel(std::string(name), {}, UnresolvedChannel::Type::Name);
SUBCASE("Typical parameters")
SECTION("Typical parameters")
{
auto params = make_typical_params();
auto channels = Channel::resolve(uc, params).value();
REQUIRE_EQ(channels.size(), 1);
REQUIRE(channels.size() == 1);
const auto& chan = channels.front();
CHECK_EQ(
chan.url(),
CondaURL::parse(util::path_concat(params.channel_alias.str(), name))
REQUIRE(
chan.url() == CondaURL::parse(util::path_concat(params.channel_alias.str(), name))
);
CHECK_EQ(chan.platforms(), params.platforms);
CHECK_EQ(chan.display_name(), name);
REQUIRE(chan.platforms() == params.platforms);
REQUIRE(chan.display_name() == name);
}
SUBCASE("Custom channel")
SECTION("Custom channel")
{
auto params = make_typical_params();
params.custom_channels.emplace(
@ -801,18 +801,17 @@ TEST_SUITE("specs::channel")
);
auto channels = Channel::resolve(uc, params).value();
REQUIRE_EQ(channels.size(), 1);
REQUIRE(channels.size() == 1);
const auto& chan = channels.front();
CHECK_EQ(
chan.url(),
CondaURL::parse("https://server.com/private/testchannel/mylabel/xyz")
REQUIRE(
chan.url() == CondaURL::parse("https://server.com/private/testchannel/mylabel/xyz")
);
CHECK_EQ(chan.display_name(), name);
CHECK_EQ(chan.platforms(), params.platforms);
REQUIRE(chan.display_name() == name);
REQUIRE(chan.platforms() == params.platforms);
}
}
SUBCASE("prefix-and-more")
SECTION("prefix-and-more")
{
const auto name = "prefix-and-more"sv;
auto uc = UnresolvedChannel(std::string(name), {}, UnresolvedChannel::Type::Name);
@ -829,60 +828,64 @@ TEST_SUITE("specs::channel")
);
auto channels = Channel::resolve(uc, params).value();
REQUIRE_EQ(channels.size(), 1);
REQUIRE(channels.size() == 1);
const auto& chan = channels.front();
CHECK_EQ(chan.url(), CondaURL::parse("https://ali.as/prefix-and-more"));
CHECK_EQ(chan.display_name(), name);
CHECK_EQ(chan.platforms(), params.platforms);
REQUIRE(chan.url() == CondaURL::parse("https://ali.as/prefix-and-more"));
REQUIRE(chan.display_name() == name);
REQUIRE(chan.platforms() == params.platforms);
}
SUBCASE("defaults")
SECTION("defaults")
{
const auto name = "defaults"sv;
auto uc = UnresolvedChannel(std::string(name), { "linux-64" }, UnresolvedChannel::Type::Name);
SUBCASE("Typical parameters")
SECTION("Typical parameters")
{
auto params = make_typical_params();
auto channels = Channel::resolve(uc, params).value();
REQUIRE_EQ(channels.size(), 3);
REQUIRE(channels.size() == 3);
auto found_names = util::flat_set<std::string>();
for (const auto& chan : channels)
{
CHECK_EQ(chan.platforms(), uc.platform_filters()); // Overridden
REQUIRE(chan.platforms() == uc.platform_filters()); // Overridden
found_names.insert(chan.display_name());
}
CHECK_EQ(found_names, util::flat_set<std::string>{ "pkgs/main", "pkgs/pro", "pkgs/r" });
REQUIRE(
found_names == util::flat_set<std::string>{ "pkgs/main", "pkgs/pro", "pkgs/r" }
);
}
}
SUBCASE("<unknown>")
SECTION("<unknown>")
{
auto uc = UnresolvedChannel({}, { "linux-64" }, UnresolvedChannel::Type::Unknown);
auto channels = Channel::resolve(uc, ChannelResolveParams{}).value();
REQUIRE_EQ(channels.size(), 1);
REQUIRE(channels.size() == 1);
const auto& chan = channels.front();
CHECK_EQ(chan.url(), CondaURL());
CHECK_EQ(chan.platforms(), platform_list());
CHECK_EQ(chan.display_name(), "<unknown>");
REQUIRE(chan.url() == CondaURL());
REQUIRE(chan.platforms() == platform_list());
REQUIRE(chan.display_name() == "<unknown>");
}
SUBCASE("https://conda.anaconda.org/conda-forge/linux-64/x264-1%21164.3095-h166bdaf_2.tar.bz2")
SECTION("https://conda.anaconda.org/conda-forge/linux-64/x264-1%21164.3095-h166bdaf_2.tar.bz2")
{
// Version 1!164.3095 is URL encoded
const auto url = "https://conda.anaconda.org/conda-forge/linux-64/x264-1%21164.3095-h166bdaf_2.tar.bz2"sv;
auto uc = UnresolvedChannel(std::string(url), {}, UnresolvedChannel::Type::PackageURL);
SUBCASE("Typical parameters")
SECTION("Typical parameters")
{
auto params = make_typical_params();
auto channels = Channel::resolve(uc, params).value();
REQUIRE_EQ(channels.size(), 1);
REQUIRE(channels.size() == 1);
const auto& chan = channels.front();
CHECK_EQ(chan.url(), CondaURL::parse(url));
CHECK_EQ(chan.platforms(), platform_list()); // Empty because package
CHECK_EQ(chan.display_name(), "conda-forge/linux-64/x264-1!164.3095-h166bdaf_2.tar.bz2");
REQUIRE(chan.url() == CondaURL::parse(url));
REQUIRE(chan.platforms() == platform_list()); // Empty because package
REQUIRE(
chan.display_name() == "conda-forge/linux-64/x264-1!164.3095-h166bdaf_2.tar.bz2"
);
}
}
}

View File

@ -4,84 +4,84 @@
//
// The full license is in the file LICENSE, distributed with this software.
#include <doctest/doctest.h>
#include <catch2/catch_all.hpp>
#include "mamba/specs/chimera_string_spec.hpp"
using namespace mamba::specs;
TEST_SUITE("specs::chimera_string_spec")
namespace
{
TEST_CASE("Free")
TEST_CASE("ChimeraStringSpec Free")
{
auto spec = ChimeraStringSpec();
CHECK(spec.contains(""));
CHECK(spec.contains("hello"));
REQUIRE(spec.contains(""));
REQUIRE(spec.contains("hello"));
CHECK_EQ(spec.str(), "*");
CHECK(spec.is_explicitly_free());
CHECK_FALSE(spec.is_exact());
CHECK(spec.is_glob());
REQUIRE(spec.str() == "*");
REQUIRE(spec.is_explicitly_free());
REQUIRE_FALSE(spec.is_exact());
REQUIRE(spec.is_glob());
}
TEST_CASE("mkl")
TEST_CASE("ChimeraStringSpec mkl")
{
auto spec = ChimeraStringSpec::parse("mkl").value();
CHECK(spec.contains("mkl"));
CHECK_FALSE(spec.contains(""));
CHECK_FALSE(spec.contains("nomkl"));
CHECK_FALSE(spec.contains("hello"));
REQUIRE(spec.contains("mkl"));
REQUIRE_FALSE(spec.contains(""));
REQUIRE_FALSE(spec.contains("nomkl"));
REQUIRE_FALSE(spec.contains("hello"));
CHECK_EQ(spec.str(), "mkl");
CHECK_FALSE(spec.is_explicitly_free());
CHECK(spec.is_exact());
CHECK(spec.is_glob());
REQUIRE(spec.str() == "mkl");
REQUIRE_FALSE(spec.is_explicitly_free());
REQUIRE(spec.is_exact());
REQUIRE(spec.is_glob());
}
TEST_CASE("py.*")
TEST_CASE("ChimeraStringSpec py.*")
{
auto spec = ChimeraStringSpec::parse("py.*").value();
CHECK(spec.contains("python"));
CHECK(spec.contains("py"));
CHECK(spec.contains("pypy"));
CHECK_FALSE(spec.contains(""));
CHECK_FALSE(spec.contains("cpython"));
REQUIRE(spec.contains("python"));
REQUIRE(spec.contains("py"));
REQUIRE(spec.contains("pypy"));
REQUIRE_FALSE(spec.contains(""));
REQUIRE_FALSE(spec.contains("cpython"));
CHECK_EQ(spec.str(), "^py.*$");
CHECK_FALSE(spec.is_explicitly_free());
CHECK_FALSE(spec.is_exact());
CHECK_FALSE(spec.is_glob());
REQUIRE(spec.str() == "^py.*$");
REQUIRE_FALSE(spec.is_explicitly_free());
REQUIRE_FALSE(spec.is_exact());
REQUIRE_FALSE(spec.is_glob());
}
TEST_CASE("^.*(accelerate|mkl)$")
TEST_CASE("ChimeraStringSpec ^.*(accelerate|mkl)$")
{
auto spec = ChimeraStringSpec::parse("^.*(accelerate|mkl)$").value();
CHECK(spec.contains("accelerate"));
CHECK(spec.contains("mkl"));
CHECK_FALSE(spec.contains(""));
CHECK_FALSE(spec.contains("openblas"));
REQUIRE(spec.contains("accelerate"));
REQUIRE(spec.contains("mkl"));
REQUIRE_FALSE(spec.contains(""));
REQUIRE_FALSE(spec.contains("openblas"));
CHECK_EQ(spec.str(), "^.*(accelerate|mkl)$");
CHECK_FALSE(spec.is_explicitly_free());
CHECK_FALSE(spec.is_exact());
CHECK_FALSE(spec.is_glob());
REQUIRE(spec.str() == "^.*(accelerate|mkl)$");
REQUIRE_FALSE(spec.is_explicitly_free());
REQUIRE_FALSE(spec.is_exact());
REQUIRE_FALSE(spec.is_glob());
}
TEST_CASE("Comparability and hashability")
TEST_CASE("ChimeraStringSpec Comparability and hashability")
{
auto spec1 = ChimeraStringSpec::parse("mkl").value();
auto spec2 = ChimeraStringSpec::parse("mkl").value();
auto spec3 = ChimeraStringSpec::parse("*").value();
CHECK_EQ(spec1, spec2);
CHECK_NE(spec1, spec3);
REQUIRE(spec1 == spec2);
REQUIRE(spec1 != spec3);
std::hash<ChimeraStringSpec> hash_fn;
CHECK_EQ(hash_fn(spec1), hash_fn(spec2));
CHECK_NE(hash_fn(spec1), hash_fn(spec3));
REQUIRE(hash_fn(spec1) == hash_fn(spec2));
REQUIRE(hash_fn(spec1) != hash_fn(spec3));
}
}

View File

@ -5,13 +5,13 @@
// The full license is in the file LICENSE, distributed with this software.
#include <doctest/doctest.h>
#include <catch2/catch_all.hpp>
#include "mamba/specs/conda_url.hpp"
using namespace mamba::specs;
TEST_SUITE("specs::CondaURL")
namespace
{
TEST_CASE("Token")
{
@ -19,95 +19,95 @@ TEST_SUITE("specs::CondaURL")
url.set_scheme("https");
url.set_host("repo.mamba.pm");
SUBCASE("https://repo.mamba.pm/folder/file.txt")
SECTION("https://repo.mamba.pm/folder/file.txt")
{
url.set_path("/folder/file.txt");
CHECK_FALSE(url.has_token());
CHECK_EQ(url.token(), "");
CHECK_EQ(url.path_without_token(), "/folder/file.txt");
REQUIRE_FALSE(url.has_token());
REQUIRE(url.token() == "");
REQUIRE(url.path_without_token() == "/folder/file.txt");
url.set_token("mytoken");
CHECK(url.has_token());
CHECK_EQ(url.token(), "mytoken");
CHECK_EQ(url.path_without_token(), "/folder/file.txt");
CHECK_EQ(url.path(), "/t/mytoken/folder/file.txt");
REQUIRE(url.has_token());
REQUIRE(url.token() == "mytoken");
REQUIRE(url.path_without_token() == "/folder/file.txt");
REQUIRE(url.path() == "/t/mytoken/folder/file.txt");
CHECK(url.clear_token());
CHECK_FALSE(url.has_token());
CHECK_EQ(url.path_without_token(), "/folder/file.txt");
CHECK_EQ(url.path(), "/folder/file.txt");
REQUIRE(url.clear_token());
REQUIRE_FALSE(url.has_token());
REQUIRE(url.path_without_token() == "/folder/file.txt");
REQUIRE(url.path() == "/folder/file.txt");
}
SUBCASE("https://repo.mamba.pm/t/xy-12345678-1234/conda-forge/linux-64")
SECTION("https://repo.mamba.pm/t/xy-12345678-1234/conda-forge/linux-64")
{
url.set_path("/t/xy-12345678-1234/conda-forge/linux-64");
CHECK(url.has_token());
CHECK_EQ(url.token(), "xy-12345678-1234");
CHECK_EQ(url.path_without_token(), "/conda-forge/linux-64");
REQUIRE(url.has_token());
REQUIRE(url.token() == "xy-12345678-1234");
REQUIRE(url.path_without_token() == "/conda-forge/linux-64");
SUBCASE("Cannot set invalid token")
SECTION("Cannot set invalid token")
{
CHECK_THROWS_AS(url.set_token(""), std::invalid_argument);
CHECK_THROWS_AS(url.set_token("?fds:g"), std::invalid_argument);
CHECK(url.has_token());
CHECK_EQ(url.token(), "xy-12345678-1234");
CHECK_EQ(url.path_without_token(), "/conda-forge/linux-64");
CHECK_EQ(url.path(), "/t/xy-12345678-1234/conda-forge/linux-64");
REQUIRE_THROWS_AS(url.set_token(""), std::invalid_argument);
REQUIRE_THROWS_AS(url.set_token("?fds:g"), std::invalid_argument);
REQUIRE(url.has_token());
REQUIRE(url.token() == "xy-12345678-1234");
REQUIRE(url.path_without_token() == "/conda-forge/linux-64");
REQUIRE(url.path() == "/t/xy-12345678-1234/conda-forge/linux-64");
}
SUBCASE("Clear token")
SECTION("Clear token")
{
CHECK(url.clear_token());
CHECK_FALSE(url.has_token());
CHECK_EQ(url.token(), "");
CHECK_EQ(url.path_without_token(), "/conda-forge/linux-64");
CHECK_EQ(url.path(), "/conda-forge/linux-64");
REQUIRE(url.clear_token());
REQUIRE_FALSE(url.has_token());
REQUIRE(url.token() == "");
REQUIRE(url.path_without_token() == "/conda-forge/linux-64");
REQUIRE(url.path() == "/conda-forge/linux-64");
}
SUBCASE("Set token")
SECTION("Set token")
{
url.set_token("abcd");
CHECK(url.has_token());
CHECK_EQ(url.token(), "abcd");
CHECK_EQ(url.path_without_token(), "/conda-forge/linux-64");
CHECK_EQ(url.path(), "/t/abcd/conda-forge/linux-64");
REQUIRE(url.has_token());
REQUIRE(url.token() == "abcd");
REQUIRE(url.path_without_token() == "/conda-forge/linux-64");
REQUIRE(url.path() == "/t/abcd/conda-forge/linux-64");
}
}
SUBCASE("https://repo.mamba.pm/t/xy-12345678-1234-1234-1234-123456789012")
SECTION("https://repo.mamba.pm/t/xy-12345678-1234-1234-1234-123456789012")
{
url.set_path("/t/xy-12345678-1234-1234-1234-123456789012");
CHECK(url.has_token());
CHECK_EQ(url.token(), "xy-12345678-1234-1234-1234-123456789012");
REQUIRE(url.has_token());
REQUIRE(url.token() == "xy-12345678-1234-1234-1234-123456789012");
url.set_token("abcd");
CHECK(url.has_token());
CHECK_EQ(url.token(), "abcd");
CHECK_EQ(url.path_without_token(), "/");
CHECK_EQ(url.path(), "/t/abcd/");
REQUIRE(url.has_token());
REQUIRE(url.token() == "abcd");
REQUIRE(url.path_without_token() == "/");
REQUIRE(url.path() == "/t/abcd/");
CHECK(url.clear_token());
CHECK_FALSE(url.has_token());
CHECK_EQ(url.token(), "");
CHECK_EQ(url.path_without_token(), "/");
CHECK_EQ(url.path(), "/");
REQUIRE(url.clear_token());
REQUIRE_FALSE(url.has_token());
REQUIRE(url.token() == "");
REQUIRE(url.path_without_token() == "/");
REQUIRE(url.path() == "/");
}
SUBCASE("https://repo.mamba.pm/bar/t/xy-12345678-1234-1234-1234-123456789012/")
SECTION("https://repo.mamba.pm/bar/t/xy-12345678-1234-1234-1234-123456789012/")
{
url.set_path("/bar/t/xy-12345678-1234-1234-1234-123456789012/");
CHECK_FALSE(url.has_token());
CHECK_EQ(url.token(), ""); // Not at beginning of path
REQUIRE_FALSE(url.has_token());
REQUIRE(url.token() == ""); // Not at beginning of path
url.set_token("abcd");
CHECK(url.has_token());
CHECK_EQ(url.token(), "abcd");
CHECK_EQ(url.path_without_token(), "/bar/t/xy-12345678-1234-1234-1234-123456789012/");
CHECK_EQ(url.path(), "/t/abcd/bar/t/xy-12345678-1234-1234-1234-123456789012/");
REQUIRE(url.has_token());
REQUIRE(url.token() == "abcd");
REQUIRE(url.path_without_token() == "/bar/t/xy-12345678-1234-1234-1234-123456789012/");
REQUIRE(url.path() == "/t/abcd/bar/t/xy-12345678-1234-1234-1234-123456789012/");
CHECK(url.clear_token());
CHECK_EQ(url.path_without_token(), "/bar/t/xy-12345678-1234-1234-1234-123456789012/");
CHECK_EQ(url.path(), "/bar/t/xy-12345678-1234-1234-1234-123456789012/");
REQUIRE(url.clear_token());
REQUIRE(url.path_without_token() == "/bar/t/xy-12345678-1234-1234-1234-123456789012/");
REQUIRE(url.path() == "/bar/t/xy-12345678-1234-1234-1234-123456789012/");
}
}
@ -117,41 +117,41 @@ TEST_SUITE("specs::CondaURL")
url.set_scheme("https");
url.set_host("repo.mamba.pm");
SUBCASE("Setters")
SECTION("Setters")
{
url.set_path_without_token("foo");
CHECK_EQ(url.path_without_token(), "/foo");
REQUIRE(url.path_without_token() == "/foo");
url.set_token("mytoken");
CHECK_EQ(url.path_without_token(), "/foo");
CHECK(url.clear_path_without_token());
CHECK_EQ(url.path_without_token(), "/");
REQUIRE(url.path_without_token() == "/foo");
REQUIRE(url.clear_path_without_token());
REQUIRE(url.path_without_token() == "/");
}
SUBCASE("Parse")
SECTION("Parse")
{
url = CondaURL::parse("mamba.org/t/xy-12345678-1234-1234-1234-123456789012").value();
CHECK(url.has_token());
CHECK_EQ(url.token(), "xy-12345678-1234-1234-1234-123456789012");
CHECK_EQ(url.path_without_token(), "/");
CHECK_EQ(url.path(), "/t/xy-12345678-1234-1234-1234-123456789012/");
REQUIRE(url.has_token());
REQUIRE(url.token() == "xy-12345678-1234-1234-1234-123456789012");
REQUIRE(url.path_without_token() == "/");
REQUIRE(url.path() == "/t/xy-12345678-1234-1234-1234-123456789012/");
}
SUBCASE("Encoding")
SECTION("Encoding")
{
url.set_token("mytoken");
SUBCASE("Encode")
SECTION("Encode")
{
url.set_path_without_token("some / weird/path %");
CHECK_EQ(url.path_without_token(), "/some / weird/path %");
CHECK_EQ(url.path_without_token(CondaURL::Decode::no), "/some%20/%20weird/path%20%25");
REQUIRE(url.path_without_token() == "/some / weird/path %");
REQUIRE(url.path_without_token(CondaURL::Decode::no) == "/some%20/%20weird/path%20%25");
}
SUBCASE("Encoded")
SECTION("Encoded")
{
url.set_path_without_token("/some%20/%20weird/path%20%25", CondaURL::Encode::no);
CHECK_EQ(url.path_without_token(), "/some / weird/path %");
CHECK_EQ(url.path_without_token(CondaURL::Decode::no), "/some%20/%20weird/path%20%25");
REQUIRE(url.path_without_token() == "/some / weird/path %");
REQUIRE(url.path_without_token(CondaURL::Decode::no) == "/some%20/%20weird/path%20%25");
}
}
}
@ -162,90 +162,90 @@ TEST_SUITE("specs::CondaURL")
url.set_scheme("https");
url.set_host("repo.mamba.pm");
SUBCASE("https://repo.mamba.pm/")
SECTION("https://repo.mamba.pm/")
{
CHECK_FALSE(url.platform().has_value());
CHECK_EQ(url.platform_name(), "");
REQUIRE_FALSE(url.platform().has_value());
REQUIRE(url.platform_name() == "");
CHECK_THROWS_AS(url.set_platform(KnownPlatform::linux_64), std::invalid_argument);
CHECK_EQ(url.path_without_token(), "/");
CHECK_EQ(url.path(), "/");
REQUIRE_THROWS_AS(url.set_platform(KnownPlatform::linux_64), std::invalid_argument);
REQUIRE(url.path_without_token() == "/");
REQUIRE(url.path() == "/");
CHECK_FALSE(url.clear_platform());
CHECK_EQ(url.path(), "/");
REQUIRE_FALSE(url.clear_platform());
REQUIRE(url.path() == "/");
}
SUBCASE("https://repo.mamba.pm/conda-forge")
SECTION("https://repo.mamba.pm/conda-forge")
{
url.set_path("conda-forge");
CHECK_FALSE(url.platform().has_value());
CHECK_EQ(url.platform_name(), "");
REQUIRE_FALSE(url.platform().has_value());
REQUIRE(url.platform_name() == "");
CHECK_THROWS_AS(url.set_platform(KnownPlatform::linux_64), std::invalid_argument);
CHECK_EQ(url.path(), "/conda-forge");
REQUIRE_THROWS_AS(url.set_platform(KnownPlatform::linux_64), std::invalid_argument);
REQUIRE(url.path() == "/conda-forge");
CHECK_FALSE(url.clear_platform());
CHECK_EQ(url.path(), "/conda-forge");
REQUIRE_FALSE(url.clear_platform());
REQUIRE(url.path() == "/conda-forge");
}
SUBCASE("https://repo.mamba.pm/conda-forge/")
SECTION("https://repo.mamba.pm/conda-forge/")
{
url.set_path("conda-forge/");
CHECK_FALSE(url.platform().has_value());
CHECK_EQ(url.platform_name(), "");
REQUIRE_FALSE(url.platform().has_value());
REQUIRE(url.platform_name() == "");
CHECK_THROWS_AS(url.set_platform(KnownPlatform::linux_64), std::invalid_argument);
CHECK_EQ(url.path(), "/conda-forge/");
REQUIRE_THROWS_AS(url.set_platform(KnownPlatform::linux_64), std::invalid_argument);
REQUIRE(url.path() == "/conda-forge/");
CHECK_FALSE(url.clear_platform());
CHECK_EQ(url.path(), "/conda-forge/");
REQUIRE_FALSE(url.clear_platform());
REQUIRE(url.path() == "/conda-forge/");
}
SUBCASE("https://repo.mamba.pm/conda-forge/win-64")
SECTION("https://repo.mamba.pm/conda-forge/win-64")
{
url.set_path("conda-forge/win-64");
CHECK_EQ(url.platform(), KnownPlatform::win_64);
CHECK_EQ(url.platform_name(), "win-64");
REQUIRE(url.platform() == KnownPlatform::win_64);
REQUIRE(url.platform_name() == "win-64");
url.set_platform(KnownPlatform::linux_64);
CHECK_EQ(url.platform(), KnownPlatform::linux_64);
CHECK_EQ(url.path(), "/conda-forge/linux-64");
REQUIRE(url.platform() == KnownPlatform::linux_64);
REQUIRE(url.path() == "/conda-forge/linux-64");
CHECK(url.clear_platform());
CHECK_EQ(url.path(), "/conda-forge");
REQUIRE(url.clear_platform());
REQUIRE(url.path() == "/conda-forge");
}
SUBCASE("https://repo.mamba.pm/conda-forge/OSX-64/")
SECTION("https://repo.mamba.pm/conda-forge/OSX-64/")
{
url.set_path("conda-forge/OSX-64");
CHECK_EQ(url.platform(), KnownPlatform::osx_64);
CHECK_EQ(url.platform_name(), "OSX-64"); // Capitalization not changed
REQUIRE(url.platform() == KnownPlatform::osx_64);
REQUIRE(url.platform_name() == "OSX-64"); // Capitalization not changed
url.set_platform("Win-64");
CHECK_EQ(url.platform(), KnownPlatform::win_64);
CHECK_EQ(url.path(), "/conda-forge/Win-64"); // Capitalization not changed
REQUIRE(url.platform() == KnownPlatform::win_64);
REQUIRE(url.path() == "/conda-forge/Win-64"); // Capitalization not changed
CHECK(url.clear_platform());
CHECK_EQ(url.path(), "/conda-forge");
REQUIRE(url.clear_platform());
REQUIRE(url.path() == "/conda-forge");
}
SUBCASE("https://repo.mamba.pm/conda-forge/linux-64/micromamba-1.5.1-0.tar.bz2")
SECTION("https://repo.mamba.pm/conda-forge/linux-64/micromamba-1.5.1-0.tar.bz2")
{
url.set_path("/conda-forge/linux-64/micromamba-1.5.1-0.tar.bz2");
CHECK_EQ(url.platform(), KnownPlatform::linux_64);
CHECK_EQ(url.platform_name(), "linux-64");
REQUIRE(url.platform() == KnownPlatform::linux_64);
REQUIRE(url.platform_name() == "linux-64");
url.set_platform("osx-64");
CHECK_EQ(url.platform(), KnownPlatform::osx_64);
CHECK_EQ(url.path(), "/conda-forge/osx-64/micromamba-1.5.1-0.tar.bz2");
REQUIRE(url.platform() == KnownPlatform::osx_64);
REQUIRE(url.path() == "/conda-forge/osx-64/micromamba-1.5.1-0.tar.bz2");
CHECK(url.clear_platform());
CHECK_EQ(url.path(), "/conda-forge/micromamba-1.5.1-0.tar.bz2");
REQUIRE(url.clear_platform());
REQUIRE(url.path() == "/conda-forge/micromamba-1.5.1-0.tar.bz2");
}
}
@ -255,197 +255,199 @@ TEST_SUITE("specs::CondaURL")
url.set_scheme("https");
url.set_host("repo.mamba.pm");
SUBCASE("https://repo.mamba.pm/")
SECTION("https://repo.mamba.pm/")
{
CHECK_EQ(url.package(), "");
REQUIRE(url.package() == "");
CHECK_THROWS_AS(url.set_package("not-package/"), std::invalid_argument);
CHECK_EQ(url.path(), "/");
REQUIRE_THROWS_AS(url.set_package("not-package/"), std::invalid_argument);
REQUIRE(url.path() == "/");
CHECK_FALSE(url.clear_package());
CHECK_EQ(url.package(), "");
CHECK_EQ(url.path(), "/");
REQUIRE_FALSE(url.clear_package());
REQUIRE(url.package() == "");
REQUIRE(url.path() == "/");
url.set_package("micromamba-1.5.1-0.tar.bz2");
CHECK_EQ(url.package(), "micromamba-1.5.1-0.tar.bz2");
CHECK_EQ(url.path(), "/micromamba-1.5.1-0.tar.bz2");
REQUIRE(url.package() == "micromamba-1.5.1-0.tar.bz2");
REQUIRE(url.path() == "/micromamba-1.5.1-0.tar.bz2");
CHECK(url.clear_package());
CHECK_EQ(url.package(), "");
CHECK_EQ(url.path(), "/");
REQUIRE(url.clear_package());
REQUIRE(url.package() == "");
REQUIRE(url.path() == "/");
}
SUBCASE("https://repo.mamba.pm/conda-forge")
SECTION("https://repo.mamba.pm/conda-forge")
{
url.set_path("conda-forge");
CHECK_EQ(url.package(), "");
REQUIRE(url.package() == "");
url.set_package("micromamba-1.5.1-0.tar.bz2");
CHECK_EQ(url.package(), "micromamba-1.5.1-0.tar.bz2");
CHECK_EQ(url.path(), "/conda-forge/micromamba-1.5.1-0.tar.bz2");
REQUIRE(url.package() == "micromamba-1.5.1-0.tar.bz2");
REQUIRE(url.path() == "/conda-forge/micromamba-1.5.1-0.tar.bz2");
CHECK(url.clear_package());
CHECK_EQ(url.package(), "");
CHECK_EQ(url.path(), "/conda-forge");
REQUIRE(url.clear_package());
REQUIRE(url.package() == "");
REQUIRE(url.path() == "/conda-forge");
}
SUBCASE("https://repo.mamba.pm/conda-forge/")
SECTION("https://repo.mamba.pm/conda-forge/")
{
url.set_path("conda-forge/");
CHECK_EQ(url.package(), "");
REQUIRE(url.package() == "");
url.set_package("micromamba-1.5.1-0.tar.bz2");
CHECK_EQ(url.package(), "micromamba-1.5.1-0.tar.bz2");
CHECK_EQ(url.path(), "/conda-forge/micromamba-1.5.1-0.tar.bz2");
REQUIRE(url.package() == "micromamba-1.5.1-0.tar.bz2");
REQUIRE(url.path() == "/conda-forge/micromamba-1.5.1-0.tar.bz2");
CHECK(url.clear_package());
CHECK_EQ(url.package(), "");
CHECK_EQ(url.path(), "/conda-forge");
REQUIRE(url.clear_package());
REQUIRE(url.package() == "");
REQUIRE(url.path() == "/conda-forge");
}
SUBCASE("https://repo.mamba.pm/conda-forge/linux-64/micromamba-1.5.1-0.tar.bz2")
SECTION("https://repo.mamba.pm/conda-forge/linux-64/micromamba-1.5.1-0.tar.bz2")
{
url.set_path("/conda-forge/linux-64/micromamba-1.5.1-0.tar.bz2");
CHECK_EQ(url.package(), "micromamba-1.5.1-0.tar.bz2");
REQUIRE(url.package() == "micromamba-1.5.1-0.tar.bz2");
url.set_package("mamba-1.5.1-0.tar.bz2");
CHECK_EQ(url.package(), "mamba-1.5.1-0.tar.bz2");
CHECK_EQ(url.path(), "/conda-forge/linux-64/mamba-1.5.1-0.tar.bz2");
REQUIRE(url.package() == "mamba-1.5.1-0.tar.bz2");
REQUIRE(url.path() == "/conda-forge/linux-64/mamba-1.5.1-0.tar.bz2");
CHECK(url.clear_package());
CHECK_EQ(url.package(), "");
CHECK_EQ(url.path(), "/conda-forge/linux-64");
REQUIRE(url.clear_package());
REQUIRE(url.package() == "");
REQUIRE(url.path() == "/conda-forge/linux-64");
}
}
TEST_CASE("str options")
TEST_CASE("CondaURL str options")
{
CondaURL url = {};
SUBCASE("without credentials")
SECTION("without credentials")
{
CHECK_EQ(url.str(CondaURL::Credentials::Show), "https://localhost/");
CHECK_EQ(url.str(CondaURL::Credentials::Hide), "https://localhost/");
CHECK_EQ(url.str(CondaURL::Credentials::Remove), "https://localhost/");
REQUIRE(url.str(CondaURL::Credentials::Show) == "https://localhost/");
REQUIRE(url.str(CondaURL::Credentials::Hide) == "https://localhost/");
REQUIRE(url.str(CondaURL::Credentials::Remove) == "https://localhost/");
}
SUBCASE("with some credentials")
SECTION("with some credentials")
{
url.set_user("user@mamba.org");
url.set_password("pass");
CHECK_EQ(url.str(CondaURL::Credentials::Show), "https://user%40mamba.org:pass@localhost/");
CHECK_EQ(url.str(CondaURL::Credentials::Hide), "https://user%40mamba.org:*****@localhost/");
CHECK_EQ(url.str(CondaURL::Credentials::Remove), "https://localhost/");
REQUIRE(url.str(CondaURL::Credentials::Show) == "https://user%40mamba.org:pass@localhost/");
REQUIRE(
url.str(CondaURL::Credentials::Hide) == "https://user%40mamba.org:*****@localhost/"
);
REQUIRE(url.str(CondaURL::Credentials::Remove) == "https://localhost/");
SUBCASE("and token")
SECTION("and token")
{
url.set_path("/t/abcd1234/linux-64");
CHECK_EQ(
url.str(CondaURL::Credentials::Show),
"https://user%40mamba.org:pass@localhost/t/abcd1234/linux-64"
REQUIRE(
url.str(CondaURL::Credentials::Show)
== "https://user%40mamba.org:pass@localhost/t/abcd1234/linux-64"
);
CHECK_EQ(
url.str(CondaURL::Credentials::Hide),
"https://user%40mamba.org:*****@localhost/t/*****/linux-64"
REQUIRE(
url.str(CondaURL::Credentials::Hide)
== "https://user%40mamba.org:*****@localhost/t/*****/linux-64"
);
CHECK_EQ(url.str(CondaURL::Credentials::Remove), "https://localhost/linux-64");
REQUIRE(url.str(CondaURL::Credentials::Remove) == "https://localhost/linux-64");
}
}
}
TEST_CASE("pretty_str options")
TEST_CASE("CondaURL pretty_str options")
{
SUBCASE("scheme option")
SECTION("scheme option")
{
CondaURL url = {};
url.set_host("mamba.org");
SUBCASE("default scheme")
SECTION("default scheme")
{
CHECK_EQ(url.pretty_str(CondaURL::StripScheme::no), "https://mamba.org/");
CHECK_EQ(url.pretty_str(CondaURL::StripScheme::yes), "mamba.org/");
REQUIRE(url.pretty_str(CondaURL::StripScheme::no) == "https://mamba.org/");
REQUIRE(url.pretty_str(CondaURL::StripScheme::yes) == "mamba.org/");
}
SUBCASE("ftp scheme")
SECTION("ftp scheme")
{
url.set_scheme("ftp");
CHECK_EQ(url.pretty_str(CondaURL::StripScheme::no), "ftp://mamba.org/");
CHECK_EQ(url.pretty_str(CondaURL::StripScheme::yes), "mamba.org/");
REQUIRE(url.pretty_str(CondaURL::StripScheme::no) == "ftp://mamba.org/");
REQUIRE(url.pretty_str(CondaURL::StripScheme::yes) == "mamba.org/");
}
}
SUBCASE("rstrip option")
SECTION("rstrip option")
{
CondaURL url = {};
url.set_host("mamba.org");
CHECK_EQ(url.pretty_str(CondaURL::StripScheme::no, 0), "https://mamba.org/");
CHECK_EQ(url.pretty_str(CondaURL::StripScheme::no, '/'), "https://mamba.org");
REQUIRE(url.pretty_str(CondaURL::StripScheme::no, 0) == "https://mamba.org/");
REQUIRE(url.pretty_str(CondaURL::StripScheme::no, '/') == "https://mamba.org");
url.set_path("/page/");
CHECK_EQ(url.pretty_str(CondaURL::StripScheme::no, ':'), "https://mamba.org/page/");
CHECK_EQ(url.pretty_str(CondaURL::StripScheme::no, '/'), "https://mamba.org/page");
REQUIRE(url.pretty_str(CondaURL::StripScheme::no, ':') == "https://mamba.org/page/");
REQUIRE(url.pretty_str(CondaURL::StripScheme::no, '/') == "https://mamba.org/page");
}
SUBCASE("Credential option")
SECTION("Credential option")
{
CondaURL url = {};
SUBCASE("without credentials")
SECTION("without credentials")
{
CHECK_EQ(
url.pretty_str(CondaURL::StripScheme::no, 0, CondaURL::Credentials::Show),
"https://localhost/"
REQUIRE(
url.pretty_str(CondaURL::StripScheme::no, 0, CondaURL::Credentials::Show)
== "https://localhost/"
);
CHECK_EQ(
url.pretty_str(CondaURL::StripScheme::no, 0, CondaURL::Credentials::Hide),
"https://localhost/"
REQUIRE(
url.pretty_str(CondaURL::StripScheme::no, 0, CondaURL::Credentials::Hide)
== "https://localhost/"
);
CHECK_EQ(
url.pretty_str(CondaURL::StripScheme::no, 0, CondaURL::Credentials::Remove),
"https://localhost/"
REQUIRE(
url.pretty_str(CondaURL::StripScheme::no, 0, CondaURL::Credentials::Remove)
== "https://localhost/"
);
}
SUBCASE("with user:password")
SECTION("with user:password")
{
url.set_user("user");
url.set_password("pass");
CHECK_EQ(
url.pretty_str(CondaURL::StripScheme::no, 0, CondaURL::Credentials::Show),
"https://user:pass@localhost/"
REQUIRE(
url.pretty_str(CondaURL::StripScheme::no, 0, CondaURL::Credentials::Show)
== "https://user:pass@localhost/"
);
CHECK_EQ(
url.pretty_str(CondaURL::StripScheme::no, 0, CondaURL::Credentials::Hide),
"https://user:*****@localhost/"
REQUIRE(
url.pretty_str(CondaURL::StripScheme::no, 0, CondaURL::Credentials::Hide)
== "https://user:*****@localhost/"
);
CHECK_EQ(
url.pretty_str(CondaURL::StripScheme::no, 0, CondaURL::Credentials::Remove),
"https://localhost/"
REQUIRE(
url.pretty_str(CondaURL::StripScheme::no, 0, CondaURL::Credentials::Remove)
== "https://localhost/"
);
SUBCASE("and token")
SECTION("and token")
{
url.set_path("/t/abcd1234/linux-64");
CHECK_EQ(
url.pretty_str(CondaURL::StripScheme::no, 0, CondaURL::Credentials::Show),
"https://user:pass@localhost/t/abcd1234/linux-64"
REQUIRE(
url.pretty_str(CondaURL::StripScheme::no, 0, CondaURL::Credentials::Show)
== "https://user:pass@localhost/t/abcd1234/linux-64"
);
CHECK_EQ(
url.pretty_str(CondaURL::StripScheme::no, 0, CondaURL::Credentials::Hide),
"https://user:*****@localhost/t/*****/linux-64"
REQUIRE(
url.pretty_str(CondaURL::StripScheme::no, 0, CondaURL::Credentials::Hide)
== "https://user:*****@localhost/t/*****/linux-64"
);
CHECK_EQ(
url.pretty_str(CondaURL::StripScheme::no, 0, CondaURL::Credentials::Remove),
"https://localhost/linux-64"
REQUIRE(
url.pretty_str(CondaURL::StripScheme::no, 0, CondaURL::Credentials::Remove)
== "https://localhost/linux-64"
);
}
}
}
SUBCASE("https://user:password@mamba.org:8080/folder/file.html?param=value#fragment")
SECTION("https://user:password@mamba.org:8080/folder/file.html?param=value#fragment")
{
CondaURL url{};
url.set_scheme("https");
@ -457,21 +459,20 @@ TEST_SUITE("specs::CondaURL")
url.set_query("param=value");
url.set_fragment("fragment");
CHECK_EQ(
url.str(),
"https://user:*****@mamba.org:8080/folder/file.html?param=value#fragment"
REQUIRE(
url.str() == "https://user:*****@mamba.org:8080/folder/file.html?param=value#fragment"
);
CHECK_EQ(
url.str(CondaURL::Credentials::Show),
"https://user:password@mamba.org:8080/folder/file.html?param=value#fragment"
REQUIRE(
url.str(CondaURL::Credentials::Show)
== "https://user:password@mamba.org:8080/folder/file.html?param=value#fragment"
);
CHECK_EQ(
url.pretty_str(),
"https://user:*****@mamba.org:8080/folder/file.html?param=value#fragment"
REQUIRE(
url.pretty_str()
== "https://user:*****@mamba.org:8080/folder/file.html?param=value#fragment"
);
}
SUBCASE("https://user@email.com:pw%rd@mamba.org/some /path$/")
SECTION("https://user@email.com:pw%rd@mamba.org/some /path$/")
{
CondaURL url{};
url.set_scheme("https");
@ -479,12 +480,12 @@ TEST_SUITE("specs::CondaURL")
url.set_user("user@email.com");
url.set_password("pw%rd");
url.set_path("/some /path$/");
CHECK_EQ(url.str(), "https://user%40email.com:*****@mamba.org/some%20/path%24/");
CHECK_EQ(
url.str(CondaURL::Credentials::Show),
"https://user%40email.com:pw%25rd@mamba.org/some%20/path%24/"
REQUIRE(url.str() == "https://user%40email.com:*****@mamba.org/some%20/path%24/");
REQUIRE(
url.str(CondaURL::Credentials::Show)
== "https://user%40email.com:pw%25rd@mamba.org/some%20/path%24/"
);
CHECK_EQ(url.pretty_str(), "https://user@email.com:*****@mamba.org/some /path$/");
REQUIRE(url.pretty_str() == "https://user@email.com:*****@mamba.org/some /path$/");
}
}
}

View File

@ -4,40 +4,40 @@
//
// The full license is in the file LICENSE, distributed with this software.
#include <doctest/doctest.h>
#include <catch2/catch_all.hpp>
#include "mamba/specs/glob_spec.hpp"
using namespace mamba::specs;
TEST_SUITE("specs::glob_spec")
namespace
{
// See also test_parser for Glob matcher tests
TEST_CASE("Free")
TEST_CASE("GlobSpec Free")
{
auto spec = GlobSpec();
CHECK(spec.contains(""));
CHECK(spec.contains("hello"));
REQUIRE(spec.contains(""));
REQUIRE(spec.contains("hello"));
CHECK_EQ(spec.str(), "*");
CHECK(spec.is_free());
CHECK_FALSE(spec.is_exact());
REQUIRE(spec.str() == "*");
REQUIRE(spec.is_free());
REQUIRE_FALSE(spec.is_exact());
}
TEST_CASE("*mkl*")
{
auto spec = GlobSpec("mkl");
CHECK(spec.contains("mkl"));
CHECK_FALSE(spec.contains(""));
CHECK_FALSE(spec.contains("nomkl"));
CHECK_FALSE(spec.contains("hello"));
REQUIRE(spec.contains("mkl"));
REQUIRE_FALSE(spec.contains(""));
REQUIRE_FALSE(spec.contains("nomkl"));
REQUIRE_FALSE(spec.contains("hello"));
CHECK_EQ(spec.str(), "mkl");
CHECK_FALSE(spec.is_free());
CHECK(spec.is_exact());
REQUIRE(spec.str() == "mkl");
REQUIRE_FALSE(spec.is_free());
REQUIRE(spec.is_exact());
}
TEST_CASE("*py*")
@ -45,28 +45,28 @@ TEST_SUITE("specs::glob_spec")
// See also test_parser for Glob matcher tests
auto spec = GlobSpec("*py*");
CHECK(spec.contains("py"));
CHECK(spec.contains("pypy"));
CHECK(spec.contains("cpython-linux-64"));
CHECK_FALSE(spec.contains("rust"));
CHECK_FALSE(spec.contains("hello"));
REQUIRE(spec.contains("py"));
REQUIRE(spec.contains("pypy"));
REQUIRE(spec.contains("cpython-linux-64"));
REQUIRE_FALSE(spec.contains("rust"));
REQUIRE_FALSE(spec.contains("hello"));
CHECK_EQ(spec.str(), "*py*");
CHECK_FALSE(spec.is_free());
CHECK_FALSE(spec.is_exact());
REQUIRE(spec.str() == "*py*");
REQUIRE_FALSE(spec.is_free());
REQUIRE_FALSE(spec.is_exact());
}
TEST_CASE("Comparability and hashability")
TEST_CASE("GlobSpec Comparability and hashability")
{
auto spec1 = GlobSpec("py*");
auto spec2 = GlobSpec("py*");
auto spec3 = GlobSpec("pyth*");
CHECK_EQ(spec1, spec2);
CHECK_NE(spec1, spec3);
REQUIRE(spec1 == spec2);
REQUIRE(spec1 != spec3);
auto hash_fn = std::hash<GlobSpec>();
CHECK_EQ(hash_fn(spec1), hash_fn(spec2));
CHECK_NE(hash_fn(spec1), hash_fn(spec3));
REQUIRE(hash_fn(spec1) == hash_fn(spec2));
REQUIRE(hash_fn(spec1) != hash_fn(spec3));
}
}

File diff suppressed because it is too large Load Diff

View File

@ -7,57 +7,55 @@
#include <string>
#include <vector>
#include <doctest/doctest.h>
#include <catch2/catch_all.hpp>
#include <nlohmann/json.hpp>
#include "mamba/specs/package_info.hpp"
#include "doctest-printer/vector.hpp"
namespace nl = nlohmann;
using namespace mamba::specs;
TEST_SUITE("specs::package_info")
namespace
{
TEST_CASE("PackageInfo::from_url")
{
SUBCASE("https://conda.anaconda.org/conda-forge/linux-64/pkg-6.4-bld.conda")
SECTION("https://conda.anaconda.org/conda-forge/linux-64/pkg-6.4-bld.conda")
{
static constexpr std::string_view url = "https://conda.anaconda.org/conda-forge/linux-64/pkg-6.4-bld.conda";
auto pkg = PackageInfo::from_url(url).value();
CHECK_EQ(pkg.name, "pkg");
CHECK_EQ(pkg.version, "6.4");
CHECK_EQ(pkg.build_string, "bld");
CHECK_EQ(pkg.filename, "pkg-6.4-bld.conda");
CHECK_EQ(pkg.package_url, url);
CHECK_EQ(pkg.md5, "");
CHECK_EQ(pkg.platform, "linux-64");
CHECK_EQ(pkg.channel, "https://conda.anaconda.org/conda-forge");
REQUIRE(pkg.name == "pkg");
REQUIRE(pkg.version == "6.4");
REQUIRE(pkg.build_string == "bld");
REQUIRE(pkg.filename == "pkg-6.4-bld.conda");
REQUIRE(pkg.package_url == url);
REQUIRE(pkg.md5 == "");
REQUIRE(pkg.platform == "linux-64");
REQUIRE(pkg.channel == "https://conda.anaconda.org/conda-forge");
}
SUBCASE("https://conda.anaconda.org/conda-forge/linux-64/pkg-6.4-bld.conda#7dbaa197d7ba6032caf7ae7f32c1efa0"
SECTION("https://conda.anaconda.org/conda-forge/linux-64/pkg-6.4-bld.conda#7dbaa197d7ba6032caf7ae7f32c1efa0"
)
{
static constexpr std::string_view url = "https://conda.anaconda.org/conda-forge/linux-64/pkg-6.4-bld.conda#7dbaa197d7ba6032caf7ae7f32c1efa0";
auto pkg = PackageInfo::from_url(url).value();
CHECK_EQ(pkg.name, "pkg");
CHECK_EQ(pkg.version, "6.4");
CHECK_EQ(pkg.build_string, "bld");
CHECK_EQ(pkg.filename, "pkg-6.4-bld.conda");
CHECK_EQ(pkg.package_url, url.substr(0, url.rfind('#')));
CHECK_EQ(pkg.md5, url.substr(url.rfind('#') + 1));
CHECK_EQ(pkg.platform, "linux-64");
CHECK_EQ(pkg.channel, "https://conda.anaconda.org/conda-forge");
REQUIRE(pkg.name == "pkg");
REQUIRE(pkg.version == "6.4");
REQUIRE(pkg.build_string == "bld");
REQUIRE(pkg.filename == "pkg-6.4-bld.conda");
REQUIRE(pkg.package_url == url.substr(0, url.rfind('#')));
REQUIRE(pkg.md5 == url.substr(url.rfind('#') + 1));
REQUIRE(pkg.platform == "linux-64");
REQUIRE(pkg.channel == "https://conda.anaconda.org/conda-forge");
}
SUBCASE("https://conda.anaconda.org/conda-forge/linux-64/pkg.conda")
SECTION("https://conda.anaconda.org/conda-forge/linux-64/pkg.conda")
{
static constexpr std::string_view url = "https://conda.anaconda.org/conda-forge/linux-64/pkg.conda";
CHECK_FALSE(PackageInfo::from_url(url).has_value());
REQUIRE_FALSE(PackageInfo::from_url(url).has_value());
}
}
@ -85,52 +83,54 @@ TEST_SUITE("specs::package_info")
pkg.dependencies = { "python>=3.7", "requests" };
pkg.constrains = { "pip>=2.1" };
SUBCASE("field")
SECTION("field")
{
CHECK_EQ(pkg.field("name"), "foo");
CHECK_EQ(pkg.field("version"), "4.0");
CHECK_EQ(pkg.field("build_string"), "mybld");
CHECK_EQ(pkg.field("build_number"), "5");
CHECK_EQ(pkg.field("noarch"), "generic");
CHECK_EQ(pkg.field("channel"), "conda-forge");
CHECK_EQ(
pkg.field("package_url"),
"https://repo.mamba.pm/conda-forge/linux-64/foo-4.0-mybld.conda"
REQUIRE(pkg.field("name") == "foo");
REQUIRE(pkg.field("version") == "4.0");
REQUIRE(pkg.field("build_string") == "mybld");
REQUIRE(pkg.field("build_number") == "5");
REQUIRE(pkg.field("noarch") == "generic");
REQUIRE(pkg.field("channel") == "conda-forge");
REQUIRE(
pkg.field("package_url")
== "https://repo.mamba.pm/conda-forge/linux-64/foo-4.0-mybld.conda"
);
CHECK_EQ(pkg.field("subdir"), "linux-64");
CHECK_EQ(pkg.field("filename"), "foo-4.0-mybld.conda");
CHECK_EQ(pkg.field("license"), "MIT");
CHECK_EQ(pkg.field("size"), "3200");
CHECK_EQ(pkg.field("timestamp"), "4532");
REQUIRE(pkg.field("subdir") == "linux-64");
REQUIRE(pkg.field("filename") == "foo-4.0-mybld.conda");
REQUIRE(pkg.field("license") == "MIT");
REQUIRE(pkg.field("size") == "3200");
REQUIRE(pkg.field("timestamp") == "4532");
}
SUBCASE("to_json")
SECTION("to_json")
{
const auto j = nl::json(pkg);
CHECK_EQ(j.at("name"), "foo");
CHECK_EQ(j.at("version"), "4.0");
CHECK_EQ(j.at("build_string"), "mybld");
CHECK_EQ(j.at("build_number"), 5);
CHECK_EQ(j.at("noarch"), "generic");
CHECK_EQ(j.at("channel"), "conda-forge");
CHECK_EQ(j.at("url"), "https://repo.mamba.pm/conda-forge/linux-64/foo-4.0-mybld.conda");
CHECK_EQ(j.at("subdir"), "linux-64");
CHECK_EQ(j.at("fn"), "foo-4.0-mybld.conda");
CHECK_EQ(j.at("license"), "MIT");
CHECK_EQ(j.at("size"), 3200);
CHECK_EQ(j.at("timestamp"), 4532);
CHECK_EQ(j.at("sha256"), "01ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b");
CHECK_EQ(
j.at("signatures"),
R"("signatures": { "some_file.tar.bz2": { "a133184c9c7a651f55db194031a6c1240b798333923dc9319d1fe2c94a1242d": { "signature": "7a67a875d0454c14671d960a02858e059d154876dab6b3873304a27102063c9c25"}}})"
REQUIRE(j.at("name") == "foo");
REQUIRE(j.at("version") == "4.0");
REQUIRE(j.at("build_string") == "mybld");
REQUIRE(j.at("build_number") == 5);
REQUIRE(j.at("noarch") == "generic");
REQUIRE(j.at("channel") == "conda-forge");
REQUIRE(j.at("url") == "https://repo.mamba.pm/conda-forge/linux-64/foo-4.0-mybld.conda");
REQUIRE(j.at("subdir") == "linux-64");
REQUIRE(j.at("fn") == "foo-4.0-mybld.conda");
REQUIRE(j.at("license") == "MIT");
REQUIRE(j.at("size") == 3200);
REQUIRE(j.at("timestamp") == 4532);
REQUIRE(
j.at("sha256") == "01ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b"
);
CHECK_EQ(j.at("md5"), "68b329da9893e34099c7d8ad5cb9c940");
CHECK_EQ(j.at("track_features"), "mkl,blas");
CHECK_EQ(j.at("depends"), StrVec{ "python>=3.7", "requests" });
CHECK_EQ(j.at("constrains"), StrVec{ "pip>=2.1" });
REQUIRE(
j.at("signatures")
== R"("signatures": { "some_file.tar.bz2": { "a133184c9c7a651f55db194031a6c1240b798333923dc9319d1fe2c94a1242d": { "signature": "7a67a875d0454c14671d960a02858e059d154876dab6b3873304a27102063c9c25"}}})"
);
REQUIRE(j.at("md5") == "68b329da9893e34099c7d8ad5cb9c940");
REQUIRE(j.at("track_features") == "mkl,blas");
REQUIRE(j.at("depends") == StrVec{ "python>=3.7", "requests" });
REQUIRE(j.at("constrains") == StrVec{ "pip>=2.1" });
}
SUBCASE("from_json")
SECTION("from_json")
{
auto j = nl::json::object();
j["name"] = "foo";
@ -152,46 +152,46 @@ TEST_SUITE("specs::package_info")
j["depends"] = StrVec{ "python>=3.7", "requests" };
j["constrains"] = StrVec{ "pip>=2.1" };
CHECK_EQ(j.get<PackageInfo>(), pkg);
REQUIRE(j.get<PackageInfo>() == pkg);
SUBCASE("noarch")
SECTION("noarch")
{
j["noarch"] = "Python";
CHECK_EQ(j.get<PackageInfo>().noarch, NoArchType::Python);
REQUIRE(j.get<PackageInfo>().noarch == NoArchType::Python);
j["noarch"] = true;
CHECK_EQ(j.get<PackageInfo>().noarch, NoArchType::Generic);
REQUIRE(j.get<PackageInfo>().noarch == NoArchType::Generic);
j["noarch"] = false;
CHECK_EQ(j.get<PackageInfo>().noarch, NoArchType::No);
REQUIRE(j.get<PackageInfo>().noarch == NoArchType::No);
j["noarch"] = nullptr;
CHECK_EQ(j.get<PackageInfo>().noarch, NoArchType::No);
REQUIRE(j.get<PackageInfo>().noarch == NoArchType::No);
j.erase("noarch");
CHECK_EQ(j.get<PackageInfo>().noarch, NoArchType::No);
REQUIRE(j.get<PackageInfo>().noarch == NoArchType::No);
}
SUBCASE("track_features")
SECTION("track_features")
{
j["track_features"] = "python";
CHECK_EQ(j.get<PackageInfo>().track_features, StrVec{ "python" });
REQUIRE(j.get<PackageInfo>().track_features == StrVec{ "python" });
j["track_features"] = "python,mkl";
CHECK_EQ(j.get<PackageInfo>().track_features, StrVec{ "python", "mkl" });
REQUIRE(j.get<PackageInfo>().track_features == StrVec{ "python", "mkl" });
j.erase("track_features");
CHECK_EQ(j.get<PackageInfo>().track_features, StrVec{});
REQUIRE(j.get<PackageInfo>().track_features == StrVec{});
j["track_features"] = nl::json::array({ "py", "malloc" });
CHECK_EQ(j.get<PackageInfo>().track_features, StrVec{ "py", "malloc" });
REQUIRE(j.get<PackageInfo>().track_features == StrVec{ "py", "malloc" });
}
SUBCASE("equality_operator")
SECTION("equality_operator")
{
CHECK(j.get<PackageInfo>() == pkg);
REQUIRE(j.get<PackageInfo>() == pkg);
}
SUBCASE("inequality_operator")
SECTION("inequality_operator")
{
CHECK_FALSE(j.get<PackageInfo>() != pkg);
REQUIRE_FALSE(j.get<PackageInfo>() != pkg);
}
}
SUBCASE("PackageInfo comparability and hashability")
SECTION("PackageInfo comparability and hashability")
{
auto pkg2 = PackageInfo();
pkg2.name = "foo";
@ -215,14 +215,14 @@ TEST_SUITE("specs::package_info")
auto hash_fn = std::hash<PackageInfo>{};
CHECK_EQ(pkg, pkg2);
CHECK_EQ(hash_fn(pkg), hash_fn(pkg2));
REQUIRE(pkg == pkg2);
REQUIRE(hash_fn(pkg) == hash_fn(pkg2));
pkg2.md5[0] = '0';
CHECK_NE(pkg, pkg2);
CHECK_NE(hash_fn(pkg), hash_fn(pkg2));
REQUIRE(pkg != pkg2);
REQUIRE(hash_fn(pkg) != hash_fn(pkg2));
}
}
}

View File

@ -4,32 +4,32 @@
//
// The full license is in the file LICENSE, distributed with this software.
#include <doctest/doctest.h>
#include <catch2/catch_all.hpp>
#include "mamba/specs/platform.hpp"
using namespace mamba::specs;
TEST_SUITE("specs::platform")
namespace
{
TEST_CASE("KnownPlatform")
{
SUBCASE("name")
SECTION("name")
{
CHECK_EQ(platform_name(KnownPlatform::linux_riscv32), "linux-riscv32");
CHECK_EQ(platform_name(KnownPlatform::osx_arm64), "osx-arm64");
CHECK_EQ(platform_name(KnownPlatform::win_64), "win-64");
REQUIRE(platform_name(KnownPlatform::linux_riscv32) == "linux-riscv32");
REQUIRE(platform_name(KnownPlatform::osx_arm64) == "osx-arm64");
REQUIRE(platform_name(KnownPlatform::win_64) == "win-64");
}
SUBCASE("parse")
SECTION("parse")
{
CHECK_EQ(platform_parse("linux-armv6l"), KnownPlatform::linux_armv6l);
CHECK_EQ(platform_parse(" win-32 "), KnownPlatform::win_32);
CHECK_EQ(platform_parse(" OSX-64"), KnownPlatform::osx_64);
CHECK_EQ(platform_parse("linus-46"), std::nullopt);
REQUIRE(platform_parse("linux-armv6l") == KnownPlatform::linux_armv6l);
REQUIRE(platform_parse(" win-32 ") == KnownPlatform::win_32);
REQUIRE(platform_parse(" OSX-64") == KnownPlatform::osx_64);
REQUIRE(platform_parse("linus-46") == std::nullopt);
}
SUBCASE("known_platform")
SECTION("known_platform")
{
static constexpr decltype(known_platform_names()) expected{
"noarch", "linux-32", "linux-64", "linux-armv6l", "linux-armv7l",
@ -38,13 +38,13 @@ TEST_SUITE("specs::platform")
"win-arm64", "zos-z",
};
CHECK_EQ(expected, known_platform_names());
REQUIRE(expected == known_platform_names());
}
}
TEST_CASE("platform_is_xxx")
{
SUBCASE("KnownPlatform")
SECTION("KnownPlatform")
{
// Making sure no-one forgot to add the platform with a specific OS
for (auto plat : known_platforms())
@ -54,47 +54,47 @@ TEST_SUITE("specs::platform")
|| platform_is_win(plat) //
|| (plat == KnownPlatform::noarch) //
|| (plat == KnownPlatform::zos_z);
CHECK(check);
REQUIRE(check);
}
}
SUBCASE("DynamicPlatform")
SECTION("DynamicPlatform")
{
CHECK_FALSE(platform_is_linux("win-64"));
CHECK_FALSE(platform_is_linux("osx-64"));
CHECK(platform_is_linux("linux-64"));
REQUIRE_FALSE(platform_is_linux("win-64"));
REQUIRE_FALSE(platform_is_linux("osx-64"));
REQUIRE(platform_is_linux("linux-64"));
CHECK_FALSE(platform_is_osx("win-64"));
CHECK(platform_is_osx("osx-64"));
CHECK_FALSE(platform_is_osx("linux-64"));
REQUIRE_FALSE(platform_is_osx("win-64"));
REQUIRE(platform_is_osx("osx-64"));
REQUIRE_FALSE(platform_is_osx("linux-64"));
CHECK(platform_is_win("win-64"));
CHECK_FALSE(platform_is_win("osx-64"));
CHECK_FALSE(platform_is_win("linux-64"));
REQUIRE(platform_is_win("win-64"));
REQUIRE_FALSE(platform_is_win("osx-64"));
REQUIRE_FALSE(platform_is_win("linux-64"));
}
}
TEST_CASE("NoArch")
{
SUBCASE("name")
SECTION("name")
{
CHECK_EQ(noarch_name(NoArchType::No), "no");
CHECK_EQ(noarch_name(NoArchType::Generic), "generic");
CHECK_EQ(noarch_name(NoArchType::Python), "python");
REQUIRE(noarch_name(NoArchType::No) == "no");
REQUIRE(noarch_name(NoArchType::Generic) == "generic");
REQUIRE(noarch_name(NoArchType::Python) == "python");
}
SUBCASE("parse")
SECTION("parse")
{
CHECK_EQ(noarch_parse(""), std::nullopt);
CHECK_EQ(noarch_parse(" Python "), NoArchType::Python);
CHECK_EQ(noarch_parse(" geNeric"), NoArchType::Generic);
CHECK_EQ(noarch_parse("Nothing we know"), std::nullopt);
REQUIRE(noarch_parse("") == std::nullopt);
REQUIRE(noarch_parse(" Python ") == NoArchType::Python);
REQUIRE(noarch_parse(" geNeric") == NoArchType::Generic);
REQUIRE(noarch_parse("Nothing we know") == std::nullopt);
}
SUBCASE("known_noarch")
SECTION("known_noarch")
{
static constexpr decltype(known_noarch_names()) expected{ "no", "generic", "python" };
CHECK_EQ(expected, known_noarch_names());
REQUIRE(expected == known_noarch_names());
}
}
}

View File

@ -4,80 +4,80 @@
//
// The full license is in the file LICENSE, distributed with this software.
#include <doctest/doctest.h>
#include <catch2/catch_all.hpp>
#include "mamba/specs/regex_spec.hpp"
using namespace mamba::specs;
TEST_SUITE("specs::regex_spec")
namespace
{
TEST_CASE("Free")
TEST_CASE("RegexSpec Free")
{
auto spec = RegexSpec();
CHECK(spec.contains(""));
CHECK(spec.contains("hello"));
REQUIRE(spec.contains(""));
REQUIRE(spec.contains("hello"));
CHECK_EQ(spec.str(), "^.*$");
CHECK(spec.is_explicitly_free());
CHECK_FALSE(spec.is_exact());
REQUIRE(spec.str() == "^.*$");
REQUIRE(spec.is_explicitly_free());
REQUIRE_FALSE(spec.is_exact());
}
TEST_CASE("mkl")
TEST_CASE("RegexSpec mkl")
{
auto spec = RegexSpec::parse("mkl").value();
CHECK(spec.contains("mkl"));
CHECK_FALSE(spec.contains(""));
CHECK_FALSE(spec.contains("nomkl"));
CHECK_FALSE(spec.contains("hello"));
REQUIRE(spec.contains("mkl"));
REQUIRE_FALSE(spec.contains(""));
REQUIRE_FALSE(spec.contains("nomkl"));
REQUIRE_FALSE(spec.contains("hello"));
CHECK_EQ(spec.str(), "^mkl$");
CHECK_FALSE(spec.is_explicitly_free());
CHECK(spec.is_exact());
REQUIRE(spec.str() == "^mkl$");
REQUIRE_FALSE(spec.is_explicitly_free());
REQUIRE(spec.is_exact());
}
TEST_CASE("py.*")
TEST_CASE("RegexSpec py.*")
{
auto spec = RegexSpec::parse("py.*").value();
CHECK(spec.contains("python"));
CHECK(spec.contains("py"));
CHECK(spec.contains("pypy"));
CHECK_FALSE(spec.contains(""));
CHECK_FALSE(spec.contains("cpython"));
REQUIRE(spec.contains("python"));
REQUIRE(spec.contains("py"));
REQUIRE(spec.contains("pypy"));
REQUIRE_FALSE(spec.contains(""));
REQUIRE_FALSE(spec.contains("cpython"));
CHECK_EQ(spec.str(), "^py.*$");
CHECK_FALSE(spec.is_explicitly_free());
CHECK_FALSE(spec.is_exact());
REQUIRE(spec.str() == "^py.*$");
REQUIRE_FALSE(spec.is_explicitly_free());
REQUIRE_FALSE(spec.is_exact());
}
TEST_CASE("^.*(accelerate|mkl)$")
TEST_CASE("RegexSpec ^.*(accelerate|mkl)$")
{
auto spec = RegexSpec::parse("^.*(accelerate|mkl)$").value();
CHECK(spec.contains("accelerate"));
CHECK(spec.contains("mkl"));
CHECK_FALSE(spec.contains(""));
CHECK_FALSE(spec.contains("openblas"));
REQUIRE(spec.contains("accelerate"));
REQUIRE(spec.contains("mkl"));
REQUIRE_FALSE(spec.contains(""));
REQUIRE_FALSE(spec.contains("openblas"));
CHECK_EQ(spec.str(), "^.*(accelerate|mkl)$");
CHECK_FALSE(spec.is_explicitly_free());
CHECK_FALSE(spec.is_exact());
REQUIRE(spec.str() == "^.*(accelerate|mkl)$");
REQUIRE_FALSE(spec.is_explicitly_free());
REQUIRE_FALSE(spec.is_exact());
}
TEST_CASE("Comparability and hashability")
TEST_CASE("RegexSpec Comparability and hashability")
{
auto spec1 = RegexSpec::parse("pyth*").value();
auto spec2 = RegexSpec::parse("pyth*").value();
auto spec3 = RegexSpec::parse("python").value();
CHECK_EQ(spec1, spec2);
CHECK_NE(spec1, spec3);
REQUIRE(spec1 == spec2);
REQUIRE(spec1 != spec3);
auto hash_fn = std::hash<RegexSpec>();
CHECK_EQ(hash_fn(spec1), hash_fn(spec2));
CHECK_NE(hash_fn(spec1), hash_fn(spec3));
REQUIRE(hash_fn(spec1) == hash_fn(spec2));
REQUIRE(hash_fn(spec1) != hash_fn(spec3));
}
}

View File

@ -6,7 +6,7 @@
#include <fstream>
#include <doctest/doctest.h>
#include <catch2/catch_all.hpp>
#include <nlohmann/json.hpp>
#include "mamba/specs/repo_data.hpp"
@ -15,7 +15,7 @@
using namespace mamba::specs;
namespace nl = nlohmann;
TEST_SUITE("specs::repo_data")
namespace
{
TEST_CASE("RepoDataPackage_to_json")
{
@ -29,14 +29,14 @@ TEST_SUITE("specs::repo_data")
p.noarch = NoArchType::Python;
const nl::json j = p;
CHECK_EQ(j.at("name"), p.name);
CHECK_EQ(j.at("version"), p.version.str());
CHECK_EQ(j.at("build"), p.build_string);
CHECK_EQ(j.at("build_number"), p.build_number);
CHECK_EQ(j.at("subdir"), p.subdir);
CHECK_EQ(j.at("md5"), p.md5);
CHECK(j.at("sha256").is_null());
CHECK_EQ(j.at("noarch"), "python");
REQUIRE(j.at("name") == p.name);
REQUIRE(j.at("version") == p.version.str());
REQUIRE(j.at("build") == p.build_string);
REQUIRE(j.at("build_number") == p.build_number);
REQUIRE(j.at("subdir") == p.subdir);
REQUIRE(j.at("md5") == p.md5);
REQUIRE(j.at("sha256").is_null());
REQUIRE(j.at("noarch") == "python");
}
TEST_CASE("RepoDataPackage_from_json")
@ -53,34 +53,34 @@ TEST_SUITE("specs::repo_data")
j["track_features"] = nl::json::array();
{
const auto p = j.get<RepoDataPackage>();
CHECK_EQ(p.name, j.at("name"));
REQUIRE(p.name == j.at("name"));
// Note Version::parse is not injective
CHECK_EQ(p.version.str(), j.at("version"));
CHECK_EQ(p.build_string, j.at("build"));
CHECK_EQ(p.build_number, j.at("build_number"));
CHECK_EQ(p.subdir, j.at("subdir"));
CHECK_FALSE(p.md5.has_value());
CHECK_FALSE(p.platform.has_value());
CHECK_EQ(p.depends, decltype(p.depends){ "libsolv>=1.0" });
CHECK(p.constrains.empty());
CHECK(p.track_features.empty());
CHECK_FALSE(p.noarch.has_value());
REQUIRE(p.version.str() == 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_FALSE(p.md5.has_value());
REQUIRE_FALSE(p.platform.has_value());
REQUIRE(p.depends == decltype(p.depends){ "libsolv>=1.0" });
REQUIRE(p.constrains.empty());
REQUIRE(p.track_features.empty());
REQUIRE_FALSE(p.noarch.has_value());
}
j["noarch"] = "python";
{
const auto p = j.get<RepoDataPackage>();
CHECK_EQ(p.noarch, NoArchType::Python);
REQUIRE(p.noarch == NoArchType::Python);
}
// Old beahiour
j["noarch"] = true;
{
const auto p = j.get<RepoDataPackage>();
CHECK_EQ(p.noarch, NoArchType::Generic);
REQUIRE(p.noarch == NoArchType::Generic);
}
j["noarch"] = false;
{
const auto p = j.get<RepoDataPackage>();
CHECK_FALSE(p.noarch.has_value());
REQUIRE_FALSE(p.noarch.has_value());
}
}
@ -96,20 +96,20 @@ TEST_SUITE("specs::repo_data")
data.removed = { "bad-package-1" };
const nl::json j = data;
CHECK_EQ(j.at("version"), data.version);
CHECK_EQ(
j.at("info").at("subdir").get<std::string_view>(),
platform_name(data.info.value().subdir)
REQUIRE(j.at("version") == data.version);
REQUIRE(
j.at("info").at("subdir").get<std::string_view>()
== platform_name(data.info.value().subdir)
);
CHECK_EQ(
j.at("packages").at("mamba-1.0-h12345.tar.bz2"),
data.packages.at("mamba-1.0-h12345.tar.bz2")
REQUIRE(
j.at("packages").at("mamba-1.0-h12345.tar.bz2")
== data.packages.at("mamba-1.0-h12345.tar.bz2")
);
CHECK_EQ(
j.at("packages").at("conda-1.0-h54321.tar.bz2"),
data.packages.at("conda-1.0-h54321.tar.bz2")
REQUIRE(
j.at("packages").at("conda-1.0-h54321.tar.bz2")
== data.packages.at("conda-1.0-h54321.tar.bz2")
);
CHECK_EQ(j.at("removed"), std::vector{ "bad-package-1" });
REQUIRE(j.at("removed") == std::vector{ "bad-package-1" });
}
TEST_CASE("RepoData_from_json")
@ -130,15 +130,15 @@ TEST_SUITE("specs::repo_data")
const auto data = j.get<RepoData>();
REQUIRE(data.version.has_value());
CHECK_EQ(data.version, j["version"]);
REQUIRE(data.version == j["version"]);
REQUIRE(data.info.has_value());
CHECK_EQ(platform_name(data.info.value().subdir), j["info"]["subdir"].get<std::string_view>());
CHECK_EQ(
data.packages.at("mamba-1.0-h12345.tar.bz2").name,
j["packages"]["mamba-1.0-h12345.tar.bz2"]["name"]
REQUIRE(platform_name(data.info.value().subdir) == j["info"]["subdir"].get<std::string_view>());
REQUIRE(
data.packages.at("mamba-1.0-h12345.tar.bz2").name
== j["packages"]["mamba-1.0-h12345.tar.bz2"]["name"]
);
CHECK(data.conda_packages.empty());
CHECK_EQ(data.removed, j["removed"]);
REQUIRE(data.conda_packages.empty());
REQUIRE(data.removed == j["removed"]);
}
TEST_CASE("repodata_json")

View File

@ -4,7 +4,7 @@
//
// The full license is in the file LICENSE, distributed with this software.
#include <doctest/doctest.h>
#include <catch2/catch_all.hpp>
#include "mamba/specs/unresolved_channel.hpp"
#include "mamba/util/build.hpp"
@ -12,256 +12,258 @@
using namespace mamba;
using namespace mamba::specs;
TEST_SUITE("specs::unresolved_channel")
namespace
{
using PlatformSet = typename util::flat_set<std::string>;
using Type = typename UnresolvedChannel::Type;
TEST_CASE("Constructor")
{
SUBCASE("Default")
SECTION("Default")
{
const auto uc = UnresolvedChannel();
CHECK_EQ(uc.type(), UnresolvedChannel::Type::Unknown);
CHECK_EQ(uc.location(), "<unknown>");
CHECK(uc.platform_filters().empty());
REQUIRE(uc.type() == UnresolvedChannel::Type::Unknown);
REQUIRE(uc.location() == "<unknown>");
REQUIRE(uc.platform_filters().empty());
}
SUBCASE("Unknown")
SECTION("Unknown")
{
const auto uc = UnresolvedChannel("hello", { "linux-78" }, UnresolvedChannel::Type::Unknown);
CHECK_EQ(uc.type(), UnresolvedChannel::Type::Unknown);
CHECK_EQ(uc.location(), "<unknown>");
CHECK_EQ(uc.platform_filters(), PlatformSet{ "linux-78" });
REQUIRE(uc.type() == UnresolvedChannel::Type::Unknown);
REQUIRE(uc.location() == "<unknown>");
REQUIRE(uc.platform_filters() == PlatformSet{ "linux-78" });
}
}
TEST_CASE("Parsing")
{
SUBCASE("Unknown channels")
SECTION("Unknown channels")
{
for (std::string_view str : { "", "<unknown>", ":///<unknown>", "none" })
{
CAPTURE(str);
const auto uc = UnresolvedChannel::parse(str).value();
CHECK_EQ(uc.type(), Type::Unknown);
CHECK_EQ(uc.location(), "<unknown>");
CHECK_EQ(uc.platform_filters(), PlatformSet{});
REQUIRE(uc.type() == Type::Unknown);
REQUIRE(uc.location() == "<unknown>");
REQUIRE(uc.platform_filters() == PlatformSet{});
}
}
SUBCASE("Invalid channels")
SECTION("Invalid channels")
{
for (std::string_view str : { "forgelinux-64]" })
{
CAPTURE(str);
CHECK_FALSE(UnresolvedChannel::parse(str).has_value());
REQUIRE_FALSE(UnresolvedChannel::parse(str).has_value());
}
}
SUBCASE("https://repo.anaconda.com/conda-forge")
SECTION("https://repo.anaconda.com/conda-forge")
{
const auto uc = UnresolvedChannel::parse("https://repo.anaconda.com/conda-forge").value();
CHECK_EQ(uc.type(), Type::URL);
CHECK_EQ(uc.location(), "https://repo.anaconda.com/conda-forge");
CHECK_EQ(uc.platform_filters(), PlatformSet{});
REQUIRE(uc.type() == Type::URL);
REQUIRE(uc.location() == "https://repo.anaconda.com/conda-forge");
REQUIRE(uc.platform_filters() == PlatformSet{});
}
SUBCASE("https://repo.anaconda.com/conda-forge/osx-64")
SECTION("https://repo.anaconda.com/conda-forge/osx-64")
{
const auto uc = UnresolvedChannel::parse("https://repo.anaconda.com/conda-forge/osx-64")
.value();
CHECK_EQ(uc.type(), Type::URL);
CHECK_EQ(uc.location(), "https://repo.anaconda.com/conda-forge");
CHECK_EQ(uc.platform_filters(), PlatformSet{ "osx-64" });
REQUIRE(uc.type() == Type::URL);
REQUIRE(uc.location() == "https://repo.anaconda.com/conda-forge");
REQUIRE(uc.platform_filters() == PlatformSet{ "osx-64" });
}
SUBCASE("https://repo.anaconda.com/conda-forge[win-64|noarch]")
SECTION("https://repo.anaconda.com/conda-forge[win-64|noarch]")
{
const auto uc = UnresolvedChannel::parse(
"https://repo.anaconda.com/conda-forge[win-64|noarch]"
)
.value();
CHECK_EQ(uc.type(), Type::URL);
CHECK_EQ(uc.location(), "https://repo.anaconda.com/conda-forge");
CHECK_EQ(uc.platform_filters(), PlatformSet{ "win-64", "noarch" });
REQUIRE(uc.type() == Type::URL);
REQUIRE(uc.location() == "https://repo.anaconda.com/conda-forge");
REQUIRE(uc.platform_filters() == PlatformSet{ "win-64", "noarch" });
}
SUBCASE("https://repo.anaconda.com/conda-forge/linux-64/pkg-0.0-bld.conda")
SECTION("https://repo.anaconda.com/conda-forge/linux-64/pkg-0.0-bld.conda")
{
const auto uc = UnresolvedChannel::parse(
"https://repo.anaconda.com/conda-forge/linux-64/pkg-0.0-bld.conda"
)
.value();
CHECK_EQ(uc.type(), Type::PackageURL);
CHECK_EQ(uc.location(), "https://repo.anaconda.com/conda-forge/linux-64/pkg-0.0-bld.conda");
CHECK_EQ(uc.platform_filters(), PlatformSet{});
REQUIRE(uc.type() == Type::PackageURL);
REQUIRE(
uc.location() == "https://repo.anaconda.com/conda-forge/linux-64/pkg-0.0-bld.conda"
);
REQUIRE(uc.platform_filters() == PlatformSet{});
}
SUBCASE("file:///Users/name/conda")
SECTION("file:///Users/name/conda")
{
const auto uc = UnresolvedChannel::parse("file:///Users/name/conda").value();
CHECK_EQ(uc.type(), Type::Path);
CHECK_EQ(uc.location(), "file:///Users/name/conda");
CHECK_EQ(uc.platform_filters(), PlatformSet{});
REQUIRE(uc.type() == Type::Path);
REQUIRE(uc.location() == "file:///Users/name/conda");
REQUIRE(uc.platform_filters() == PlatformSet{});
}
SUBCASE("file:///Users/name/conda[linux-64]")
SECTION("file:///Users/name/conda[linux-64]")
{
const auto uc = UnresolvedChannel::parse("file:///Users/name/conda[linux-64]").value();
CHECK_EQ(uc.type(), Type::Path);
CHECK_EQ(uc.location(), "file:///Users/name/conda");
CHECK_EQ(uc.platform_filters(), PlatformSet{ "linux-64" });
REQUIRE(uc.type() == Type::Path);
REQUIRE(uc.location() == "file:///Users/name/conda");
REQUIRE(uc.platform_filters() == PlatformSet{ "linux-64" });
}
SUBCASE("file://C:/Users/name/conda")
SECTION("file://C:/Users/name/conda")
{
if (util::on_win)
{
const auto uc = UnresolvedChannel::parse("file://C:/Users/name/conda").value();
CHECK_EQ(uc.type(), Type::Path);
CHECK_EQ(uc.location(), "file://C:/Users/name/conda");
CHECK_EQ(uc.platform_filters(), PlatformSet{});
REQUIRE(uc.type() == Type::Path);
REQUIRE(uc.location() == "file://C:/Users/name/conda");
REQUIRE(uc.platform_filters() == PlatformSet{});
}
}
SUBCASE("/Users/name/conda")
SECTION("/Users/name/conda")
{
const auto uc = UnresolvedChannel::parse("/Users/name/conda").value();
CHECK_EQ(uc.type(), Type::Path);
CHECK_EQ(uc.location(), "/Users/name/conda");
CHECK_EQ(uc.platform_filters(), PlatformSet{});
REQUIRE(uc.type() == Type::Path);
REQUIRE(uc.location() == "/Users/name/conda");
REQUIRE(uc.platform_filters() == PlatformSet{});
}
SUBCASE("./folder/../folder/.")
SECTION("./folder/../folder/.")
{
const auto uc = UnresolvedChannel::parse("./folder/../folder/.").value();
CHECK_EQ(uc.type(), Type::Path);
CHECK_EQ(uc.location(), "./folder");
CHECK_EQ(uc.platform_filters(), PlatformSet{});
REQUIRE(uc.type() == Type::Path);
REQUIRE(uc.location() == "./folder");
REQUIRE(uc.platform_filters() == PlatformSet{});
}
SUBCASE("./folder/subfolder/")
SECTION("./folder/subfolder/")
{
const auto uc = UnresolvedChannel::parse("./folder/subfolder/").value();
CHECK_EQ(uc.type(), Type::Path);
CHECK_EQ(uc.location(), "./folder/subfolder");
CHECK_EQ(uc.platform_filters(), PlatformSet{});
REQUIRE(uc.type() == Type::Path);
REQUIRE(uc.location() == "./folder/subfolder");
REQUIRE(uc.platform_filters() == PlatformSet{});
}
SUBCASE("~/folder/")
SECTION("~/folder/")
{
const auto uc = UnresolvedChannel::parse("~/folder/").value();
CHECK_EQ(uc.type(), Type::Path);
CHECK_EQ(uc.location(), "~/folder");
CHECK_EQ(uc.platform_filters(), PlatformSet{});
REQUIRE(uc.type() == Type::Path);
REQUIRE(uc.location() == "~/folder");
REQUIRE(uc.platform_filters() == PlatformSet{});
}
SUBCASE("/tmp/pkg-0.0-bld.tar.bz2")
SECTION("/tmp/pkg-0.0-bld.tar.bz2")
{
const auto uc = UnresolvedChannel::parse("/tmp/pkg-0.0-bld.tar.bz2").value();
CHECK_EQ(uc.type(), Type::PackagePath);
CHECK_EQ(uc.location(), "/tmp/pkg-0.0-bld.tar.bz2");
CHECK_EQ(uc.platform_filters(), PlatformSet{});
REQUIRE(uc.type() == Type::PackagePath);
REQUIRE(uc.location() == "/tmp/pkg-0.0-bld.tar.bz2");
REQUIRE(uc.platform_filters() == PlatformSet{});
}
SUBCASE("C:/tmp//pkg-0.0-bld.tar.bz2")
SECTION("C:/tmp//pkg-0.0-bld.tar.bz2")
{
const auto uc = UnresolvedChannel::parse("C:/tmp//pkg-0.0-bld.tar.bz2").value();
CHECK_EQ(uc.type(), Type::PackagePath);
CHECK_EQ(uc.location(), "C:/tmp/pkg-0.0-bld.tar.bz2");
CHECK_EQ(uc.platform_filters(), PlatformSet{});
REQUIRE(uc.type() == Type::PackagePath);
REQUIRE(uc.location() == "C:/tmp/pkg-0.0-bld.tar.bz2");
REQUIRE(uc.platform_filters() == PlatformSet{});
}
SUBCASE(R"(C:\tmp\pkg-0.0-bld.tar.bz2)")
SECTION(R"(C:\tmp\pkg-0.0-bld.tar.bz2)")
{
if (util::on_win)
{
const auto uc = UnresolvedChannel::parse(R"(C:\tmp\pkg-0.0-bld.tar.bz2)").value();
CHECK_EQ(uc.type(), Type::PackagePath);
CHECK_EQ(uc.location(), "C:/tmp/pkg-0.0-bld.tar.bz2");
CHECK_EQ(uc.platform_filters(), PlatformSet{});
REQUIRE(uc.type() == Type::PackagePath);
REQUIRE(uc.location() == "C:/tmp/pkg-0.0-bld.tar.bz2");
REQUIRE(uc.platform_filters() == PlatformSet{});
}
}
SUBCASE("conda-forge")
SECTION("conda-forge")
{
const auto uc = UnresolvedChannel::parse("conda-forge").value();
CHECK_EQ(uc.type(), Type::Name);
CHECK_EQ(uc.location(), "conda-forge");
CHECK_EQ(uc.platform_filters(), PlatformSet{});
REQUIRE(uc.type() == Type::Name);
REQUIRE(uc.location() == "conda-forge");
REQUIRE(uc.platform_filters() == PlatformSet{});
}
SUBCASE("repo.anaconda.com")
SECTION("repo.anaconda.com")
{
const auto uc = UnresolvedChannel::parse("repo.anaconda.com").value();
// Unintuitive but correct type, this is not a URL. Better explicit than clever.
CHECK_EQ(uc.type(), Type::Name);
CHECK_EQ(uc.location(), "repo.anaconda.com");
CHECK_EQ(uc.platform_filters(), PlatformSet{});
REQUIRE(uc.type() == Type::Name);
REQUIRE(uc.location() == "repo.anaconda.com");
REQUIRE(uc.platform_filters() == PlatformSet{});
}
SUBCASE("conda-forge/linux-64")
SECTION("conda-forge/linux-64")
{
const auto uc = UnresolvedChannel::parse("conda-forge/linux-64").value();
CHECK_EQ(uc.type(), Type::Name);
CHECK_EQ(uc.location(), "conda-forge");
CHECK_EQ(uc.platform_filters(), PlatformSet{ "linux-64" });
REQUIRE(uc.type() == Type::Name);
REQUIRE(uc.location() == "conda-forge");
REQUIRE(uc.platform_filters() == PlatformSet{ "linux-64" });
}
SUBCASE("conda-forge[linux-avx512]")
SECTION("conda-forge[linux-avx512]")
{
const auto uc = UnresolvedChannel::parse("conda-forge[linux-avx512]").value();
CHECK_EQ(uc.type(), Type::Name);
CHECK_EQ(uc.location(), "conda-forge");
CHECK_EQ(uc.platform_filters(), PlatformSet{ "linux-avx512" });
REQUIRE(uc.type() == Type::Name);
REQUIRE(uc.location() == "conda-forge");
REQUIRE(uc.platform_filters() == PlatformSet{ "linux-avx512" });
}
SUBCASE("conda-forge[]")
SECTION("conda-forge[]")
{
const auto uc = UnresolvedChannel::parse("conda-forge[linux-64]").value();
CHECK_EQ(uc.type(), Type::Name);
CHECK_EQ(uc.location(), "conda-forge");
CHECK_EQ(uc.platform_filters(), PlatformSet{ "linux-64" });
REQUIRE(uc.type() == Type::Name);
REQUIRE(uc.location() == "conda-forge");
REQUIRE(uc.platform_filters() == PlatformSet{ "linux-64" });
}
SUBCASE("conda-forge/linux-64/label/foo_dev")
SECTION("conda-forge/linux-64/label/foo_dev")
{
const auto uc = UnresolvedChannel::parse("conda-forge/linux-64/label/foo_dev").value();
CHECK_EQ(uc.type(), Type::Name);
CHECK_EQ(uc.location(), "conda-forge/label/foo_dev");
CHECK_EQ(uc.platform_filters(), PlatformSet{ "linux-64" });
REQUIRE(uc.type() == Type::Name);
REQUIRE(uc.location() == "conda-forge/label/foo_dev");
REQUIRE(uc.platform_filters() == PlatformSet{ "linux-64" });
}
SUBCASE("conda-forge/label/foo_dev[linux-64]")
SECTION("conda-forge/label/foo_dev[linux-64]")
{
const auto uc = UnresolvedChannel::parse("conda-forge/label/foo_dev[linux-64]").value();
CHECK_EQ(uc.type(), Type::Name);
CHECK_EQ(uc.location(), "conda-forge/label/foo_dev");
CHECK_EQ(uc.platform_filters(), PlatformSet{ "linux-64" });
REQUIRE(uc.type() == Type::Name);
REQUIRE(uc.location() == "conda-forge/label/foo_dev");
REQUIRE(uc.platform_filters() == PlatformSet{ "linux-64" });
}
}
TEST_CASE("str")
{
CHECK_EQ(UnresolvedChannel("location", {}, Type::Name).str(), "location");
CHECK_EQ(
UnresolvedChannel("location", { "linux-64", "noarch" }, Type::Name).str(),
"location[linux-64,noarch]"
REQUIRE(UnresolvedChannel("location", {}, Type::Name).str() == "location");
REQUIRE(
UnresolvedChannel("location", { "linux-64", "noarch" }, Type::Name).str()
== "location[linux-64,noarch]"
);
}
TEST_CASE("Comparability and hashability")
TEST_CASE("UnresolvedChannel Comparability and hashability")
{
auto uc1 = UnresolvedChannel::parse("conda-forge").value();
auto uc2 = UnresolvedChannel::parse("conda-forge").value();
auto uc3 = UnresolvedChannel::parse("conda-forge/linux-64").value();
CHECK_EQ(uc1, uc2);
CHECK_NE(uc1, uc3);
REQUIRE(uc1 == uc2);
REQUIRE(uc1 != uc3);
auto hash_fn = std::hash<UnresolvedChannel>();
CHECK_EQ(hash_fn(uc1), hash_fn(uc2));
CHECK_NE(hash_fn(uc1), hash_fn(uc3));
REQUIRE(hash_fn(uc1) == hash_fn(uc2));
REQUIRE(hash_fn(uc1) != hash_fn(uc3));
}
}

View File

@ -8,33 +8,33 @@
#include <array>
#include <vector>
#include <doctest/doctest.h>
#include <catch2/catch_all.hpp>
#include <fmt/format.h>
#include "mamba/specs/version.hpp"
using namespace mamba::specs;
TEST_SUITE("specs::version")
namespace
{
TEST_CASE("atom_comparison")
{
// No literal
CHECK_EQ(VersionPartAtom(1), VersionPartAtom(1, ""));
REQUIRE(VersionPartAtom(1) == VersionPartAtom(1, ""));
// lowercase
CHECK_EQ(VersionPartAtom(1, "dev"), VersionPartAtom(1, "DEV"));
REQUIRE(VersionPartAtom(1, "dev") == VersionPartAtom(1, "DEV"));
// All operator comparison for mumerals
CHECK_NE(VersionPartAtom(1), VersionPartAtom(2, "dev"));
CHECK_LT(VersionPartAtom(1), VersionPartAtom(2, "dev"));
CHECK_LE(VersionPartAtom(1), VersionPartAtom(2, "dev"));
CHECK_GT(VersionPartAtom(2, "dev"), VersionPartAtom(1));
CHECK_GE(VersionPartAtom(2, "dev"), VersionPartAtom(1));
REQUIRE(VersionPartAtom(1) != VersionPartAtom(2, "dev"));
REQUIRE(VersionPartAtom(1) < VersionPartAtom(2, "dev"));
REQUIRE(VersionPartAtom(1) <= VersionPartAtom(2, "dev"));
REQUIRE(VersionPartAtom(2, "dev") > VersionPartAtom(1));
REQUIRE(VersionPartAtom(2, "dev") >= VersionPartAtom(1));
// All operator comparison for literals
CHECK_NE(VersionPartAtom(1, "dev"), VersionPartAtom(1, "a"));
CHECK_LT(VersionPartAtom(1, "dev"), VersionPartAtom(1, "a"));
CHECK_LE(VersionPartAtom(1, "dev"), VersionPartAtom(1, "a"));
CHECK_GT(VersionPartAtom(1, "a"), VersionPartAtom(1, "dev"));
CHECK_GE(VersionPartAtom(1, "a"), VersionPartAtom(1, "dev"));
REQUIRE(VersionPartAtom(1, "dev") != VersionPartAtom(1, "a"));
REQUIRE(VersionPartAtom(1, "dev") < VersionPartAtom(1, "a"));
REQUIRE(VersionPartAtom(1, "dev") <= VersionPartAtom(1, "a"));
REQUIRE(VersionPartAtom(1, "a") > VersionPartAtom(1, "dev"));
REQUIRE(VersionPartAtom(1, "a") >= VersionPartAtom(1, "dev"));
// clang-format off
auto sorted_atoms = std::array{
@ -54,52 +54,52 @@ TEST_SUITE("specs::version")
// clang-format on
// Strict ordering
CHECK(std::is_sorted(sorted_atoms.cbegin(), sorted_atoms.cend()));
REQUIRE(std::is_sorted(sorted_atoms.cbegin(), sorted_atoms.cend()));
// None compare equal (given the is_sorted assumption)
CHECK_EQ(std::adjacent_find(sorted_atoms.cbegin(), sorted_atoms.cend()), sorted_atoms.cend());
REQUIRE(std::adjacent_find(sorted_atoms.cbegin(), sorted_atoms.cend()) == sorted_atoms.cend());
}
TEST_CASE("atom_format")
{
CHECK_EQ(VersionPartAtom(1, "dev").str(), "1dev");
CHECK_EQ(VersionPartAtom(2).str(), "2");
REQUIRE(VersionPartAtom(1, "dev").str() == "1dev");
REQUIRE(VersionPartAtom(2).str() == "2");
}
TEST_CASE("version_comparison")
{
auto v = Version(0, { { { 1, "post" } } });
REQUIRE_EQ(v.version().size(), 1);
REQUIRE_EQ(v.version().front().size(), 1);
REQUIRE_EQ(v.version().front().front(), VersionPartAtom(1, "post"));
REQUIRE(v.version().size() == 1);
REQUIRE(v.version().front().size() == 1);
REQUIRE(v.version().front().front() == VersionPartAtom(1, "post"));
// Same empty 0!1post version
CHECK_EQ(Version(0, { { { 1, "post" } } }), Version(0, { { { 1, "post" } } }));
REQUIRE(Version(0, { { { 1, "post" } } }) == Version(0, { { { 1, "post" } } }));
// Empty trailing atom 0!1a == 0!1a0""
CHECK_EQ(Version(0, { { { 1, "a" } } }), Version(0, { { { 1, "a" }, {} } }));
REQUIRE(Version(0, { { { 1, "a" } } }) == Version(0, { { { 1, "a" }, {} } }));
// Empty trailing part 0!1a == 0!1a.0""
CHECK_EQ(Version(0, { { { 1, "a" } } }), Version(0, { { { 1, "a" } }, { {} } }));
REQUIRE(Version(0, { { { 1, "a" } } }) == Version(0, { { { 1, "a" } }, { {} } }));
// Mixed 0!1a0""0"" == 0!1a.0""
CHECK_EQ(Version(0, { { { 1, "a" }, {}, {} } }), Version(0, { { { 1, "a" } }, { {} } }));
REQUIRE(Version(0, { { { 1, "a" }, {}, {} } }) == Version(0, { { { 1, "a" } }, { {} } }));
// Different epoch 0!2post < 1!1dev
CHECK_LT(Version(0, { { { 2, "post" } } }), Version(1, { { { 1, "dev" } } }));
CHECK_GE(Version(1, { { { 1, "dev" } } }), Version(0, { { { 2, "post" } } }));
REQUIRE(Version(0, { { { 2, "post" } } }) < Version(1, { { { 1, "dev" } } }));
REQUIRE(Version(1, { { { 1, "dev" } } }) >= Version(0, { { { 2, "post" } } }));
// Different length with dev
CHECK_LT(Version(0, { { { 1 } }, { { 0, "dev" } } }), Version(0, { { { 1 } } }));
CHECK_LT(Version(0, { { { 1 } }, { { 0 } }, { { 0, "dev" } } }), Version(0, { { { 1 } } }));
REQUIRE(Version(0, { { { 1 } }, { { 0, "dev" } } }) < Version(0, { { { 1 } } }));
REQUIRE(Version(0, { { { 1 } }, { { 0 } }, { { 0, "dev" } } }) < Version(0, { { { 1 } } }));
// Different major 0!1post < 0!2dev
CHECK_LT(Version(0, { { { 1, "post" } } }), Version(0, { { { 2, "dev" } } }));
REQUIRE(Version(0, { { { 1, "post" } } }) < Version(0, { { { 2, "dev" } } }));
// Different length 0!2"".0"" < 0!11"".0"".0post all operator
CHECK_NE(Version(0, { { { 2 }, { 0 } } }), Version(0, { { { 11 }, { 0 }, { 0, "post" } } }));
CHECK_LT(Version(0, { { { 2 }, { 0 } } }), Version(0, { { { 11 }, { 0 }, { 0, "post" } } }));
CHECK_LE(Version(0, { { { 2 }, { 0 } } }), Version(0, { { { 11 }, { 0 }, { 0, "post" } } }));
CHECK_GT(Version(0, { { { 11 }, { 0 }, { 0, "post" } } }), Version(0, { { { 2 }, { 0 } } }));
CHECK_GE(Version(0, { { { 11 }, { 0 }, { 0, "post" } } }), Version(0, { { { 2 }, { 0 } } }));
REQUIRE(Version(0, { { { 2 }, { 0 } } }) != Version(0, { { { 11 }, { 0 }, { 0, "post" } } }));
REQUIRE(Version(0, { { { 2 }, { 0 } } }) < Version(0, { { { 11 }, { 0 }, { 0, "post" } } }));
REQUIRE(Version(0, { { { 2 }, { 0 } } }) <= Version(0, { { { 11 }, { 0 }, { 0, "post" } } }));
REQUIRE(Version(0, { { { 11 }, { 0 }, { 0, "post" } } }) > Version(0, { { { 2 }, { 0 } } }));
REQUIRE(Version(0, { { { 11 }, { 0 }, { 0, "post" } } }) >= Version(0, { { { 2 }, { 0 } } }));
}
TEST_CASE("starts_with")
TEST_CASE("Version starts_with")
{
SUBCASE("positive")
SECTION("positive")
{
// clang-format off
auto const versions = std::vector<std::tuple<Version, Version>>{
@ -149,11 +149,11 @@ TEST_SUITE("specs::version")
// Working around clang compilation issue.
const auto msg = fmt::format(R"(prefix="{}" version="{}")", prefix.str(), ver.str());
CAPTURE(msg);
CHECK(ver.starts_with(prefix));
REQUIRE(ver.starts_with(prefix));
}
}
SUBCASE("negative")
SECTION("negative")
{
// clang-format off
auto const versions = std::vector<std::tuple<Version, Version>>{
@ -183,14 +183,14 @@ TEST_SUITE("specs::version")
// Working around clang compilation issue.
const auto msg = fmt::format(R"(prefix="{}" version="{}")", prefix.str(), ver.str());
CAPTURE(msg);
CHECK_FALSE(ver.starts_with(prefix));
REQUIRE_FALSE(ver.starts_with(prefix));
}
}
}
TEST_CASE("compatible_with")
{
SUBCASE("positive")
SECTION("positive")
{
// clang-format off
auto const versions = std::vector<std::tuple<std::size_t, Version, Version>>{
@ -249,11 +249,11 @@ TEST_SUITE("specs::version")
newer.str()
);
CAPTURE(msg);
CHECK(newer.compatible_with(older, level));
REQUIRE(newer.compatible_with(older, level));
}
}
SUBCASE("negative")
SECTION("negative")
{
// clang-format off
auto const versions = std::vector<std::tuple<std::size_t, Version, Version>>{
@ -298,46 +298,46 @@ TEST_SUITE("specs::version")
newer.str()
);
CAPTURE(msg);
CHECK_FALSE(newer.compatible_with(older, level));
REQUIRE_FALSE(newer.compatible_with(older, level));
}
}
}
TEST_CASE("version_format")
{
SUBCASE("11a0post.3.4dev")
SECTION("11a0post.3.4dev")
{
auto v = Version(0, { { { 11, "a" }, { 0, "post" } }, { { 3 } }, { { 4, "dev" } } });
CHECK_EQ(v.str(), "11a0post.3.4dev");
CHECK_EQ(v.str(1), "11a0post");
CHECK_EQ(v.str(2), "11a0post.3");
CHECK_EQ(v.str(3), "11a0post.3.4dev");
CHECK_EQ(v.str(4), "11a0post.3.4dev.0");
CHECK_EQ(v.str(5), "11a0post.3.4dev.0.0");
REQUIRE(v.str() == "11a0post.3.4dev");
REQUIRE(v.str(1) == "11a0post");
REQUIRE(v.str(2) == "11a0post.3");
REQUIRE(v.str(3) == "11a0post.3.4dev");
REQUIRE(v.str(4) == "11a0post.3.4dev.0");
REQUIRE(v.str(5) == "11a0post.3.4dev.0.0");
}
SUBCASE("1!11a0.3.4dev")
SECTION("1!11a0.3.4dev")
{
auto v = Version(1, { { { 11, "a" }, { 0 } }, { { 3 } }, { { 4, "dev" } } });
CHECK_EQ(v.str(), "1!11a0.3.4dev");
CHECK_EQ(v.str(1), "1!11a0");
CHECK_EQ(v.str(2), "1!11a0.3");
CHECK_EQ(v.str(3), "1!11a0.3.4dev");
CHECK_EQ(v.str(4), "1!11a0.3.4dev.0");
REQUIRE(v.str() == "1!11a0.3.4dev");
REQUIRE(v.str(1) == "1!11a0");
REQUIRE(v.str(2) == "1!11a0.3");
REQUIRE(v.str(3) == "1!11a0.3.4dev");
REQUIRE(v.str(4) == "1!11a0.3.4dev.0");
}
SUBCASE("1!11a0.3.4dev+1.2")
SECTION("1!11a0.3.4dev+1.2")
{
auto v = Version(
1,
{ { { 11, "a" }, { 0 } }, { { 3 } }, { { 4, "dev" } } },
{ { { 1 } }, { { 2 } } }
);
CHECK_EQ(v.str(), "1!11a0.3.4dev+1.2");
CHECK_EQ(v.str(1), "1!11a0+1");
CHECK_EQ(v.str(2), "1!11a0.3+1.2");
CHECK_EQ(v.str(3), "1!11a0.3.4dev+1.2.0");
CHECK_EQ(v.str(4), "1!11a0.3.4dev.0+1.2.0.0");
REQUIRE(v.str() == "1!11a0.3.4dev+1.2");
REQUIRE(v.str(1) == "1!11a0+1");
REQUIRE(v.str(2) == "1!11a0.3+1.2");
REQUIRE(v.str(3) == "1!11a0.3.4dev+1.2.0");
REQUIRE(v.str(4) == "1!11a0.3.4dev.0+1.2.0.0");
}
}
@ -346,7 +346,7 @@ TEST_SUITE("specs::version")
*
* @see https://github.com/conda/conda/blob/main/tests/models/test_version.py
*/
TEST_CASE("parse")
TEST_CASE("Version parse")
{
// clang-format off
auto sorted_version = std::vector<std::pair<std::string_view, Version>>{
@ -408,61 +408,61 @@ TEST_SUITE("specs::version")
// clang-format on
for (const auto& [raw, expected] : sorted_version)
{
CHECK_EQ(Version::parse(raw), expected);
REQUIRE(Version::parse(raw) == expected);
}
CHECK(std::is_sorted(
REQUIRE(std::is_sorted(
sorted_version.cbegin(),
sorted_version.cend(),
[](const auto& a, const auto& b) { return a.second < b.second; }
));
// Default constructed
CHECK_EQ(Version::parse("0.0").value(), Version());
REQUIRE(Version::parse("0.0").value() == Version());
// Lowercase and strip
CHECK_EQ(Version::parse("0.4.1.rc").value(), Version::parse(" 0.4.1.RC "));
CHECK_EQ(Version::parse(" 0.4.1.RC ").value(), Version::parse("0.4.1.rc"));
REQUIRE(Version::parse("0.4.1.rc").value() == Version::parse(" 0.4.1.RC "));
REQUIRE(Version::parse(" 0.4.1.RC ").value() == Version::parse("0.4.1.rc"));
// Functional assertions
CHECK_EQ(Version::parse(" 0.4.rc ").value(), Version::parse("0.4.RC"));
CHECK_EQ(Version::parse("0.4").value(), Version::parse("0.4.0"));
CHECK_NE(Version::parse("0.4").value(), Version::parse("0.4.1"));
CHECK_EQ(Version::parse("0.4.a1").value(), Version::parse("0.4.0a1"));
CHECK_NE(Version::parse("0.4.a1").value(), Version::parse("0.4.1a1"));
REQUIRE(Version::parse(" 0.4.rc ").value() == Version::parse("0.4.RC"));
REQUIRE(Version::parse("0.4").value() == Version::parse("0.4.0"));
REQUIRE(Version::parse("0.4").value() != Version::parse("0.4.1"));
REQUIRE(Version::parse("0.4.a1").value() == Version::parse("0.4.0a1"));
REQUIRE(Version::parse("0.4.a1").value() != Version::parse("0.4.1a1"));
}
TEST_CASE("parse_invalid")
{
// Wrong epoch
CHECK_FALSE(Version::parse("!1.1").has_value());
CHECK_FALSE(Version::parse("-1!1.1").has_value());
CHECK_FALSE(Version::parse("foo!1.1").has_value());
CHECK_FALSE(Version::parse("0post1!1.1").has_value());
REQUIRE_FALSE(Version::parse("!1.1").has_value());
REQUIRE_FALSE(Version::parse("-1!1.1").has_value());
REQUIRE_FALSE(Version::parse("foo!1.1").has_value());
REQUIRE_FALSE(Version::parse("0post1!1.1").has_value());
// Empty parts
CHECK_FALSE(Version::parse("").has_value());
CHECK_FALSE(Version::parse(" ").has_value());
CHECK_FALSE(Version::parse("!2.2").has_value());
CHECK_FALSE(Version::parse("0!").has_value());
CHECK_FALSE(Version::parse("!").has_value());
CHECK_FALSE(Version::parse("1.").has_value());
CHECK_FALSE(Version::parse("1..1").has_value());
CHECK_FALSE(Version::parse("5.5..mw").has_value());
CHECK_FALSE(Version::parse("1.2post+").has_value());
CHECK_FALSE(Version::parse("1!+1.1").has_value());
REQUIRE_FALSE(Version::parse("").has_value());
REQUIRE_FALSE(Version::parse(" ").has_value());
REQUIRE_FALSE(Version::parse("!2.2").has_value());
REQUIRE_FALSE(Version::parse("0!").has_value());
REQUIRE_FALSE(Version::parse("!").has_value());
REQUIRE_FALSE(Version::parse("1.").has_value());
REQUIRE_FALSE(Version::parse("1..1").has_value());
REQUIRE_FALSE(Version::parse("5.5..mw").has_value());
REQUIRE_FALSE(Version::parse("1.2post+").has_value());
REQUIRE_FALSE(Version::parse("1!+1.1").has_value());
// Repeated delimiters
CHECK_FALSE(Version::parse("5.5++").has_value());
CHECK_FALSE(Version::parse("5.5+1+0.0").has_value());
CHECK_FALSE(Version::parse("1!2!3.0").has_value());
REQUIRE_FALSE(Version::parse("5.5++").has_value());
REQUIRE_FALSE(Version::parse("5.5+1+0.0").has_value());
REQUIRE_FALSE(Version::parse("1!2!3.0").has_value());
// '-' and '_' delimiters not allowed together.
CHECK_FALSE(Version::parse("1-1_1").has_value());
REQUIRE_FALSE(Version::parse("1-1_1").has_value());
// Forbidden characters
CHECK_FALSE(Version::parse("3.5&1").has_value());
CHECK_FALSE(Version::parse("3.5|1").has_value());
REQUIRE_FALSE(Version::parse("3.5&1").has_value());
REQUIRE_FALSE(Version::parse("3.5|1").has_value());
}
/**
@ -506,9 +506,9 @@ TEST_SUITE("specs::version")
// clang-format on
// Strict ordering
CHECK(std::is_sorted(versions.cbegin(), versions.cend()));
REQUIRE(std::is_sorted(versions.cbegin(), versions.cend()));
// None compare equal (given the is_sorted assumption)
CHECK_EQ(std::adjacent_find(versions.cbegin(), versions.cend()), versions.cend());
REQUIRE(std::adjacent_find(versions.cbegin(), versions.cend()) == versions.cend());
}
/**
@ -578,8 +578,8 @@ TEST_SUITE("specs::version")
// clang-format on
// Strict ordering
CHECK(std::is_sorted(versions.cbegin(), versions.cend()));
REQUIRE(std::is_sorted(versions.cbegin(), versions.cend()));
// None compare equal (given the is_sorted assumption)
CHECK_EQ(std::adjacent_find(versions.cbegin(), versions.cend()), versions.cend());
REQUIRE(std::adjacent_find(versions.cbegin(), versions.cend()) == versions.cend());
}
}

View File

@ -7,13 +7,13 @@
#include <array>
#include <string_view>
#include <doctest/doctest.h>
#include <catch2/catch_all.hpp>
#include "mamba/specs/version_spec.hpp"
using namespace mamba::specs;
TEST_SUITE("specs::version_spec")
namespace
{
using namespace mamba::specs::version_literals;
using namespace mamba::specs::version_spec_literals;
@ -27,118 +27,118 @@ TEST_SUITE("specs::version_spec")
const auto v4 = "4.0"_v;
const auto free = VersionPredicate::make_free();
CHECK(free.contains(v1));
CHECK(free.contains(v2));
CHECK(free.contains(v3));
CHECK(free.contains(v4));
CHECK_EQ(free.str(), "=*");
REQUIRE(free.contains(v1));
REQUIRE(free.contains(v2));
REQUIRE(free.contains(v3));
REQUIRE(free.contains(v4));
REQUIRE(free.str() == "=*");
const auto eq = VersionPredicate::make_equal_to(v2);
CHECK_FALSE(eq.contains(v1));
CHECK(eq.contains(v2));
CHECK_FALSE(eq.contains(v3));
CHECK_FALSE(eq.contains(v4));
CHECK_EQ(eq.str(), "==2.0");
REQUIRE_FALSE(eq.contains(v1));
REQUIRE(eq.contains(v2));
REQUIRE_FALSE(eq.contains(v3));
REQUIRE_FALSE(eq.contains(v4));
REQUIRE(eq.str() == "==2.0");
const auto ne = VersionPredicate::make_not_equal_to(v2);
CHECK(ne.contains(v1));
CHECK_FALSE(ne.contains(v2));
CHECK(ne.contains(v3));
CHECK(ne.contains(v4));
CHECK_EQ(ne.str(), "!=2.0");
REQUIRE(ne.contains(v1));
REQUIRE_FALSE(ne.contains(v2));
REQUIRE(ne.contains(v3));
REQUIRE(ne.contains(v4));
REQUIRE(ne.str() == "!=2.0");
const auto gt = VersionPredicate::make_greater(v2);
CHECK_FALSE(gt.contains(v1));
CHECK_FALSE(gt.contains(v2));
CHECK(gt.contains(v3));
CHECK(gt.contains(v4));
CHECK_EQ(gt.str(), ">2.0");
REQUIRE_FALSE(gt.contains(v1));
REQUIRE_FALSE(gt.contains(v2));
REQUIRE(gt.contains(v3));
REQUIRE(gt.contains(v4));
REQUIRE(gt.str() == ">2.0");
const auto ge = VersionPredicate::make_greater_equal(v2);
CHECK_FALSE(ge.contains(v1));
CHECK(ge.contains(v2));
CHECK(ge.contains(v3));
CHECK(ge.contains(v4));
CHECK_EQ(ge.str(), ">=2.0");
REQUIRE_FALSE(ge.contains(v1));
REQUIRE(ge.contains(v2));
REQUIRE(ge.contains(v3));
REQUIRE(ge.contains(v4));
REQUIRE(ge.str() == ">=2.0");
const auto lt = VersionPredicate::make_less(v2);
CHECK(lt.contains(v1));
CHECK_FALSE(lt.contains(v2));
CHECK_FALSE(lt.contains(v3));
CHECK_FALSE(lt.contains(v4));
CHECK_EQ(lt.str(), "<2.0");
REQUIRE(lt.contains(v1));
REQUIRE_FALSE(lt.contains(v2));
REQUIRE_FALSE(lt.contains(v3));
REQUIRE_FALSE(lt.contains(v4));
REQUIRE(lt.str() == "<2.0");
const auto le = VersionPredicate::make_less_equal(v2);
CHECK(le.contains(v1));
CHECK(le.contains(v2));
CHECK_FALSE(le.contains(v3));
CHECK_FALSE(le.contains(v4));
CHECK_EQ(le.str(), "<=2.0");
REQUIRE(le.contains(v1));
REQUIRE(le.contains(v2));
REQUIRE_FALSE(le.contains(v3));
REQUIRE_FALSE(le.contains(v4));
REQUIRE(le.str() == "<=2.0");
const auto sw = VersionPredicate::make_starts_with(v2);
CHECK_FALSE(sw.contains(v1));
CHECK(sw.contains(v2));
CHECK(sw.contains(v201));
CHECK_FALSE(sw.contains(v3));
CHECK_FALSE(sw.contains(v4));
CHECK_EQ(sw.str(), "=2.0");
CHECK_EQ(sw.str_conda_build(), "2.0.*");
REQUIRE_FALSE(sw.contains(v1));
REQUIRE(sw.contains(v2));
REQUIRE(sw.contains(v201));
REQUIRE_FALSE(sw.contains(v3));
REQUIRE_FALSE(sw.contains(v4));
REQUIRE(sw.str() == "=2.0");
REQUIRE(sw.str_conda_build() == "2.0.*");
const auto nsw = VersionPredicate::make_not_starts_with(v2);
CHECK(nsw.contains(v1));
CHECK_FALSE(nsw.contains(v2));
CHECK_FALSE(nsw.contains(v201));
CHECK(nsw.contains(v3));
CHECK(nsw.contains(v4));
CHECK_EQ(nsw.str(), "!=2.0.*");
REQUIRE(nsw.contains(v1));
REQUIRE_FALSE(nsw.contains(v2));
REQUIRE_FALSE(nsw.contains(v201));
REQUIRE(nsw.contains(v3));
REQUIRE(nsw.contains(v4));
REQUIRE(nsw.str() == "!=2.0.*");
const auto cp2 = VersionPredicate::make_compatible_with(v2, 2);
CHECK_FALSE(cp2.contains(v1));
CHECK(cp2.contains(v2));
CHECK(cp2.contains(v201));
CHECK_FALSE(cp2.contains(v3));
CHECK_FALSE(cp2.contains(v4));
CHECK_EQ(cp2.str(), "~=2.0");
REQUIRE_FALSE(cp2.contains(v1));
REQUIRE(cp2.contains(v2));
REQUIRE(cp2.contains(v201));
REQUIRE_FALSE(cp2.contains(v3));
REQUIRE_FALSE(cp2.contains(v4));
REQUIRE(cp2.str() == "~=2.0");
const auto cp3 = VersionPredicate::make_compatible_with(v2, 3);
CHECK_FALSE(cp3.contains(v1));
CHECK(cp3.contains(v2));
CHECK_FALSE(cp3.contains(v201));
CHECK_FALSE(cp3.contains(v3));
CHECK_FALSE(cp3.contains(v4));
CHECK_EQ(cp3.str(), "~=2.0.0");
REQUIRE_FALSE(cp3.contains(v1));
REQUIRE(cp3.contains(v2));
REQUIRE_FALSE(cp3.contains(v201));
REQUIRE_FALSE(cp3.contains(v3));
REQUIRE_FALSE(cp3.contains(v4));
REQUIRE(cp3.str() == "~=2.0.0");
const auto predicates = std::array{ free, eq, ne, lt, le, gt, ge, sw, cp2, cp3 };
for (std::size_t i = 0; i < predicates.size(); ++i)
{
CHECK_EQ(predicates[i], predicates[i]);
REQUIRE(predicates[i] == predicates[i]);
for (std::size_t j = i + 1; j < predicates.size(); ++j)
{
CHECK_NE(predicates[i], predicates[j]);
REQUIRE(predicates[i] != predicates[j]);
}
}
}
TEST_CASE("Tree construction")
{
SUBCASE("empty")
SECTION("empty")
{
auto spec = VersionSpec();
CHECK(spec.contains(Version()));
CHECK_EQ(spec.str(), "=*");
REQUIRE(spec.contains(Version()));
REQUIRE(spec.str() == "=*");
}
SUBCASE("from_predicate")
SECTION("from_predicate")
{
const auto v1 = "1.0"_v;
const auto v2 = "2.0"_v;
auto spec = VersionSpec::from_predicate(VersionPredicate::make_equal_to(v1));
CHECK(spec.contains(v1));
CHECK_FALSE(spec.contains(v2));
CHECK_EQ(spec.str(), "==1.0");
REQUIRE(spec.contains(v1));
REQUIRE_FALSE(spec.contains(v2));
REQUIRE(spec.str() == "==1.0");
}
SUBCASE("<2.0|(>2.3,<=2.8.0)")
SECTION("<2.0|(>2.3,<=2.8.0)")
{
using namespace mamba::util;
@ -158,219 +158,219 @@ TEST_SUITE("specs::version_spec")
auto spec = VersionSpec(std::move(parser).tree());
CHECK(spec.contains(Version(0, { { { 2 } }, { { 3 } }, { { 1 } } }))); // 2.3.1
CHECK(spec.contains(Version(0, { { { 2 } }, { { 8 } } }))); // 2.8
CHECK(spec.contains(Version(0, { { { 1 } }, { { 8 } } }))); // 1.8
REQUIRE(spec.contains(Version(0, { { { 2 } }, { { 3 } }, { { 1 } } }))); // 2.3.1
REQUIRE(spec.contains(Version(0, { { { 2 } }, { { 8 } } }))); // 2.8
REQUIRE(spec.contains(Version(0, { { { 1 } }, { { 8 } } }))); // 1.8
CHECK_FALSE(spec.contains(Version(0, { { { 2 } }, { { 0 } }, { { 0 } } }))); // 2.0.0
CHECK_FALSE(spec.contains(Version(0, { { { 2 } }, { { 1 } } }))); // 2.1
CHECK_FALSE(spec.contains(Version(0, { { { 2 } }, { { 3 } } }))); // 2.3
REQUIRE_FALSE(spec.contains(Version(0, { { { 2 } }, { { 0 } }, { { 0 } } }))); // 2.0.0
REQUIRE_FALSE(spec.contains(Version(0, { { { 2 } }, { { 1 } } }))); // 2.1
REQUIRE_FALSE(spec.contains(Version(0, { { { 2 } }, { { 3 } } }))); // 2.3
// Note this won't always be the same as the parsed string because of the tree
// serialization
CHECK_EQ(spec.str(), "<2.0|(>2.3,<=2.8.0)");
REQUIRE(spec.str() == "<2.0|(>2.3,<=2.8.0)");
}
}
TEST_CASE("VersionSpec::parse")
{
SUBCASE("Successful")
SECTION("Successful")
{
CHECK(""_vs.contains("1.6"_v));
CHECK(""_vs.contains("0.6+0.7"_v));
REQUIRE(""_vs.contains("1.6"_v));
REQUIRE(""_vs.contains("0.6+0.7"_v));
CHECK("*"_vs.contains("1.4"_v));
CHECK("=*"_vs.contains("1.4"_v));
REQUIRE("*"_vs.contains("1.4"_v));
REQUIRE("=*"_vs.contains("1.4"_v));
CHECK("1.7"_vs.contains("1.7"_v));
CHECK("1.7"_vs.contains("1.7.0.0"_v));
CHECK_FALSE("1.7"_vs.contains("1.6"_v));
CHECK_FALSE("1.7"_vs.contains("1.7.7"_v));
CHECK_FALSE("1.7"_vs.contains("1.7.0.1"_v));
REQUIRE("1.7"_vs.contains("1.7"_v));
REQUIRE("1.7"_vs.contains("1.7.0.0"_v));
REQUIRE_FALSE("1.7"_vs.contains("1.6"_v));
REQUIRE_FALSE("1.7"_vs.contains("1.7.7"_v));
REQUIRE_FALSE("1.7"_vs.contains("1.7.0.1"_v));
CHECK("==1.7"_vs.contains("1.7"_v));
CHECK("==1.7"_vs.contains("1.7.0.0"_v));
CHECK_FALSE("==1.7"_vs.contains("1.6"_v));
CHECK_FALSE("==1.7"_vs.contains("1.7.7"_v));
CHECK_FALSE("==1.7"_vs.contains("1.7.0.1"_v));
REQUIRE("==1.7"_vs.contains("1.7"_v));
REQUIRE("==1.7"_vs.contains("1.7.0.0"_v));
REQUIRE_FALSE("==1.7"_vs.contains("1.6"_v));
REQUIRE_FALSE("==1.7"_vs.contains("1.7.7"_v));
REQUIRE_FALSE("==1.7"_vs.contains("1.7.0.1"_v));
CHECK_FALSE("!=1.7"_vs.contains("1.7"_v));
CHECK_FALSE("!=1.7"_vs.contains("1.7.0.0"_v));
CHECK("!=1.7"_vs.contains("1.6"_v));
CHECK("!=1.7"_vs.contains("1.7.7"_v));
CHECK("!=1.7"_vs.contains("1.7.0.1"_v));
REQUIRE_FALSE("!=1.7"_vs.contains("1.7"_v));
REQUIRE_FALSE("!=1.7"_vs.contains("1.7.0.0"_v));
REQUIRE("!=1.7"_vs.contains("1.6"_v));
REQUIRE("!=1.7"_vs.contains("1.7.7"_v));
REQUIRE("!=1.7"_vs.contains("1.7.0.1"_v));
CHECK_FALSE("<1.7"_vs.contains("1.7"_v));
CHECK_FALSE("<1.7"_vs.contains("1.7.0.0"_v));
CHECK("<1.7"_vs.contains("1.6"_v));
CHECK("<1.7"_vs.contains("1.7a"_v));
CHECK_FALSE("<1.7"_vs.contains("1.7.7"_v));
CHECK_FALSE("<1.7"_vs.contains("1.7.0.1"_v));
REQUIRE_FALSE("<1.7"_vs.contains("1.7"_v));
REQUIRE_FALSE("<1.7"_vs.contains("1.7.0.0"_v));
REQUIRE("<1.7"_vs.contains("1.6"_v));
REQUIRE("<1.7"_vs.contains("1.7a"_v));
REQUIRE_FALSE("<1.7"_vs.contains("1.7.7"_v));
REQUIRE_FALSE("<1.7"_vs.contains("1.7.0.1"_v));
CHECK("<=1.7"_vs.contains("1.7"_v));
CHECK("<=1.7"_vs.contains("1.7.0.0"_v));
CHECK("<=1.7"_vs.contains("1.6"_v));
CHECK("<=1.7"_vs.contains("1.7a"_v));
CHECK_FALSE("<=1.7"_vs.contains("1.7.7"_v));
CHECK_FALSE("<=1.7"_vs.contains("1.7.0.1"_v));
REQUIRE("<=1.7"_vs.contains("1.7"_v));
REQUIRE("<=1.7"_vs.contains("1.7.0.0"_v));
REQUIRE("<=1.7"_vs.contains("1.6"_v));
REQUIRE("<=1.7"_vs.contains("1.7a"_v));
REQUIRE_FALSE("<=1.7"_vs.contains("1.7.7"_v));
REQUIRE_FALSE("<=1.7"_vs.contains("1.7.0.1"_v));
CHECK_FALSE(">1.7"_vs.contains("1.7"_v));
CHECK_FALSE(">1.7"_vs.contains("1.7.0.0"_v));
CHECK_FALSE(">1.7"_vs.contains("1.6"_v));
CHECK_FALSE(">1.7"_vs.contains("1.7a"_v));
CHECK(">1.7"_vs.contains("1.7.7"_v));
CHECK(">1.7"_vs.contains("1.7.0.1"_v));
REQUIRE_FALSE(">1.7"_vs.contains("1.7"_v));
REQUIRE_FALSE(">1.7"_vs.contains("1.7.0.0"_v));
REQUIRE_FALSE(">1.7"_vs.contains("1.6"_v));
REQUIRE_FALSE(">1.7"_vs.contains("1.7a"_v));
REQUIRE(">1.7"_vs.contains("1.7.7"_v));
REQUIRE(">1.7"_vs.contains("1.7.0.1"_v));
CHECK(">= 1.7"_vs.contains("1.7"_v));
CHECK(">= 1.7"_vs.contains("1.7.0.0"_v));
CHECK_FALSE(">= 1.7"_vs.contains("1.6"_v));
CHECK_FALSE(">= 1.7"_vs.contains("1.7a"_v));
CHECK(">= 1.7"_vs.contains("1.7.7"_v));
CHECK(">= 1.7"_vs.contains("1.7.0.1"_v));
REQUIRE(">= 1.7"_vs.contains("1.7"_v));
REQUIRE(">= 1.7"_vs.contains("1.7.0.0"_v));
REQUIRE_FALSE(">= 1.7"_vs.contains("1.6"_v));
REQUIRE_FALSE(">= 1.7"_vs.contains("1.7a"_v));
REQUIRE(">= 1.7"_vs.contains("1.7.7"_v));
REQUIRE(">= 1.7"_vs.contains("1.7.0.1"_v));
CHECK_FALSE(" = 1.8"_vs.contains("1.7.0.1"_v));
CHECK(" = 1.8"_vs.contains("1.8"_v));
CHECK(" = 1.8"_vs.contains("1.8.0"_v));
CHECK(" = 1.8"_vs.contains("1.8.1"_v));
CHECK(" = 1.8"_vs.contains("1.8alpha"_v));
CHECK_FALSE(" = 1.8"_vs.contains("1.9"_v));
REQUIRE_FALSE(" = 1.8"_vs.contains("1.7.0.1"_v));
REQUIRE(" = 1.8"_vs.contains("1.8"_v));
REQUIRE(" = 1.8"_vs.contains("1.8.0"_v));
REQUIRE(" = 1.8"_vs.contains("1.8.1"_v));
REQUIRE(" = 1.8"_vs.contains("1.8alpha"_v));
REQUIRE_FALSE(" = 1.8"_vs.contains("1.9"_v));
CHECK_FALSE(" = 1.8.* "_vs.contains("1.7.0.1"_v));
CHECK(" = 1.8.*"_vs.contains("1.8"_v));
CHECK(" = 1.8.*"_vs.contains("1.8.0"_v));
CHECK(" = 1.8.*"_vs.contains("1.8.1"_v));
CHECK(" = 1.8.*"_vs.contains("1.8alpha"_v)); // Like Conda
CHECK_FALSE(" = 1.8.*"_vs.contains("1.9"_v));
REQUIRE_FALSE(" = 1.8.* "_vs.contains("1.7.0.1"_v));
REQUIRE(" = 1.8.*"_vs.contains("1.8"_v));
REQUIRE(" = 1.8.*"_vs.contains("1.8.0"_v));
REQUIRE(" = 1.8.*"_vs.contains("1.8.1"_v));
REQUIRE(" = 1.8.*"_vs.contains("1.8alpha"_v)); // Like Conda
REQUIRE_FALSE(" = 1.8.*"_vs.contains("1.9"_v));
CHECK_FALSE(" 1.8.* "_vs.contains("1.7.0.1"_v));
CHECK(" 1.8.*"_vs.contains("1.8"_v));
CHECK(" 1.8.*"_vs.contains("1.8.0"_v));
CHECK(" 1.8.*"_vs.contains("1.8.1"_v));
CHECK(" 1.8.*"_vs.contains("1.8alpha"_v)); // Like Conda
CHECK_FALSE(" 1.8.*"_vs.contains("1.9"_v));
REQUIRE_FALSE(" 1.8.* "_vs.contains("1.7.0.1"_v));
REQUIRE(" 1.8.*"_vs.contains("1.8"_v));
REQUIRE(" 1.8.*"_vs.contains("1.8.0"_v));
REQUIRE(" 1.8.*"_vs.contains("1.8.1"_v));
REQUIRE(" 1.8.*"_vs.contains("1.8alpha"_v)); // Like Conda
REQUIRE_FALSE(" 1.8.*"_vs.contains("1.9"_v));
CHECK(" != 1.8.*"_vs.contains("1.7.0.1"_v));
CHECK_FALSE(" != 1.8.*"_vs.contains("1.8"_v));
CHECK_FALSE(" != 1.8.*"_vs.contains("1.8.0"_v));
CHECK_FALSE(" != 1.8.*"_vs.contains("1.8.1"_v));
CHECK_FALSE(" != 1.8.*"_vs.contains("1.8alpha"_v)); // Like Conda
CHECK(" != 1.8.*"_vs.contains("1.9"_v));
REQUIRE(" != 1.8.*"_vs.contains("1.7.0.1"_v));
REQUIRE_FALSE(" != 1.8.*"_vs.contains("1.8"_v));
REQUIRE_FALSE(" != 1.8.*"_vs.contains("1.8.0"_v));
REQUIRE_FALSE(" != 1.8.*"_vs.contains("1.8.1"_v));
REQUIRE_FALSE(" != 1.8.*"_vs.contains("1.8alpha"_v)); // Like Conda
REQUIRE(" != 1.8.*"_vs.contains("1.9"_v));
CHECK_FALSE(" ~= 1.8 "_vs.contains("1.7.0.1"_v));
CHECK(" ~= 1.8 "_vs.contains("1.8"_v));
CHECK(" ~= 1.8 "_vs.contains("1.8.0"_v));
CHECK(" ~= 1.8 "_vs.contains("1.8.1"_v));
CHECK(" ~= 1.8 "_vs.contains("1.9"_v));
CHECK(" ~= 1.8 "_vs.contains("1.8post"_v));
CHECK_FALSE(" ~= 1.8 "_vs.contains("1.8alpha"_v));
REQUIRE_FALSE(" ~= 1.8 "_vs.contains("1.7.0.1"_v));
REQUIRE(" ~= 1.8 "_vs.contains("1.8"_v));
REQUIRE(" ~= 1.8 "_vs.contains("1.8.0"_v));
REQUIRE(" ~= 1.8 "_vs.contains("1.8.1"_v));
REQUIRE(" ~= 1.8 "_vs.contains("1.9"_v));
REQUIRE(" ~= 1.8 "_vs.contains("1.8post"_v));
REQUIRE_FALSE(" ~= 1.8 "_vs.contains("1.8alpha"_v));
CHECK(" ~=1 "_vs.contains("1.7.0.1"_v));
CHECK(" ~=1 "_vs.contains("1.8"_v));
CHECK(" ~=1 "_vs.contains("1.8post"_v));
CHECK(" ~=1 "_vs.contains("2.0"_v));
CHECK_FALSE(" ~=1 "_vs.contains("0.1"_v));
CHECK_FALSE(" ~=1 "_vs.contains("1.0.alpha"_v));
REQUIRE(" ~=1 "_vs.contains("1.7.0.1"_v));
REQUIRE(" ~=1 "_vs.contains("1.8"_v));
REQUIRE(" ~=1 "_vs.contains("1.8post"_v));
REQUIRE(" ~=1 "_vs.contains("2.0"_v));
REQUIRE_FALSE(" ~=1 "_vs.contains("0.1"_v));
REQUIRE_FALSE(" ~=1 "_vs.contains("1.0.alpha"_v));
CHECK_FALSE(" (>= 1.7, <1.8) |>=1.9.0.0 "_vs.contains("1.6"_v));
CHECK(" (>= 1.7, <1.8) |>=1.9.0.0 "_vs.contains("1.7.0.0"_v));
CHECK_FALSE(" (>= 1.7, <1.8) |>=1.9.0.0 "_vs.contains("1.8.1"_v));
CHECK(" (>= 1.7, <1.8) |>=1.9.0.0 "_vs.contains("6.33"_v));
REQUIRE_FALSE(" (>= 1.7, <1.8) |>=1.9.0.0 "_vs.contains("1.6"_v));
REQUIRE(" (>= 1.7, <1.8) |>=1.9.0.0 "_vs.contains("1.7.0.0"_v));
REQUIRE_FALSE(" (>= 1.7, <1.8) |>=1.9.0.0 "_vs.contains("1.8.1"_v));
REQUIRE(" (>= 1.7, <1.8) |>=1.9.0.0 "_vs.contains("6.33"_v));
// Test from Conda
CHECK("==1.7"_vs.contains("1.7.0"_v));
CHECK("<=1.7"_vs.contains("1.7.0"_v));
CHECK_FALSE("<1.7"_vs.contains("1.7.0"_v));
CHECK(">=1.7"_vs.contains("1.7.0"_v));
CHECK_FALSE(">1.7"_vs.contains("1.7.0"_v));
CHECK_FALSE(">=1.7"_vs.contains("1.6.7"_v));
CHECK_FALSE(">2013b"_vs.contains("2013a"_v));
CHECK(">2013b"_vs.contains("2013k"_v));
CHECK_FALSE(">2013b"_vs.contains("3.0.0"_v));
CHECK(">1.0.0a"_vs.contains("1.0.0"_v));
CHECK(">1.0.0*"_vs.contains("1.0.0"_v));
CHECK("1.0*"_vs.contains("1.0"_v));
CHECK("1.0*"_vs.contains("1.0.0"_v));
CHECK("1.0.0*"_vs.contains("1.0"_v));
CHECK_FALSE("1.0.0*"_vs.contains("1.0.1"_v));
CHECK("2013a*"_vs.contains("2013a"_v));
CHECK_FALSE("2013b*"_vs.contains("2013a"_v));
CHECK_FALSE("1.2.4*"_vs.contains("1.3.4"_v));
CHECK("1.2.3*"_vs.contains("1.2.3+4.5.6"_v));
CHECK("1.2.3+4*"_vs.contains("1.2.3+4.5.6"_v));
CHECK_FALSE("1.2.3+5*"_vs.contains("1.2.3+4.5.6"_v));
CHECK_FALSE("1.2.4+5*"_vs.contains("1.2.3+4.5.6"_v));
CHECK("1.7.*"_vs.contains("1.7.1"_v));
CHECK("1.7.1"_vs.contains("1.7.1"_v));
CHECK_FALSE("1.7.0"_vs.contains("1.7.1"_v));
CHECK_FALSE("1.7"_vs.contains("1.7.1"_v));
CHECK_FALSE("1.5.*"_vs.contains("1.7.1"_v));
CHECK(">=1.5"_vs.contains("1.7.1"_v));
CHECK("!=1.5"_vs.contains("1.7.1"_v));
CHECK_FALSE("!=1.7.1"_vs.contains("1.7.1"_v));
CHECK("==1.7.1"_vs.contains("1.7.1"_v));
CHECK_FALSE("==1.7"_vs.contains("1.7.1"_v));
CHECK_FALSE("==1.7.2"_vs.contains("1.7.1"_v));
CHECK("==1.7.1.0"_vs.contains("1.7.1"_v));
CHECK("==1.7.1.*"_vs.contains("1.7.1.1"_v)); // Degenerate case
CHECK("1.7.*|1.8.*"_vs.contains("1.7.1"_v));
CHECK(">1.7,<1.8"_vs.contains("1.7.1"_v));
CHECK_FALSE(">1.7.1,<1.8"_vs.contains("1.7.1"_v));
CHECK("*"_vs.contains("1.7.1"_v));
CHECK("1.5.*|>1.7,<1.8"_vs.contains("1.7.1"_v));
CHECK_FALSE("1.5.*|>1.7,<1.7.1"_vs.contains("1.7.1"_v));
CHECK("1.7.0.post123"_vs.contains("1.7.0.post123"_v));
CHECK("1.7.0.post123.gabcdef9"_vs.contains("1.7.0.post123.gabcdef9"_v));
CHECK("1.7.0.post123+gabcdef9"_vs.contains("1.7.0.post123+gabcdef9"_v));
CHECK("=3.3"_vs.contains("3.3.1"_v));
CHECK("=3.3"_vs.contains("3.3"_v));
CHECK_FALSE("=3.3"_vs.contains("3.4"_v));
CHECK("3.3.*"_vs.contains("3.3.1"_v));
CHECK("3.3.*"_vs.contains("3.3"_v));
CHECK_FALSE("3.3.*"_vs.contains("3.4"_v));
CHECK("=3.3.*"_vs.contains("3.3.1"_v));
CHECK("=3.3.*"_vs.contains("3.3"_v));
CHECK_FALSE("=3.3.*"_vs.contains("3.4"_v));
CHECK_FALSE("!=3.3.*"_vs.contains("3.3.1"_v));
CHECK("!=3.3.*"_vs.contains("3.4"_v));
CHECK("!=3.3.*"_vs.contains("3.4.1"_v));
CHECK("!=3.3"_vs.contains("3.3.1"_v));
CHECK_FALSE("!=3.3"_vs.contains("3.3.0.0"_v));
CHECK_FALSE("!=3.3.*"_vs.contains("3.3.0.0"_v));
CHECK_FALSE(">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"_vs.contains("2.6.8"_v));
CHECK(">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"_vs.contains("2.7.2"_v));
CHECK_FALSE(">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"_vs.contains("3.3"_v));
CHECK_FALSE(">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"_vs.contains("3.3.4"_v));
CHECK(">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"_vs.contains("3.4"_v));
CHECK(">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"_vs.contains("3.4a"_v));
CHECK("~=1.10"_vs.contains("1.11.0"_v));
CHECK_FALSE("~=1.10.0"_vs.contains("1.11.0"_v));
CHECK_FALSE("~=3.3.2"_vs.contains("3.4.0"_v));
CHECK_FALSE("~=3.3.2"_vs.contains("3.3.1"_v));
CHECK("~=3.3.2"_vs.contains("3.3.2.0"_v));
CHECK("~=3.3.2"_vs.contains("3.3.3"_v));
CHECK("~=3.3.2|==2.2"_vs.contains("2.2.0"_v));
CHECK("~=3.3.2|==2.2"_vs.contains("3.3.3"_v));
CHECK_FALSE("~=3.3.2|==2.2"_vs.contains("2.2.1"_v));
REQUIRE("==1.7"_vs.contains("1.7.0"_v));
REQUIRE("<=1.7"_vs.contains("1.7.0"_v));
REQUIRE_FALSE("<1.7"_vs.contains("1.7.0"_v));
REQUIRE(">=1.7"_vs.contains("1.7.0"_v));
REQUIRE_FALSE(">1.7"_vs.contains("1.7.0"_v));
REQUIRE_FALSE(">=1.7"_vs.contains("1.6.7"_v));
REQUIRE_FALSE(">2013b"_vs.contains("2013a"_v));
REQUIRE(">2013b"_vs.contains("2013k"_v));
REQUIRE_FALSE(">2013b"_vs.contains("3.0.0"_v));
REQUIRE(">1.0.0a"_vs.contains("1.0.0"_v));
REQUIRE(">1.0.0*"_vs.contains("1.0.0"_v));
REQUIRE("1.0*"_vs.contains("1.0"_v));
REQUIRE("1.0*"_vs.contains("1.0.0"_v));
REQUIRE("1.0.0*"_vs.contains("1.0"_v));
REQUIRE_FALSE("1.0.0*"_vs.contains("1.0.1"_v));
REQUIRE("2013a*"_vs.contains("2013a"_v));
REQUIRE_FALSE("2013b*"_vs.contains("2013a"_v));
REQUIRE_FALSE("1.2.4*"_vs.contains("1.3.4"_v));
REQUIRE("1.2.3*"_vs.contains("1.2.3+4.5.6"_v));
REQUIRE("1.2.3+4*"_vs.contains("1.2.3+4.5.6"_v));
REQUIRE_FALSE("1.2.3+5*"_vs.contains("1.2.3+4.5.6"_v));
REQUIRE_FALSE("1.2.4+5*"_vs.contains("1.2.3+4.5.6"_v));
REQUIRE("1.7.*"_vs.contains("1.7.1"_v));
REQUIRE("1.7.1"_vs.contains("1.7.1"_v));
REQUIRE_FALSE("1.7.0"_vs.contains("1.7.1"_v));
REQUIRE_FALSE("1.7"_vs.contains("1.7.1"_v));
REQUIRE_FALSE("1.5.*"_vs.contains("1.7.1"_v));
REQUIRE(">=1.5"_vs.contains("1.7.1"_v));
REQUIRE("!=1.5"_vs.contains("1.7.1"_v));
REQUIRE_FALSE("!=1.7.1"_vs.contains("1.7.1"_v));
REQUIRE("==1.7.1"_vs.contains("1.7.1"_v));
REQUIRE_FALSE("==1.7"_vs.contains("1.7.1"_v));
REQUIRE_FALSE("==1.7.2"_vs.contains("1.7.1"_v));
REQUIRE("==1.7.1.0"_vs.contains("1.7.1"_v));
REQUIRE("==1.7.1.*"_vs.contains("1.7.1.1"_v)); // Degenerate case
REQUIRE("1.7.*|1.8.*"_vs.contains("1.7.1"_v));
REQUIRE(">1.7,<1.8"_vs.contains("1.7.1"_v));
REQUIRE_FALSE(">1.7.1,<1.8"_vs.contains("1.7.1"_v));
REQUIRE("*"_vs.contains("1.7.1"_v));
REQUIRE("1.5.*|>1.7,<1.8"_vs.contains("1.7.1"_v));
REQUIRE_FALSE("1.5.*|>1.7,<1.7.1"_vs.contains("1.7.1"_v));
REQUIRE("1.7.0.post123"_vs.contains("1.7.0.post123"_v));
REQUIRE("1.7.0.post123.gabcdef9"_vs.contains("1.7.0.post123.gabcdef9"_v));
REQUIRE("1.7.0.post123+gabcdef9"_vs.contains("1.7.0.post123+gabcdef9"_v));
REQUIRE("=3.3"_vs.contains("3.3.1"_v));
REQUIRE("=3.3"_vs.contains("3.3"_v));
REQUIRE_FALSE("=3.3"_vs.contains("3.4"_v));
REQUIRE("3.3.*"_vs.contains("3.3.1"_v));
REQUIRE("3.3.*"_vs.contains("3.3"_v));
REQUIRE_FALSE("3.3.*"_vs.contains("3.4"_v));
REQUIRE("=3.3.*"_vs.contains("3.3.1"_v));
REQUIRE("=3.3.*"_vs.contains("3.3"_v));
REQUIRE_FALSE("=3.3.*"_vs.contains("3.4"_v));
REQUIRE_FALSE("!=3.3.*"_vs.contains("3.3.1"_v));
REQUIRE("!=3.3.*"_vs.contains("3.4"_v));
REQUIRE("!=3.3.*"_vs.contains("3.4.1"_v));
REQUIRE("!=3.3"_vs.contains("3.3.1"_v));
REQUIRE_FALSE("!=3.3"_vs.contains("3.3.0.0"_v));
REQUIRE_FALSE("!=3.3.*"_vs.contains("3.3.0.0"_v));
REQUIRE_FALSE(">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"_vs.contains("2.6.8"_v));
REQUIRE(">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"_vs.contains("2.7.2"_v));
REQUIRE_FALSE(">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"_vs.contains("3.3"_v));
REQUIRE_FALSE(">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"_vs.contains("3.3.4"_v));
REQUIRE(">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"_vs.contains("3.4"_v));
REQUIRE(">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"_vs.contains("3.4a"_v));
REQUIRE("~=1.10"_vs.contains("1.11.0"_v));
REQUIRE_FALSE("~=1.10.0"_vs.contains("1.11.0"_v));
REQUIRE_FALSE("~=3.3.2"_vs.contains("3.4.0"_v));
REQUIRE_FALSE("~=3.3.2"_vs.contains("3.3.1"_v));
REQUIRE("~=3.3.2"_vs.contains("3.3.2.0"_v));
REQUIRE("~=3.3.2"_vs.contains("3.3.3"_v));
REQUIRE("~=3.3.2|==2.2"_vs.contains("2.2.0"_v));
REQUIRE("~=3.3.2|==2.2"_vs.contains("3.3.3"_v));
REQUIRE_FALSE("~=3.3.2|==2.2"_vs.contains("2.2.1"_v));
// Regex are currently not supported
// CHECK("^1.7.1$"_vs.contains("1.7.1"_v));
// CHECK(R"(^1\.7\.1$)"_vs.contains("1.7.1"_v));
// CHECK(R"(^1\.7\.[0-9]+$)"_vs.contains("1.7.1"_v));
// CHECK_FALSE(R"(^1\.8.*$)"_vs.contains("1.7.1"_v));
// CHECK(R"(^1\.[5-8]\.1$)"_vs.contains("1.7.1"_v));
// CHECK_FALSE(R"(^[^1].*$)"_vs.contains("1.7.1"_v));
// CHECK(R"(^[0-9+]+\.[0-9+]+\.[0-9]+$)"_vs.contains("1.7.1"_v));
// CHECK_FALSE("^$"_vs.contains("1.7.1"_v));
// CHECK("^.*$"_vs.contains("1.7.1"_v));
// CHECK("1.7.*|^0.*$"_vs.contains("1.7.1"_v));
// CHECK_FALSE("1.6.*|^0.*$"_vs.contains("1.7.1"_v));
// CHECK("1.6.*|^0.*$|1.7.1"_vs.contains("1.7.1"_v));
// CHECK("^0.*$|1.7.1"_vs.contains("1.7.1"_v));
// CHECK(R"(1.6.*|^.*\.7\.1$|0.7.1)"_vs.contains("1.7.1"_v));
// CHECK("1.*.1"_vs.contains("1.7.1"_v));
// REQUIRE("^1.7.1$"_vs.contains("1.7.1"_v));
// REQUIRE(R"(^1\.7\.1$)"_vs.contains("1.7.1"_v));
// REQUIRE(R"(^1\.7\.[0-9]+$)"_vs.contains("1.7.1"_v));
// REQUIRE_FALSE(R"(^1\.8.*$)"_vs.contains("1.7.1"_v));
// REQUIRE(R"(^1\.[5-8]\.1$)"_vs.contains("1.7.1"_v));
// REQUIRE_FALSE(R"(^[^1].*$)"_vs.contains("1.7.1"_v));
// REQUIRE(R"(^[0-9+]+\.[0-9+]+\.[0-9]+$)"_vs.contains("1.7.1"_v));
// REQUIRE_FALSE("^$"_vs.contains("1.7.1"_v));
// REQUIRE("^.*$"_vs.contains("1.7.1"_v));
// REQUIRE("1.7.*|^0.*$"_vs.contains("1.7.1"_v));
// REQUIRE_FALSE("1.6.*|^0.*$"_vs.contains("1.7.1"_v));
// REQUIRE("1.6.*|^0.*$|1.7.1"_vs.contains("1.7.1"_v));
// REQUIRE("^0.*$|1.7.1"_vs.contains("1.7.1"_v));
// REQUIRE(R"(1.6.*|^.*\.7\.1$|0.7.1)"_vs.contains("1.7.1"_v));
// REQUIRE("1.*.1"_vs.contains("1.7.1"_v));
}
SUBCASE("Unsuccessful")
SECTION("Unsuccessful")
{
using namespace std::literals::string_view_literals;
static constexpr auto bad_specs = std::array{
@ -402,25 +402,25 @@ TEST_SUITE("specs::version_spec")
for (const auto& spec : bad_specs)
{
CAPTURE(spec);
CHECK_FALSE(VersionSpec::parse(spec).has_value());
REQUIRE_FALSE(VersionSpec::parse(spec).has_value());
}
}
}
TEST_CASE("VersionSpec::str")
{
SUBCASE("2.3")
SECTION("2.3")
{
auto vs = VersionSpec::parse("2.3").value();
CHECK_EQ(vs.str(), "==2.3");
CHECK_EQ(vs.str_conda_build(), "==2.3");
REQUIRE(vs.str() == "==2.3");
REQUIRE(vs.str_conda_build() == "==2.3");
}
SUBCASE("=2.3,<3.0")
SECTION("=2.3,<3.0")
{
auto vs = VersionSpec::parse("=2.3,<3.0").value();
CHECK_EQ(vs.str(), "=2.3,<3.0");
CHECK_EQ(vs.str_conda_build(), "2.3.*,<3.0");
REQUIRE(vs.str() == "=2.3,<3.0");
REQUIRE(vs.str_conda_build() == "2.3.*,<3.0");
}
}
@ -434,29 +434,28 @@ TEST_SUITE("specs::version_spec")
REQUIRE(parser.finalize());
auto spec = VersionSpec(std::move(parser).tree());
CHECK(spec.is_explicitly_free());
REQUIRE(spec.is_explicitly_free());
}
CHECK(VersionSpec().is_explicitly_free());
CHECK(VersionSpec::parse("*").value().is_explicitly_free());
CHECK(VersionSpec::parse("").value().is_explicitly_free());
REQUIRE(VersionSpec().is_explicitly_free());
REQUIRE(VersionSpec::parse("*").value().is_explicitly_free());
REQUIRE(VersionSpec::parse("").value().is_explicitly_free());
CHECK_FALSE(VersionSpec::parse("==2.3|!=2.3").value().is_explicitly_free());
CHECK_FALSE(VersionSpec::parse("=2.3,<3.0").value().is_explicitly_free());
REQUIRE_FALSE(VersionSpec::parse("==2.3|!=2.3").value().is_explicitly_free());
REQUIRE_FALSE(VersionSpec::parse("=2.3,<3.0").value().is_explicitly_free());
}
TEST_CASE("Comparability and hashability")
TEST_CASE("VersionSpec Comparability and hashability")
{
auto spec1 = VersionSpec::parse("*").value();
auto spec2 = VersionSpec::parse("*").value();
auto spec3 = VersionSpec::parse("=2.4").value();
CHECK_EQ(spec1, spec2);
CHECK_NE(spec1, spec3);
REQUIRE(spec1 == spec2);
REQUIRE(spec1 != spec3);
auto hash_fn = std::hash<VersionSpec>();
CHECK_EQ(hash_fn(spec1), hash_fn(spec2));
CHECK_NE(hash_fn(spec1), hash_fn(spec3));
REQUIRE(hash_fn(spec1) == hash_fn(spec2));
REQUIRE(hash_fn(spec1) != hash_fn(spec3));
}
}

View File

@ -1,3 +1,3 @@
#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
#define CATCH_CONFIG_MAIN
#include <doctest/doctest.h>
#include <catch2/catch_all.hpp>

View File

@ -8,7 +8,7 @@
#include <limits>
#include <utility>
#include <doctest/doctest.h>
#include <catch2/catch_all.hpp>
#include "mamba/util/cast.hpp"
@ -42,44 +42,59 @@ using OverflowLowestTypes = std::tuple<
std::pair<double, int>,
std::pair<float, char>>;
TEST_SUITE("util::cast")
namespace
{
TEST_CASE_TEMPLATE_DEFINE("checked_exact_num_cast_widen", T, cast_widen)
template <typename T>
void check_exact_num_cast_widen()
{
using From = typename T::first_type;
using To = typename T::second_type;
static constexpr auto from_lowest = std::numeric_limits<From>::lowest();
static constexpr auto from_max = std::numeric_limits<From>::max();
CHECK_EQ(safe_num_cast<To>(From(0)), To(0));
CHECK_EQ(safe_num_cast<To>(From(1)), To(1));
CHECK_EQ(safe_num_cast<To>(from_lowest), static_cast<To>(from_lowest));
CHECK_EQ(safe_num_cast<To>(from_max), static_cast<To>(from_max));
REQUIRE(safe_num_cast<To>(From(0)) == To(0));
REQUIRE(safe_num_cast<To>(From(1)) == To(1));
REQUIRE(safe_num_cast<To>(from_lowest) == static_cast<To>(from_lowest));
REQUIRE(safe_num_cast<To>(from_max) == static_cast<To>(from_max));
}
TEST_CASE_TEMPLATE_APPLY(cast_widen, WidenTypes);
TEST_CASE_TEMPLATE_DEFINE("checked_exact_num_cast_narrow", T, cast_narrow)
TEMPLATE_LIST_TEST_CASE("Exact num cast widen", "", WidenTypes)
{
check_exact_num_cast_widen<TestType>();
}
template <typename T>
void check_exact_num_cast_narrow()
{
using From = typename T::second_type; // inversed
using To = typename T::first_type; // inversed
CHECK_EQ(safe_num_cast<To>(From(0)), To(0));
CHECK_EQ(safe_num_cast<To>(From(1)), To(1));
REQUIRE(safe_num_cast<To>(From(0)) == To(0));
REQUIRE(safe_num_cast<To>(From(1)) == To(1));
}
TEST_CASE_TEMPLATE_APPLY(cast_narrow, WidenTypes);
TEST_CASE_TEMPLATE_DEFINE("checked_exact_num_cast_overflow", T, cast_overflow)
TEMPLATE_LIST_TEST_CASE("Exact num cast narrow", "", WidenTypes)
{
check_exact_num_cast_narrow<TestType>();
}
template <typename T>
void check_exact_num_cast_overflow()
{
using From = typename T::first_type;
using To = typename T::second_type;
static constexpr auto from_lowest = std::numeric_limits<From>::lowest();
CHECK_THROWS_AS(safe_num_cast<To>(from_lowest), std::overflow_error);
REQUIRE_THROWS_AS(safe_num_cast<To>(from_lowest), std::overflow_error);
}
TEMPLATE_LIST_TEST_CASE("Exact num cast overflow", "", OverflowLowestTypes)
{
check_exact_num_cast_overflow<TestType>();
}
TEST_CASE_TEMPLATE_APPLY(cast_overflow, OverflowLowestTypes);
TEST_CASE("precision")
{
CHECK_THROWS_AS(safe_num_cast<int>(1.1), std::runtime_error);
CHECK_THROWS_AS(safe_num_cast<float>(std::nextafter(double(1), 2)), std::runtime_error);
REQUIRE_THROWS_AS(safe_num_cast<int>(1.1), std::runtime_error);
REQUIRE_THROWS_AS(safe_num_cast<float>(std::nextafter(double(1), 2)), std::runtime_error);
}
}

View File

@ -7,82 +7,82 @@
#include <limits>
#include <utility>
#include <doctest/doctest.h>
#include <catch2/catch_all.hpp>
#include "mamba/util/compare.hpp"
using namespace mamba::util;
TEST_SUITE("util::compare")
namespace
{
TEST_CASE("equal")
{
CHECK(cmp_equal(char{ 0 }, char{ 0 }));
CHECK(cmp_equal(char{ 1 }, char{ 1 }));
CHECK(cmp_equal(char{ -1 }, char{ -1 }));
CHECK(cmp_equal(int{ 0 }, int{ 0 }));
CHECK(cmp_equal(int{ 1 }, int{ 1 }));
CHECK(cmp_equal(int{ -1 }, int{ -1 }));
CHECK(cmp_equal(std::size_t{ 0 }, std::size_t{ 0 }));
CHECK(cmp_equal(std::size_t{ 1 }, std::size_t{ 1 }));
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 }));
CHECK(cmp_equal(char{ 0 }, int{ 0 }));
CHECK(cmp_equal(char{ 1 }, int{ 1 }));
CHECK(cmp_equal(char{ -1 }, int{ -1 }));
CHECK(cmp_equal(std::size_t{ 0 }, char{ 0 }));
CHECK(cmp_equal(std::size_t{ 1 }, char{ 1 }));
CHECK(cmp_equal(std::size_t{ 0 }, int{ 0 }));
CHECK(cmp_equal(std::size_t{ 1 }, int{ 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 }));
CHECK_FALSE(cmp_equal(char{ 0 }, char{ 1 }));
CHECK_FALSE(cmp_equal(char{ 1 }, char{ -1 }));
CHECK_FALSE(cmp_equal(int{ 0 }, int{ 1 }));
CHECK_FALSE(cmp_equal(int{ -1 }, int{ 1 }));
CHECK_FALSE(cmp_equal(std::size_t{ 0 }, std::size_t{ 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 }));
CHECK_FALSE(cmp_equal(char{ 0 }, int{ 1 }));
CHECK_FALSE(cmp_equal(char{ 1 }, int{ -1 }));
CHECK_FALSE(cmp_equal(char{ -1 }, int{ 1 }));
CHECK_FALSE(cmp_equal(std::size_t{ 1 }, int{ -1 }));
CHECK_FALSE(cmp_equal(static_cast<std::size_t>(-1), int{ -1 }));
CHECK_FALSE(cmp_equal(std::size_t{ 1 }, int{ 0 }));
CHECK_FALSE(cmp_equal(std::numeric_limits<std::size_t>::max(), int{ 0 }));
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<std::size_t>(-1), int{ -1 }));
REQUIRE_FALSE(cmp_equal(std::size_t{ 1 }, int{ 0 }));
REQUIRE_FALSE(cmp_equal(std::numeric_limits<std::size_t>::max(), int{ 0 }));
}
TEST_CASE("less")
{
CHECK(cmp_less(char{ 0 }, char{ 1 }));
CHECK(cmp_less(char{ -1 }, char{ 0 }));
CHECK(cmp_less(int{ 0 }, int{ 1 }));
CHECK(cmp_less(int{ -1 }, int{ 1 }));
CHECK(cmp_less(std::size_t{ 0 }, std::size_t{ 1 }));
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 }));
CHECK(cmp_less(char{ 0 }, int{ 1 }));
CHECK(cmp_less(char{ -1 }, int{ 0 }));
CHECK(cmp_less(char{ -1 }, int{ 1 }));
CHECK(cmp_less(char{ -1 }, std::size_t{ 1 }));
CHECK(cmp_less(std::size_t{ 0 }, int{ 1 }));
CHECK(cmp_less(std::numeric_limits<int>::min(), char{ 0 }));
CHECK(cmp_less(std::numeric_limits<int>::min(), std::size_t{ 0 }));
CHECK(cmp_less(int{ -1 }, std::numeric_limits<std::size_t>::max()));
CHECK(cmp_less(std::size_t{ 1 }, std::numeric_limits<int>::max()));
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<int>::min(), char{ 0 }));
REQUIRE(cmp_less(std::numeric_limits<int>::min(), std::size_t{ 0 }));
REQUIRE(cmp_less(int{ -1 }, std::numeric_limits<std::size_t>::max()));
REQUIRE(cmp_less(std::size_t{ 1 }, std::numeric_limits<int>::max()));
CHECK_FALSE(cmp_less(char{ 1 }, char{ 0 }));
CHECK_FALSE(cmp_less(char{ 1 }, char{ 1 }));
CHECK_FALSE(cmp_less(char{ 0 }, char{ -1 }));
CHECK_FALSE(cmp_less(int{ 1 }, int{ 0 }));
CHECK_FALSE(cmp_less(int{ 1 }, int{ -1 }));
CHECK_FALSE(cmp_less(std::size_t{ 1 }, std::size_t{ 0 }));
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 }));
CHECK_FALSE(cmp_less(char{ 1 }, int{ 1 }));
CHECK_FALSE(cmp_less(char{ 1 }, int{ 0 }));
CHECK_FALSE(cmp_less(char{ 0 }, int{ -1 }));
CHECK_FALSE(cmp_less(char{ 1 }, int{ -11 }));
CHECK_FALSE(cmp_less(std::size_t{ 1 }, char{ -1 }));
CHECK_FALSE(cmp_less(int{ 1 }, std::size_t{ 0 }));
CHECK_FALSE(cmp_less(char{ 0 }, std::numeric_limits<int>::min()));
CHECK_FALSE(cmp_less(std::size_t{ 0 }, std::numeric_limits<int>::min()));
CHECK_FALSE(cmp_less(std::numeric_limits<std::size_t>::max(), int{ -1 }));
CHECK_FALSE(cmp_less(std::numeric_limits<int>::max(), std::size_t{ 1 }));
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<int>::min()));
REQUIRE_FALSE(cmp_less(std::size_t{ 0 }, std::numeric_limits<int>::min()));
REQUIRE_FALSE(cmp_less(std::numeric_limits<std::size_t>::max(), int{ -1 }));
REQUIRE_FALSE(cmp_less(std::numeric_limits<int>::max(), std::size_t{ 1 }));
}
}

View File

@ -7,17 +7,14 @@
#include <array>
#include <utility>
#include <doctest/doctest.h>
#include <catch2/catch_all.hpp>
#include "mamba/core/util.hpp"
#include "mamba/util/cryptography.hpp"
#include "doctest-printer/array.hpp"
#include "doctest-printer/optional.hpp"
using namespace mamba::util;
TEST_SUITE("util::cryptography")
namespace
{
TEST_CASE("Hasher")
{
@ -59,34 +56,34 @@ TEST_SUITE("util::cryptography")
} };
SUBCASE("Hash string")
SECTION("Hash string")
{
SUBCASE("sha256")
SECTION("sha256")
{
auto reused_hasher = Sha256Hasher();
for (auto [data, hash] : known_sha256)
{
CHECK_EQ(reused_hasher.str_hex_str(data), hash);
REQUIRE(reused_hasher.str_hex_str(data) == hash);
auto new_hasher = Sha256Hasher();
CHECK_EQ(new_hasher.str_hex_str(data), hash);
REQUIRE(new_hasher.str_hex_str(data) == hash);
}
}
SUBCASE("md5")
SECTION("md5")
{
auto reused_hasher = Md5Hasher();
for (auto [data, hash] : known_md5)
{
CHECK_EQ(reused_hasher.str_hex_str(data), hash);
REQUIRE(reused_hasher.str_hex_str(data) == hash);
auto new_hasher = Md5Hasher();
CHECK_EQ(new_hasher.str_hex_str(data), hash);
REQUIRE(new_hasher.str_hex_str(data) == hash);
}
}
}
SUBCASE("Hash file")
SECTION("Hash file")
{
SUBCASE("sha256")
SECTION("sha256")
{
auto hasher = Sha256Hasher();
for (auto [data, hash] : known_sha256)
@ -100,11 +97,11 @@ TEST_SUITE("util::cryptography")
}
auto file = std::ifstream(tmp.path().std_path());
REQUIRE(file.good());
CHECK_EQ(hasher.file_hex_str(file), hash);
REQUIRE(hasher.file_hex_str(file) == hash);
}
}
SUBCASE("md5")
SECTION("md5")
{
auto hasher = Md5Hasher();
for (auto [data, hash] : known_md5)
@ -118,7 +115,7 @@ TEST_SUITE("util::cryptography")
}
auto file = std::ifstream(tmp.path().std_path());
REQUIRE(file.good());
CHECK_EQ(hasher.file_hex_str(file), hash);
REQUIRE(hasher.file_hex_str(file) == hash);
}
}
}

View File

@ -8,27 +8,25 @@
#include <array>
#include <string_view>
#include <doctest/doctest.h>
#include <catch2/catch_all.hpp>
#include "mamba/util/encoding.hpp"
#include "doctest-printer/array.hpp"
using namespace mamba::util;
TEST_SUITE("util::encoding")
namespace
{
TEST_CASE("Hexadecimal")
{
SUBCASE("nibble_to_hex")
SECTION("nibble_to_hex")
{
CHECK_EQ(nibble_to_hex(std::byte{ 0x00 }), '0');
CHECK_EQ(nibble_to_hex(std::byte{ 0x10 }), '0'); // high ignored
CHECK_EQ(nibble_to_hex(std::byte{ 0x01 }), '1');
CHECK_EQ(nibble_to_hex(std::byte{ 0x0D }), 'd');
REQUIRE(nibble_to_hex(std::byte{ 0x00 }) == '0');
REQUIRE(nibble_to_hex(std::byte{ 0x10 }) == '0'); // high ignored
REQUIRE(nibble_to_hex(std::byte{ 0x01 }) == '1');
REQUIRE(nibble_to_hex(std::byte{ 0x0D }) == 'd');
}
SUBCASE("bytes_to_hex_to")
SECTION("bytes_to_hex_to")
{
constexpr auto bytes = std::array{
std::byte{ 0x00 }, std::byte{ 0x01 }, std::byte{ 0x03 }, std::byte{ 0x09 },
@ -38,60 +36,60 @@ TEST_SUITE("util::encoding")
std::byte{ 0xEF }, std::byte{ 0xFF },
};
CHECK_EQ(
bytes_to_hex_str(bytes.data(), bytes.data() + bytes.size()),
"000103090a0d0fad1030a0d0f0ada94eefff"
REQUIRE(
bytes_to_hex_str(bytes.data(), bytes.data() + bytes.size())
== "000103090a0d0fad1030a0d0f0ada94eefff"
);
}
SUBCASE("hex_to_nibble")
SECTION("hex_to_nibble")
{
CHECK_EQ(hex_to_nibble('0').value(), std::byte{ 0x00 });
CHECK_EQ(hex_to_nibble('a').value(), std::byte{ 0x0A });
CHECK_EQ(hex_to_nibble('f').value(), std::byte{ 0x0F });
CHECK_EQ(hex_to_nibble('B').value(), std::byte{ 0x0B });
REQUIRE(hex_to_nibble('0').value() == std::byte{ 0x00 });
REQUIRE(hex_to_nibble('a').value() == std::byte{ 0x0A });
REQUIRE(hex_to_nibble('f').value() == std::byte{ 0x0F });
REQUIRE(hex_to_nibble('B').value() == std::byte{ 0x0B });
CHECK_FALSE(hex_to_nibble('x').has_value());
CHECK_FALSE(hex_to_nibble('*').has_value());
CHECK_FALSE(hex_to_nibble('\0').has_value());
CHECK_FALSE(hex_to_nibble('~').has_value());
REQUIRE_FALSE(hex_to_nibble('x').has_value());
REQUIRE_FALSE(hex_to_nibble('*').has_value());
REQUIRE_FALSE(hex_to_nibble('\0').has_value());
REQUIRE_FALSE(hex_to_nibble('~').has_value());
}
SUBCASE("two_hex_to_byte")
SECTION("two_hex_to_byte")
{
CHECK_EQ(two_hex_to_byte('0', '0').value(), std::byte{ 0x00 });
CHECK_EQ(two_hex_to_byte('0', '4').value(), std::byte{ 0x04 });
CHECK_EQ(two_hex_to_byte('5', '0').value(), std::byte{ 0x50 });
CHECK_EQ(two_hex_to_byte('F', 'F').value(), std::byte{ 0xFF });
CHECK_EQ(two_hex_to_byte('0', 'A').value(), std::byte{ 0x0A });
CHECK_EQ(two_hex_to_byte('b', '8').value(), std::byte{ 0xB8 });
REQUIRE(two_hex_to_byte('0', '0').value() == std::byte{ 0x00 });
REQUIRE(two_hex_to_byte('0', '4').value() == std::byte{ 0x04 });
REQUIRE(two_hex_to_byte('5', '0').value() == std::byte{ 0x50 });
REQUIRE(two_hex_to_byte('F', 'F').value() == std::byte{ 0xFF });
REQUIRE(two_hex_to_byte('0', 'A').value() == std::byte{ 0x0A });
REQUIRE(two_hex_to_byte('b', '8').value() == std::byte{ 0xB8 });
CHECK_FALSE(two_hex_to_byte('b', 'x').has_value());
CHECK_FALSE(two_hex_to_byte('!', 'b').has_value());
CHECK_FALSE(two_hex_to_byte(' ', '~').has_value());
REQUIRE_FALSE(two_hex_to_byte('b', 'x').has_value());
REQUIRE_FALSE(two_hex_to_byte('!', 'b').has_value());
REQUIRE_FALSE(two_hex_to_byte(' ', '~').has_value());
}
SUBCASE("hex_to_bytes")
SECTION("hex_to_bytes")
{
using bytes = std::vector<std::byte>;
SUBCASE("1234")
SECTION("1234")
{
auto str = std::string_view("1234");
auto b = bytes(str.size() / 2);
REQUIRE(hex_to_bytes_to(str, b.data()).has_value());
CHECK_EQ(b, bytes{ std::byte{ 0x12 }, std::byte{ 0x34 } });
REQUIRE(b == bytes{ std::byte{ 0x12 }, std::byte{ 0x34 } });
}
SUBCASE("1f4DaB")
SECTION("1f4DaB")
{
auto str = std::string_view("1f4DaB");
auto b = bytes(str.size() / 2);
REQUIRE(hex_to_bytes_to(str, b.data()).has_value());
CHECK_EQ(b, bytes{ std::byte{ 0x1F }, std::byte{ 0x4D }, std::byte{ 0xAB } });
REQUIRE(b == bytes{ std::byte{ 0x1F }, std::byte{ 0x4D }, std::byte{ 0xAB } });
}
SUBCASE("1f4Da")
SECTION("1f4Da")
{
// Odd number
auto str = std::string_view("1f4Da");
@ -99,7 +97,7 @@ TEST_SUITE("util::encoding")
REQUIRE_FALSE(hex_to_bytes_to(str, b.data()).has_value());
}
SUBCASE("1fx4")
SECTION("1fx4")
{
// Bad hex
auto str = std::string_view("1fx4");
@ -111,62 +109,62 @@ TEST_SUITE("util::encoding")
TEST_CASE("percent")
{
SUBCASE("encode")
SECTION("encode")
{
CHECK_EQ(encode_percent(""), "");
CHECK_EQ(encode_percent("page"), "page");
CHECK_EQ(encode_percent(" /word%"), "%20%2Fword%25");
CHECK_EQ(encode_percent("user@email.com"), "user%40email.com");
CHECK_EQ(
encode_percent(R"(#!$&'"(ab23)*+,/:;=?@[])"),
"%23%21%24%26%27%22%28ab23%29%2A%2B%2C%2F%3A%3B%3D%3F%40%5B%5D"
REQUIRE(encode_percent("") == "");
REQUIRE(encode_percent("page") == "page");
REQUIRE(encode_percent(" /word%") == "%20%2Fword%25");
REQUIRE(encode_percent("user@email.com") == "user%40email.com");
REQUIRE(
encode_percent(R"(#!$&'"(ab23)*+,/:;=?@[])")
== "%23%21%24%26%27%22%28ab23%29%2A%2B%2C%2F%3A%3B%3D%3F%40%5B%5D"
);
// Does NOT parse URL
CHECK_EQ(encode_percent("https://foo/"), "https%3A%2F%2Ffoo%2F");
REQUIRE(encode_percent("https://foo/") == "https%3A%2F%2Ffoo%2F");
// Exclude characters
CHECK_EQ(encode_percent(" /word%", '/'), "%20/word%25");
REQUIRE(encode_percent(" /word%", '/') == "%20/word%25");
}
SUBCASE("decode")
SECTION("decode")
{
CHECK_EQ(decode_percent(""), "");
CHECK_EQ(decode_percent("page"), "page");
CHECK_EQ(decode_percent("%20%2Fword%25"), " /word%");
CHECK_EQ(decode_percent(" /word%25"), " /word%");
CHECK_EQ(decode_percent("user%40email.com"), "user@email.com");
CHECK_EQ(decode_percent("https%3A%2F%2Ffoo%2F"), "https://foo/");
CHECK_EQ(
decode_percent("%23%21%24%26%27%22%28ab23%29%2A%2B%2C%2F%3A%3B%3D%3F%40%5B%5D"),
R"(#!$&'"(ab23)*+,/:;=?@[])"
REQUIRE(decode_percent("") == "");
REQUIRE(decode_percent("page") == "page");
REQUIRE(decode_percent("%20%2Fword%25") == " /word%");
REQUIRE(decode_percent(" /word%25") == " /word%");
REQUIRE(decode_percent("user%40email.com") == "user@email.com");
REQUIRE(decode_percent("https%3A%2F%2Ffoo%2F") == "https://foo/");
REQUIRE(
decode_percent("%23%21%24%26%27%22%28ab23%29%2A%2B%2C%2F%3A%3B%3D%3F%40%5B%5D")
== R"(#!$&'"(ab23)*+,/:;=?@[])"
);
}
}
TEST_CASE("base64")
{
SUBCASE("encode")
SECTION("encode")
{
CHECK_EQ(encode_base64("Hello").value(), "SGVsbG8=");
CHECK_EQ(encode_base64("Hello World!").value(), "SGVsbG8gV29ybGQh");
CHECK_EQ(encode_base64("!@#$%^U&I*O").value(), "IUAjJCVeVSZJKk8=");
CHECK_EQ(
encode_base64(u8"_私のにほHelloわへたです").value(),
"X+engeOBruOBq+OBu0hlbGxv44KP44G444Gf44Gn44GZ"
REQUIRE(encode_base64("Hello").value() == "SGVsbG8=");
REQUIRE(encode_base64("Hello World!").value() == "SGVsbG8gV29ybGQh");
REQUIRE(encode_base64("!@#$%^U&I*O").value() == "IUAjJCVeVSZJKk8=");
REQUIRE(
encode_base64(u8"_私のにほHelloわへたです").value()
== "X+engeOBruOBq+OBu0hlbGxv44KP44G444Gf44Gn44GZ"
);
CHECK_EQ(encode_base64("xyzpass").value(), "eHl6cGFzcw==");
REQUIRE(encode_base64("xyzpass").value() == "eHl6cGFzcw==");
}
SUBCASE("decode")
SECTION("decode")
{
CHECK_EQ(decode_base64("SGVsbG8=").value(), "Hello");
CHECK_EQ(decode_base64("SGVsbG8gV29ybGQh").value(), "Hello World!");
CHECK_EQ(decode_base64("IUAjJCVeVSZJKk8=").value(), "!@#$%^U&I*O");
CHECK_EQ(
decode_base64(u8"X+engeOBruOBq+OBu0hlbGxv44KP44G444Gf44Gn44GZ").value(),
"_私のにほHelloわへたです"
REQUIRE(decode_base64("SGVsbG8=").value() == "Hello");
REQUIRE(decode_base64("SGVsbG8gV29ybGQh").value() == "Hello World!");
REQUIRE(decode_base64("IUAjJCVeVSZJKk8=").value() == "!@#$%^U&I*O");
REQUIRE(
decode_base64(u8"X+engeOBruOBq+OBu0hlbGxv44KP44G444Gf44Gn44GZ").value()
== "_私のにほHelloわへたです"
);
CHECK_EQ(decode_base64("eHl6cGFzcw==").value(), "xyzpass");
REQUIRE(decode_base64("eHl6cGFzcw==").value() == "xyzpass");
}
}
}

View File

@ -4,7 +4,7 @@
//
// The full license is in the file LICENSE, distributed with this software.
#include <doctest/doctest.h>
#include <catch2/catch_all.hpp>
#include "mamba/util/build.hpp"
#include "mamba/util/environment.hpp"
@ -13,40 +13,40 @@
using namespace mamba::util;
TEST_SUITE("util::environment")
namespace
{
TEST_CASE("get_env")
{
const auto restore = mambatests::EnvironmentCleaner();
CHECK_FALSE(get_env("VAR_THAT_DOES_NOT_EXIST_XYZ").has_value());
CHECK(get_env("PATH").has_value());
REQUIRE_FALSE(get_env("VAR_THAT_DOES_NOT_EXIST_XYZ").has_value());
REQUIRE(get_env("PATH").has_value());
}
TEST_CASE("set_env")
{
const auto restore = mambatests::EnvironmentCleaner();
SUBCASE("ASCII")
SECTION("ASCII")
{
const auto key = std::string(u8"VAR_THAT_DOES_NOT_EXIST_XYZ");
const auto value1 = std::string(u8"VALUE");
set_env(key, value1);
CHECK_EQ(get_env(key), value1);
REQUIRE(get_env(key) == value1);
const auto value2 = std::string(u8"VALUE_NEW");
set_env(key, value2);
CHECK_EQ(get_env(key), value2);
REQUIRE(get_env(key) == value2);
}
SUBCASE("UTF-8")
SECTION("UTF-8")
{
const auto key = std::string(u8"VAR_私のにほんごわへたです");
const auto value1 = std::string(u8"😀");
set_env(key, value1);
CHECK_EQ(get_env(key), value1);
REQUIRE(get_env(key) == value1);
const auto value2 = std::string(u8"🤗");
set_env(key, value2);
CHECK_EQ(get_env(key), value2);
REQUIRE(get_env(key) == value2);
}
}
@ -55,13 +55,13 @@ TEST_SUITE("util::environment")
const auto restore = mambatests::EnvironmentCleaner();
const auto key = std::string(u8"VAR_THAT_DOES_NOT_EXIST_ABC_😀");
CHECK_FALSE(get_env(key).has_value());
REQUIRE_FALSE(get_env(key).has_value());
unset_env(key);
CHECK_FALSE(get_env(key).has_value());
REQUIRE_FALSE(get_env(key).has_value());
set_env(key, "VALUE");
CHECK(get_env(key).has_value());
REQUIRE(get_env(key).has_value());
unset_env(key);
CHECK_FALSE(get_env(key).has_value());
REQUIRE_FALSE(get_env(key).has_value());
}
TEST_CASE("get_env_map")
@ -69,15 +69,15 @@ TEST_SUITE("util::environment")
const auto restore = mambatests::EnvironmentCleaner();
auto env = mamba::util::get_env_map();
CHECK_GT(env.size(), 0);
CHECK_EQ(env.count("VAR_THAT_MUST_NOT_EXIST_XYZ"), 0);
CHECK_EQ(env.count("PATH"), 1);
REQUIRE(env.size() > 0);
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"😀");
set_env(key, value);
env = get_env_map();
CHECK_EQ(env.at(key), value);
REQUIRE(env.at(key) == value);
}
TEST_CASE("update_env_map")
@ -88,21 +88,21 @@ TEST_SUITE("util::environment")
const auto key_unchanged = std::string(u8"MAMBA😀");
const auto key_changed = std::string(u8"PIXI😀");
CHECK_FALSE(get_env(key_inexistent).has_value());
CHECK_FALSE(get_env(key_unchanged).has_value());
CHECK_FALSE(get_env(key_changed).has_value());
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😀");
update_env_map({ { key_changed, val_set_1 }, { key_unchanged, val_set_1 } });
CHECK_EQ(get_env(key_inexistent), std::nullopt);
CHECK_EQ(get_env(key_unchanged), val_set_1);
CHECK_EQ(get_env(key_changed), 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😀");
update_env_map({ { key_changed, val_set_2 } });
CHECK_EQ(get_env(key_inexistent), std::nullopt);
CHECK_EQ(get_env(key_unchanged), val_set_1);
CHECK_EQ(get_env(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")
@ -113,54 +113,54 @@ TEST_SUITE("util::environment")
const auto key_unchanged = std::string(u8"MAMBA🤗");
const auto key_changed = std::string(u8"PIXI🤗");
CHECK_FALSE(get_env(key_inexistent).has_value());
CHECK_FALSE(get_env(key_unchanged).has_value());
CHECK_FALSE(get_env(key_changed).has_value());
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😀");
set_env_map({ { key_changed, val_set_1 }, { key_unchanged, val_set_1 } });
CHECK_EQ(get_env(key_inexistent), std::nullopt);
CHECK_EQ(get_env(key_unchanged), val_set_1);
CHECK_EQ(get_env(key_changed), 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😀");
set_env_map({ { key_changed, val_set_2 } });
CHECK_EQ(get_env(key_inexistent), std::nullopt);
CHECK_EQ(get_env(key_unchanged), std::nullopt); // Difference with update_env_map
CHECK_EQ(get_env(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")
{
const auto restore = mambatests::EnvironmentCleaner();
SUBCASE("default")
SECTION("default")
{
[[maybe_unused]] const auto home = user_home_dir(); // Must not raise error
if (!on_win)
{
unset_env("HOME");
CHECK_EQ(user_home_dir(), home); // Fallback does not need $HOME
REQUIRE(user_home_dir() == home); // Fallback does not need $HOME
}
}
SUBCASE("explicit")
SECTION("explicit")
{
if (on_win)
{
set_env("USERPROFILE", R"(D:\user\mamba)");
CHECK_EQ(user_home_dir(), R"(D:\user\mamba)");
REQUIRE(user_home_dir() == R"(D:\user\mamba)");
unset_env("USERPROFILE");
set_env("HOMEDRIVE", R"(D:\user\)");
set_env("HOMEPATH", "mamba");
CHECK_EQ(user_home_dir(), R"(D:\user\mamba)");
REQUIRE(user_home_dir() == R"(D:\user\mamba)");
}
else
{
set_env("HOME", "/user/mamba");
CHECK_EQ(user_home_dir(), "/user/mamba");
REQUIRE(user_home_dir() == "/user/mamba");
}
}
}
@ -169,48 +169,48 @@ TEST_SUITE("util::environment")
{
const auto restore = mambatests::EnvironmentCleaner();
SUBCASE("XDG environment variables")
SECTION("XDG environment variables")
{
update_env_map({
{ "XDG_CONFIG_HOME", "xconfig" },
{ "XDG_DATA_HOME", "xdata" },
{ "XDG_CACHE_HOME", "xcache" },
});
CHECK_EQ(user_config_dir(), "xconfig");
CHECK_EQ(user_data_dir(), "xdata");
CHECK_EQ(user_cache_dir(), "xcache");
REQUIRE(user_config_dir() == "xconfig");
REQUIRE(user_data_dir() == "xdata");
REQUIRE(user_cache_dir() == "xcache");
}
SUBCASE("Defaults")
SECTION("Defaults")
{
if (!on_win)
{
set_env_map({ { "HOME", "/user/mamba" } });
CHECK_EQ(user_config_dir(), "/user/mamba/.config");
CHECK_EQ(user_data_dir(), "/user/mamba/.local/share");
CHECK_EQ(user_cache_dir(), "/user/mamba/.cache");
REQUIRE(user_config_dir() == "/user/mamba/.config");
REQUIRE(user_data_dir() == "/user/mamba/.local/share");
REQUIRE(user_cache_dir() == "/user/mamba/.cache");
}
}
}
TEST_CASE("which_in")
{
SUBCASE("Inexistent search dirs")
SECTION("Inexistent search dirs")
{
CHECK_EQ(which_in("echo", "/obviously/does/not/exist"), "");
REQUIRE(which_in("echo", "/obviously/does/not/exist") == "");
}
SUBCASE("testing_libmamba_lock")
SECTION("testing_libmamba_lock")
{
const auto test_exe = which_in(
"testing_libmamba_lock",
mambatests::testing_libmamba_lock_exe.parent_path()
);
CHECK_EQ(test_exe.stem(), "testing_libmamba_lock");
CHECK(mamba::fs::exists(test_exe));
REQUIRE(test_exe.stem() == "testing_libmamba_lock");
REQUIRE(mamba::fs::exists(test_exe));
}
SUBCASE("testing_libmamba_lock.exe")
SECTION("testing_libmamba_lock.exe")
{
if (on_win)
{
@ -218,19 +218,19 @@ TEST_SUITE("util::environment")
"testing_libmamba_lock.exe",
mambatests::testing_libmamba_lock_exe.parent_path()
);
CHECK_EQ(test_exe.stem(), "testing_libmamba_lock");
CHECK(mamba::fs::exists(test_exe));
REQUIRE(test_exe.stem() == "testing_libmamba_lock");
REQUIRE(mamba::fs::exists(test_exe));
}
}
}
TEST_CASE("which")
{
SUBCASE("echo")
SECTION("echo")
{
const auto echo = which("echo");
CHECK_EQ(echo.stem(), "echo");
CHECK(mamba::fs::exists(echo));
REQUIRE(echo.stem() == "echo");
REQUIRE(mamba::fs::exists(echo));
if (!on_win)
{
@ -241,23 +241,23 @@ TEST_SUITE("util::environment")
"/usr/bin",
"/usr/sbin",
};
CHECK(starts_with_any(echo.string(), reasonable_locations));
REQUIRE(starts_with_any(echo.string(), reasonable_locations));
}
}
SUBCASE("echo.exe")
SECTION("echo.exe")
{
if (on_win)
{
const auto echo = which("echo.exe");
CHECK_EQ(echo.stem(), "echo");
CHECK(mamba::fs::exists(echo));
REQUIRE(echo.stem() == "echo");
REQUIRE(mamba::fs::exists(echo));
}
}
SUBCASE("Inexistent path")
SECTION("Inexistent path")
{
CHECK_EQ(which("obviously-does-not-exist"), "");
REQUIRE(which("obviously-does-not-exist") == "");
}
}
}

View File

@ -10,64 +10,62 @@
#include <string>
#include <vector>
#include <doctest/doctest.h>
#include <catch2/catch_all.hpp>
#include "mamba/util/flat_bool_expr_tree.hpp"
#include "doctest-printer/array.hpp"
using namespace mamba::util;
TEST_SUITE("util::flat_bool_expr_tree")
namespace
{
TEST_CASE("flat_binary_tree")
{
auto tree = flat_binary_tree<std::string, int>{};
CHECK(tree.empty());
CHECK_EQ(tree.size(), 0);
REQUIRE(tree.empty());
REQUIRE(tree.size() == 0);
SUBCASE("Add nodes")
SECTION("Add nodes")
{
const auto l1 = tree.add_leaf(1);
CHECK(tree.is_leaf(l1));
CHECK_FALSE(tree.is_branch(l1));
CHECK_EQ(tree.leaf(l1), 1);
CHECK_EQ(tree.root(), l1);
REQUIRE(tree.is_leaf(l1));
REQUIRE_FALSE(tree.is_branch(l1));
REQUIRE(tree.leaf(l1) == 1);
REQUIRE(tree.root() == l1);
const auto l2 = tree.add_leaf(2);
CHECK(tree.is_leaf(l2));
CHECK_FALSE(tree.is_branch(l2));
CHECK_EQ(tree.leaf(l2), 2);
REQUIRE(tree.is_leaf(l2));
REQUIRE_FALSE(tree.is_branch(l2));
REQUIRE(tree.leaf(l2) == 2);
const auto pa = tree.add_branch("a", l1, l2);
CHECK_FALSE(tree.is_leaf(pa));
CHECK(tree.is_branch(pa));
CHECK_EQ(tree.branch(pa), "a");
CHECK_EQ(tree.left(pa), l1);
CHECK_EQ(tree.right(pa), l2);
CHECK_EQ(tree.root(), pa);
REQUIRE_FALSE(tree.is_leaf(pa));
REQUIRE(tree.is_branch(pa));
REQUIRE(tree.branch(pa) == "a");
REQUIRE(tree.left(pa) == l1);
REQUIRE(tree.right(pa) == l2);
REQUIRE(tree.root() == pa);
const auto l3 = tree.add_leaf(3);
CHECK(tree.is_leaf(l3));
CHECK_FALSE(tree.is_branch(l3));
CHECK_EQ(tree.leaf(l2), 2);
REQUIRE(tree.is_leaf(l3));
REQUIRE_FALSE(tree.is_branch(l3));
REQUIRE(tree.leaf(l2) == 2);
const auto pb = tree.add_branch("b", pa, l3);
CHECK_FALSE(tree.is_leaf(pb));
CHECK(tree.is_branch(pb));
CHECK_EQ(tree.branch(pb), "b");
CHECK_EQ(tree.left(pb), pa);
CHECK_EQ(tree.right(pb), l3);
CHECK_EQ(tree.root(), pb);
REQUIRE_FALSE(tree.is_leaf(pb));
REQUIRE(tree.is_branch(pb));
REQUIRE(tree.branch(pb) == "b");
REQUIRE(tree.left(pb) == pa);
REQUIRE(tree.right(pb) == l3);
REQUIRE(tree.root() == pb);
CHECK_FALSE(tree.empty());
CHECK_EQ(tree.size(), 5);
REQUIRE_FALSE(tree.empty());
REQUIRE(tree.size() == 5);
SUBCASE("Clear nodes")
SECTION("Clear nodes")
{
tree.clear();
CHECK(tree.empty());
CHECK_EQ(tree.size(), 0);
REQUIRE(tree.empty());
REQUIRE(tree.size() == 0);
}
}
}
@ -107,73 +105,73 @@ TEST_SUITE("util::flat_bool_expr_tree")
{
auto parser = PostfixParser<char, std::string>{};
SUBCASE("empty")
SECTION("empty")
{
CHECK(parser.finalize());
REQUIRE(parser.finalize());
const auto& tree = parser.tree();
CHECK(tree.empty());
REQUIRE(tree.empty());
}
SUBCASE("a")
SECTION("a")
{
CHECK(parser.push_variable('a'));
CHECK(parser.finalize());
REQUIRE(parser.push_variable('a'));
REQUIRE(parser.finalize());
const auto& tree = parser.tree();
CHECK_EQ(tree.size(), 1);
REQUIRE(tree.size() == 1);
REQUIRE(tree.is_leaf(0));
CHECK_EQ(tree.leaf(0), 'a');
CHECK_EQ(tree.root(), 0);
REQUIRE(tree.leaf(0) == 'a');
REQUIRE(tree.root() == 0);
}
SUBCASE("a b + c d e + * *")
SECTION("a b + c d e + * *")
{
// Infix: (a + b) * (c * (d + e))
CHECK(parser.push_variable('a'));
CHECK(parser.push_variable('b'));
CHECK(parser.push_operator("+"));
CHECK(parser.push_variable('c'));
CHECK(parser.push_variable('d'));
CHECK(parser.push_variable('e'));
CHECK(parser.push_operator("+"));
CHECK(parser.push_operator("*"));
CHECK(parser.push_operator("*"));
CHECK(parser.finalize());
REQUIRE(parser.push_variable('a'));
REQUIRE(parser.push_variable('b'));
REQUIRE(parser.push_operator("+"));
REQUIRE(parser.push_variable('c'));
REQUIRE(parser.push_variable('d'));
REQUIRE(parser.push_variable('e'));
REQUIRE(parser.push_operator("+"));
REQUIRE(parser.push_operator("*"));
REQUIRE(parser.push_operator("*"));
REQUIRE(parser.finalize());
const auto& tree = parser.tree();
CHECK_EQ(tree.size(), 9);
REQUIRE(tree.size() == 9);
const auto visited = visit_all_once_no_cycle(tree);
CHECK_EQ(visited.size(), tree.size());
REQUIRE(visited.size() == tree.size());
}
SUBCASE("a b")
SECTION("a b")
{
CHECK(parser.push_variable('a'));
CHECK(parser.push_variable('b'));
CHECK_FALSE(parser.finalize());
REQUIRE(parser.push_variable('a'));
REQUIRE(parser.push_variable('b'));
REQUIRE_FALSE(parser.finalize());
}
SUBCASE("+")
SECTION("+")
{
CHECK_FALSE(parser.push_operator("+"));
REQUIRE_FALSE(parser.push_operator("+"));
}
SUBCASE("a b + *")
SECTION("a b + *")
{
CHECK(parser.push_variable('a'));
CHECK(parser.push_variable('b'));
CHECK(parser.push_operator("+"));
CHECK_FALSE(parser.push_operator("*"));
REQUIRE(parser.push_variable('a'));
REQUIRE(parser.push_variable('b'));
REQUIRE(parser.push_operator("+"));
REQUIRE_FALSE(parser.push_operator("*"));
}
SUBCASE("a b + c")
SECTION("a b + c")
{
CHECK(parser.push_variable('a'));
CHECK(parser.push_variable('b'));
CHECK(parser.push_operator("+"));
CHECK(parser.push_variable('c'));
CHECK_FALSE(parser.finalize());
REQUIRE(parser.push_variable('a'));
REQUIRE(parser.push_variable('b'));
REQUIRE(parser.push_operator("+"));
REQUIRE(parser.push_variable('c'));
REQUIRE_FALSE(parser.finalize());
}
}
@ -181,149 +179,149 @@ TEST_SUITE("util::flat_bool_expr_tree")
{
auto parser = InfixParser<char, std::string>{};
SUBCASE("empty")
SECTION("empty")
{
CHECK(parser.finalize());
REQUIRE(parser.finalize());
const auto& tree = parser.tree();
CHECK(tree.empty());
REQUIRE(tree.empty());
}
SUBCASE("(((a)))")
SECTION("(((a)))")
{
CHECK(parser.push_left_parenthesis());
CHECK(parser.push_left_parenthesis());
CHECK(parser.push_left_parenthesis());
CHECK(parser.push_variable('a'));
CHECK(parser.push_right_parenthesis());
CHECK(parser.push_right_parenthesis());
CHECK(parser.push_right_parenthesis());
CHECK(parser.finalize());
REQUIRE(parser.push_left_parenthesis());
REQUIRE(parser.push_left_parenthesis());
REQUIRE(parser.push_left_parenthesis());
REQUIRE(parser.push_variable('a'));
REQUIRE(parser.push_right_parenthesis());
REQUIRE(parser.push_right_parenthesis());
REQUIRE(parser.push_right_parenthesis());
REQUIRE(parser.finalize());
const auto& tree = parser.tree();
REQUIRE_EQ(tree.size(), 1);
REQUIRE(tree.size() == 1);
REQUIRE(tree.is_leaf(0));
CHECK_EQ(tree.root(), 0);
CHECK_EQ(tree.leaf(0), 'a');
REQUIRE(tree.root() == 0);
REQUIRE(tree.leaf(0) == 'a');
}
SUBCASE("(((a)) + b)")
SECTION("(((a)) + b)")
{
CHECK(parser.push_left_parenthesis());
CHECK(parser.push_left_parenthesis());
CHECK(parser.push_left_parenthesis());
CHECK(parser.push_variable('a'));
CHECK(parser.push_right_parenthesis());
CHECK(parser.push_right_parenthesis());
CHECK(parser.push_operator("+"));
CHECK(parser.push_variable('b'));
CHECK(parser.push_right_parenthesis());
CHECK(parser.finalize());
REQUIRE(parser.push_left_parenthesis());
REQUIRE(parser.push_left_parenthesis());
REQUIRE(parser.push_left_parenthesis());
REQUIRE(parser.push_variable('a'));
REQUIRE(parser.push_right_parenthesis());
REQUIRE(parser.push_right_parenthesis());
REQUIRE(parser.push_operator("+"));
REQUIRE(parser.push_variable('b'));
REQUIRE(parser.push_right_parenthesis());
REQUIRE(parser.finalize());
const auto& tree = parser.tree();
REQUIRE_EQ(tree.size(), 3);
REQUIRE(tree.size() == 3);
const auto root = tree.root();
REQUIRE(tree.is_branch(root));
CHECK_EQ(tree.branch(root), "+");
REQUIRE(tree.branch(root) == "+");
REQUIRE(tree.is_leaf(tree.left(root)));
CHECK_EQ(tree.leaf(tree.left(root)), 'a');
REQUIRE(tree.leaf(tree.left(root)) == 'a');
REQUIRE(tree.is_leaf(tree.right(root)));
CHECK_EQ(tree.leaf(tree.right(root)), 'b');
REQUIRE(tree.leaf(tree.right(root)) == 'b');
}
SUBCASE("(a + b) * (c * (d + e))")
SECTION("(a + b) * (c * (d + e))")
{
CHECK(parser.push_left_parenthesis());
CHECK(parser.push_variable('a'));
CHECK(parser.push_operator("+"));
CHECK(parser.push_variable('b'));
CHECK(parser.push_right_parenthesis());
CHECK(parser.push_operator("*"));
CHECK(parser.push_left_parenthesis());
CHECK(parser.push_variable('c'));
CHECK(parser.push_operator("*"));
CHECK(parser.push_left_parenthesis());
CHECK(parser.push_variable('d'));
CHECK(parser.push_operator("+"));
CHECK(parser.push_variable('e'));
CHECK(parser.push_right_parenthesis());
CHECK(parser.push_right_parenthesis());
CHECK(parser.finalize());
REQUIRE(parser.push_left_parenthesis());
REQUIRE(parser.push_variable('a'));
REQUIRE(parser.push_operator("+"));
REQUIRE(parser.push_variable('b'));
REQUIRE(parser.push_right_parenthesis());
REQUIRE(parser.push_operator("*"));
REQUIRE(parser.push_left_parenthesis());
REQUIRE(parser.push_variable('c'));
REQUIRE(parser.push_operator("*"));
REQUIRE(parser.push_left_parenthesis());
REQUIRE(parser.push_variable('d'));
REQUIRE(parser.push_operator("+"));
REQUIRE(parser.push_variable('e'));
REQUIRE(parser.push_right_parenthesis());
REQUIRE(parser.push_right_parenthesis());
REQUIRE(parser.finalize());
const auto& tree = parser.tree();
CHECK_EQ(tree.size(), 9);
REQUIRE(tree.size() == 9);
const auto visited = visit_all_once_no_cycle(tree);
CHECK_EQ(visited.size(), tree.size());
REQUIRE(visited.size() == tree.size());
}
SUBCASE("(")
SECTION("(")
{
CHECK(parser.push_left_parenthesis());
CHECK_FALSE(parser.finalize());
REQUIRE(parser.push_left_parenthesis());
REQUIRE_FALSE(parser.finalize());
}
SUBCASE(")")
SECTION(")")
{
CHECK_FALSE(parser.push_right_parenthesis());
REQUIRE_FALSE(parser.push_right_parenthesis());
}
SUBCASE("(a+b")
SECTION("(a+b")
{
CHECK(parser.push_left_parenthesis());
CHECK(parser.push_variable('a'));
CHECK(parser.push_operator("+"));
CHECK(parser.push_variable('b'));
CHECK_FALSE(parser.finalize());
REQUIRE(parser.push_left_parenthesis());
REQUIRE(parser.push_variable('a'));
REQUIRE(parser.push_operator("+"));
REQUIRE(parser.push_variable('b'));
REQUIRE_FALSE(parser.finalize());
}
SUBCASE("a)")
SECTION("a)")
{
CHECK(parser.push_variable('a'));
CHECK_FALSE(parser.push_right_parenthesis());
REQUIRE(parser.push_variable('a'));
REQUIRE_FALSE(parser.push_right_parenthesis());
}
SUBCASE("+")
SECTION("+")
{
CHECK_FALSE(parser.push_operator("+"));
REQUIRE_FALSE(parser.push_operator("+"));
}
SUBCASE("a b +")
SECTION("a b +")
{
CHECK(parser.push_variable('a'));
CHECK_FALSE(parser.push_variable('b'));
REQUIRE(parser.push_variable('a'));
REQUIRE_FALSE(parser.push_variable('b'));
}
SUBCASE("a + + b")
SECTION("a + + b")
{
CHECK(parser.push_variable('a'));
CHECK(parser.push_operator("+"));
CHECK_FALSE(parser.push_operator("+"));
REQUIRE(parser.push_variable('a'));
REQUIRE(parser.push_operator("+"));
REQUIRE_FALSE(parser.push_operator("+"));
}
SUBCASE("a +")
SECTION("a +")
{
CHECK(parser.push_variable('a'));
CHECK(parser.push_operator("+"));
CHECK_FALSE(parser.finalize());
REQUIRE(parser.push_variable('a'));
REQUIRE(parser.push_operator("+"));
REQUIRE_FALSE(parser.finalize());
}
SUBCASE("a + )")
SECTION("a + )")
{
CHECK(parser.push_variable('a'));
CHECK(parser.push_operator("+"));
CHECK_FALSE(parser.push_right_parenthesis());
REQUIRE(parser.push_variable('a'));
REQUIRE(parser.push_operator("+"));
REQUIRE_FALSE(parser.push_right_parenthesis());
}
SUBCASE("(((a)) + b (* c")
SECTION("(((a)) + b (* c")
{
CHECK(parser.push_left_parenthesis());
CHECK(parser.push_left_parenthesis());
CHECK(parser.push_left_parenthesis());
CHECK(parser.push_variable('a'));
CHECK(parser.push_right_parenthesis());
CHECK(parser.push_right_parenthesis());
CHECK(parser.push_operator("+"));
CHECK(parser.push_variable('b'));
CHECK_FALSE(parser.push_left_parenthesis());
REQUIRE(parser.push_left_parenthesis());
REQUIRE(parser.push_left_parenthesis());
REQUIRE(parser.push_left_parenthesis());
REQUIRE(parser.push_variable('a'));
REQUIRE(parser.push_right_parenthesis());
REQUIRE(parser.push_right_parenthesis());
REQUIRE(parser.push_operator("+"));
REQUIRE(parser.push_variable('b'));
REQUIRE_FALSE(parser.push_left_parenthesis());
}
}
@ -332,30 +330,30 @@ TEST_SUITE("util::flat_bool_expr_tree")
// Infix: (false and false) or (false or (false or true))
// Postfix: false true or false or false false and or
auto parser = PostfixParser<bool, BoolOperator>{};
CHECK(parser.push_variable(false));
CHECK(parser.push_variable(true));
CHECK(parser.push_operator(BoolOperator::logical_or));
CHECK(parser.push_variable(false));
CHECK(parser.push_operator(BoolOperator::logical_or));
CHECK(parser.push_variable(false));
CHECK(parser.push_variable(false));
CHECK(parser.push_operator(BoolOperator::logical_and));
CHECK(parser.push_operator(BoolOperator::logical_or));
REQUIRE(parser.push_variable(false));
REQUIRE(parser.push_variable(true));
REQUIRE(parser.push_operator(BoolOperator::logical_or));
REQUIRE(parser.push_variable(false));
REQUIRE(parser.push_operator(BoolOperator::logical_or));
REQUIRE(parser.push_variable(false));
REQUIRE(parser.push_variable(false));
REQUIRE(parser.push_operator(BoolOperator::logical_and));
REQUIRE(parser.push_operator(BoolOperator::logical_or));
auto tree = flat_bool_expr_tree(std::move(parser).tree());
SUBCASE("Empty")
SECTION("Empty")
{
tree.clear();
CHECK(tree.evaluate());
CHECK_FALSE(tree.evaluate({}, false));
CHECK(tree.evaluate([](auto b) { return !b; }));
CHECK_FALSE(tree.evaluate([](auto b) { return !b; }, false));
REQUIRE(tree.evaluate());
REQUIRE_FALSE(tree.evaluate({}, false));
REQUIRE(tree.evaluate([](auto b) { return !b; }));
REQUIRE_FALSE(tree.evaluate([](auto b) { return !b; }, false));
}
SUBCASE("Evaluate tree")
SECTION("Evaluate tree")
{
CHECK(tree.evaluate());
CHECK(tree.evaluate([](auto b) { return !b; }));
REQUIRE(tree.evaluate());
REQUIRE(tree.evaluate([](auto b) { return !b; }));
}
}
@ -381,11 +379,10 @@ TEST_SUITE("util::flat_bool_expr_tree")
TEST_CASE("Test exponential boolean cross-product")
{
CHECK_EQ(integer_to_bools<5>(0b00000), std::array{ false, false, false, false, false });
CHECK_EQ(integer_to_bools<4>(0b1111), std::array{ true, true, true, true });
CHECK_EQ(
integer_to_bools<7>(0b1001101),
std::array{ true, false, true, true, false, false, true }
REQUIRE(integer_to_bools<5>(0b00000) == std::array{ false, false, false, false, false });
REQUIRE(integer_to_bools<4>(0b1111) == std::array{ true, true, true, true });
REQUIRE(
integer_to_bools<7>(0b1001101) == std::array{ true, false, true, true, false, false, true }
);
}
@ -396,15 +393,15 @@ TEST_SUITE("util::flat_bool_expr_tree")
// Infix: ((x3 or x4) and x2) and (x0 or x1)
// Postfix: x0 x1 or x2 x3 x4 or and and
auto parser = PostfixParser<std::size_t, BoolOperator>{};
CHECK(parser.push_variable(0));
CHECK(parser.push_variable(1));
CHECK(parser.push_operator(BoolOperator::logical_or));
CHECK(parser.push_variable(2));
CHECK(parser.push_variable(3));
CHECK(parser.push_variable(4));
CHECK(parser.push_operator(BoolOperator::logical_or));
CHECK(parser.push_operator(BoolOperator::logical_and));
CHECK(parser.push_operator(BoolOperator::logical_and));
REQUIRE(parser.push_variable(0));
REQUIRE(parser.push_variable(1));
REQUIRE(parser.push_operator(BoolOperator::logical_or));
REQUIRE(parser.push_variable(2));
REQUIRE(parser.push_variable(3));
REQUIRE(parser.push_variable(4));
REQUIRE(parser.push_operator(BoolOperator::logical_or));
REQUIRE(parser.push_operator(BoolOperator::logical_and));
REQUIRE(parser.push_operator(BoolOperator::logical_and));
auto tree = flat_bool_expr_tree(std::move(parser).tree());
static constexpr std::size_t n_vars = 5;
@ -412,7 +409,7 @@ TEST_SUITE("util::flat_bool_expr_tree")
{
const auto values = integer_to_bools<n_vars>(x);
const auto eval = [&values](std::size_t idx) { return values[idx]; };
CHECK_EQ(tree.evaluate(eval), reference_eval(values));
REQUIRE(tree.evaluate(eval) == reference_eval(values));
}
}
@ -422,26 +419,26 @@ TEST_SUITE("util::flat_bool_expr_tree")
{ return ((x[0] || x[1]) && (x[2] || x[3] || x[4]) && x[5]) || x[6]; };
auto parser = InfixParser<std::size_t, BoolOperator>{};
// Infix: ((x0 or x1) and (x2 or x3 or x4) and x5) or x6
CHECK(parser.push_left_parenthesis());
CHECK(parser.push_left_parenthesis());
CHECK(parser.push_variable(0));
CHECK(parser.push_operator(BoolOperator::logical_or));
CHECK(parser.push_variable(1));
CHECK(parser.push_right_parenthesis());
CHECK(parser.push_operator(BoolOperator::logical_and));
CHECK(parser.push_left_parenthesis());
CHECK(parser.push_variable(2));
CHECK(parser.push_operator(BoolOperator::logical_or));
CHECK(parser.push_variable(3));
CHECK(parser.push_operator(BoolOperator::logical_or));
CHECK(parser.push_variable(4));
CHECK(parser.push_right_parenthesis());
CHECK(parser.push_operator(BoolOperator::logical_and));
CHECK(parser.push_variable(5));
CHECK(parser.push_right_parenthesis());
CHECK(parser.push_operator(BoolOperator::logical_or));
CHECK(parser.push_variable(6));
CHECK(parser.finalize());
REQUIRE(parser.push_left_parenthesis());
REQUIRE(parser.push_left_parenthesis());
REQUIRE(parser.push_variable(0));
REQUIRE(parser.push_operator(BoolOperator::logical_or));
REQUIRE(parser.push_variable(1));
REQUIRE(parser.push_right_parenthesis());
REQUIRE(parser.push_operator(BoolOperator::logical_and));
REQUIRE(parser.push_left_parenthesis());
REQUIRE(parser.push_variable(2));
REQUIRE(parser.push_operator(BoolOperator::logical_or));
REQUIRE(parser.push_variable(3));
REQUIRE(parser.push_operator(BoolOperator::logical_or));
REQUIRE(parser.push_variable(4));
REQUIRE(parser.push_right_parenthesis());
REQUIRE(parser.push_operator(BoolOperator::logical_and));
REQUIRE(parser.push_variable(5));
REQUIRE(parser.push_right_parenthesis());
REQUIRE(parser.push_operator(BoolOperator::logical_or));
REQUIRE(parser.push_variable(6));
REQUIRE(parser.finalize());
auto tree = flat_bool_expr_tree(std::move(parser).tree());
static constexpr std::size_t n_vars = 7;
@ -450,7 +447,7 @@ TEST_SUITE("util::flat_bool_expr_tree")
const auto values = integer_to_bools<n_vars>(x);
CAPTURE(values);
const auto eval = [&values](std::size_t idx) { return values[idx]; };
CHECK_EQ(tree.evaluate(eval), reference_eval(values));
REQUIRE(tree.evaluate(eval) == reference_eval(values));
}
}
@ -458,26 +455,26 @@ TEST_SUITE("util::flat_bool_expr_tree")
{
auto parser = InfixParser<std::size_t, BoolOperator>{};
// Infix: ((x0 or x1) and (x2 or x3 or x4) and x5) or x6
CHECK(parser.push_left_parenthesis());
CHECK(parser.push_left_parenthesis());
CHECK(parser.push_variable(0));
CHECK(parser.push_operator(BoolOperator::logical_or));
CHECK(parser.push_variable(1));
CHECK(parser.push_right_parenthesis());
CHECK(parser.push_operator(BoolOperator::logical_and));
CHECK(parser.push_left_parenthesis());
CHECK(parser.push_variable(2));
CHECK(parser.push_operator(BoolOperator::logical_or));
CHECK(parser.push_variable(3));
CHECK(parser.push_operator(BoolOperator::logical_or));
CHECK(parser.push_variable(4));
CHECK(parser.push_right_parenthesis());
CHECK(parser.push_operator(BoolOperator::logical_and));
CHECK(parser.push_variable(5));
CHECK(parser.push_right_parenthesis());
CHECK(parser.push_operator(BoolOperator::logical_or));
CHECK(parser.push_variable(6));
CHECK(parser.finalize());
REQUIRE(parser.push_left_parenthesis());
REQUIRE(parser.push_left_parenthesis());
REQUIRE(parser.push_variable(0));
REQUIRE(parser.push_operator(BoolOperator::logical_or));
REQUIRE(parser.push_variable(1));
REQUIRE(parser.push_right_parenthesis());
REQUIRE(parser.push_operator(BoolOperator::logical_and));
REQUIRE(parser.push_left_parenthesis());
REQUIRE(parser.push_variable(2));
REQUIRE(parser.push_operator(BoolOperator::logical_or));
REQUIRE(parser.push_variable(3));
REQUIRE(parser.push_operator(BoolOperator::logical_or));
REQUIRE(parser.push_variable(4));
REQUIRE(parser.push_right_parenthesis());
REQUIRE(parser.push_operator(BoolOperator::logical_and));
REQUIRE(parser.push_variable(5));
REQUIRE(parser.push_right_parenthesis());
REQUIRE(parser.push_operator(BoolOperator::logical_or));
REQUIRE(parser.push_variable(6));
REQUIRE(parser.finalize());
auto tree = flat_bool_expr_tree(std::move(parser).tree());
auto result = std::string();
@ -506,6 +503,6 @@ TEST_SUITE("util::flat_bool_expr_tree")
}
);
// There could be many representations, here is one
CHECK_EQ(result, "((x0 or x1) and ((x2 or (x3 or x4)) and x5)) or x6");
REQUIRE(result == "((x0 or x1) and ((x2 or (x3 or x4)) and x5)) or x6");
}
}

View File

@ -8,60 +8,58 @@
#include <type_traits>
#include <vector>
#include <doctest/doctest.h>
#include <catch2/catch_all.hpp>
#include "mamba/util/flat_set.hpp"
#include "doctest-printer/flat_set.hpp"
using namespace mamba::util;
TEST_SUITE("util::flat_set")
namespace
{
TEST_CASE("constructor")
{
const auto s1 = flat_set<int>();
CHECK_EQ(s1.size(), 0);
REQUIRE(s1.size() == 0);
auto s2 = flat_set<int>({ 1, 2 });
CHECK_EQ(s2.size(), 2);
REQUIRE(s2.size() == 2);
const auto s3 = flat_set<int>{ s2 };
CHECK_EQ(s3.size(), 2);
REQUIRE(s3.size() == 2);
const auto s4 = flat_set<int>{ std::move(s2) };
CHECK_EQ(s4.size(), 2);
REQUIRE(s4.size() == 2);
// CTAD
auto s5 = flat_set({ 1, 2 });
CHECK_EQ(s5.size(), 2);
REQUIRE(s5.size() == 2);
static_assert(std::is_same_v<decltype(s5)::value_type, int>);
auto s6 = flat_set(s5.begin(), s5.end(), std::greater{});
CHECK_EQ(s6.size(), s5.size());
REQUIRE(s6.size() == s5.size());
static_assert(std::is_same_v<decltype(s6)::value_type, decltype(s5)::value_type>);
}
TEST_CASE("equality")
{
CHECK_EQ(flat_set<int>(), flat_set<int>());
CHECK_EQ(flat_set<int>({ 1, 2 }), flat_set<int>({ 1, 2 }));
CHECK_EQ(flat_set<int>({ 1, 2 }), flat_set<int>({ 2, 1 }));
CHECK_EQ(flat_set<int>({ 1, 2, 1 }), flat_set<int>({ 2, 2, 1 }));
CHECK_NE(flat_set<int>({ 1, 2 }), flat_set<int>({ 1, 2, 3 }));
CHECK_NE(flat_set<int>({ 2 }), flat_set<int>({}));
REQUIRE(flat_set<int>() == flat_set<int>());
REQUIRE(flat_set<int>({ 1, 2 }) == flat_set<int>({ 1, 2 }));
REQUIRE(flat_set<int>({ 1, 2 }) == flat_set<int>({ 2, 1 }));
REQUIRE(flat_set<int>({ 1, 2, 1 }) == flat_set<int>({ 2, 2, 1 }));
REQUIRE(flat_set<int>({ 1, 2 }) != flat_set<int>({ 1, 2, 3 }));
REQUIRE(flat_set<int>({ 2 }) != flat_set<int>({}));
}
TEST_CASE("insert")
{
auto s = flat_set<int>();
s.insert(33);
CHECK_EQ(s, flat_set<int>({ 33 }));
REQUIRE(s == flat_set<int>({ 33 }));
s.insert(33);
s.insert(17);
CHECK_EQ(s, flat_set<int>({ 17, 33 }));
REQUIRE(s == flat_set<int>({ 17, 33 }));
s.insert(22);
CHECK_EQ(s, flat_set<int>({ 17, 22, 33 }));
REQUIRE(s == flat_set<int>({ 17, 22, 33 }));
s.insert(33);
CHECK_EQ(s, flat_set<int>({ 17, 22, 33 }));
REQUIRE(s == flat_set<int>({ 17, 22, 33 }));
auto v = std::vector<int>({ 33, 22, 17, 0 });
s.insert(v.begin(), v.end());
CHECK_EQ(s, flat_set<int>({ 0, 17, 22, 33 }));
REQUIRE(s == flat_set<int>({ 0, 17, 22, 33 }));
}
TEST_CASE("insert conversion")
@ -69,43 +67,43 @@ TEST_SUITE("util::flat_set")
auto s = flat_set<std::string>();
const auto v = std::array<std::string_view, 2>{ "hello", "world" };
s.insert(v.cbegin(), v.cend());
REQUIRE_EQ(s.size(), 2);
CHECK_EQ(s.at(0), "hello");
CHECK_EQ(s.at(1), "world");
REQUIRE(s.size() == 2);
REQUIRE(s.at(0) == "hello");
REQUIRE(s.at(1) == "world");
}
TEST_CASE("erase")
{
auto s = flat_set<int>{ 4, 3, 2, 1 };
CHECK_EQ(s.erase(4), 1);
CHECK_EQ(s, flat_set<int>({ 1, 2, 3 }));
CHECK_EQ(s.erase(4), 0);
CHECK_EQ(s, flat_set<int>({ 1, 2, 3 }));
REQUIRE(s.erase(4) == 1);
REQUIRE(s == flat_set<int>({ 1, 2, 3 }));
REQUIRE(s.erase(4) == 0);
REQUIRE(s == flat_set<int>({ 1, 2, 3 }));
const auto it = s.erase(s.begin());
CHECK_EQ(it, s.begin());
CHECK_EQ(s, flat_set<int>({ 2, 3 }));
REQUIRE(it == s.begin());
REQUIRE(s == flat_set<int>({ 2, 3 }));
}
TEST_CASE("contains")
TEST_CASE("set_contains")
{
const auto s = flat_set<int>({ 1, 3, 4, 5 });
CHECK_FALSE(s.contains(0));
CHECK(s.contains(1));
CHECK_FALSE(s.contains(2));
CHECK(s.contains(3));
CHECK(s.contains(4));
CHECK(s.contains(5));
CHECK_FALSE(s.contains(6));
REQUIRE_FALSE(s.contains(0));
REQUIRE(s.contains(1));
REQUIRE_FALSE(s.contains(2));
REQUIRE(s.contains(3));
REQUIRE(s.contains(4));
REQUIRE(s.contains(5));
REQUIRE_FALSE(s.contains(6));
}
TEST_CASE("key_compare")
{
auto s = flat_set({ 1, 3, 4, 5 }, std::greater{});
CHECK_EQ(s.front(), 5);
CHECK_EQ(s.back(), 1);
REQUIRE(s.front() == 5);
REQUIRE(s.back() == 1);
s.insert(6);
CHECK_EQ(s.front(), 6);
REQUIRE(s.front() == 6);
}
TEST_CASE("Set operations")
@ -114,108 +112,108 @@ TEST_SUITE("util::flat_set")
const auto s2 = flat_set<int>({ 3, 5 });
const auto s3 = flat_set<int>({ 4, 6 });
SUBCASE("Disjoint")
SECTION("Disjoint")
{
CHECK(set_is_disjoint_of(s1, flat_set<int>{}));
CHECK_FALSE(set_is_disjoint_of(s1, s1));
CHECK_FALSE(set_is_disjoint_of(s1, s2));
CHECK_FALSE(set_is_disjoint_of(s1, s3));
CHECK(set_is_disjoint_of(s2, s3));
CHECK(set_is_disjoint_of(s3, s2));
REQUIRE(set_is_disjoint_of(s1, flat_set<int>{}));
REQUIRE_FALSE(set_is_disjoint_of(s1, s1));
REQUIRE_FALSE(set_is_disjoint_of(s1, s2));
REQUIRE_FALSE(set_is_disjoint_of(s1, s3));
REQUIRE(set_is_disjoint_of(s2, s3));
REQUIRE(set_is_disjoint_of(s3, s2));
}
SUBCASE("Subset")
SECTION("Subset")
{
CHECK(set_is_subset_of(s1, s1));
CHECK_FALSE(set_is_strict_subset_of(s1, s1));
CHECK(set_is_subset_of(flat_set<int>{}, s1));
CHECK(set_is_strict_subset_of(flat_set<int>{}, s1));
CHECK_FALSE(set_is_subset_of(s1, s2));
CHECK_FALSE(set_is_subset_of(s1, flat_set<int>{}));
CHECK(set_is_subset_of(flat_set<int>{ 1, 4 }, s1));
CHECK(set_is_strict_subset_of(flat_set<int>{ 1, 4 }, s1));
CHECK(set_is_subset_of(s2, s1));
CHECK(set_is_strict_subset_of(s2, s1));
REQUIRE(set_is_subset_of(s1, s1));
REQUIRE_FALSE(set_is_strict_subset_of(s1, s1));
REQUIRE(set_is_subset_of(flat_set<int>{}, s1));
REQUIRE(set_is_strict_subset_of(flat_set<int>{}, s1));
REQUIRE_FALSE(set_is_subset_of(s1, s2));
REQUIRE_FALSE(set_is_subset_of(s1, flat_set<int>{}));
REQUIRE(set_is_subset_of(flat_set<int>{ 1, 4 }, s1));
REQUIRE(set_is_strict_subset_of(flat_set<int>{ 1, 4 }, s1));
REQUIRE(set_is_subset_of(s2, s1));
REQUIRE(set_is_strict_subset_of(s2, s1));
}
SUBCASE("Superset")
SECTION("Superset")
{
CHECK(set_is_superset_of(s1, s1));
CHECK_FALSE(set_is_strict_superset_of(s1, s1));
CHECK(set_is_superset_of(s1, flat_set<int>{}));
CHECK(set_is_strict_superset_of(s1, flat_set<int>{}));
CHECK_FALSE(set_is_superset_of(s2, s1));
CHECK_FALSE(set_is_superset_of(flat_set<int>{}, s1));
CHECK(set_is_superset_of(s1, flat_set<int>{ 1, 4 }));
CHECK(set_is_strict_superset_of(s1, flat_set<int>{ 1, 4 }));
CHECK(set_is_superset_of(s1, s2));
CHECK(set_is_strict_superset_of(s1, s2));
REQUIRE(set_is_superset_of(s1, s1));
REQUIRE_FALSE(set_is_strict_superset_of(s1, s1));
REQUIRE(set_is_superset_of(s1, flat_set<int>{}));
REQUIRE(set_is_strict_superset_of(s1, flat_set<int>{}));
REQUIRE_FALSE(set_is_superset_of(s2, s1));
REQUIRE_FALSE(set_is_superset_of(flat_set<int>{}, s1));
REQUIRE(set_is_superset_of(s1, flat_set<int>{ 1, 4 }));
REQUIRE(set_is_strict_superset_of(s1, flat_set<int>{ 1, 4 }));
REQUIRE(set_is_superset_of(s1, s2));
REQUIRE(set_is_strict_superset_of(s1, s2));
}
SUBCASE("Union")
SECTION("Union")
{
CHECK_EQ(set_union(s1, s1), s1);
CHECK_EQ(set_union(s1, s2), s1);
CHECK_EQ(set_union(s2, s1), set_union(s1, s2));
CHECK_EQ(set_union(s1, s3), flat_set<int>{ 1, 3, 4, 5, 6 });
CHECK_EQ(set_union(s3, s1), set_union(s1, s3));
CHECK_EQ(set_union(s2, s3), flat_set<int>{ 3, 4, 5, 6 });
CHECK_EQ(set_union(s3, s2), set_union(s2, s3));
REQUIRE(set_union(s1, s1) == s1);
REQUIRE(set_union(s1, s2) == s1);
REQUIRE(set_union(s2, s1) == set_union(s1, s2));
REQUIRE(set_union(s1, s3) == flat_set<int>{ 1, 3, 4, 5, 6 });
REQUIRE(set_union(s3, s1) == set_union(s1, s3));
REQUIRE(set_union(s2, s3) == flat_set<int>{ 3, 4, 5, 6 });
REQUIRE(set_union(s3, s2) == set_union(s2, s3));
}
SUBCASE("Intersection")
SECTION("Intersection")
{
CHECK_EQ(set_intersection(s1, s1), s1);
CHECK_EQ(set_intersection(s1, s2), s2);
CHECK_EQ(set_intersection(s2, s1), set_intersection(s1, s2));
CHECK_EQ(set_intersection(s1, s3), flat_set<int>{ 4 });
CHECK_EQ(set_intersection(s3, s1), set_intersection(s1, s3));
CHECK_EQ(set_intersection(s2, s3), flat_set<int>{});
CHECK_EQ(set_intersection(s3, s2), set_intersection(s2, s3));
REQUIRE(set_intersection(s1, s1) == s1);
REQUIRE(set_intersection(s1, s2) == s2);
REQUIRE(set_intersection(s2, s1) == set_intersection(s1, s2));
REQUIRE(set_intersection(s1, s3) == flat_set<int>{ 4 });
REQUIRE(set_intersection(s3, s1) == set_intersection(s1, s3));
REQUIRE(set_intersection(s2, s3) == flat_set<int>{});
REQUIRE(set_intersection(s3, s2) == set_intersection(s2, s3));
}
SUBCASE("Difference")
SECTION("Difference")
{
CHECK_EQ(set_difference(s1, s1), flat_set<int>{});
CHECK_EQ(set_difference(s1, s2), flat_set<int>{ 1, 4 });
CHECK_EQ(set_difference(s2, s1), flat_set<int>{});
CHECK_EQ(set_difference(s1, s3), flat_set<int>{ 1, 3, 5 });
CHECK_EQ(set_difference(s3, s1), flat_set<int>{ 6 });
CHECK_EQ(set_difference(s2, s3), s2);
CHECK_EQ(set_difference(s3, s2), s3);
REQUIRE(set_difference(s1, s1) == flat_set<int>{});
REQUIRE(set_difference(s1, s2) == flat_set<int>{ 1, 4 });
REQUIRE(set_difference(s2, s1) == flat_set<int>{});
REQUIRE(set_difference(s1, s3) == flat_set<int>{ 1, 3, 5 });
REQUIRE(set_difference(s3, s1) == flat_set<int>{ 6 });
REQUIRE(set_difference(s2, s3) == s2);
REQUIRE(set_difference(s3, s2) == s3);
}
SUBCASE("Symmetric difference")
SECTION("Symmetric difference")
{
CHECK_EQ(set_symmetric_difference(s1, s1), flat_set<int>{});
CHECK_EQ(set_symmetric_difference(s1, s2), flat_set<int>{ 1, 4 });
CHECK_EQ(set_symmetric_difference(s2, s1), set_symmetric_difference(s1, s2));
CHECK_EQ(set_symmetric_difference(s1, s3), flat_set<int>{ 1, 3, 5, 6 });
CHECK_EQ(set_symmetric_difference(s3, s1), set_symmetric_difference(s1, s3));
CHECK_EQ(set_symmetric_difference(s2, s3), flat_set<int>{ 3, 4, 5, 6 });
CHECK_EQ(set_symmetric_difference(s3, s2), set_symmetric_difference(s2, s3));
REQUIRE(set_symmetric_difference(s1, s1) == flat_set<int>{});
REQUIRE(set_symmetric_difference(s1, s2) == flat_set<int>{ 1, 4 });
REQUIRE(set_symmetric_difference(s2, s1) == set_symmetric_difference(s1, s2));
REQUIRE(set_symmetric_difference(s1, s3) == flat_set<int>{ 1, 3, 5, 6 });
REQUIRE(set_symmetric_difference(s3, s1) == set_symmetric_difference(s1, s3));
REQUIRE(set_symmetric_difference(s2, s3) == flat_set<int>{ 3, 4, 5, 6 });
REQUIRE(set_symmetric_difference(s3, s2) == set_symmetric_difference(s2, s3));
}
SUBCASE("Algebra")
SECTION("Algebra")
{
for (const auto& u : { s1, s2, s3 })
{
for (const auto& v : { s1, s2, s3 })
{
CHECK_EQ(
REQUIRE(
set_union(
set_difference(u, v),
set_union(set_difference(v, u), set_intersection(u, v))
),
set_union(u, v)
)
== set_union(u, v)
);
CHECK_EQ(
set_union(set_symmetric_difference(u, v), set_intersection(u, v)),
set_union(u, v)
REQUIRE(
set_union(set_symmetric_difference(u, v), set_intersection(u, v))
== set_union(u, v)
);
CHECK_EQ(
set_difference(set_union(u, v), set_intersection(u, v)),
set_symmetric_difference(u, v)
REQUIRE(
set_difference(set_union(u, v), set_intersection(u, v))
== set_symmetric_difference(u, v)
);
}
}

View File

@ -9,7 +9,7 @@
#include <string>
#include <vector>
#include <doctest/doctest.h>
#include <catch2/catch_all.hpp>
#include "mamba/util/graph.hpp"
@ -132,29 +132,29 @@ private:
node_id_list m_finish_nodes;
};
TEST_SUITE("util::graph")
namespace
{
TEST_CASE("build_simple")
{
const auto g = build_graph();
using node_map = decltype(g)::node_map;
using node_id_list = decltype(g)::node_id_list;
CHECK_EQ(g.number_of_nodes(), 7ul);
CHECK_EQ(g.number_of_edges(), 7ul);
CHECK_EQ(
g.nodes(),
node_map(
REQUIRE(g.number_of_nodes() == 7ul);
REQUIRE(g.number_of_edges() == 7ul);
REQUIRE(
g.nodes()
== node_map(
{ { 0, 0.5 }, { 1, 1.5 }, { 2, 2.5 }, { 3, 3.5 }, { 4, 4.5 }, { 5, 5.5 }, { 6, 6.5 } }
)
);
CHECK_EQ(g.successors(0u), node_id_list({ 1u, 2u }));
CHECK_EQ(g.successors(1u), node_id_list({ 3u, 4u }));
CHECK_EQ(g.successors(2u), node_id_list({ 3u, 5u }));
CHECK_EQ(g.successors(3u), node_id_list({ 6u }));
CHECK_EQ(g.predecessors(0u), node_id_list());
CHECK_EQ(g.predecessors(1u), node_id_list({ 0u }));
CHECK_EQ(g.predecessors(2u), node_id_list({ 0u }));
CHECK_EQ(g.predecessors(3u), node_id_list({ 1u, 2u }));
REQUIRE(g.successors(0u) == node_id_list({ 1u, 2u }));
REQUIRE(g.successors(1u) == node_id_list({ 3u, 4u }));
REQUIRE(g.successors(2u) == node_id_list({ 3u, 5u }));
REQUIRE(g.successors(3u) == node_id_list({ 6u }));
REQUIRE(g.predecessors(0u) == node_id_list());
REQUIRE(g.predecessors(1u) == node_id_list({ 0u }));
REQUIRE(g.predecessors(2u) == node_id_list({ 0u }));
REQUIRE(g.predecessors(3u) == node_id_list({ 1u, 2u }));
}
TEST_CASE("build_edge_data")
@ -162,32 +162,32 @@ TEST_SUITE("util::graph")
const auto g = build_edge_data_graph();
using node_map = decltype(g)::node_map;
using node_id_list = decltype(g)::node_id_list;
CHECK_EQ(g.number_of_nodes(), 3ul);
CHECK_EQ(g.number_of_edges(), 2ul);
CHECK_EQ(g.nodes(), node_map({ { 0, 0.5 }, { 1, 1.5 }, { 2, 2.5 } }));
CHECK_EQ(g.successors(0ul), node_id_list({ 1ul }));
CHECK_EQ(g.successors(1ul), node_id_list({ 2ul }));
CHECK_EQ(g.successors(2ul), node_id_list());
CHECK_EQ(g.predecessors(0ul), node_id_list());
CHECK_EQ(g.predecessors(1ul), node_id_list({ 0ul }));
CHECK_EQ(g.predecessors(2ul), node_id_list({ 1ul }));
REQUIRE(g.number_of_nodes() == 3ul);
REQUIRE(g.number_of_edges() == 2ul);
REQUIRE(g.nodes() == node_map({ { 0, 0.5 }, { 1, 1.5 }, { 2, 2.5 } }));
REQUIRE(g.successors(0ul) == node_id_list({ 1ul }));
REQUIRE(g.successors(1ul) == node_id_list({ 2ul }));
REQUIRE(g.successors(2ul) == node_id_list());
REQUIRE(g.predecessors(0ul) == node_id_list());
REQUIRE(g.predecessors(1ul) == node_id_list({ 0ul }));
REQUIRE(g.predecessors(2ul) == node_id_list({ 1ul }));
using edge_map = decltype(g)::edge_map;
CHECK_EQ(g.edges(), edge_map({ { { 0ul, 1ul }, "n0->n1" }, { { 1ul, 2ul }, "n1->n2" } }));
REQUIRE(g.edges() == edge_map({ { { 0ul, 1ul }, "n0->n1" }, { { 1ul, 2ul }, "n1->n2" } }));
}
TEST_CASE("has_node_edge")
{
const auto g = build_graph();
CHECK(g.has_node(1ul));
CHECK(g.has_node(4ul));
CHECK_FALSE(g.has_node(g.number_of_nodes()));
CHECK(g.has_edge(1ul, 4ul));
CHECK_FALSE(g.has_edge(4ul, 1ul));
CHECK(g.has_edge(0ul, 2ul));
CHECK_FALSE(g.has_edge(0ul, 5ul));
CHECK_FALSE(g.has_edge(0ul, g.number_of_nodes()));
CHECK_FALSE(g.has_edge(g.number_of_nodes(), 1ul));
REQUIRE(g.has_node(1ul));
REQUIRE(g.has_node(4ul));
REQUIRE_FALSE(g.has_node(g.number_of_nodes()));
REQUIRE(g.has_edge(1ul, 4ul));
REQUIRE_FALSE(g.has_edge(4ul, 1ul));
REQUIRE(g.has_edge(0ul, 2ul));
REQUIRE_FALSE(g.has_edge(0ul, 5ul));
REQUIRE_FALSE(g.has_edge(0ul, g.number_of_nodes()));
REQUIRE_FALSE(g.has_edge(g.number_of_nodes(), 1ul));
}
TEST_CASE("data_modifier")
@ -195,14 +195,14 @@ TEST_SUITE("util::graph")
auto g = build_edge_data_graph();
static constexpr auto new_node_val = -1.5;
CHECK_NE(g.node(0ul), new_node_val);
REQUIRE(g.node(0ul) != new_node_val);
g.node(0ul) = new_node_val;
CHECK_EQ(g.node(0ul), new_node_val);
REQUIRE(g.node(0ul) == new_node_val);
static constexpr auto new_edge_val = "data";
CHECK_NE(g.edge(0ul, 1ul), new_edge_val);
REQUIRE(g.edge(0ul, 1ul) != new_edge_val);
g.edge(0ul, 1ul) = new_edge_val;
CHECK_EQ(g.edge(0ul, 1ul), new_edge_val);
REQUIRE(g.edge(0ul, 1ul) == new_edge_val);
}
TEST_CASE("remove_edge")
@ -212,16 +212,16 @@ TEST_SUITE("util::graph")
REQUIRE_FALSE(g.has_edge(1, 0));
REQUIRE(g.has_edge(0, 1));
CHECK_FALSE(g.remove_edge(1, 0));
CHECK_EQ(g.number_of_edges(), n_edges_init);
CHECK_FALSE(g.has_edge(1, 0));
CHECK(g.has_edge(0, 1));
REQUIRE_FALSE(g.remove_edge(1, 0));
REQUIRE(g.number_of_edges() == n_edges_init);
REQUIRE_FALSE(g.has_edge(1, 0));
REQUIRE(g.has_edge(0, 1));
REQUIRE(g.has_edge(0, 1));
CHECK(g.remove_edge(0, 1));
CHECK_EQ(g.number_of_edges(), n_edges_init - 1u);
CHECK_FALSE(g.has_edge(0, 1));
CHECK_EQ(g.edges().count({ 0, 1 }), 0);
REQUIRE(g.remove_edge(0, 1));
REQUIRE(g.number_of_edges() == n_edges_init - 1u);
REQUIRE_FALSE(g.has_edge(0, 1));
REQUIRE(g.edges().count({ 0, 1 }) == 0);
}
TEST_CASE("remove_node")
@ -238,39 +238,39 @@ TEST_SUITE("util::graph")
const auto n_nodes_init = g.number_of_nodes();
const auto node_1_degree = g.in_degree(1) + g.out_degree(1);
CHECK(g.remove_node(1));
CHECK_EQ(g.number_of_nodes(), n_nodes_init - 1u);
CHECK_EQ(g.number_of_edges(), n_edges_init - node_1_degree);
CHECK_EQ(g.number_of_edges(), g.edges().size());
CHECK(g.has_node(0));
CHECK_FALSE(g.has_node(1));
CHECK(g.has_node(2));
CHECK_EQ(g.in_degree(1), 0);
CHECK_EQ(g.out_degree(1), 0);
CHECK_FALSE(g.has_edge(0, 1));
CHECK_FALSE(g.has_edge(1, 2));
g.for_each_node_id([&](auto id) { CHECK(g.has_node(id)); });
REQUIRE(g.remove_node(1));
REQUIRE(g.number_of_nodes() == n_nodes_init - 1u);
REQUIRE(g.number_of_edges() == n_edges_init - node_1_degree);
REQUIRE(g.number_of_edges() == g.edges().size());
REQUIRE(g.has_node(0));
REQUIRE_FALSE(g.has_node(1));
REQUIRE(g.has_node(2));
REQUIRE(g.in_degree(1) == 0);
REQUIRE(g.out_degree(1) == 0);
REQUIRE_FALSE(g.has_edge(0, 1));
REQUIRE_FALSE(g.has_edge(1, 2));
g.for_each_node_id([&](auto id) { REQUIRE(g.has_node(id)); });
CHECK_FALSE(g.remove_node(1));
CHECK_EQ(g.number_of_nodes(), n_nodes_init - 1u);
CHECK_EQ(g.number_of_edges(), n_edges_init - node_1_degree);
CHECK_EQ(g.number_of_edges(), g.edges().size());
REQUIRE_FALSE(g.remove_node(1));
REQUIRE(g.number_of_nodes() == n_nodes_init - 1u);
REQUIRE(g.number_of_edges() == n_edges_init - node_1_degree);
REQUIRE(g.number_of_edges() == g.edges().size());
const auto new_id = g.add_node(.7);
CHECK_EQ(new_id, n_nodes_init); // Ids are not invalidated so new id is used
CHECK_FALSE(g.has_node(1)); // Old id is not being confused
CHECK_EQ(g.number_of_nodes(), n_nodes_init);
REQUIRE(new_id == n_nodes_init); // Ids are not invalidated so new id is used
REQUIRE_FALSE(g.has_node(1)); // Old id is not being confused
REQUIRE(g.number_of_nodes() == n_nodes_init);
}
TEST_CASE("degree")
{
const auto g = build_graph();
CHECK_EQ(g.out_degree(0), 2);
CHECK_EQ(g.out_degree(1), 2);
CHECK_EQ(g.out_degree(6), 0);
CHECK_EQ(g.in_degree(0), 0);
CHECK_EQ(g.in_degree(3), 2);
CHECK_EQ(g.in_degree(6), 1);
REQUIRE(g.out_degree(0) == 2);
REQUIRE(g.out_degree(1) == 2);
REQUIRE(g.out_degree(6) == 0);
REQUIRE(g.in_degree(0) == 0);
REQUIRE(g.in_degree(3) == 2);
REQUIRE(g.in_degree(6) == 1);
}
TEST_CASE("for_each_node")
@ -281,11 +281,11 @@ TEST_SUITE("util::graph")
g.for_each_node_id(
[&](node_id id)
{
CHECK(g.has_node(id));
REQUIRE(g.has_node(id));
++n_nodes;
}
);
CHECK_EQ(n_nodes, g.number_of_nodes());
REQUIRE(n_nodes == g.number_of_nodes());
}
TEST_CASE("for_each_edge")
@ -296,11 +296,11 @@ TEST_SUITE("util::graph")
g.for_each_edge_id(
[&g, &n_edges](node_id from, node_id to)
{
CHECK(g.has_edge(from, to));
REQUIRE(g.has_edge(from, to));
++n_edges;
}
);
CHECK_EQ(n_edges, g.number_of_edges());
REQUIRE(n_edges == g.number_of_edges());
}
TEST_CASE("for_each_leaf")
@ -310,7 +310,7 @@ TEST_SUITE("util::graph")
using node_id_list = decltype(g)::node_id_list;
auto leaves = node_id_list();
g.for_each_leaf_id([&leaves](node_id leaf) { leaves.insert(leaf); });
CHECK_EQ(leaves, node_id_list({ 4ul, 5ul, 6ul }));
REQUIRE(leaves == node_id_list({ 4ul, 5ul, 6ul }));
}
TEST_CASE("for_each_leaf_from")
@ -320,7 +320,7 @@ TEST_SUITE("util::graph")
using node_id_list = decltype(g)::node_id_list;
auto leaves = node_id_list();
g.for_each_leaf_id_from(2ul, [&leaves](node_id leaf) { leaves.insert(leaf); });
CHECK_EQ(leaves, node_id_list({ 5ul, 6ul }));
REQUIRE(leaves == node_id_list({ 5ul, 6ul }));
}
TEST_CASE("for_each_root")
@ -330,7 +330,7 @@ TEST_SUITE("util::graph")
using node_id_list = decltype(g)::node_id_list;
auto roots = node_id_list();
g.for_each_root_id([&roots](node_id root) { roots.insert(root); });
CHECK_EQ(roots, node_id_list({ 0ul }));
REQUIRE(roots == node_id_list({ 0ul }));
}
TEST_CASE("for_each_root_from")
@ -340,7 +340,7 @@ TEST_SUITE("util::graph")
using node_id_list = decltype(g)::node_id_list;
auto leaves = node_id_list();
g.for_each_root_id_from(2ul, [&leaves](node_id leaf) { leaves.insert(leaf); });
CHECK_EQ(leaves, node_id_list({ 0ul }));
REQUIRE(leaves == node_id_list({ 0ul }));
}
TEST_CASE("depth_first_search")
@ -349,18 +349,18 @@ TEST_SUITE("util::graph")
test_visitor<DiGraph<double>> vis;
using node_id = typename decltype(g)::node_id;
dfs_raw(g, vis, /* start= */ node_id(0));
CHECK(vis.get_back_edge_map().empty());
CHECK_EQ(vis.get_cross_edge_map().find(2u)->second, 3u);
REQUIRE(vis.get_back_edge_map().empty());
REQUIRE(vis.get_cross_edge_map().find(2u)->second == 3u);
const auto& start_node_list = vis.get_start_node_list();
const auto& finish_node_list = vis.get_finish_node_list();
CHECK_FALSE(start_node_list.empty());
CHECK_FALSE(finish_node_list.empty());
REQUIRE_FALSE(start_node_list.empty());
REQUIRE_FALSE(finish_node_list.empty());
const auto start_node_set = std::set(start_node_list.begin(), start_node_list.end());
CHECK_EQ(start_node_list.size(), start_node_set.size()); // uniqueness
REQUIRE(start_node_list.size() == start_node_set.size()); // uniqueness
const auto finish_node_set = std::set(finish_node_list.begin(), finish_node_list.end());
CHECK_EQ(finish_node_list.size(), finish_node_set.size()); // uniqueness
CHECK_EQ(start_node_set, finish_node_set);
REQUIRE(finish_node_list.size() == finish_node_set.size()); // uniqueness
REQUIRE(start_node_set == finish_node_set);
}
TEST_CASE("dfs_cyclic")
@ -369,8 +369,8 @@ TEST_SUITE("util::graph")
test_visitor<DiGraph<double>> vis;
using node_id = typename decltype(g)::node_id;
dfs_raw(g, vis, /* start= */ node_id(0));
CHECK_EQ(vis.get_back_edge_map().find(2u)->second, 0u);
CHECK(vis.get_cross_edge_map().empty());
REQUIRE(vis.get_back_edge_map().find(2u)->second == 0u);
REQUIRE(vis.get_cross_edge_map().empty());
}
TEST_CASE("dfs_empty")
@ -379,8 +379,8 @@ TEST_SUITE("util::graph")
test_visitor<DiGraph<int>> vis;
using node_id = typename decltype(g)::node_id;
dfs_raw(g, vis, /* start= */ node_id(0));
CHECK(vis.get_back_edge_map().empty());
CHECK(vis.get_cross_edge_map().empty());
REQUIRE(vis.get_back_edge_map().empty());
REQUIRE(vis.get_cross_edge_map().empty());
}
template <typename Graph, typename Iter>
@ -406,13 +406,13 @@ TEST_SUITE("util::graph")
const auto& start_node_list = vis.get_start_node_list();
CHECK(is_node_id_permutation(g, start_node_list.cbegin(), start_node_list.cend()));
REQUIRE(is_node_id_permutation(g, start_node_list.cbegin(), start_node_list.cend()));
const auto& finish_node_list = vis.get_finish_node_list();
CHECK(is_node_id_permutation(g, finish_node_list.cbegin(), finish_node_list.cend()));
REQUIRE(is_node_id_permutation(g, finish_node_list.cbegin(), finish_node_list.cend()));
const auto start_node_set = std::set(start_node_list.begin(), start_node_list.end());
const auto finish_node_set = std::set(finish_node_list.begin(), finish_node_list.end());
CHECK_EQ(start_node_set, finish_node_set);
CHECK_EQ(start_node_set.size(), 3);
REQUIRE(start_node_set == finish_node_set);
REQUIRE(start_node_set.size() == 3);
}
TEST_CASE("dfs_preorder & dfs_postorder")
@ -427,33 +427,33 @@ TEST_SUITE("util::graph")
using node_id = typename decltype(g)::node_id;
auto nodes = std::vector<node_id>();
SUBCASE("dfs_preorder starting on a given node")
SECTION("dfs_preorder starting on a given node")
{
dfs_preorder_nodes_for_each_id(g, [&nodes](node_id n) { nodes.push_back(n); }, n0);
CHECK_EQ(nodes, std::vector<node_id>{ n0, n1 });
REQUIRE(nodes == std::vector<node_id>{ n0, n1 });
}
SUBCASE("dfs_preorder on all nodes")
SECTION("dfs_preorder on all nodes")
{
REQUIRE(g.has_node(n0));
REQUIRE(g.has_node(n1));
REQUIRE(g.has_node(n2));
dfs_preorder_nodes_for_each_id(g, [&nodes](node_id n) { nodes.push_back(n); });
CHECK(is_node_id_permutation(g, nodes.cbegin(), nodes.cend()));
CHECK_EQ(nodes, std::vector<node_id>{ n0, n1, n2 });
REQUIRE(is_node_id_permutation(g, nodes.cbegin(), nodes.cend()));
REQUIRE(nodes == std::vector<node_id>{ n0, n1, n2 });
}
SUBCASE("dfs_postorder starting on a given node")
SECTION("dfs_postorder starting on a given node")
{
dfs_postorder_nodes_for_each_id(g, [&nodes](node_id n) { nodes.push_back(n); }, n0);
CHECK_EQ(nodes, std::vector<node_id>{ n1, n0 });
REQUIRE(nodes == std::vector<node_id>{ n1, n0 });
}
SUBCASE("dfs_postorder on all nodes")
SECTION("dfs_postorder on all nodes")
{
dfs_postorder_nodes_for_each_id(g, [&nodes](node_id n) { nodes.push_back(n); });
CHECK(is_node_id_permutation(g, nodes.cbegin(), nodes.cend()));
CHECK_EQ(nodes, std::vector<node_id>{ n1, n0, n2 });
REQUIRE(is_node_id_permutation(g, nodes.cbegin(), nodes.cend()));
REQUIRE(nodes == std::vector<node_id>{ n1, n0, n2 });
}
}
@ -485,7 +485,7 @@ TEST_SUITE("util::graph")
auto sorted = std::vector<node_id>();
topological_sort_for_each_node_id(g, [&sorted](node_id n) { sorted.push_back(n); });
CHECK(is_node_id_permutation(g, sorted.cbegin(), sorted.cend()));
REQUIRE(is_node_id_permutation(g, sorted.cbegin(), sorted.cend()));
g.for_each_edge_id(
[&](node_id from, node_id to)
@ -493,12 +493,12 @@ TEST_SUITE("util::graph")
CAPTURE(std::pair(g.node(from), g.node(to)));
const auto from_pos = std::find(sorted.cbegin(), sorted.cend(), from);
// Must be true given the permutation assumption
REQUIRE_LT(from_pos, sorted.cend());
REQUIRE(from_pos < sorted.cend());
const auto to_pos = std::find(sorted.cbegin(), sorted.cend(), to);
// Must be true given the permutation assumption
REQUIRE_LT(to_pos, sorted.cend());
REQUIRE(to_pos < sorted.cend());
// The topological sort property
CHECK_LT(from_pos, to_pos);
REQUIRE(from_pos < to_pos);
}
);
}
@ -506,7 +506,7 @@ TEST_SUITE("util::graph")
TEST_CASE("is_reachable")
{
auto graph = build_graph();
CHECK(is_reachable(graph, 0, 6));
CHECK_FALSE(is_reachable(graph, 6, 0));
REQUIRE(is_reachable(graph, 0, 6));
REQUIRE_FALSE(is_reachable(graph, 6, 0));
}
}

View File

@ -4,144 +4,144 @@
//
// The full license is in the file LICENSE, distributed with this software.
#include <doctest/doctest.h>
#include <catch2/catch_all.hpp>
#include "mamba/util/heap_optional.hpp"
using namespace mamba::util;
TEST_SUITE("util::heap_optional")
namespace
{
TEST_CASE("heap_optional")
{
SUBCASE("Without value")
SECTION("Without value")
{
auto opt = heap_optional<int>();
CHECK_FALSE(opt.has_value());
CHECK_FALSE(opt);
CHECK_EQ(opt.get(), nullptr);
REQUIRE_FALSE(opt.has_value());
REQUIRE_FALSE(opt);
REQUIRE(opt.get() == nullptr);
SUBCASE("Emplace data")
SECTION("Emplace data")
{
opt.emplace(3);
CHECK(opt.has_value());
CHECK(opt);
REQUIRE_NE(opt.get(), nullptr);
CHECK_EQ(*opt, 3);
REQUIRE(opt.has_value());
REQUIRE(opt);
REQUIRE(opt.get() != nullptr);
REQUIRE(*opt == 3);
}
SUBCASE("Reset")
SECTION("Reset")
{
opt.reset();
CHECK_FALSE(opt.has_value());
CHECK_FALSE(opt);
CHECK_EQ(opt.get(), nullptr);
REQUIRE_FALSE(opt.has_value());
REQUIRE_FALSE(opt);
REQUIRE(opt.get() == nullptr);
}
SUBCASE("Value")
SECTION("Value")
{
// Silence [[nodiscard]] warnings
auto lref = [](heap_optional<int>& o) { return o.value(); };
CHECK_THROWS_AS(lref(opt), std::bad_optional_access);
REQUIRE_THROWS_AS(lref(opt), std::bad_optional_access);
auto clref = [](const heap_optional<int>& o) { return o.value(); };
CHECK_THROWS_AS(clref(opt), std::bad_optional_access);
REQUIRE_THROWS_AS(clref(opt), std::bad_optional_access);
auto rref = [](heap_optional<int>& o) { return std::move(o).value(); };
CHECK_THROWS_AS(rref(opt), std::bad_optional_access);
REQUIRE_THROWS_AS(rref(opt), std::bad_optional_access);
}
SUBCASE("Value Or")
SECTION("Value Or")
{
CHECK_EQ(opt.value_or(42), 42);
CHECK_EQ(const_cast<const heap_optional<int>&>(opt).value_or(42), 42);
CHECK_EQ(std::move(opt).value_or(42), 42);
REQUIRE(opt.value_or(42) == 42);
REQUIRE(const_cast<const heap_optional<int>&>(opt).value_or(42) == 42);
REQUIRE(std::move(opt).value_or(42) == 42);
}
}
SUBCASE("With copy and move value")
SECTION("With copy and move value")
{
auto opt = heap_optional(std::string("hello"));
using Opt = heap_optional<std::string>;
static_assert(std::is_same_v<decltype(opt), Opt>);
CHECK(opt.has_value());
CHECK(opt);
REQUIRE_NE(opt.get(), nullptr);
CHECK_EQ(*opt, "hello");
CHECK_EQ(opt->size(), 5);
REQUIRE(opt.has_value());
REQUIRE(opt);
REQUIRE(opt.get() != nullptr);
REQUIRE(*opt == "hello");
REQUIRE(opt->size() == 5);
SUBCASE("Emplace data")
SECTION("Emplace data")
{
opt.emplace("bonjour");
CHECK(opt.has_value());
CHECK(opt);
REQUIRE_NE(opt.get(), nullptr);
CHECK_EQ(*opt, "bonjour");
CHECK_EQ(opt->size(), 7);
REQUIRE(opt.has_value());
REQUIRE(opt);
REQUIRE(opt.get() != nullptr);
REQUIRE(*opt == "bonjour");
REQUIRE(opt->size() == 7);
}
SUBCASE("Reset")
SECTION("Reset")
{
opt.reset();
CHECK_FALSE(opt.has_value());
CHECK_FALSE(opt);
CHECK_EQ(opt.get(), nullptr);
REQUIRE_FALSE(opt.has_value());
REQUIRE_FALSE(opt);
REQUIRE(opt.get() == nullptr);
}
SUBCASE("Value")
SECTION("Value")
{
CHECK_EQ(opt.value(), "hello");
CHECK_EQ(const_cast<const Opt&>(opt).value(), "hello");
CHECK_EQ(std::move(opt).value(), "hello");
REQUIRE(opt.value() == "hello");
REQUIRE(const_cast<const Opt&>(opt).value() == "hello");
REQUIRE(std::move(opt).value() == "hello");
}
SUBCASE("Value Or")
SECTION("Value Or")
{
CHECK_EQ(opt.value_or("world"), "hello");
CHECK_EQ(const_cast<const Opt&>(opt).value_or("world"), "hello");
CHECK_EQ(std::move(opt).value_or("world"), "hello");
REQUIRE(opt.value_or("world") == "hello");
REQUIRE(const_cast<const Opt&>(opt).value_or("world") == "hello");
REQUIRE(std::move(opt).value_or("world") == "hello");
}
}
SUBCASE("With move only value")
SECTION("With move only value")
{
auto opt = heap_optional(std::make_unique<int>(3));
using Opt = heap_optional<std::unique_ptr<int>>;
static_assert(std::is_same_v<decltype(opt), Opt>);
CHECK(opt.has_value());
CHECK(opt);
REQUIRE_NE(opt.get(), nullptr);
CHECK_EQ(**opt, 3);
CHECK_EQ(*(opt->get()), 3);
REQUIRE(opt.has_value());
REQUIRE(opt);
REQUIRE(opt.get() != nullptr);
REQUIRE(**opt == 3);
REQUIRE(*(opt->get()) == 3);
SUBCASE("Emplace data")
SECTION("Emplace data")
{
opt.emplace(std::make_unique<int>(5));
CHECK(opt.has_value());
CHECK(opt);
REQUIRE_NE(opt.get(), nullptr);
CHECK_EQ(**opt, 5);
CHECK_EQ(*(opt->get()), 5);
REQUIRE(opt.has_value());
REQUIRE(opt);
REQUIRE(opt.get() != nullptr);
REQUIRE(**opt == 5);
REQUIRE(*(opt->get()) == 5);
}
SUBCASE("Reset")
SECTION("Reset")
{
opt.reset();
CHECK_FALSE(opt.has_value());
CHECK_FALSE(opt);
CHECK_EQ(opt.get(), nullptr);
REQUIRE_FALSE(opt.has_value());
REQUIRE_FALSE(opt);
REQUIRE(opt.get() == nullptr);
}
SUBCASE("Value")
SECTION("Value")
{
CHECK_EQ(*(opt.value()), 3);
CHECK_EQ(*(const_cast<const Opt&>(opt).value()), 3);
CHECK_EQ(*(std::move(opt).value()), 3);
REQUIRE(*(opt.value()) == 3);
REQUIRE(*(const_cast<const Opt&>(opt).value()) == 3);
REQUIRE(*(std::move(opt).value()) == 3);
}
SUBCASE("Value Or")
SECTION("Value Or")
{
CHECK_EQ(*(std::move(opt).value_or(std::make_unique<int>(5))), 3);
REQUIRE(*(std::move(opt).value_or(std::make_unique<int>(5))) == 3);
}
}
}

View File

@ -11,7 +11,7 @@
#include <utility>
#include <vector>
#include <doctest/doctest.h>
#include <catch2/catch_all.hpp>
#include "mamba/util/iterator.hpp"
@ -71,16 +71,16 @@ test_forward_api(Seq& input, const Seq& res, Pred p)
while (res_iter != res_iter_end)
{
CHECK_EQ(*iter, *res_iter);
CHECK_EQ(*iter, *citer);
REQUIRE(*iter == *res_iter);
REQUIRE(*iter == *citer);
++iter, ++citer, ++res_iter;
}
CHECK_EQ(iter, iter_end);
CHECK_EQ(citer, citer_end);
CHECK(iter == iter_end);
REQUIRE(iter == iter_end);
REQUIRE(citer == citer_end);
REQUIRE(iter == iter_end);
CHECK_EQ(iter2.operator->(), (++input.begin()).operator->());
CHECK(iter2++ != ++iter3);
REQUIRE(iter2.operator->() == (++input.begin()).operator->());
REQUIRE(iter2++ != ++iter3);
}
template <class Seq, class Pred>
@ -102,16 +102,16 @@ test_bidirectional_api(Seq& input, const Seq& res, Pred pred)
while (res_iter_end != res_iter)
{
--iter_end, --citer_end, --res_iter_end;
CHECK_EQ(*iter_end, *res_iter_end);
CHECK_EQ(*iter_end, *citer_end);
REQUIRE(*iter_end == *res_iter_end);
REQUIRE(*iter_end == *citer_end);
}
CHECK_EQ(iter, iter_end);
CHECK_EQ(citer, citer_end);
REQUIRE(iter == iter_end);
REQUIRE(citer == citer_end);
--iter_end, --citer_end;
CHECK_EQ(iter2.operator->(), input.end().operator->());
CHECK(iter2-- != --iter3);
REQUIRE(iter2.operator->() == input.end().operator->());
REQUIRE(iter2-- != --iter3);
}
template <class Seq, class Pred>
@ -132,20 +132,20 @@ test_random_access_api(Seq& input, const Seq& res, Pred pred)
auto citer2 = citer;
auto res_iter2 = res_iter;
CHECK_EQ(iter_end - iter, static_cast<std::ptrdiff_t>(res.size()));
CHECK_EQ(citer_end - citer, static_cast<std::ptrdiff_t>(res.size()));
REQUIRE(iter_end - iter == static_cast<std::ptrdiff_t>(res.size()));
REQUIRE(citer_end - citer == static_cast<std::ptrdiff_t>(res.size()));
CHECK_EQ(*(iter + 2), *(res_iter + 2));
CHECK_EQ(*(citer + 2), *(res_iter + 2));
REQUIRE(*(iter + 2) == *(res_iter + 2));
REQUIRE(*(citer + 2) == *(res_iter + 2));
iter += 2, res_iter += 2, citer += 2;
CHECK_EQ(*iter, *res_iter);
CHECK_EQ(*citer, *res_iter);
REQUIRE(*iter == *res_iter);
REQUIRE(*citer == *res_iter);
CHECK_EQ(iter2[1], res_iter2[1]);
CHECK_EQ(citer2[1], res_iter2[1]);
REQUIRE(iter2[1] == res_iter2[1]);
REQUIRE(citer2[1] == res_iter2[1]);
}
TEST_SUITE("util::filter_iterator")
namespace
{
TEST_CASE("forward_iterator_api")
{

View File

@ -6,7 +6,7 @@
#include <regex>
#include <doctest/doctest.h>
#include <catch2/catch_all.hpp>
#include "mamba/util/build.hpp"
#include "mamba/util/os_linux.hpp"
@ -14,7 +14,7 @@
using namespace mamba;
using namespace mamba::util;
TEST_SUITE("util::os_linux")
namespace
{
TEST_CASE("linux_version")
{
@ -23,11 +23,11 @@ TEST_SUITE("util::os_linux")
{
REQUIRE(maybe_version.has_value());
static const auto version_regex = std::regex(R"r(\d+\.\d+\.\d+)r");
CHECK(std ::regex_match(maybe_version.value(), version_regex));
REQUIRE(std ::regex_match(maybe_version.value(), version_regex));
}
else
{
CHECK_FALSE(maybe_version.has_value());
REQUIRE_FALSE(maybe_version.has_value());
}
}
}

View File

@ -6,7 +6,7 @@
#include <regex>
#include <doctest/doctest.h>
#include <catch2/catch_all.hpp>
#include "mamba/util/build.hpp"
#include "mamba/util/os_osx.hpp"
@ -14,14 +14,14 @@
using namespace mamba;
using namespace mamba::util;
TEST_SUITE("util::os_osx")
namespace
{
TEST_CASE("osx_version")
{
const auto maybe_version = osx_version();
if (util::on_mac)
{
REQUIRE(maybe_version.has_value());
CHECK(maybe_version.has_value());
// The version would be a sequence:
// 'x.x' or 'x.x.x'
// with 'x' matching one or more digits
@ -30,7 +30,7 @@ TEST_SUITE("util::os_osx")
}
else
{
CHECK_FALSE(maybe_version.has_value());
REQUIRE_FALSE(maybe_version.has_value());
}
}
}

View File

@ -6,7 +6,7 @@
#include <regex>
#include <doctest/doctest.h>
#include <catch2/catch_all.hpp>
#include "mamba/util/build.hpp"
#include "mamba/util/os_unix.hpp"
@ -14,7 +14,7 @@
using namespace mamba;
using namespace mamba::util;
TEST_SUITE("util::os_unix")
namespace
{
TEST_CASE("unix_name_version")
{
@ -22,20 +22,20 @@ TEST_SUITE("util::os_unix")
if (util::on_linux)
{
REQUIRE(maybe_name_version.has_value());
CHECK_EQ(maybe_name_version.value().first, "Linux");
REQUIRE(maybe_name_version.value().first == "Linux");
static const auto version_regex = std::regex(R"r(\d+\.\d+\.\d+)r");
CHECK(std ::regex_match(maybe_name_version.value().second, version_regex));
REQUIRE(std ::regex_match(maybe_name_version.value().second, version_regex));
}
else if (util::on_mac)
{
REQUIRE(maybe_name_version.has_value());
CHECK_EQ(maybe_name_version.value().first, "Darwin");
REQUIRE(maybe_name_version.value().first == "Darwin");
static const auto version_regex = std::regex(R"r(\d+\.\d+\.\d+)r");
CHECK(std ::regex_match(maybe_name_version.value().second, version_regex));
REQUIRE(std ::regex_match(maybe_name_version.value().second, version_regex));
}
else
{
CHECK_FALSE(maybe_name_version.has_value());
REQUIRE_FALSE(maybe_name_version.has_value());
}
}
}

View File

@ -8,7 +8,7 @@
#include <regex>
#include <string>
#include <doctest/doctest.h>
#include <catch2/catch_all.hpp>
#include "mamba/util/build.hpp"
#include "mamba/util/os_win.hpp"
@ -16,23 +16,27 @@
using namespace mamba;
using namespace mamba::util;
TEST_SUITE("util::os_win")
namespace
{
TEST_CASE("utf8" * doctest::skip(!util::on_win))
TEST_CASE("utf8")
{
if (!util::on_win)
{
SKIP();
}
const std::wstring text_utf16 = L"Hello, I am Joël. 私のにほんごわへたです";
const std::string text_utf8 = u8"Hello, I am Joël. 私のにほんごわへたです";
SUBCASE("utf8_to_windows_encoding")
SECTION("utf8_to_windows_encoding")
{
CHECK_EQ(utf8_to_windows_encoding(""), L"");
CHECK_EQ(utf8_to_windows_encoding(text_utf8), text_utf16);
REQUIRE(utf8_to_windows_encoding("") == L"");
REQUIRE(utf8_to_windows_encoding(text_utf8) == text_utf16);
}
SUBCASE("windows_encoding_to_utf8")
SECTION("windows_encoding_to_utf8")
{
CHECK_EQ(windows_encoding_to_utf8(L""), "");
CHECK_EQ(windows_encoding_to_utf8(text_utf16), text_utf8);
REQUIRE(windows_encoding_to_utf8(L"") == "");
REQUIRE(windows_encoding_to_utf8(text_utf16) == text_utf8);
}
}
@ -43,11 +47,11 @@ TEST_SUITE("util::os_win")
{
REQUIRE(maybe_version.has_value());
static const auto version_regex = std::regex(R"r(\d+\.\d+\.\d+)r");
CHECK(std::regex_match(maybe_version.value(), version_regex));
REQUIRE(std::regex_match(maybe_version.value(), version_regex));
}
else
{
CHECK_FALSE(maybe_version.has_value());
REQUIRE_FALSE(maybe_version.has_value());
}
}
}

View File

@ -4,13 +4,13 @@
//
// The full license is in the file LICENSE, distributed with this software.
#include <doctest/doctest.h>
#include <catch2/catch_all.hpp>
#include "mamba/util/parsers.hpp"
using namespace mamba::util;
TEST_SUITE("util::parsers")
namespace
{
inline static constexpr auto npos = std::string_view::npos;
@ -18,41 +18,45 @@ TEST_SUITE("util::parsers")
{
using Slice = std::pair<std::size_t, std::size_t>;
SUBCASE("Different open/close pair")
SECTION("Different open/close pair")
{
CHECK_EQ(find_matching_parentheses(""), Slice(npos, npos));
CHECK_EQ(find_matching_parentheses("Nothing to see here"), Slice(npos, npos));
CHECK_EQ(find_matching_parentheses("(hello)", '[', ']'), Slice(npos, npos));
REQUIRE(find_matching_parentheses("") == Slice(npos, npos));
REQUIRE(find_matching_parentheses("Nothing to see here") == Slice(npos, npos));
REQUIRE(find_matching_parentheses("(hello)", '[', ']') == Slice(npos, npos));
CHECK_EQ(find_matching_parentheses("()"), Slice(0, 1));
CHECK_EQ(find_matching_parentheses("hello()"), Slice(5, 6));
CHECK_EQ(find_matching_parentheses("(hello)"), Slice(0, 6));
CHECK_EQ(find_matching_parentheses("(hello (dear (sir))(!))(how(are(you)))"), Slice(0, 22));
CHECK_EQ(find_matching_parentheses("[hello]", '[', ']'), Slice(0, 6));
REQUIRE(find_matching_parentheses("()") == Slice(0, 1));
REQUIRE(find_matching_parentheses("hello()") == Slice(5, 6));
REQUIRE(find_matching_parentheses("(hello)") == Slice(0, 6));
REQUIRE(
find_matching_parentheses("(hello (dear (sir))(!))(how(are(you)))") == Slice(0, 22)
);
REQUIRE(find_matching_parentheses("[hello]", '[', ']') == Slice(0, 6));
CHECK_EQ(find_matching_parentheses(")(").error(), ParseError::InvalidInput);
CHECK_EQ(find_matching_parentheses("((hello)").error(), ParseError::InvalidInput);
REQUIRE(find_matching_parentheses(")(").error() == ParseError::InvalidInput);
REQUIRE(find_matching_parentheses("((hello)").error() == ParseError::InvalidInput);
static constexpr auto opens = std::array{ '[', '(' };
static constexpr auto closes = std::array{ ']', ')' };
CHECK_EQ(find_matching_parentheses("([hello])", opens, closes), Slice(0, 8));
CHECK_EQ(find_matching_parentheses("(hello)[hello]", opens, closes), Slice(0, 6));
REQUIRE(find_matching_parentheses("([hello])", opens, closes) == Slice(0, 8));
REQUIRE(find_matching_parentheses("(hello)[hello]", opens, closes) == Slice(0, 6));
}
SUBCASE("Similar open/close pair")
SECTION("Similar open/close pair")
{
CHECK_EQ(find_matching_parentheses(R"("")", '"', '"'), Slice(0, 1));
CHECK_EQ(find_matching_parentheses(R"("hello")", '"', '"'), Slice(0, 6));
CHECK_EQ(find_matching_parentheses(R"("some","csv","value")", '"', '"'), Slice(0, 5));
CHECK_EQ(
find_matching_parentheses(R"(Here is "some)", '"', '"').error(),
ParseError::InvalidInput
REQUIRE(find_matching_parentheses(R"("")", '"', '"') == Slice(0, 1));
REQUIRE(find_matching_parentheses(R"("hello")", '"', '"') == Slice(0, 6));
REQUIRE(find_matching_parentheses(R"("some","csv","value")", '"', '"') == Slice(0, 5));
REQUIRE(
find_matching_parentheses(R"(Here is "some)", '"', '"').error()
== ParseError::InvalidInput
);
static constexpr auto opens = std::array{ '[', '(', '\'' };
static constexpr auto closes = std::array{ ']', ')', '\'' };
CHECK_EQ(find_matching_parentheses("'[hello]'", opens, closes), Slice(0, 8));
CHECK_EQ(find_matching_parentheses("hello['hello', 'world']", opens, closes), Slice(5, 22));
REQUIRE(find_matching_parentheses("'[hello]'", opens, closes) == Slice(0, 8));
REQUIRE(
find_matching_parentheses("hello['hello', 'world']", opens, closes) == Slice(5, 22)
);
}
}
@ -60,367 +64,366 @@ TEST_SUITE("util::parsers")
{
using Slice = std::pair<std::size_t, std::size_t>;
SUBCASE("Different open/close pair")
SECTION("Different open/close pair")
{
CHECK_EQ(rfind_matching_parentheses(""), Slice(npos, npos));
CHECK_EQ(rfind_matching_parentheses("Nothing to see here"), Slice(npos, npos));
CHECK_EQ(rfind_matching_parentheses("(hello)", '[', ']'), Slice(npos, npos));
REQUIRE(rfind_matching_parentheses("") == Slice(npos, npos));
REQUIRE(rfind_matching_parentheses("Nothing to see here") == Slice(npos, npos));
REQUIRE(rfind_matching_parentheses("(hello)", '[', ']') == Slice(npos, npos));
CHECK_EQ(rfind_matching_parentheses("()"), Slice(0, 1));
CHECK_EQ(rfind_matching_parentheses("hello()"), Slice(5, 6));
CHECK_EQ(rfind_matching_parentheses("(hello)dear"), Slice(0, 6));
CHECK_EQ(
rfind_matching_parentheses("(hello (dear (sir))(!))(how(are(you)))"),
Slice(23, 37)
REQUIRE(rfind_matching_parentheses("()") == Slice(0, 1));
REQUIRE(rfind_matching_parentheses("hello()") == Slice(5, 6));
REQUIRE(rfind_matching_parentheses("(hello)dear") == Slice(0, 6));
REQUIRE(
rfind_matching_parentheses("(hello (dear (sir))(!))(how(are(you)))") == Slice(23, 37)
);
CHECK_EQ(rfind_matching_parentheses("[hello]", '[', ']'), Slice(0, 6));
REQUIRE(rfind_matching_parentheses("[hello]", '[', ']') == Slice(0, 6));
CHECK_EQ(rfind_matching_parentheses(")(").error(), ParseError::InvalidInput);
CHECK_EQ(rfind_matching_parentheses("(hello))").error(), ParseError::InvalidInput);
REQUIRE(rfind_matching_parentheses(")(").error() == ParseError::InvalidInput);
REQUIRE(rfind_matching_parentheses("(hello))").error() == ParseError::InvalidInput);
static constexpr auto opens = std::array{ '[', '(' };
static constexpr auto closes = std::array{ ']', ')' };
CHECK_EQ(rfind_matching_parentheses("([hello])", opens, closes), Slice(0, 8));
CHECK_EQ(rfind_matching_parentheses("(hello)[hello]", opens, closes), Slice(7, 13));
REQUIRE(rfind_matching_parentheses("([hello])", opens, closes) == Slice(0, 8));
REQUIRE(rfind_matching_parentheses("(hello)[hello]", opens, closes) == Slice(7, 13));
}
SUBCASE("Similar open/close pair")
SECTION("Similar open/close pair")
{
CHECK_EQ(rfind_matching_parentheses(R"("")", '"', '"'), Slice(0, 1));
CHECK_EQ(rfind_matching_parentheses(R"("hello")", '"', '"'), Slice(0, 6));
CHECK_EQ(rfind_matching_parentheses(R"("some","csv","value")", '"', '"'), Slice(13, 19));
CHECK_EQ(
rfind_matching_parentheses(R"(Here is "some)", '"', '"').error(),
ParseError::InvalidInput
REQUIRE(rfind_matching_parentheses(R"("")", '"', '"') == Slice(0, 1));
REQUIRE(rfind_matching_parentheses(R"("hello")", '"', '"') == Slice(0, 6));
REQUIRE(rfind_matching_parentheses(R"("some","csv","value")", '"', '"') == Slice(13, 19));
REQUIRE(
rfind_matching_parentheses(R"(Here is "some)", '"', '"').error()
== ParseError::InvalidInput
);
static constexpr auto opens = std::array{ '[', '(', '\'' };
static constexpr auto closes = std::array{ ']', ')', '\'' };
CHECK_EQ(rfind_matching_parentheses("'[hello]'", opens, closes), Slice(0, 8));
CHECK_EQ(rfind_matching_parentheses("['hello', 'world']dear", opens, closes), Slice(0, 17));
REQUIRE(rfind_matching_parentheses("'[hello]'", opens, closes) == Slice(0, 8));
REQUIRE(
rfind_matching_parentheses("['hello', 'world']dear", opens, closes) == Slice(0, 17)
);
}
}
TEST_CASE("find_not_in_parentheses")
{
SUBCASE("Single char and different open/close pair")
SECTION("Single char and different open/close pair")
{
CHECK_EQ(find_not_in_parentheses("", ','), npos);
CHECK_EQ(find_not_in_parentheses("Nothing to see here", ','), npos);
CHECK_EQ(find_not_in_parentheses("(hello, world)", ','), npos);
REQUIRE(find_not_in_parentheses("", ',') == npos);
REQUIRE(find_not_in_parentheses("Nothing to see here", ',') == npos);
REQUIRE(find_not_in_parentheses("(hello, world)", ',') == npos);
CHECK_EQ(find_not_in_parentheses("hello, world", ','), 5);
CHECK_EQ(find_not_in_parentheses("hello, world, welcome", ','), 5);
CHECK_EQ(find_not_in_parentheses("(hello, world), (welcome, here),", ','), 14);
CHECK_EQ(find_not_in_parentheses("(hello, world), (welcome, here),", ',', '[', ']'), 6);
CHECK_EQ(find_not_in_parentheses("[hello, world](welcome, here),", ',', '[', ']'), 22);
REQUIRE(find_not_in_parentheses("hello, world", ',') == 5);
REQUIRE(find_not_in_parentheses("hello, world, welcome", ',') == 5);
REQUIRE(find_not_in_parentheses("(hello, world), (welcome, here),", ',') == 14);
REQUIRE(find_not_in_parentheses("(hello, world), (welcome, here),", ',', '[', ']') == 6);
REQUIRE(find_not_in_parentheses("[hello, world](welcome, here),", ',', '[', ']') == 22);
CHECK_EQ(find_not_in_parentheses("(hello, world,", ',').error(), ParseError::InvalidInput);
CHECK_EQ(find_not_in_parentheses("(hello", ',').error(), ParseError::InvalidInput);
REQUIRE(find_not_in_parentheses("(hello, world,", ',').error() == ParseError::InvalidInput);
REQUIRE(find_not_in_parentheses("(hello", ',').error() == ParseError::InvalidInput);
static constexpr auto opens = std::array{ '[', '(' };
static constexpr auto closes = std::array{ ']', ')' };
CHECK_EQ(
find_not_in_parentheses("(hello, world), [welcome, here],", ',', opens, closes),
14
REQUIRE(
find_not_in_parentheses("(hello, world), [welcome, here],", ',', opens, closes) == 14
);
CHECK_EQ(
find_not_in_parentheses("([(hello)], ([world])), [welcome, here],", ',', opens, closes),
22
REQUIRE(
find_not_in_parentheses("([(hello)], ([world])), [welcome, here],", ',', opens, closes)
== 22
);
CHECK_EQ(find_not_in_parentheses("[hello, world](welcome, here),", ',', opens, closes), 29);
CHECK_EQ(
find_not_in_parentheses("(hello, ]world,) welcome, here],", ',', opens, closes).error(),
ParseError::InvalidInput
REQUIRE(
find_not_in_parentheses("[hello, world](welcome, here),", ',', opens, closes) == 29
);
REQUIRE(
find_not_in_parentheses("(hello, ]world,) welcome, here],", ',', opens, closes).error()
== ParseError::InvalidInput
);
// The following unfortunately does not work as we would need to allocate a stack
// to keep track of the opening and closing of parentheses.
// CHECK_EQ(
// REQUIRE(
// find_not_in_parentheses("(hello, [world, )welcome, here],", ',', opens,
// closes).error(), ParseError::InvalidInput
// closes).error() == ParseError::InvalidInput
// );
}
SUBCASE("Single char and similar open/close pair")
SECTION("Single char and similar open/close pair")
{
CHECK_EQ(find_not_in_parentheses(R"("some, csv")", ',', '"', '"'), npos);
REQUIRE(find_not_in_parentheses(R"("some, csv")", ',', '"', '"') == npos);
CHECK_EQ(find_not_in_parentheses(R"("some, csv",value)", ',', '"', '"'), 11);
CHECK_EQ(find_not_in_parentheses(R"("some, csv""value","here")", ',', '"', '"'), 18);
REQUIRE(find_not_in_parentheses(R"("some, csv",value)", ',', '"', '"') == 11);
REQUIRE(find_not_in_parentheses(R"("some, csv""value","here")", ',', '"', '"') == 18);
CHECK_EQ(
find_not_in_parentheses(R"("some, csv)", ',', '"', '"').error(),
ParseError::InvalidInput
REQUIRE(
find_not_in_parentheses(R"("some, csv)", ',', '"', '"').error()
== ParseError::InvalidInput
);
static constexpr auto opens = std::array{ '[', '(', '\'', '"' };
static constexpr auto closes = std::array{ ']', ')', '\'', '"' };
CHECK_EQ(
find_not_in_parentheses(R"('("hello", world)', [welcome, here],)", ',', opens, closes),
18
REQUIRE(
find_not_in_parentheses(R"('("hello", world)', [welcome, here],)", ',', opens, closes)
== 18
);
CHECK_EQ(
find_not_in_parentheses("('[(hello)], ([world])'), [welcome, here],", ',', opens, closes),
24
REQUIRE(
find_not_in_parentheses("('[(hello)], ([world])'), [welcome, here],", ',', opens, closes)
== 24
);
CHECK_EQ(
find_not_in_parentheses("('hello', ']world,) welcome, here],", ',', opens, closes)
.error(),
ParseError::InvalidInput
REQUIRE(
find_not_in_parentheses("('hello', ']world,) welcome, here],", ',', opens, closes).error()
== ParseError::InvalidInput
);
}
SUBCASE("Substring and different open/close pair")
SECTION("Substring and different open/close pair")
{
CHECK_EQ(find_not_in_parentheses("", "::"), npos);
CHECK_EQ(find_not_in_parentheses("Nothing to see here", "::"), npos);
CHECK_EQ(find_not_in_parentheses("(hello::world)", "::"), npos);
REQUIRE(find_not_in_parentheses("", "::") == npos);
REQUIRE(find_not_in_parentheses("Nothing to see here", "::") == npos);
REQUIRE(find_not_in_parentheses("(hello::world)", "::") == npos);
CHECK_EQ(find_not_in_parentheses("hello::world", "::"), 5);
CHECK_EQ(find_not_in_parentheses("hello::world::welcome", "::"), 5);
CHECK_EQ(find_not_in_parentheses("(hello::world)::(welcome::here)::", "::").value(), 14);
CHECK_EQ(find_not_in_parentheses("(hello::world)::(welcome::here)", "::", '[', ']'), 6);
CHECK_EQ(find_not_in_parentheses("[hello::world](welcome::here),", "::", '[', ']'), 22);
REQUIRE(find_not_in_parentheses("hello::world", "::") == 5);
REQUIRE(find_not_in_parentheses("hello::world::welcome", "::") == 5);
REQUIRE(find_not_in_parentheses("(hello::world)::(welcome::here)::", "::").value() == 14);
REQUIRE(find_not_in_parentheses("(hello::world)::(welcome::here)", "::", '[', ']') == 6);
REQUIRE(find_not_in_parentheses("[hello::world](welcome::here),", "::", '[', ']') == 22);
//
CHECK_EQ(find_not_in_parentheses("(hello::world::", "::").error(), ParseError::InvalidInput);
CHECK_EQ(find_not_in_parentheses("(hello", "::").error(), ParseError::InvalidInput);
REQUIRE(
find_not_in_parentheses("(hello::world::", "::").error() == ParseError::InvalidInput
);
REQUIRE(find_not_in_parentheses("(hello", "::").error() == ParseError::InvalidInput);
static constexpr auto opens = std::array{ '[', '(' };
static constexpr auto closes = std::array{ ']', ')' };
CHECK_EQ(
find_not_in_parentheses("(some str)", "", opens, closes).error(),
ParseError::InvalidInput
REQUIRE(
find_not_in_parentheses("(some str)", "", opens, closes).error()
== ParseError::InvalidInput
);
CHECK_EQ(
find_not_in_parentheses(R"((hello , world), [welcome , here] ,elf)", " ,", opens, closes),
33
REQUIRE(
find_not_in_parentheses(R"((hello , world), [welcome , here] ,elf)", " ,", opens, closes)
== 33
);
CHECK_EQ(
find_not_in_parentheses("([(hello)] , ([world])), [welcome , here] ,elf", " ,", opens, closes),
41
REQUIRE(
find_not_in_parentheses("([(hello)] , ([world])), [welcome , here] ,elf", " ,", opens, closes)
== 41
);
CHECK_EQ(
find_not_in_parentheses("(hello , ]world,) welcome, here],", ", ", opens, closes).error(),
ParseError::InvalidInput
REQUIRE(
find_not_in_parentheses("(hello , ]world,) welcome, here],", ", ", opens, closes).error()
== ParseError::InvalidInput
);
}
SUBCASE("Substring and similar open/close pair")
SECTION("Substring and similar open/close pair")
{
CHECK_EQ(find_not_in_parentheses(R"("some::csv")", "::", '"', '"'), npos);
REQUIRE(find_not_in_parentheses(R"("some::csv")", "::", '"', '"') == npos);
CHECK_EQ(find_not_in_parentheses(R"("some::csv"::value)", "::", '"', '"'), 11);
CHECK_EQ(find_not_in_parentheses(R"("some::csv""value"::"here")", "::", '"', '"'), 18);
REQUIRE(find_not_in_parentheses(R"("some::csv"::value)", "::", '"', '"') == 11);
REQUIRE(find_not_in_parentheses(R"("some::csv""value"::"here")", "::", '"', '"') == 18);
CHECK_EQ(
find_not_in_parentheses(R"("some::csv)", "::", '"', '"').error(),
ParseError::InvalidInput
REQUIRE(
find_not_in_parentheses(R"("some::csv)", "::", '"', '"').error()
== ParseError::InvalidInput
);
static constexpr auto opens = std::array{ '[', '(', '\'', '"' };
static constexpr auto closes = std::array{ ']', ')', '\'', '"' };
CHECK_EQ(
find_not_in_parentheses("(some str)", "", opens, closes).error(),
ParseError::InvalidInput
REQUIRE(
find_not_in_parentheses("(some str)", "", opens, closes).error()
== ParseError::InvalidInput
);
CHECK_EQ(
find_not_in_parentheses(R"('("hello" , world)', [welcome , here] ,elf)", " ,", opens, closes),
37
REQUIRE(
find_not_in_parentheses(R"('("hello" , world)', [welcome , here] ,elf)", " ,", opens, closes)
== 37
);
CHECK_EQ(
find_not_in_parentheses(
"('[(hello)] , ([world])'), [welcome , here] ,elf",
" ,",
opens,
closes
),
43
REQUIRE(
find_not_in_parentheses("('[(hello)] , ([world])'), [welcome , here] ,elf", " ,", opens, closes)
== 43
);
CHECK_EQ(
REQUIRE(
find_not_in_parentheses("('hello' , ']world,) welcome, here],", ", ", opens, closes)
.error(),
ParseError::InvalidInput
.error()
== ParseError::InvalidInput
);
}
}
TEST_CASE("rfind_not_in_parentheses")
{
SUBCASE("Single char and different open/close pair")
SECTION("Single char and different open/close pair")
{
CHECK_EQ(rfind_not_in_parentheses("", ','), npos);
CHECK_EQ(rfind_not_in_parentheses("Nothing to see here", ','), npos);
CHECK_EQ(rfind_not_in_parentheses("(hello, world)", ','), npos);
REQUIRE(rfind_not_in_parentheses("", ',') == npos);
REQUIRE(rfind_not_in_parentheses("Nothing to see here", ',') == npos);
REQUIRE(rfind_not_in_parentheses("(hello, world)", ',') == npos);
CHECK_EQ(rfind_not_in_parentheses("hello, world", ','), 5);
CHECK_EQ(rfind_not_in_parentheses("hello, world, welcome", ','), 12);
CHECK_EQ(rfind_not_in_parentheses("(hello, world), (welcome, here),", ','), 31);
CHECK_EQ(rfind_not_in_parentheses("(hello, world), (welcome, here)", ',', '[', ']'), 24);
CHECK_EQ(rfind_not_in_parentheses("[hello, world](welcome, here)", ',', '(', ')'), 6);
REQUIRE(rfind_not_in_parentheses("hello, world", ',') == 5);
REQUIRE(rfind_not_in_parentheses("hello, world, welcome", ',') == 12);
REQUIRE(rfind_not_in_parentheses("(hello, world), (welcome, here),", ',') == 31);
REQUIRE(rfind_not_in_parentheses("(hello, world), (welcome, here)", ',', '[', ']') == 24);
REQUIRE(rfind_not_in_parentheses("[hello, world](welcome, here)", ',', '(', ')') == 6);
CHECK_EQ(find_not_in_parentheses("(hello, world,", ',').error(), ParseError::InvalidInput);
CHECK_EQ(find_not_in_parentheses("(hello", ',').error(), ParseError::InvalidInput);
REQUIRE(find_not_in_parentheses("(hello, world,", ',').error() == ParseError::InvalidInput);
REQUIRE(find_not_in_parentheses("(hello", ',').error() == ParseError::InvalidInput);
static constexpr auto opens = std::array{ '[', '(' };
static constexpr auto closes = std::array{ ']', ')' };
CHECK_EQ(
rfind_not_in_parentheses(",(hello, world), [welcome, here]", ',', opens, closes),
15
REQUIRE(
rfind_not_in_parentheses(",(hello, world), [welcome, here]", ',', opens, closes) == 15
);
CHECK_EQ(
rfind_not_in_parentheses(",[welcome, here], ([(hello)], ([world]))", ',', opens, closes),
16
REQUIRE(
rfind_not_in_parentheses(",[welcome, here], ([(hello)], ([world]))", ',', opens, closes)
== 16
);
CHECK_EQ(rfind_not_in_parentheses(",[hello, world](welcome, here)", ',', opens, closes), 0);
CHECK_EQ(
rfind_not_in_parentheses(",(hello, ]world,) welcome, here]", ',', opens, closes).error(),
ParseError::InvalidInput
REQUIRE(
rfind_not_in_parentheses(",[hello, world](welcome, here)", ',', opens, closes) == 0
);
REQUIRE(
rfind_not_in_parentheses(",(hello, ]world,) welcome, here]", ',', opens, closes).error()
== ParseError::InvalidInput
);
CHECK_EQ(rfind_not_in_parentheses("this, is, (a, string)", ',', opens, closes), 8);
CHECK_EQ(rfind_not_in_parentheses(",this (a, string)", ',', opens, closes), 0);
CHECK_EQ(rfind_not_in_parentheses("this (a, string)", ',', opens, closes), npos);
CHECK_EQ(rfind_not_in_parentheses("(a, string)", ',', opens, closes), npos);
REQUIRE(rfind_not_in_parentheses("this, is, (a, string)", ',', opens, closes) == 8);
REQUIRE(rfind_not_in_parentheses(",this (a, string)", ',', opens, closes) == 0);
REQUIRE(rfind_not_in_parentheses("this (a, string)", ',', opens, closes) == npos);
REQUIRE(rfind_not_in_parentheses("(a, string)", ',', opens, closes) == npos);
}
SUBCASE("Single char and similar open/close pair")
SECTION("Single char and similar open/close pair rfind")
{
CHECK_EQ(rfind_not_in_parentheses(R"("some, csv")", ',', '"', '"'), npos);
CHECK_EQ(rfind_not_in_parentheses(R"("some, csv","some, value")", ',', '"', '"'), 11);
CHECK_EQ(rfind_not_in_parentheses(R"("some, csv","value""here")", ',', '"', '"'), 11);
REQUIRE(rfind_not_in_parentheses(R"("some, csv")", ',', '"', '"') == npos);
REQUIRE(rfind_not_in_parentheses(R"("some, csv","some, value")", ',', '"', '"') == 11);
REQUIRE(rfind_not_in_parentheses(R"("some, csv","value""here")", ',', '"', '"') == 11);
CHECK_EQ(
find_not_in_parentheses(R"("some, csv)", ',', '"', '"').error(),
ParseError::InvalidInput
REQUIRE(
find_not_in_parentheses(R"("some, csv)", ',', '"', '"').error()
== ParseError::InvalidInput
);
static constexpr auto opens = std::array{ '[', '(', '\'', '"' };
static constexpr auto closes = std::array{ ']', ')', '\'', '"' };
CHECK_EQ(
rfind_not_in_parentheses(R"(,[welcome, here], '("hello", world)')", ',', opens, closes),
16
REQUIRE(
rfind_not_in_parentheses(R"(,[welcome, here], '("hello", world)')", ',', opens, closes)
== 16
);
CHECK_EQ(
rfind_not_in_parentheses(",[welcome, here], ('[(hello)], ([world])')", ',', opens, closes),
16
REQUIRE(
rfind_not_in_parentheses(",[welcome, here], ('[(hello)], ([world])')", ',', opens, closes)
== 16
);
CHECK_EQ(
rfind_not_in_parentheses(",('hello', ']world,) welcome, here]", ',', opens, closes)
.error(),
ParseError::InvalidInput
REQUIRE(
rfind_not_in_parentheses(",('hello', ']world,) welcome, here]", ',', opens, closes).error()
== ParseError::InvalidInput
);
}
SUBCASE("Substring and different open/close pair")
SECTION("Substring and different open/close pair")
{
CHECK_EQ(rfind_not_in_parentheses("", "::"), npos);
CHECK_EQ(rfind_not_in_parentheses("Nothing to see here", "::"), npos);
CHECK_EQ(rfind_not_in_parentheses("(hello::world)", "::"), npos);
REQUIRE(rfind_not_in_parentheses("", "::") == npos);
REQUIRE(rfind_not_in_parentheses("Nothing to see here", "::") == npos);
REQUIRE(rfind_not_in_parentheses("(hello::world)", "::") == npos);
CHECK_EQ(rfind_not_in_parentheses("hello::world", "::"), 5);
CHECK_EQ(rfind_not_in_parentheses("hello::", "::"), 5);
CHECK_EQ(rfind_not_in_parentheses("hello::world::welcome", "::"), 12);
CHECK_EQ(rfind_not_in_parentheses("::(hello::world)::(welcome::here)", "::"), 16);
CHECK_EQ(rfind_not_in_parentheses("(hello::world)::(welcome::here)", "::", '[', ']'), 24);
CHECK_EQ(rfind_not_in_parentheses(",(welcome::here)[hello::world]", "::", '[', ']'), 9);
REQUIRE(rfind_not_in_parentheses("hello::world", "::") == 5);
REQUIRE(rfind_not_in_parentheses("hello::", "::") == 5);
REQUIRE(rfind_not_in_parentheses("hello::world::welcome", "::") == 12);
REQUIRE(rfind_not_in_parentheses("::(hello::world)::(welcome::here)", "::") == 16);
REQUIRE(rfind_not_in_parentheses("(hello::world)::(welcome::here)", "::", '[', ']') == 24);
REQUIRE(rfind_not_in_parentheses(",(welcome::here)[hello::world]", "::", '[', ']') == 9);
CHECK_EQ(rfind_not_in_parentheses("hello::world::)", "::").error(), ParseError::InvalidInput);
CHECK_EQ(rfind_not_in_parentheses("hello)", "::").error(), ParseError::InvalidInput);
CHECK_EQ(rfind_not_in_parentheses("(hello", "::").error(), ParseError::InvalidInput);
REQUIRE(
rfind_not_in_parentheses("hello::world::)", "::").error() == ParseError::InvalidInput
);
REQUIRE(rfind_not_in_parentheses("hello)", "::").error() == ParseError::InvalidInput);
REQUIRE(rfind_not_in_parentheses("(hello", "::").error() == ParseError::InvalidInput);
static constexpr auto opens = std::array{ '[', '(' };
static constexpr auto closes = std::array{ ']', ')' };
CHECK_EQ(
rfind_not_in_parentheses("(some str)", "", opens, closes).error(),
ParseError::InvalidInput
REQUIRE(
rfind_not_in_parentheses("(some str)", "", opens, closes).error()
== ParseError::InvalidInput
);
CHECK_EQ(
rfind_not_in_parentheses(R"(hoy ,(hello , world), [welcome , here],elf)", " ,", opens, closes),
3
REQUIRE(
rfind_not_in_parentheses(R"(hoy ,(hello , world), [welcome , here],elf)", " ,", opens, closes)
== 3
);
CHECK_EQ(
rfind_not_in_parentheses("hey ,([(hello)] , ([world])), [it , here]", " ,", opens, closes),
3
REQUIRE(
rfind_not_in_parentheses("hey ,([(hello)] , ([world])), [it , here]", " ,", opens, closes)
== 3
);
CHECK_EQ(
rfind_not_in_parentheses("(hello , ]world,) welcome, here],", ", ", opens, closes)
.error(),
ParseError::InvalidInput
REQUIRE(
rfind_not_in_parentheses("(hello , ]world,) welcome, here],", ", ", opens, closes).error()
== ParseError::InvalidInput
);
}
SUBCASE("Substring and similar open/close pair")
SECTION("Substring and similar open/close pair")
{
CHECK_EQ(rfind_not_in_parentheses(R"("some::csv")", "::", '"', '"'), npos);
CHECK_EQ(rfind_not_in_parentheses(R"("some::csv"::"some::value")", "::", '"', '"'), 11);
CHECK_EQ(rfind_not_in_parentheses(R"("some::csv"::"value""here")", "::", '"', '"'), 11);
CHECK_EQ(
rfind_not_in_parentheses(R"(some::csv")", "::", '"', '"').error(),
ParseError::InvalidInput
REQUIRE(rfind_not_in_parentheses(R"("some::csv")", "::", '"', '"') == npos);
REQUIRE(rfind_not_in_parentheses(R"("some::csv"::"some::value")", "::", '"', '"') == 11);
REQUIRE(rfind_not_in_parentheses(R"("some::csv"::"value""here")", "::", '"', '"') == 11);
REQUIRE(
rfind_not_in_parentheses(R"(some::csv")", "::", '"', '"').error()
== ParseError::InvalidInput
);
static constexpr auto opens = std::array{ '[', '(', '\'', '"' };
static constexpr auto closes = std::array{ ']', ')', '\'', '"' };
CHECK_EQ(
rfind_not_in_parentheses("(some str)", "", opens, closes).error(),
ParseError::InvalidInput
REQUIRE(
rfind_not_in_parentheses("(some str)", "", opens, closes).error()
== ParseError::InvalidInput
);
CHECK_EQ(
REQUIRE(
find_not_in_parentheses(
"hoy , ('[(hello)] , ([world])'), [welcome , here]",
" ,",
opens,
closes
),
3
)
== 3
);
CHECK_EQ(
REQUIRE(
rfind_not_in_parentheses("('hello' , ']world,) welcome, here],", ", ", opens, closes)
.error(),
ParseError::InvalidInput
.error()
== ParseError::InvalidInput
);
}
}
TEST_CASE("glob_match")
{
CHECK(glob_match("python", "python"));
CHECK_FALSE(glob_match("cpython", "python"));
CHECK_FALSE(glob_match("python", "cpython"));
CHECK_FALSE(glob_match("python", ""));
REQUIRE(glob_match("python", "python"));
REQUIRE_FALSE(glob_match("cpython", "python"));
REQUIRE_FALSE(glob_match("python", "cpython"));
REQUIRE_FALSE(glob_match("python", ""));
CHECK(glob_match("py*", "py"));
CHECK(glob_match("py*", "py"));
CHECK(glob_match("py*", "python"));
CHECK_FALSE(glob_match("py*", "cpython"));
CHECK_FALSE(glob_match("py*", ""));
REQUIRE(glob_match("py*", "py"));
REQUIRE(glob_match("py*", "py"));
REQUIRE(glob_match("py*", "python"));
REQUIRE_FALSE(glob_match("py*", "cpython"));
REQUIRE_FALSE(glob_match("py*", ""));
CHECK(glob_match("*37", "python37"));
CHECK(glob_match("*37", "37"));
CHECK_FALSE(glob_match("*37", "python37-linux64"));
CHECK_FALSE(glob_match("*37", ""));
REQUIRE(glob_match("*37", "python37"));
REQUIRE(glob_match("*37", "37"));
REQUIRE_FALSE(glob_match("*37", "python37-linux64"));
REQUIRE_FALSE(glob_match("*37", ""));
CHECK(glob_match("*py*", "python"));
CHECK(glob_match("*py*", "cpython"));
CHECK(glob_match("*py*", "cpy"));
CHECK_FALSE(glob_match("*py*", "linux"));
CHECK_FALSE(glob_match("*py*", ""));
REQUIRE(glob_match("*py*", "python"));
REQUIRE(glob_match("*py*", "cpython"));
REQUIRE(glob_match("*py*", "cpy"));
REQUIRE_FALSE(glob_match("*py*", "linux"));
REQUIRE_FALSE(glob_match("*py*", ""));
CHECK(glob_match("*py*-3*-*-64", "cpython-37-linux-64"));
CHECK(glob_match("*py*-3*-*-64", "python-37-more-linux-64"));
CHECK_FALSE(glob_match("*py*-3*-*-64", "cpython-37-linux-64-more"));
CHECK_FALSE(glob_match("*py*-3*-*-64", ""));
REQUIRE(glob_match("*py*-3*-*-64", "cpython-37-linux-64"));
REQUIRE(glob_match("*py*-3*-*-64", "python-37-more-linux-64"));
REQUIRE_FALSE(glob_match("*py*-3*-*-64", "cpython-37-linux-64-more"));
REQUIRE_FALSE(glob_match("*py*-3*-*-64", ""));
CHECK(glob_match("py**", "python"));
CHECK_FALSE(glob_match("py**", "cpython"));
CHECK(glob_match("**37", "python37"));
CHECK_FALSE(glob_match("**37", "python37-linux64"));
CHECK(glob_match("**py**", "python"));
CHECK_FALSE(glob_match("**py**", "linux"));
REQUIRE(glob_match("py**", "python"));
REQUIRE_FALSE(glob_match("py**", "cpython"));
REQUIRE(glob_match("**37", "python37"));
REQUIRE_FALSE(glob_match("**37", "python37-linux64"));
REQUIRE(glob_match("**py**", "python"));
REQUIRE_FALSE(glob_match("**py**", "linux"));
}
}

View File

@ -5,168 +5,169 @@
// The full license is in the file LICENSE, distributed with this software.
#include <doctest/doctest.h>
#include <catch2/catch_all.hpp>
#include "mamba/util/build.hpp"
#include "mamba/util/path_manip.hpp"
using namespace mamba::util;
TEST_SUITE("util::path_manip")
namespace
{
TEST_CASE("is_explicit_path")
{
CHECK(is_explicit_path("."));
CHECK(is_explicit_path("./"));
CHECK(is_explicit_path("./folder/file.txt"));
CHECK(is_explicit_path(".."));
CHECK(is_explicit_path("../file.txt"));
CHECK(is_explicit_path("~"));
CHECK(is_explicit_path("~/there"));
CHECK(is_explicit_path("/"));
CHECK(is_explicit_path("/asset"));
REQUIRE(is_explicit_path("."));
REQUIRE(is_explicit_path("./"));
REQUIRE(is_explicit_path("./folder/file.txt"));
REQUIRE(is_explicit_path(".."));
REQUIRE(is_explicit_path("../file.txt"));
REQUIRE(is_explicit_path("~"));
REQUIRE(is_explicit_path("~/there"));
REQUIRE(is_explicit_path("/"));
REQUIRE(is_explicit_path("/asset"));
CHECK_FALSE(is_explicit_path(""));
CHECK_FALSE(is_explicit_path("name"));
CHECK_FALSE(is_explicit_path("folder/file.txt"));
CHECK_FALSE(is_explicit_path("file://makefile"));
REQUIRE_FALSE(is_explicit_path(""));
REQUIRE_FALSE(is_explicit_path("name"));
REQUIRE_FALSE(is_explicit_path("folder/file.txt"));
REQUIRE_FALSE(is_explicit_path("file://makefile"));
}
TEST_CASE("path_has_drive_letter")
{
CHECK(path_has_drive_letter("C:/folder/file"));
CHECK_EQ(path_get_drive_letter("C:/folder/file"), 'C');
CHECK(path_has_drive_letter(R"(C:\folder\file)"));
CHECK_EQ(path_get_drive_letter(R"(C:\folder\file)"), 'C');
CHECK_FALSE(path_has_drive_letter("/folder/file"));
CHECK_FALSE(path_has_drive_letter("folder/file"));
CHECK_FALSE(path_has_drive_letter(R"(\folder\file)"));
CHECK_FALSE(path_has_drive_letter(R"(folder\file)"));
REQUIRE(path_has_drive_letter("C:/folder/file"));
REQUIRE(path_get_drive_letter("C:/folder/file") == 'C');
REQUIRE(path_has_drive_letter(R"(C:\folder\file)"));
REQUIRE(path_get_drive_letter(R"(C:\folder\file)") == 'C');
REQUIRE_FALSE(path_has_drive_letter("/folder/file"));
REQUIRE_FALSE(path_has_drive_letter("folder/file"));
REQUIRE_FALSE(path_has_drive_letter(R"(\folder\file)"));
REQUIRE_FALSE(path_has_drive_letter(R"(folder\file)"));
}
TEST_CASE("path_win_detect_sep")
{
CHECK_EQ(path_win_detect_sep("file"), std::nullopt);
REQUIRE(path_win_detect_sep("file") == std::nullopt);
CHECK_EQ(path_win_detect_sep("C:/file"), '/');
CHECK_EQ(path_win_detect_sep("~/file"), '/');
CHECK_EQ(path_win_detect_sep("/folder/file"), '/');
REQUIRE(path_win_detect_sep("C:/file") == '/');
REQUIRE(path_win_detect_sep("~/file") == '/');
REQUIRE(path_win_detect_sep("/folder/file") == '/');
CHECK_EQ(path_win_detect_sep(R"(C:\file)"), '\\');
CHECK_EQ(path_win_detect_sep(R"(~\file)"), '\\');
CHECK_EQ(path_win_detect_sep(R"(\\folder\\file)"), '\\');
REQUIRE(path_win_detect_sep(R"(C:\file)") == '\\');
REQUIRE(path_win_detect_sep(R"(~\file)") == '\\');
REQUIRE(path_win_detect_sep(R"(\\folder\\file)") == '\\');
}
TEST_CASE("path_win_to_posix")
{
CHECK_EQ(path_win_to_posix(""), "");
CHECK_EQ(path_win_to_posix("file"), "file");
CHECK_EQ(path_win_to_posix(R"(C:\folder\file)"), "C:/folder/file");
CHECK_EQ(path_win_to_posix("C:/folder/file"), "C:/folder/file");
REQUIRE(path_win_to_posix("") == "");
REQUIRE(path_win_to_posix("file") == "file");
REQUIRE(path_win_to_posix(R"(C:\folder\file)") == "C:/folder/file");
REQUIRE(path_win_to_posix("C:/folder/file") == "C:/folder/file");
}
TEST_CASE("path_win_to_posix")
TEST_CASE("path_posix_to_win")
{
CHECK_EQ(path_posix_to_win(""), "");
CHECK_EQ(path_posix_to_win("file"), "file");
CHECK_EQ(path_posix_to_win("C:/folder/file"), R"(C:\folder\file)");
CHECK_EQ(path_posix_to_win(R"(C:\folder\file)"), R"(C:\folder\file)");
REQUIRE(path_posix_to_win("") == "");
REQUIRE(path_posix_to_win("file") == "file");
REQUIRE(path_posix_to_win("C:/folder/file") == R"(C:\folder\file)");
REQUIRE(path_posix_to_win(R"(C:\folder\file)") == R"(C:\folder\file)");
}
TEST_CASE("path_to_posix")
{
CHECK_EQ(path_to_posix(""), "");
CHECK_EQ(path_to_posix("file"), "file");
CHECK_EQ(path_to_posix("folder/file"), "folder/file");
CHECK_EQ(path_to_posix("/folder/file"), "/folder/file");
REQUIRE(path_to_posix("") == "");
REQUIRE(path_to_posix("file") == "file");
REQUIRE(path_to_posix("folder/file") == "folder/file");
REQUIRE(path_to_posix("/folder/file") == "/folder/file");
if (on_win)
{
CHECK_EQ(path_to_posix(R"(C:\folder\file)"), "C:/folder/file");
CHECK_EQ(path_to_posix("C:/folder/file"), "C:/folder/file");
REQUIRE(path_to_posix(R"(C:\folder\file)") == "C:/folder/file");
REQUIRE(path_to_posix("C:/folder/file") == "C:/folder/file");
}
else
{
CHECK_EQ(path_to_posix(R"(folder/weird\file)"), R"(folder/weird\file)");
REQUIRE(path_to_posix(R"(folder/weird\file)") == R"(folder/weird\file)");
}
}
TEST_CASE("path_is_prefix")
{
CHECK(path_is_prefix("", ""));
CHECK(path_is_prefix("", "folder"));
REQUIRE(path_is_prefix("", ""));
REQUIRE(path_is_prefix("", "folder"));
CHECK(path_is_prefix("folder", "folder"));
CHECK(path_is_prefix("/", "/folder"));
CHECK(path_is_prefix("/folder", "/folder"));
CHECK(path_is_prefix("/folder/", "/folder/"));
CHECK(path_is_prefix("/folder", "/folder/"));
CHECK(path_is_prefix("/folder/", "/folder/"));
CHECK(path_is_prefix("/folder", "/folder/file.txt"));
CHECK(path_is_prefix("/folder/", "/folder/file.txt"));
CHECK(path_is_prefix("/folder", "/folder/more/file.txt"));
CHECK(path_is_prefix("/folder/", "/folder/more/file.txt"));
CHECK(path_is_prefix("/folder/file.txt", "/folder/file.txt"));
CHECK(path_is_prefix("folder/file.txt", "folder/file.txt"));
REQUIRE(path_is_prefix("folder", "folder"));
REQUIRE(path_is_prefix("/", "/folder"));
REQUIRE(path_is_prefix("/folder", "/folder"));
REQUIRE(path_is_prefix("/folder/", "/folder/"));
REQUIRE(path_is_prefix("/folder", "/folder/"));
REQUIRE(path_is_prefix("/folder/", "/folder/"));
REQUIRE(path_is_prefix("/folder", "/folder/file.txt"));
REQUIRE(path_is_prefix("/folder/", "/folder/file.txt"));
REQUIRE(path_is_prefix("/folder", "/folder/more/file.txt"));
REQUIRE(path_is_prefix("/folder/", "/folder/more/file.txt"));
REQUIRE(path_is_prefix("/folder/file.txt", "/folder/file.txt"));
REQUIRE(path_is_prefix("folder/file.txt", "folder/file.txt"));
CHECK_FALSE(path_is_prefix("/folder", "/"));
CHECK_FALSE(path_is_prefix("/folder/file", "/folder"));
CHECK_FALSE(path_is_prefix("/folder", "/folder-more"));
CHECK_FALSE(path_is_prefix("/folder/file.json", "/folder/file.txt"));
CHECK_FALSE(path_is_prefix("folder/file.json", "folder/file.txt"));
REQUIRE_FALSE(path_is_prefix("/folder", "/"));
REQUIRE_FALSE(path_is_prefix("/folder/file", "/folder"));
REQUIRE_FALSE(path_is_prefix("/folder", "/folder-more"));
REQUIRE_FALSE(path_is_prefix("/folder/file.json", "/folder/file.txt"));
REQUIRE_FALSE(path_is_prefix("folder/file.json", "folder/file.txt"));
// Debatable "folder/" interpreted as ["folder", ""] in term of splits.
CHECK_FALSE(path_is_prefix("folder/", "folder"));
CHECK_FALSE(path_is_prefix("/folder/", "/folder"));
REQUIRE_FALSE(path_is_prefix("folder/", "folder"));
REQUIRE_FALSE(path_is_prefix("/folder/", "/folder"));
}
TEST_CASE("path_concat")
{
SUBCASE("proper concatenation")
SECTION("proper concatenation")
{
CHECK_EQ(path_concat("", "file", '/'), "file");
CHECK_EQ(path_concat("some/folder", "", '/'), "some/folder");
REQUIRE(path_concat("", "file", '/') == "file");
REQUIRE(path_concat("some/folder", "", '/') == "some/folder");
CHECK_EQ(path_concat("some/folder", "file", '/'), "some/folder/file");
CHECK_EQ(path_concat("some/folder/", "file", '/'), "some/folder/file");
CHECK_EQ(path_concat("some/folder", "/file", '/'), "some/folder/file");
CHECK_EQ(path_concat("some/folder/", "/file", '/'), "some/folder/file");
REQUIRE(path_concat("some/folder", "file", '/') == "some/folder/file");
REQUIRE(path_concat("some/folder/", "file", '/') == "some/folder/file");
REQUIRE(path_concat("some/folder", "/file", '/') == "some/folder/file");
REQUIRE(path_concat("some/folder/", "/file", '/') == "some/folder/file");
}
SUBCASE("Separator detection")
SECTION("Separator detection")
{
CHECK_EQ(path_concat("some/folder", "file"), "some/folder/file");
REQUIRE(path_concat("some/folder", "file") == "some/folder/file");
if (on_win)
{
CHECK_EQ(path_concat(R"(D:\some\folder)", "file"), R"(D:\some\folder\file)");
REQUIRE(path_concat(R"(D:\some\folder)", "file") == R"(D:\some\folder\file)");
}
}
}
TEST_CASE("expand_home")
{
CHECK_EQ(expand_home("", ""), "");
CHECK_EQ(expand_home("~", ""), "");
CHECK_EQ(expand_home("", "/user/mamba"), "");
CHECK_EQ(expand_home("~", "/user/mamba"), "/user/mamba");
CHECK_EQ(expand_home("~/", "/user/mamba"), "/user/mamba/");
CHECK_EQ(expand_home("~/folder", "/user/mamba"), "/user/mamba/folder");
CHECK_EQ(expand_home("~/folder", "/user/mamba/"), "/user/mamba/folder");
CHECK_EQ(expand_home("file~name", "/user/mamba"), "file~name");
CHECK_EQ(expand_home("~file", "/user/mamba"), "~file");
CHECK_EQ(expand_home("~/foo", "."), "./foo");
REQUIRE(expand_home("", "") == "");
REQUIRE(expand_home("~", "") == "");
REQUIRE(expand_home("", "/user/mamba") == "");
REQUIRE(expand_home("~", "/user/mamba") == "/user/mamba");
REQUIRE(expand_home("~/", "/user/mamba") == "/user/mamba/");
REQUIRE(expand_home("~/folder", "/user/mamba") == "/user/mamba/folder");
REQUIRE(expand_home("~/folder", "/user/mamba/") == "/user/mamba/folder");
REQUIRE(expand_home("file~name", "/user/mamba") == "file~name");
REQUIRE(expand_home("~file", "/user/mamba") == "~file");
REQUIRE(expand_home("~/foo", ".") == "./foo");
}
TEST_CASE("shrink_home")
{
CHECK_EQ(shrink_home("", ""), "");
CHECK_EQ(shrink_home("/user/mamba", ""), "/user/mamba");
CHECK_EQ(shrink_home("/user/mamba", "/user/mamba"), "~");
CHECK_EQ(shrink_home("/user/mamba/", "/user/mamba"), "~/"); // Final "/" as in first input
CHECK_EQ(shrink_home("/user/mamba", "/user/mamba/"), "~");
CHECK_EQ(shrink_home("/user/mamba/", "/user/mamba/"), "~/"); // Final "/" as in first input
CHECK_EQ(shrink_home("/user/mamba/file", "/user/mamba"), "~/file");
CHECK_EQ(shrink_home("/user/mamba/file", "/user/mamba/"), "~/file");
CHECK_EQ(shrink_home("/user/mamba-dev/file", "/user/mamba"), "/user/mamba-dev/file");
REQUIRE(shrink_home("", "") == "");
REQUIRE(shrink_home("/user/mamba", "") == "/user/mamba");
REQUIRE(shrink_home("/user/mamba", "/user/mamba") == "~");
REQUIRE(shrink_home("/user/mamba/", "/user/mamba") == "~/"); // Final "/" as in first input
REQUIRE(shrink_home("/user/mamba", "/user/mamba/") == "~");
REQUIRE(shrink_home("/user/mamba/", "/user/mamba/") == "~/"); // Final "/" as in first
// input
REQUIRE(shrink_home("/user/mamba/file", "/user/mamba") == "~/file");
REQUIRE(shrink_home("/user/mamba/file", "/user/mamba/") == "~/file");
REQUIRE(shrink_home("/user/mamba-dev/file", "/user/mamba") == "/user/mamba-dev/file");
}
}

View File

@ -6,14 +6,14 @@
#include <thread>
#include <doctest/doctest.h>
#include <catch2/catch_all.hpp>
#include "mamba/util/random.hpp"
#include "mamba/util/string.hpp"
using namespace mamba::util;
TEST_SUITE("util::random")
namespace
{
TEST_CASE("local_random_generator")
{
@ -21,13 +21,13 @@ TEST_SUITE("util::random")
{
auto& a = local_random_generator();
auto& b = local_random_generator();
CHECK_EQ(&a, &b);
REQUIRE(&a == &b);
auto& c = local_random_generator<std::mt19937>();
CHECK_EQ(&a, &c);
REQUIRE(&a == &c);
auto& d = local_random_generator<std::mt19937_64>();
CHECK_NE(static_cast<void*>(&a), static_cast<void*>(&d));
REQUIRE(static_cast<void*>(&a) != static_cast<void*>(&d));
return &a;
};
@ -37,7 +37,7 @@ TEST_SUITE("util::random")
std::thread another_thread{ [&] { pointer_to_another_thread_rng = same_thread_checks(); } };
another_thread.join();
CHECK_NE(pointer_to_this_thread_rng, pointer_to_another_thread_rng);
REQUIRE(pointer_to_this_thread_rng != pointer_to_another_thread_rng);
}
TEST_CASE("value_in_range")
@ -48,8 +48,8 @@ TEST_SUITE("util::random")
for (std::size_t i = 0; i < attempts; ++i)
{
const int value = random_int(arbitrary_min, arbitrary_max);
CHECK_GE(value, arbitrary_min);
CHECK_LE(value, arbitrary_max);
REQUIRE(value >= arbitrary_min);
REQUIRE(value <= arbitrary_max);
}
}
@ -59,8 +59,8 @@ TEST_SUITE("util::random")
for (std::size_t i = 0; i < attempts; ++i)
{
const auto value = generate_random_alphanumeric_string(i);
CHECK_EQ(value.size(), i);
CHECK(std::all_of(
REQUIRE(value.size() == i);
REQUIRE(std::all_of(
value.cbegin(),
value.cend(),
[](char c) { return is_digit(c) || is_alpha(c); }

View File

@ -8,303 +8,304 @@
#include <string_view>
#include <vector>
#include <doctest/doctest.h>
#include <catch2/catch_all.hpp>
#include "mamba/fs/filesystem.hpp"
#include "mamba/util/string.hpp"
#include "doctest-printer/array.hpp"
#include "doctest-printer/optional.hpp"
using namespace mamba::util;
namespace
{
TEST_SUITE("util::string")
namespace
{
TEST_CASE("to_lower")
{
CHECK_EQ(to_lower('A'), 'a');
CHECK_EQ(to_lower('b'), 'b');
CHECK_EQ(to_lower("ThisIsARandomTTTeeesssT"), "thisisarandomttteeessst");
REQUIRE(to_lower('A') == 'a');
REQUIRE(to_lower('b') == 'b');
REQUIRE(to_lower("ThisIsARandomTTTeeesssT") == "thisisarandomttteeessst");
}
TEST_CASE("to_upper")
{
CHECK_EQ(to_upper('a'), 'A');
CHECK_EQ(to_upper('B'), 'B');
CHECK_EQ(to_upper("ThisIsARandomTTTeeesssT"), "THISISARANDOMTTTEEESSST");
REQUIRE(to_upper('a') == 'A');
REQUIRE(to_upper('B') == 'B');
REQUIRE(to_upper("ThisIsARandomTTTeeesssT") == "THISISARANDOMTTTEEESSST");
}
TEST_CASE("starts_with")
{
CHECK(starts_with("", ""));
CHECK_FALSE(starts_with("", ":"));
CHECK_FALSE(starts_with("", ':'));
CHECK(starts_with(":hello", ""));
CHECK(starts_with(":hello", ":"));
CHECK(starts_with(":hello", ':'));
CHECK(starts_with(":hello", ":h"));
CHECK(starts_with(":hello", ":hello"));
CHECK_FALSE(starts_with(":hello", "lo"));
CHECK(starts_with("áäᜩgþhëb®hüghœ©®xb", "áäᜩ"));
REQUIRE(starts_with("", ""));
REQUIRE_FALSE(starts_with("", ":"));
REQUIRE_FALSE(starts_with("", ':'));
REQUIRE(starts_with(":hello", ""));
REQUIRE(starts_with(":hello", ":"));
REQUIRE(starts_with(":hello", ':'));
REQUIRE(starts_with(":hello", ":h"));
REQUIRE(starts_with(":hello", ":hello"));
REQUIRE_FALSE(starts_with(":hello", "lo"));
REQUIRE(starts_with("áäᜩgþhëb®hüghœ©®xb", "áäᜩ"));
}
TEST_CASE("ends_with")
{
CHECK(ends_with("", ""));
CHECK_FALSE(ends_with("", "&"));
CHECK_FALSE(ends_with("", '&'));
CHECK(ends_with("hello&", ""));
CHECK(ends_with("hello&", "&"));
CHECK(ends_with("hello&", '&'));
CHECK(ends_with("hello&", "o&"));
CHECK(ends_with("hello&", "hello&"));
CHECK_FALSE(ends_with("hello&", "he"));
CHECK(ends_with("áäᜩgþhëb®hüghœ©®xb", "©®xb"));
REQUIRE(ends_with("", ""));
REQUIRE_FALSE(ends_with("", "&"));
REQUIRE_FALSE(ends_with("", '&'));
REQUIRE(ends_with("hello&", ""));
REQUIRE(ends_with("hello&", "&"));
REQUIRE(ends_with("hello&", '&'));
REQUIRE(ends_with("hello&", "o&"));
REQUIRE(ends_with("hello&", "hello&"));
REQUIRE_FALSE(ends_with("hello&", "he"));
REQUIRE(ends_with("áäᜩgþhëb®hüghœ©®xb", "©®xb"));
}
TEST_CASE("contains")
TEST_CASE("string_contains")
{
CHECK(contains('c', 'c'));
CHECK_FALSE(contains('c', 'a'));
CHECK(contains(":hello&", ""));
CHECK(contains(":hello&", '&'));
CHECK(contains(":hello&", ':'));
CHECK(contains(":hello&", "ll"));
CHECK_FALSE(contains(":hello&", "eo"));
CHECK(contains("áäᜩgþhëb®hüghœ©®xb", "ëb®"));
CHECK_FALSE(contains("", "ab"));
CHECK(contains("", "")); // same as Python ``"" in ""``
REQUIRE(contains('c', 'c'));
REQUIRE_FALSE(contains('c', 'a'));
REQUIRE(contains(":hello&", ""));
REQUIRE(contains(":hello&", '&'));
REQUIRE(contains(":hello&", ':'));
REQUIRE(contains(":hello&", "ll"));
REQUIRE_FALSE(contains(":hello&", "eo"));
REQUIRE(contains("áäᜩgþhëb®hüghœ©®xb", "ëb®"));
REQUIRE_FALSE(contains("", "ab"));
REQUIRE(contains("", "")); // same as Python ``"" in ""``
}
TEST_CASE("split_prefix")
{
using PrefixTail = decltype(split_prefix("", ""));
CHECK_EQ(split_prefix("", ""), PrefixTail{ "", "" });
CHECK_EQ(split_prefix("hello", ""), PrefixTail{ "", "hello" });
CHECK_EQ(split_prefix("hello", "hello"), PrefixTail{ "hello", "" });
CHECK_EQ(split_prefix("", "hello"), PrefixTail{ "", "" });
CHECK_EQ(
split_prefix("https://localhost", "https://"),
PrefixTail{ "https://", "localhost" }
REQUIRE(split_prefix("", "") == PrefixTail{ "", "" });
REQUIRE(split_prefix("hello", "") == PrefixTail{ "", "hello" });
REQUIRE(split_prefix("hello", "hello") == PrefixTail{ "hello", "" });
REQUIRE(split_prefix("", "hello") == PrefixTail{ "", "" });
REQUIRE(
split_prefix("https://localhost", "https://") == PrefixTail{ "https://", "localhost" }
);
CHECK_EQ(
split_prefix("https://localhost", "http://"),
PrefixTail{ "", "https://localhost" }
REQUIRE(
split_prefix("https://localhost", "http://") == PrefixTail{ "", "https://localhost" }
);
CHECK_EQ(split_prefix("aabb", "a"), PrefixTail{ "a", "abb" });
CHECK_EQ(split_prefix("", 'a'), PrefixTail{ "", "" });
CHECK_EQ(split_prefix("a", 'a'), PrefixTail{ "a", "" });
CHECK_EQ(split_prefix("aaa", 'a'), PrefixTail{ "a", "aa" });
CHECK_EQ(split_prefix("aabb", 'b'), PrefixTail{ "", "aabb" });
REQUIRE(split_prefix("aabb", "a") == PrefixTail{ "a", "abb" });
REQUIRE(split_prefix("", 'a') == PrefixTail{ "", "" });
REQUIRE(split_prefix("a", 'a') == PrefixTail{ "a", "" });
REQUIRE(split_prefix("aaa", 'a') == PrefixTail{ "a", "aa" });
REQUIRE(split_prefix("aabb", 'b') == PrefixTail{ "", "aabb" });
}
TEST_CASE("remove_prefix")
{
CHECK_EQ(remove_prefix("", ""), "");
CHECK_EQ(remove_prefix("hello", ""), "hello");
CHECK_EQ(remove_prefix("hello", "hello"), "");
CHECK_EQ(remove_prefix("", "hello"), "");
CHECK_EQ(remove_prefix("https://localhost", "https://"), "localhost");
CHECK_EQ(remove_prefix("https://localhost", "http://"), "https://localhost");
CHECK_EQ(remove_prefix("aabb", "a"), "abb");
CHECK_EQ(remove_prefix("", 'a'), "");
CHECK_EQ(remove_prefix("a", 'a'), "");
CHECK_EQ(remove_prefix("aaa", 'a'), "aa");
CHECK_EQ(remove_prefix("aabb", 'b'), "aabb");
REQUIRE(remove_prefix("", "") == "");
REQUIRE(remove_prefix("hello", "") == "hello");
REQUIRE(remove_prefix("hello", "hello") == "");
REQUIRE(remove_prefix("", "hello") == "");
REQUIRE(remove_prefix("https://localhost", "https://") == "localhost");
REQUIRE(remove_prefix("https://localhost", "http://") == "https://localhost");
REQUIRE(remove_prefix("aabb", "a") == "abb");
REQUIRE(remove_prefix("", 'a') == "");
REQUIRE(remove_prefix("a", 'a') == "");
REQUIRE(remove_prefix("aaa", 'a') == "aa");
REQUIRE(remove_prefix("aabb", 'b') == "aabb");
}
TEST_CASE("split_suffix")
{
using HeadSuffix = decltype(split_suffix("", ""));
CHECK_EQ(split_suffix("", ""), HeadSuffix{ "", "" });
CHECK_EQ(split_suffix("hello", ""), HeadSuffix{ "hello", "" });
CHECK_EQ(split_suffix("hello", "hello"), HeadSuffix{ "", "hello" });
CHECK_EQ(split_suffix("", "hello"), HeadSuffix{ "", "" });
CHECK_EQ(split_suffix("localhost:8080", ":8080"), HeadSuffix{ "localhost", ":8080" });
CHECK_EQ(split_suffix("localhost:8080", ":80"), HeadSuffix{ "localhost:8080", "" });
CHECK_EQ(split_suffix("aabb", "b"), HeadSuffix{ "aab", "b" });
CHECK_EQ(split_suffix("", 'b'), HeadSuffix{ "", "" });
CHECK_EQ(split_suffix("b", 'b'), HeadSuffix{ "", "b" });
CHECK_EQ(split_suffix("bbb", 'b'), HeadSuffix{ "bb", "b" });
CHECK_EQ(split_suffix("aabb", 'a'), HeadSuffix{ "aabb", "" });
REQUIRE(split_suffix("", "") == HeadSuffix{ "", "" });
REQUIRE(split_suffix("hello", "") == HeadSuffix{ "hello", "" });
REQUIRE(split_suffix("hello", "hello") == HeadSuffix{ "", "hello" });
REQUIRE(split_suffix("", "hello") == HeadSuffix{ "", "" });
REQUIRE(split_suffix("localhost:8080", ":8080") == HeadSuffix{ "localhost", ":8080" });
REQUIRE(split_suffix("localhost:8080", ":80") == HeadSuffix{ "localhost:8080", "" });
REQUIRE(split_suffix("aabb", "b") == HeadSuffix{ "aab", "b" });
REQUIRE(split_suffix("", 'b') == HeadSuffix{ "", "" });
REQUIRE(split_suffix("b", 'b') == HeadSuffix{ "", "b" });
REQUIRE(split_suffix("bbb", 'b') == HeadSuffix{ "bb", "b" });
REQUIRE(split_suffix("aabb", 'a') == HeadSuffix{ "aabb", "" });
}
TEST_CASE("remove_suffix")
{
CHECK_EQ(remove_suffix("", ""), "");
CHECK_EQ(remove_suffix("hello", ""), "hello");
CHECK_EQ(remove_suffix("hello", "hello"), "");
CHECK_EQ(remove_suffix("", "hello"), "");
CHECK_EQ(remove_suffix("localhost:8080", ":8080"), "localhost");
CHECK_EQ(remove_suffix("localhost:8080", ":80"), "localhost:8080");
CHECK_EQ(remove_suffix("aabb", "b"), "aab");
CHECK_EQ(remove_suffix("", 'b'), "");
CHECK_EQ(remove_suffix("b", 'b'), "");
CHECK_EQ(remove_suffix("bbb", 'b'), "bb");
CHECK_EQ(remove_suffix("aabb", 'a'), "aabb");
REQUIRE(remove_suffix("", "") == "");
REQUIRE(remove_suffix("hello", "") == "hello");
REQUIRE(remove_suffix("hello", "hello") == "");
REQUIRE(remove_suffix("", "hello") == "");
REQUIRE(remove_suffix("localhost:8080", ":8080") == "localhost");
REQUIRE(remove_suffix("localhost:8080", ":80") == "localhost:8080");
REQUIRE(remove_suffix("aabb", "b") == "aab");
REQUIRE(remove_suffix("", 'b') == "");
REQUIRE(remove_suffix("b", 'b') == "");
REQUIRE(remove_suffix("bbb", 'b') == "bb");
REQUIRE(remove_suffix("aabb", 'a') == "aabb");
}
TEST_CASE("any_starts_with")
{
using StrVec = std::vector<std::string_view>;
CHECK_FALSE(any_starts_with(StrVec{}, { "not" }));
CHECK_FALSE(any_starts_with(StrVec{}, ""));
CHECK(any_starts_with(StrVec{ ":hello", "world" }, ""));
CHECK(any_starts_with(StrVec{ ":hello", "world" }, ":"));
CHECK(any_starts_with(StrVec{ ":hello", "world" }, ":h"));
CHECK(any_starts_with(StrVec{ ":hello", "world" }, ":hello"));
CHECK_FALSE(any_starts_with(StrVec{ ":hello", "world" }, "orld"));
CHECK(any_starts_with(StrVec{ "áäᜩgþhëb", "®hüghœ©®xb" }, "áäá"));
REQUIRE_FALSE(any_starts_with(StrVec{}, { "not" }));
REQUIRE_FALSE(any_starts_with(StrVec{}, ""));
REQUIRE(any_starts_with(StrVec{ ":hello", "world" }, ""));
REQUIRE(any_starts_with(StrVec{ ":hello", "world" }, ":"));
REQUIRE(any_starts_with(StrVec{ ":hello", "world" }, ":h"));
REQUIRE(any_starts_with(StrVec{ ":hello", "world" }, ":hello"));
REQUIRE_FALSE(any_starts_with(StrVec{ ":hello", "world" }, "orld"));
REQUIRE(any_starts_with(StrVec{ "áäᜩgþhëb", "®hüghœ©®xb" }, "áäá"));
}
TEST_CASE("starts_with_any")
{
using StrVec = std::vector<std::string_view>;
CHECK(starts_with_any(":hello", StrVec{ "", "not" }));
CHECK(starts_with_any(":hello", StrVec{ ":hello", "not" }));
CHECK_FALSE(starts_with_any(":hello", StrVec{}));
CHECK_FALSE(starts_with_any(":hello", StrVec{ "not", "any" }));
CHECK(starts_with_any("áäᜩgþhëb®hüghœ©®xb", StrVec{ "áäᜩgþhëb", "®hüghœ©®xb" }));
REQUIRE(starts_with_any(":hello", StrVec{ "", "not" }));
REQUIRE(starts_with_any(":hello", StrVec{ ":hello", "not" }));
REQUIRE_FALSE(starts_with_any(":hello", StrVec{}));
REQUIRE_FALSE(starts_with_any(":hello", StrVec{ "not", "any" }));
REQUIRE(starts_with_any("áäᜩgþhëb®hüghœ©®xb", StrVec{ "áäᜩgþhëb", "®hüghœ©®xb" }));
}
TEST_CASE("lstrip")
{
CHECK_EQ(lstrip("\n \thello \t\n"), "hello \t\n");
CHECK_EQ(lstrip(":::hello%:%", ":%"), "hello%:%");
CHECK_EQ(lstrip(":::hello%:%", ':'), "hello%:%");
CHECK_EQ(lstrip(":::hello%:%", '%'), ":::hello%:%");
CHECK_EQ(lstrip("", '%'), "");
CHECK_EQ(lstrip("aaa", 'a'), "");
CHECK_EQ(lstrip("aaa", 'b'), "aaa");
REQUIRE(lstrip("\n \thello \t\n") == "hello \t\n");
REQUIRE(lstrip(":::hello%:%", ":%") == "hello%:%");
REQUIRE(lstrip(":::hello%:%", ':') == "hello%:%");
REQUIRE(lstrip(":::hello%:%", '%') == ":::hello%:%");
REQUIRE(lstrip("", '%') == "");
REQUIRE(lstrip("aaa", 'a') == "");
REQUIRE(lstrip("aaa", 'b') == "aaa");
}
TEST_CASE("lstrip_parts")
{
using StrPair = std::array<std::string_view, 2>;
CHECK_EQ(lstrip_parts(":::hello%:%", ":%"), StrPair({ ":::", "hello%:%" }));
CHECK_EQ(lstrip_parts(":::hello%:%", ':'), StrPair({ ":::", "hello%:%" }));
CHECK_EQ(lstrip_parts(":::hello%:%", '%'), StrPair({ "", ":::hello%:%" }));
CHECK_EQ(lstrip_parts("", '%'), StrPair({ "", "" }));
CHECK_EQ(lstrip_parts("aaa", 'a'), StrPair({ "aaa", "" }));
CHECK_EQ(lstrip_parts("aaa", 'b'), StrPair({ "", "aaa" }));
REQUIRE(lstrip_parts(":::hello%:%", ":%") == StrPair({ ":::", "hello%:%" }));
REQUIRE(lstrip_parts(":::hello%:%", ':') == StrPair({ ":::", "hello%:%" }));
REQUIRE(lstrip_parts(":::hello%:%", '%') == StrPair({ "", ":::hello%:%" }));
REQUIRE(lstrip_parts("", '%') == StrPair({ "", "" }));
REQUIRE(lstrip_parts("aaa", 'a') == StrPair({ "aaa", "" }));
REQUIRE(lstrip_parts("aaa", 'b') == StrPair({ "", "aaa" }));
}
TEST_CASE("lstrip_if")
{
CHECK_EQ(lstrip_if("", [](auto) { return true; }), "");
CHECK_EQ(lstrip_if("hello", [](auto) { return true; }), "");
CHECK_EQ(lstrip_if("hello", [](auto) { return false; }), "hello");
CHECK_EQ(lstrip_if("\n \thello \t\n", [](auto c) { return !is_alphanum(c); }), "hello \t\n");
CHECK_EQ(lstrip_if("123hello456", [](auto c) { return is_digit(c); }), "hello456");
REQUIRE(lstrip_if("", [](auto) { return true; }) == "");
REQUIRE(lstrip_if("hello", [](auto) { return true; }) == "");
REQUIRE(lstrip_if("hello", [](auto) { return false; }) == "hello");
REQUIRE(
lstrip_if("\n \thello \t\n", [](auto c) { return !is_alphanum(c); }) == "hello \t\n"
);
REQUIRE(lstrip_if("123hello456", [](auto c) { return is_digit(c); }) == "hello456");
}
TEST_CASE("lstrip_if_parts")
{
using StrPair = std::array<std::string_view, 2>;
CHECK_EQ(lstrip_if_parts("", [](auto) { return true; }), StrPair({ "", "" }));
CHECK_EQ(lstrip_if_parts("hello", [](auto) { return true; }), StrPair({ "hello", "" }));
CHECK_EQ(lstrip_if_parts("hello", [](auto) { return false; }), StrPair({ "", "hello" }));
CHECK_EQ(
lstrip_if_parts("\n \thello \t\n", [](auto c) { return !is_alphanum(c); }),
StrPair({ "\n \t", "hello \t\n" })
REQUIRE(lstrip_if_parts("", [](auto) { return true; }) == StrPair({ "", "" }));
REQUIRE(lstrip_if_parts("hello", [](auto) { return true; }) == StrPair({ "hello", "" }));
REQUIRE(lstrip_if_parts("hello", [](auto) { return false; }) == StrPair({ "", "hello" }));
REQUIRE(
lstrip_if_parts("\n \thello \t\n", [](auto c) { return !is_alphanum(c); })
== StrPair({ "\n \t", "hello \t\n" })
);
CHECK_EQ(
lstrip_if_parts("123hello456", [](auto c) { return is_digit(c); }),
StrPair({ "123", "hello456" })
REQUIRE(
lstrip_if_parts("123hello456", [](auto c) { return is_digit(c); })
== StrPair({ "123", "hello456" })
);
}
TEST_CASE("rstrip")
{
CHECK_EQ(rstrip("\n \thello \t\n"), "\n \thello");
CHECK_EQ(rstrip(":::hello%:%", '%'), ":::hello%:");
CHECK_EQ(rstrip(":::hello%:%", ":%"), ":::hello");
CHECK_EQ(rstrip(":::hello%:%", ':'), ":::hello%:%");
CHECK_EQ(rstrip("", '%'), "");
CHECK_EQ(rstrip("aaa", 'a'), "");
CHECK_EQ(rstrip("aaa", 'b'), "aaa");
REQUIRE(rstrip("\n \thello \t\n") == "\n \thello");
REQUIRE(rstrip(":::hello%:%", '%') == ":::hello%:");
REQUIRE(rstrip(":::hello%:%", ":%") == ":::hello");
REQUIRE(rstrip(":::hello%:%", ':') == ":::hello%:%");
REQUIRE(rstrip("", '%') == "");
REQUIRE(rstrip("aaa", 'a') == "");
REQUIRE(rstrip("aaa", 'b') == "aaa");
}
TEST_CASE("rstrip_parts")
{
using StrPair = std::array<std::string_view, 2>;
CHECK_EQ(rstrip_parts(":::hello%:%", '%'), StrPair({ ":::hello%:", "%" }));
CHECK_EQ(rstrip_parts(":::hello%:%", ":%"), StrPair({ ":::hello", "%:%" }));
CHECK_EQ(rstrip_parts(":::hello%:%", ':'), StrPair({ ":::hello%:%", "" }));
CHECK_EQ(rstrip_parts("", '%'), StrPair({ "", "" }));
CHECK_EQ(rstrip_parts("aaa", 'a'), StrPair({ "", "aaa" }));
CHECK_EQ(rstrip_parts("aaa", 'b'), StrPair({ "aaa", "" }));
REQUIRE(rstrip_parts(":::hello%:%", '%') == StrPair({ ":::hello%:", "%" }));
REQUIRE(rstrip_parts(":::hello%:%", ":%") == StrPair({ ":::hello", "%:%" }));
REQUIRE(rstrip_parts(":::hello%:%", ':') == StrPair({ ":::hello%:%", "" }));
REQUIRE(rstrip_parts("", '%') == StrPair({ "", "" }));
REQUIRE(rstrip_parts("aaa", 'a') == StrPair({ "", "aaa" }));
REQUIRE(rstrip_parts("aaa", 'b') == StrPair({ "aaa", "" }));
}
TEST_CASE("rstrip_if")
{
CHECK_EQ(rstrip_if("", [](auto) { return true; }), "");
CHECK_EQ(rstrip_if("hello", [](auto) { return true; }), "");
CHECK_EQ(rstrip_if("hello", [](auto) { return false; }), "hello");
CHECK_EQ(rstrip_if("\n \thello \t\n", [](auto c) { return !is_alphanum(c); }), "\n \thello");
CHECK_EQ(rstrip_if("123hello456", [](auto c) { return is_digit(c); }), "123hello");
REQUIRE(rstrip_if("", [](auto) { return true; }) == "");
REQUIRE(rstrip_if("hello", [](auto) { return true; }) == "");
REQUIRE(rstrip_if("hello", [](auto) { return false; }) == "hello");
REQUIRE(
rstrip_if("\n \thello \t\n", [](auto c) { return !is_alphanum(c); }) == "\n \thello"
);
REQUIRE(rstrip_if("123hello456", [](auto c) { return is_digit(c); }) == "123hello");
}
TEST_CASE("rstrip_if_parts")
{
using StrPair = std::array<std::string_view, 2>;
CHECK_EQ(rstrip_if_parts("", [](auto) { return true; }), StrPair({ "", "" }));
CHECK_EQ(rstrip_if_parts("hello", [](auto) { return true; }), StrPair({ "", "hello" }));
CHECK_EQ(rstrip_if_parts("hello", [](auto) { return false; }), StrPair({ "hello", "" }));
CHECK_EQ(
rstrip_if_parts("\n \thello \t\n", [](auto c) { return !is_alphanum(c); }),
StrPair({ "\n \thello", " \t\n" })
REQUIRE(rstrip_if_parts("", [](auto) { return true; }) == StrPair({ "", "" }));
REQUIRE(rstrip_if_parts("hello", [](auto) { return true; }) == StrPair({ "", "hello" }));
REQUIRE(rstrip_if_parts("hello", [](auto) { return false; }) == StrPair({ "hello", "" }));
REQUIRE(
rstrip_if_parts("\n \thello \t\n", [](auto c) { return !is_alphanum(c); })
== StrPair({ "\n \thello", " \t\n" })
);
CHECK_EQ(
rstrip_if_parts("123hello456", [](auto c) { return is_digit(c); }),
StrPair({ "123hello", "456" })
REQUIRE(
rstrip_if_parts("123hello456", [](auto c) { return is_digit(c); })
== StrPair({ "123hello", "456" })
);
}
TEST_CASE("strip")
{
CHECK_EQ(strip(" hello \t\n"), "hello");
CHECK_EQ(strip(":::hello%:%", ":%"), "hello");
CHECK_EQ(strip(":::hello%:%", ':'), "hello%:%");
CHECK_EQ(strip("", '%'), "");
CHECK_EQ(strip("aaa", 'a'), "");
CHECK_EQ(strip("aaa", 'b'), "aaa");
REQUIRE(strip(" hello \t\n") == "hello");
REQUIRE(strip(":::hello%:%", ":%") == "hello");
REQUIRE(strip(":::hello%:%", ':') == "hello%:%");
REQUIRE(strip("", '%') == "");
REQUIRE(strip("aaa", 'a') == "");
REQUIRE(strip("aaa", 'b') == "aaa");
}
TEST_CASE("strip_parts")
{
using StrTrio = std::array<std::string_view, 3>;
CHECK_EQ(strip_parts(":::hello%:%", ":%"), StrTrio({ ":::", "hello", "%:%" }));
CHECK_EQ(strip_parts(":::hello%:%", ':'), StrTrio({ ":::", "hello%:%", "" }));
CHECK_EQ(strip_parts("", '%'), StrTrio({ "", "", "" }));
CHECK_EQ(strip_parts("aaa", 'a'), StrTrio({ "aaa", "", "" }));
CHECK_EQ(strip_parts("aaa", 'b'), StrTrio({ "", "aaa", "" }));
REQUIRE(strip_parts(":::hello%:%", ":%") == StrTrio({ ":::", "hello", "%:%" }));
REQUIRE(strip_parts(":::hello%:%", ':') == StrTrio({ ":::", "hello%:%", "" }));
REQUIRE(strip_parts("", '%') == StrTrio({ "", "", "" }));
REQUIRE(strip_parts("aaa", 'a') == StrTrio({ "aaa", "", "" }));
REQUIRE(strip_parts("aaa", 'b') == StrTrio({ "", "aaa", "" }));
}
TEST_CASE("strip_if")
{
CHECK_EQ(strip_if("", [](auto) { return true; }), "");
CHECK_EQ(strip_if("hello", [](auto) { return true; }), "");
CHECK_EQ(strip_if("hello", [](auto) { return false; }), "hello");
CHECK_EQ(strip_if("\n \thello \t\n", [](auto c) { return !is_alphanum(c); }), "hello");
CHECK_EQ(strip_if("123hello456", [](auto c) { return is_digit(c); }), "hello");
REQUIRE(strip_if("", [](auto) { return true; }) == "");
REQUIRE(strip_if("hello", [](auto) { return true; }) == "");
REQUIRE(strip_if("hello", [](auto) { return false; }) == "hello");
REQUIRE(strip_if("\n \thello \t\n", [](auto c) { return !is_alphanum(c); }) == "hello");
REQUIRE(strip_if("123hello456", [](auto c) { return is_digit(c); }) == "hello");
}
TEST_CASE("strip_if_parts")
{
using StrTrio = std::array<std::string_view, 3>;
CHECK_EQ(strip_if_parts("", [](auto) { return true; }), StrTrio({ "", "", "" }));
CHECK_EQ(strip_if_parts("hello", [](auto) { return true; }), StrTrio({ "hello", "", "" }));
CHECK_EQ(strip_if_parts("hello", [](auto) { return false; }), StrTrio({ "", "hello", "" }));
CHECK_EQ(
strip_if_parts("\n \thello \t\n", [](auto c) { return !is_alphanum(c); }),
StrTrio({ "\n \t", "hello", " \t\n" })
REQUIRE(strip_if_parts("", [](auto) { return true; }) == StrTrio({ "", "", "" }));
REQUIRE(strip_if_parts("hello", [](auto) { return true; }) == StrTrio({ "hello", "", "" }));
REQUIRE(
strip_if_parts("hello", [](auto) { return false; }) == StrTrio({ "", "hello", "" })
);
CHECK_EQ(
strip_if_parts("123hello456", [](auto c) { return is_digit(c); }),
StrTrio({ "123", "hello", "456" })
REQUIRE(
strip_if_parts("\n \thello \t\n", [](auto c) { return !is_alphanum(c); })
== StrTrio({ "\n \t", "hello", " \t\n" })
);
REQUIRE(
strip_if_parts("123hello456", [](auto c) { return is_digit(c); })
== StrTrio({ "123", "hello", "456" })
);
}
@ -312,59 +313,59 @@ namespace
{
{
std::string x(strip(" testwhitespacestrip "));
CHECK_EQ(x, "testwhitespacestrip");
REQUIRE(x == "testwhitespacestrip");
std::string y(rstrip(" testwhitespacestrip "));
CHECK_EQ(y, " testwhitespacestrip");
REQUIRE(y == " testwhitespacestrip");
std::string z(lstrip(" testwhitespacestrip "));
CHECK_EQ(z, "testwhitespacestrip ");
REQUIRE(z == "testwhitespacestrip ");
}
{
std::string x(strip(" "));
CHECK_EQ(x, "");
REQUIRE(x == "");
std::string y(rstrip(" "));
CHECK_EQ(y, "");
REQUIRE(y == "");
std::string z(lstrip(" "));
CHECK_EQ(z, "");
REQUIRE(z == "");
}
{
std::string x(strip("a"));
CHECK_EQ(x, "a");
REQUIRE(x == "a");
std::string y(rstrip("a"));
CHECK_EQ(y, "a");
REQUIRE(y == "a");
std::string z(lstrip("a"));
CHECK_EQ(z, "a");
REQUIRE(z == "a");
}
{
std::string x(strip(" a "));
CHECK_EQ(x, "a");
REQUIRE(x == "a");
std::string y(rstrip(" a "));
CHECK_EQ(y, " a");
REQUIRE(y == " a");
std::string z(lstrip(" a "));
CHECK_EQ(z, "a ");
REQUIRE(z == "a ");
}
{
std::string x(strip("abc"));
CHECK_EQ(x, "abc");
REQUIRE(x == "abc");
std::string y(rstrip("abc"));
CHECK_EQ(y, "abc");
REQUIRE(y == "abc");
std::string z(lstrip("abc"));
CHECK_EQ(z, "abc");
REQUIRE(z == "abc");
}
{
std::string x(strip(" \r \t \n "));
CHECK_EQ(x, "");
REQUIRE(x == "");
std::string y(rstrip(" \r \t \n "));
CHECK_EQ(y, "");
REQUIRE(y == "");
std::string z(lstrip(" \r \t \n "));
CHECK_EQ(z, "");
REQUIRE(z == "");
}
{
std::string x(strip("\r \t \n testwhitespacestrip \r \t \n"));
CHECK_EQ(x, "testwhitespacestrip");
REQUIRE(x == "testwhitespacestrip");
std::string y(rstrip(" \r \t \n testwhitespacestrip \r \t \n"));
CHECK_EQ(y, " \r \t \n testwhitespacestrip");
REQUIRE(y == " \r \t \n testwhitespacestrip");
std::string z(lstrip(" \r \t \n testwhitespacestrip \r \t \n "));
CHECK_EQ(z, "testwhitespacestrip \r \t \n ");
REQUIRE(z == "testwhitespacestrip \r \t \n ");
}
}
@ -372,93 +373,93 @@ namespace
{
using Out = std::tuple<std::string_view, std::optional<std::string_view>>;
CHECK_EQ(split_once("", '/'), Out{ "", std::nullopt });
CHECK_EQ(split_once("/", '/'), Out{ "", "" });
CHECK_EQ(split_once("hello/world", '/'), Out{ "hello", "world" });
CHECK_EQ(split_once("hello/my/world", '/'), Out{ "hello", "my/world" });
CHECK_EQ(split_once("/hello/world", '/'), Out{ "", "hello/world" });
REQUIRE(split_once("", '/') == Out{ "", std::nullopt });
REQUIRE(split_once("/", '/') == Out{ "", "" });
REQUIRE(split_once("hello/world", '/') == Out{ "hello", "world" });
REQUIRE(split_once("hello/my/world", '/') == Out{ "hello", "my/world" });
REQUIRE(split_once("/hello/world", '/') == Out{ "", "hello/world" });
CHECK_EQ(split_once("", "/"), Out{ "", std::nullopt });
CHECK_EQ(split_once("hello/world", "/"), Out{ "hello", "world" });
CHECK_EQ(split_once("hello//world", "//"), Out{ "hello", "world" });
CHECK_EQ(split_once("hello/my//world", "/"), Out{ "hello", "my//world" });
CHECK_EQ(split_once("hello/my//world", "//"), Out{ "hello/my", "world" });
REQUIRE(split_once("", "/") == Out{ "", std::nullopt });
REQUIRE(split_once("hello/world", "/") == Out{ "hello", "world" });
REQUIRE(split_once("hello//world", "//") == Out{ "hello", "world" });
REQUIRE(split_once("hello/my//world", "/") == Out{ "hello", "my//world" });
REQUIRE(split_once("hello/my//world", "//") == Out{ "hello/my", "world" });
}
TEST_CASE("rsplit_once")
{
using Out = std::tuple<std::optional<std::string_view>, std::string_view>;
CHECK_EQ(rsplit_once("", '/'), Out{ std::nullopt, "" });
CHECK_EQ(rsplit_once("/", '/'), Out{ "", "" });
CHECK_EQ(rsplit_once("hello/world", '/'), Out{ "hello", "world" });
CHECK_EQ(rsplit_once("hello/my/world", '/'), Out{ "hello/my", "world" });
CHECK_EQ(rsplit_once("hello/world/", '/'), Out{ "hello/world", "" });
REQUIRE(rsplit_once("", '/') == Out{ std::nullopt, "" });
REQUIRE(rsplit_once("/", '/') == Out{ "", "" });
REQUIRE(rsplit_once("hello/world", '/') == Out{ "hello", "world" });
REQUIRE(rsplit_once("hello/my/world", '/') == Out{ "hello/my", "world" });
REQUIRE(rsplit_once("hello/world/", '/') == Out{ "hello/world", "" });
CHECK_EQ(rsplit_once("", "/"), Out{ std::nullopt, "" });
CHECK_EQ(rsplit_once("hello/world", "/"), Out{ "hello", "world" });
CHECK_EQ(rsplit_once("hello//world", "//"), Out{ "hello", "world" });
CHECK_EQ(rsplit_once("hello//my/world", "/"), Out{ "hello//my", "world" });
CHECK_EQ(rsplit_once("hello//my/world", "//"), Out{ "hello", "my/world" });
REQUIRE(rsplit_once("", "/") == Out{ std::nullopt, "" });
REQUIRE(rsplit_once("hello/world", "/") == Out{ "hello", "world" });
REQUIRE(rsplit_once("hello//world", "//") == Out{ "hello", "world" });
REQUIRE(rsplit_once("hello//my/world", "/") == Out{ "hello//my", "world" });
REQUIRE(rsplit_once("hello//my/world", "//") == Out{ "hello", "my/world" });
}
TEST_CASE("split_once_on_any")
{
using Out = std::tuple<std::string_view, std::optional<std::string_view>>;
CHECK_EQ(split_once_on_any("", "/"), Out{ "", std::nullopt });
CHECK_EQ(split_once_on_any("hello,dear world", ", "), Out{ "hello", "dear world" });
CHECK_EQ(split_once_on_any("hello dear,world", ", "), Out{ "hello", "dear,world" });
CHECK_EQ(split_once_on_any("hello/world", "/"), Out{ "hello", "world" });
CHECK_EQ(split_once_on_any("hello//world", "//"), Out{ "hello", "/world" });
CHECK_EQ(split_once_on_any("hello/my//world", "/"), Out{ "hello", "my//world" });
CHECK_EQ(split_once_on_any("hello/my//world", "//"), Out{ "hello", "my//world" });
REQUIRE(split_once_on_any("", "/") == Out{ "", std::nullopt });
REQUIRE(split_once_on_any("hello,dear world", ", ") == Out{ "hello", "dear world" });
REQUIRE(split_once_on_any("hello dear,world", ", ") == Out{ "hello", "dear,world" });
REQUIRE(split_once_on_any("hello/world", "/") == Out{ "hello", "world" });
REQUIRE(split_once_on_any("hello//world", "//") == Out{ "hello", "/world" });
REQUIRE(split_once_on_any("hello/my//world", "/") == Out{ "hello", "my//world" });
REQUIRE(split_once_on_any("hello/my//world", "//") == Out{ "hello", "my//world" });
}
TEST_CASE("rsplit_once_on_any")
{
using Out = std::tuple<std::optional<std::string_view>, std::string_view>;
CHECK_EQ(rsplit_once_on_any("", "/"), Out{ std::nullopt, "" });
CHECK_EQ(rsplit_once_on_any("hello,dear world", ", "), Out{ "hello,dear", "world" });
CHECK_EQ(rsplit_once_on_any("hello dear,world", ", "), Out{ "hello dear", "world" });
CHECK_EQ(rsplit_once_on_any("hello/world", "/"), Out{ "hello", "world" });
CHECK_EQ(rsplit_once_on_any("hello//world", "//"), Out{ "hello/", "world" });
CHECK_EQ(rsplit_once_on_any("hello/my//world", "/"), Out{ "hello/my/", "world" });
CHECK_EQ(rsplit_once_on_any("hello/my//world", "//"), Out{ "hello/my/", "world" });
REQUIRE(rsplit_once_on_any("", "/") == Out{ std::nullopt, "" });
REQUIRE(rsplit_once_on_any("hello,dear world", ", ") == Out{ "hello,dear", "world" });
REQUIRE(rsplit_once_on_any("hello dear,world", ", ") == Out{ "hello dear", "world" });
REQUIRE(rsplit_once_on_any("hello/world", "/") == Out{ "hello", "world" });
REQUIRE(rsplit_once_on_any("hello//world", "//") == Out{ "hello/", "world" });
REQUIRE(rsplit_once_on_any("hello/my//world", "/") == Out{ "hello/my/", "world" });
REQUIRE(rsplit_once_on_any("hello/my//world", "//") == Out{ "hello/my/", "world" });
}
TEST_CASE("split")
{
std::string a = "hello.again.it's.me.mario";
std::vector<std::string> e1 = { "hello", "again", "it's", "me", "mario" };
CHECK_EQ(split(a, "."), e1);
REQUIRE(split(a, ".") == e1);
std::vector<std::string> s2 = { "hello", "again", "it's.me.mario" };
CHECK_EQ(split(a, ".", 2), s2);
REQUIRE(split(a, ".", 2) == s2);
CHECK_EQ(rsplit(a, "."), e1);
REQUIRE(rsplit(a, ".") == e1);
std::vector<std::string> r2 = { "hello.again.it's", "me", "mario" };
CHECK_EQ(rsplit(a, ".", 2), r2);
REQUIRE(rsplit(a, ".", 2) == r2);
std::string b = "...";
auto es1 = std::vector<std::string>{ "", "", "", "" };
auto es2 = std::vector<std::string>{ "", ".." };
CHECK_EQ(split(b, "."), es1);
CHECK_EQ(split(b, ".", 1), es2);
REQUIRE(split(b, ".") == es1);
REQUIRE(split(b, ".", 1) == es2);
std::vector<std::string> v = { "xtensor==0.12.3" };
CHECK_EQ(split(v[0], ":"), v);
CHECK_EQ(rsplit(v[0], ":"), v);
CHECK_EQ(split(v[0], ":", 2), v);
CHECK_EQ(rsplit(v[0], ":", 2), v);
REQUIRE(split(v[0], ":") == v);
REQUIRE(rsplit(v[0], ":") == v);
REQUIRE(split(v[0], ":", 2) == v);
REQUIRE(rsplit(v[0], ":", 2) == v);
std::vector<std::string> v2 = { "conda-forge/linux64", "", "xtensor==0.12.3" };
CHECK_EQ(split("conda-forge/linux64::xtensor==0.12.3", ":", 2), v2);
CHECK_EQ(rsplit("conda-forge/linux64::xtensor==0.12.3", ":", 2), v2);
REQUIRE(split("conda-forge/linux64::xtensor==0.12.3", ":", 2) == v2);
REQUIRE(rsplit("conda-forge/linux64::xtensor==0.12.3", ":", 2) == v2);
std::vector<std::string> v21 = { "conda-forge/linux64:", "xtensor==0.12.3" };
CHECK_EQ(rsplit("conda-forge/linux64::xtensor==0.12.3", ":", 1), v21);
REQUIRE(rsplit("conda-forge/linux64::xtensor==0.12.3", ":", 1) == v21);
}
TEST_CASE("join")
@ -467,16 +468,16 @@ namespace
std::vector<std::string> to_join = { "a", "bc", "d" };
auto joined = join("-", to_join);
static_assert(std::is_same<decltype(joined), decltype(to_join)::value_type>::value);
CHECK_EQ(joined, "a-bc-d");
REQUIRE(joined == "a-bc-d");
}
{
std::vector<mamba::fs::u8path> to_join = { "/a", "bc", "d" };
auto joined = join("/", to_join);
static_assert(std::is_same<decltype(joined), decltype(to_join)::value_type>::value);
CHECK_EQ(joined, "/a/bc/d");
REQUIRE(joined == "/a/bc/d");
}
{
CHECK_EQ(join(",", std::vector<std::string>()), "");
REQUIRE(join(",", std::vector<std::string>()) == "");
}
}
@ -487,12 +488,12 @@ namespace
auto joined = join_trunc(to_join);
static_assert(std::is_same<decltype(joined), decltype(to_join)::value_type>::value);
}
CHECK_EQ(join_trunc(to_join, "-", "..", 5, { 2, 1 }), "a-bc-d-e-f");
CHECK_EQ(join_trunc(to_join, ",", "..", 4, { 2, 1 }), "a,bc,..,f");
CHECK_EQ(join_trunc(to_join, ",", "..", 4, { 0, 1 }), "..,f");
CHECK_EQ(join_trunc(to_join, ",", "..", 4, { 2, 0 }), "a,bc,..");
CHECK_EQ(join_trunc(to_join, ",", "..", 4, { 0, 0 }), "..");
CHECK_EQ(join_trunc(std::vector<std::string>()), "");
REQUIRE(join_trunc(to_join, "-", "..", 5, { 2, 1 }) == "a-bc-d-e-f");
REQUIRE(join_trunc(to_join, ",", "..", 4, { 2, 1 }) == "a,bc,..,f");
REQUIRE(join_trunc(to_join, ",", "..", 4, { 0, 1 }) == "..,f");
REQUIRE(join_trunc(to_join, ",", "..", 4, { 2, 0 }) == "a,bc,..");
REQUIRE(join_trunc(to_join, ",", "..", 4, { 0, 0 }) == "..");
REQUIRE(join_trunc(std::vector<std::string>()) == "");
}
TEST_CASE("replace_all")
@ -500,19 +501,19 @@ namespace
std::string testbuf = "this is just a test a just a a abc bca";
replace_all(testbuf, "just", "JU");
CHECK_EQ(testbuf, "this is JU a test a JU a a abc bca");
REQUIRE(testbuf == "this is JU a test a JU a a abc bca");
replace_all(testbuf, "a", "MAMBA");
CHECK_EQ(testbuf, "this is JU MAMBA test MAMBA JU MAMBA MAMBA MAMBAbc bcMAMBA");
REQUIRE(testbuf == "this is JU MAMBA test MAMBA JU MAMBA MAMBA MAMBAbc bcMAMBA");
replace_all(testbuf, " ", "");
CHECK_EQ(testbuf, "thisisJUMAMBAtestMAMBAJUMAMBAMAMBAMAMBAbcbcMAMBA");
REQUIRE(testbuf == "thisisJUMAMBAtestMAMBAJUMAMBAMAMBAMAMBAbcbcMAMBA");
std::string prefix = "/I/am/a/PREFIX\n\nabcdefg\nxyz";
replace_all(prefix, "/I/am/a/PREFIX", "/Yes/Thats/great/");
CHECK(starts_with(prefix, "/Yes/Thats/great/\n"));
REQUIRE(starts_with(prefix, "/Yes/Thats/great/\n"));
std::string testbuf2 = "this is another test wow";
replace_all(testbuf2, "", "somereplacement");
CHECK_EQ(testbuf2, "this is another test wow");
REQUIRE(testbuf2 == "this is another test wow");
std::string prefix_unicode = "/I/am/Dörte朩æ©fðgb®/PREFIX\n\nabcdefg\nxyz";
replace_all(
@ -520,12 +521,12 @@ namespace
"/I/am/Dörte朩æ©fðgb®/PREFIX",
"/home/åéäáßðæœ©ðfßfáðß/123123123"
);
CHECK_EQ(prefix_unicode, "/home/åéäáßðæœ©ðfßfáðß/123123123\n\nabcdefg\nxyz");
REQUIRE(prefix_unicode == "/home/åéäáßðæœ©ðfßfáðß/123123123\n\nabcdefg\nxyz");
}
TEST_CASE("concat")
{
CHECK_EQ(concat("aa", std::string("bb"), std::string_view("cc"), 'd'), "aabbccd");
REQUIRE(concat("aa", std::string("bb"), std::string_view("cc"), 'd') == "aabbccd");
}
TEST_CASE("concat_dedup_splits")
@ -534,65 +535,61 @@ namespace
{
CAPTURE(sep);
CHECK_EQ(concat_dedup_splits("", "", sep), "");
REQUIRE(concat_dedup_splits("", "", sep) == "");
CHECK_EQ(
concat_dedup_splits(fmt::format("test{}chan", sep), "", sep),
fmt::format("test{}chan", sep)
REQUIRE(
concat_dedup_splits(fmt::format("test{}chan", sep), "", sep)
== fmt::format("test{}chan", sep)
);
CHECK_EQ(
concat_dedup_splits("", fmt::format("test{}chan", sep), sep),
fmt::format("test{}chan", sep)
REQUIRE(
concat_dedup_splits("", fmt::format("test{}chan", sep), sep)
== fmt::format("test{}chan", sep)
);
CHECK_EQ(
concat_dedup_splits("test", fmt::format("test{}chan", sep), sep),
fmt::format("test{}chan", sep)
REQUIRE(
concat_dedup_splits("test", fmt::format("test{}chan", sep), sep)
== fmt::format("test{}chan", sep)
);
CHECK_EQ(concat_dedup_splits("test", "chan", sep), fmt::format("test{}chan", sep));
CHECK_EQ(
concat_dedup_splits(fmt::format("test{}chan", sep), "chan", sep),
fmt::format("test{}chan", sep)
REQUIRE(concat_dedup_splits("test", "chan", sep) == fmt::format("test{}chan", sep));
REQUIRE(
concat_dedup_splits(fmt::format("test{}chan", sep), "chan", sep)
== fmt::format("test{}chan", sep)
);
CHECK_EQ(
concat_dedup_splits(fmt::format("test{}chan", sep), fmt::format("chan{}foo", sep), sep),
fmt::format("test{}chan{}foo", sep, sep)
REQUIRE(
concat_dedup_splits(fmt::format("test{}chan", sep), fmt::format("chan{}foo", sep), sep)
== fmt::format("test{}chan{}foo", sep, sep)
);
CHECK_EQ(
REQUIRE(
concat_dedup_splits(
fmt::format("test{}chan-foo", sep),
fmt::format("foo{}bar", sep),
sep
),
fmt::format("test{}chan-foo{}foo{}bar", sep, sep, sep, sep)
)
== fmt::format("test{}chan-foo{}foo{}bar", sep, sep, sep, sep)
);
CHECK_EQ(
REQUIRE(
concat_dedup_splits(
fmt::format("ab{}test{}chan", sep, sep),
fmt::format("chan{}foo{}ab", sep, sep),
sep
),
fmt::format("ab{}test{}chan{}foo{}ab", sep, sep, sep, sep)
)
== fmt::format("ab{}test{}chan{}foo{}ab", sep, sep, sep, sep)
);
CHECK_EQ(
REQUIRE(
concat_dedup_splits(
fmt::format("{}test{}chan", sep, sep),
fmt::format("chan{}foo{}", sep, sep),
sep
),
fmt::format("{}test{}chan{}foo{}", sep, sep, sep, sep)
)
== fmt::format("{}test{}chan{}foo{}", sep, sep, sep, sep)
);
CHECK_EQ(
concat_dedup_splits(
fmt::format("test{}chan", sep),
fmt::format("chan{}test", sep),
sep
),
fmt::format("test{}chan{}test", sep, sep)
REQUIRE(
concat_dedup_splits(fmt::format("test{}chan", sep), fmt::format("chan{}test", sep), sep)
== fmt::format("test{}chan{}test", sep, sep)
);
}
CHECK_EQ(concat_dedup_splits("test/chan", "chan/foo", "//"), "test/chan//chan/foo");
CHECK_EQ(concat_dedup_splits("test/chan", "chan/foo", '/'), "test/chan/foo");
REQUIRE(concat_dedup_splits("test/chan", "chan/foo", "//") == "test/chan//chan/foo");
REQUIRE(concat_dedup_splits("test/chan", "chan/foo", '/') == "test/chan/foo");
}
}
} // namespace mamba

View File

@ -7,26 +7,26 @@
#include <string>
#include <tuple>
#include <doctest/doctest.h>
#include <catch2/catch_all.hpp>
#include "mamba/util/tuple_hash.hpp"
using namespace mamba::util;
TEST_SUITE("util::tuple_hash")
namespace
{
TEST_CASE("hash_tuple")
{
const auto t1 = std::tuple{ 33, std::string("hello") };
CHECK_NE(hash_tuple(t1), 0);
REQUIRE(hash_tuple(t1) != 0);
// Hash collision are hard to predict, but this is so trivial it is likely a bug if it
// fails.
const auto t2 = std::tuple{ 0, std::string("hello") };
CHECK_NE(hash_tuple(t1), hash_tuple(t2));
REQUIRE(hash_tuple(t1) != hash_tuple(t2));
const auto t3 = std::tuple{ std::string("hello"), 33 };
CHECK_NE(hash_tuple(t1), hash_tuple(t3));
REQUIRE(hash_tuple(t1) != hash_tuple(t3));
}
TEST_CASE("hash_combine_val_range")
@ -34,11 +34,11 @@ TEST_SUITE("util::tuple_hash")
const auto hello = std::string("hello");
// Hash collision are hard to predict, but this is so trivial it is likely a bug if it
// fails.
CHECK_NE(hash_combine_val_range(0, hello.cbegin(), hello.cend()), 0);
CHECK_NE(hash_combine_val_range(0, hello.crbegin(), hello.crend()), 0);
CHECK_NE(
hash_combine_val_range(0, hello.cbegin(), hello.cend()),
hash_combine_val_range(0, hello.crbegin(), hello.crend())
REQUIRE(hash_combine_val_range(0, hello.cbegin(), hello.cend()) != 0);
REQUIRE(hash_combine_val_range(0, hello.crbegin(), hello.crend()) != 0);
REQUIRE(
hash_combine_val_range(0, hello.cbegin(), hello.cend())
!= hash_combine_val_range(0, hello.crbegin(), hello.crend())
);
}
@ -48,8 +48,8 @@ TEST_SUITE("util::tuple_hash")
const auto world = std::string("world");
// Hash collision are hard to predict, but this is so trivial it is likely a bug if it
// fails.
CHECK_NE(hash_range(hello), 0);
CHECK_NE(hash_range(world), 0);
CHECK_NE(hash_range(hello), hash_range(world));
REQUIRE(hash_range(hello) != 0);
REQUIRE(hash_range(world) != 0);
REQUIRE(hash_range(hello) != hash_range(world));
}
}

View File

@ -6,29 +6,27 @@
#include <string>
#include <doctest/doctest.h>
#include <catch2/catch_all.hpp>
#include "mamba/util/type_traits.hpp"
using namespace mamba::util;
TEST_SUITE("util::type_traits")
struct NotOStreamable
{
struct NotOStreamable
{
};
};
struct OStreamable
{
};
struct OStreamable
{
};
auto operator<<(std::ostream& s, const OStreamable&)->std::ostream&;
auto
operator<<(std::ostream& s, const OStreamable&) -> std::ostream&;
TEST_CASE("ostreamable")
{
CHECK(is_ostreamable_v<int>);
CHECK(is_ostreamable_v<std::string>);
CHECK_FALSE(is_ostreamable_v<NotOStreamable>);
CHECK(is_ostreamable_v<OStreamable>);
}
TEST_CASE("ostreamable")
{
REQUIRE(is_ostreamable_v<int>);
REQUIRE(is_ostreamable_v<std::string>);
REQUIRE_FALSE(is_ostreamable_v<NotOStreamable>);
REQUIRE(is_ostreamable_v<OStreamable>);
}

File diff suppressed because it is too large Load Diff

View File

@ -7,7 +7,7 @@
#include <string>
#include <string_view>
#include <doctest/doctest.h>
#include <catch2/catch_all.hpp>
#include "mamba/fs/filesystem.hpp"
#include "mamba/util/build.hpp"
@ -17,42 +17,43 @@
using namespace mamba;
using namespace mamba::util;
TEST_SUITE("util::url_manip")
namespace
{
TEST_CASE("abs_path_to_url")
{
SUBCASE("/users/test/miniconda3")
SECTION("/users/test/miniconda3")
{
CHECK_EQ(abs_path_to_url("/users/test/miniconda3"), "file:///users/test/miniconda3");
REQUIRE(abs_path_to_url("/users/test/miniconda3") == "file:///users/test/miniconda3");
}
SUBCASE(R"(D:\users\test\miniconda3)")
SECTION(R"(D:\users\test\miniconda3)")
{
if (on_win)
{
CHECK_EQ(
abs_path_to_url(R"(D:\users\test\miniconda3)"),
"file://D:/users/test/miniconda3"
REQUIRE(
abs_path_to_url(R"(D:\users\test\miniconda3)") == "file://D:/users/test/miniconda3"
);
}
}
SUBCASE("/tmp/foo bar")
SECTION("/tmp/foo bar")
{
CHECK_EQ(abs_path_to_url("/tmp/foo bar"), "file:///tmp/foo%20bar");
REQUIRE(abs_path_to_url("/tmp/foo bar") == "file:///tmp/foo%20bar");
}
}
TEST_CASE("abs_path_or_url_to_url")
{
SUBCASE("/users/test/miniconda3")
SECTION("/users/test/miniconda3")
{
CHECK_EQ(abs_path_or_url_to_url("/users/test/miniconda3"), "file:///users/test/miniconda3");
REQUIRE(
abs_path_or_url_to_url("/users/test/miniconda3") == "file:///users/test/miniconda3"
);
}
SUBCASE("file:///tmp/bar")
SECTION("file:///tmp/bar")
{
CHECK_EQ(abs_path_or_url_to_url("file:///tmp/bar"), "file:///tmp/bar");
REQUIRE(abs_path_or_url_to_url("file:///tmp/bar") == "file:///tmp/bar");
}
}
@ -60,52 +61,54 @@ TEST_SUITE("util::url_manip")
{
const std::string win_drive = fs::absolute(fs::u8path("/")).string().substr(0, 1);
SUBCASE("/users/test/miniconda3")
SECTION("/users/test/miniconda3")
{
auto url = path_to_url("/users/test/miniconda3");
if (on_win)
{
CHECK_EQ(url, concat("file://", win_drive, ":/users/test/miniconda3"));
REQUIRE(url == concat("file://", win_drive, ":/users/test/miniconda3"));
}
else
{
CHECK_EQ(url, "file:///users/test/miniconda3");
REQUIRE(url == "file:///users/test/miniconda3");
}
}
SUBCASE(R"(D:\users\test\miniconda3)")
SECTION(R"(D:\users\test\miniconda3)")
{
if (on_win)
{
CHECK_EQ(path_to_url(R"(D:\users\test\miniconda3)"), "file://D:/users/test/miniconda3");
REQUIRE(
path_to_url(R"(D:\users\test\miniconda3)") == "file://D:/users/test/miniconda3"
);
}
}
SUBCASE("/tmp/foo bar")
SECTION("/tmp/foo bar")
{
auto url = path_to_url("/tmp/foo bar");
if (on_win)
{
CHECK_EQ(url, concat("file://", win_drive, ":/tmp/foo%20bar"));
REQUIRE(url == concat("file://", win_drive, ":/tmp/foo%20bar"));
}
else
{
CHECK_EQ(url, "file:///tmp/foo%20bar");
REQUIRE(url == "file:///tmp/foo%20bar");
}
}
SUBCASE("./folder/./../folder")
SECTION("./folder/./../folder")
{
auto url = path_to_url("./folder/./../folder");
if (on_win)
{
CHECK(starts_with(url, concat("file://", win_drive, ":/")));
CHECK(ends_with(url, "/folder"));
REQUIRE(starts_with(url, concat("file://", win_drive, ":/")));
REQUIRE(ends_with(url, "/folder"));
}
else
{
const auto expected_folder = fs::absolute("folder").lexically_normal();
CHECK_EQ(url, concat("file://", expected_folder.string()));
REQUIRE(url == concat("file://", expected_folder.string()));
}
}
}
@ -114,40 +117,40 @@ TEST_SUITE("util::url_manip")
{
const std::string win_drive = fs::absolute(fs::u8path("/")).string().substr(0, 1);
SUBCASE("/tmp/foo bar")
SECTION("/tmp/foo bar")
{
auto url = path_or_url_to_url("/tmp/foo bar");
if (on_win)
{
CHECK_EQ(url, concat("file://", win_drive, ":/tmp/foo%20bar"));
REQUIRE(url == concat("file://", win_drive, ":/tmp/foo%20bar"));
}
else
{
CHECK_EQ(url, "file:///tmp/foo%20bar");
REQUIRE(url == "file:///tmp/foo%20bar");
}
}
SUBCASE("file:///tmp/bar")
SECTION("file:///tmp/bar")
{
CHECK_EQ(path_or_url_to_url("file:///tmp/bar"), "file:///tmp/bar");
REQUIRE(path_or_url_to_url("file:///tmp/bar") == "file:///tmp/bar");
}
}
TEST_CASE("url_concat")
{
CHECK_EQ(url_concat("", ""), "");
CHECK_EQ(url_concat("", "/"), "/");
CHECK_EQ(url_concat("/", ""), "/");
CHECK_EQ(url_concat("/", "/"), "/");
REQUIRE(url_concat("", "") == "");
REQUIRE(url_concat("", "/") == "/");
REQUIRE(url_concat("/", "") == "/");
REQUIRE(url_concat("/", "/") == "/");
CHECK_EQ(url_concat("mamba.org", "folder"), "mamba.org/folder");
CHECK_EQ(url_concat("mamba.org", "/folder"), "mamba.org/folder");
CHECK_EQ(url_concat("mamba.org/", "folder"), "mamba.org/folder");
CHECK_EQ(url_concat("mamba.org/", "/folder"), "mamba.org/folder");
REQUIRE(url_concat("mamba.org", "folder") == "mamba.org/folder");
REQUIRE(url_concat("mamba.org", "/folder") == "mamba.org/folder");
REQUIRE(url_concat("mamba.org/", "folder") == "mamba.org/folder");
REQUIRE(url_concat("mamba.org/", "/folder") == "mamba.org/folder");
CHECK_EQ(
url_concat("mamba.org", 't', std::string("/sometoken/"), std::string_view("conda-forge")),
"mamba.org/t/sometoken/conda-forge"
REQUIRE(
url_concat("mamba.org", 't', std::string("/sometoken/"), std::string_view("conda-forge"))
== "mamba.org/t/sometoken/conda-forge"
);
}
@ -164,31 +167,31 @@ TEST_SUITE("util::url_manip")
})
{
CAPTURE(uri);
CHECK_EQ(file_uri_unc2_to_unc4(uri), uri);
REQUIRE(file_uri_unc2_to_unc4(uri) == uri);
}
CHECK_EQ(file_uri_unc2_to_unc4("file://server/share"), "file:////server/share");
CHECK_EQ(file_uri_unc2_to_unc4("file://server"), "file:////server");
REQUIRE(file_uri_unc2_to_unc4("file://server/share") == "file:////server/share");
REQUIRE(file_uri_unc2_to_unc4("file://server") == "file:////server");
}
TEST_CASE("url_get_scheme")
{
CHECK_EQ(url_get_scheme("http://mamba.org"), "http");
CHECK_EQ(url_get_scheme("file:///folder/file.txt"), "file");
CHECK_EQ(url_get_scheme("s3://bucket/file.txt"), "s3");
CHECK_EQ(url_get_scheme("mamba.org"), "");
CHECK_EQ(url_get_scheme("://"), "");
CHECK_EQ(url_get_scheme("f#gre://"), "");
CHECK_EQ(url_get_scheme(""), "");
REQUIRE(url_get_scheme("http://mamba.org") == "http");
REQUIRE(url_get_scheme("file:///folder/file.txt") == "file");
REQUIRE(url_get_scheme("s3://bucket/file.txt") == "s3");
REQUIRE(url_get_scheme("mamba.org") == "");
REQUIRE(url_get_scheme("://") == "");
REQUIRE(url_get_scheme("f#gre://") == "");
REQUIRE(url_get_scheme("") == "");
}
TEST_CASE("url_has_scheme")
{
CHECK(url_has_scheme("http://mamba.org"));
CHECK(url_has_scheme("file:///folder/file.txt"));
CHECK(url_has_scheme("s3://bucket/file.txt"));
CHECK_FALSE(url_has_scheme("mamba.org"));
CHECK_FALSE(url_has_scheme("://"));
CHECK_FALSE(url_has_scheme("f#gre://"));
CHECK_FALSE(url_has_scheme(""));
REQUIRE(url_has_scheme("http://mamba.org"));
REQUIRE(url_has_scheme("file:///folder/file.txt"));
REQUIRE(url_has_scheme("s3://bucket/file.txt"));
REQUIRE_FALSE(url_has_scheme("mamba.org"));
REQUIRE_FALSE(url_has_scheme("://"));
REQUIRE_FALSE(url_has_scheme("f#gre://"));
REQUIRE_FALSE(url_has_scheme(""));
}
}

View File

@ -7,14 +7,14 @@
#include <optional>
#include <unordered_map>
#include <doctest/doctest.h>
#include <catch2/catch_all.hpp>
#include "mamba/util/weakening_map.hpp"
using namespace mamba::util;
TEST_SUITE("util::weakening_map")
namespace
{
TEST_CASE("DecreaseWeakener")
{
@ -37,23 +37,23 @@ TEST_SUITE("util::weakening_map")
using test_map = weakening_map<std::unordered_map<int, int>, DecreaseWeakener>;
SUBCASE("empty")
SECTION("empty")
{
auto map = test_map();
CHECK_FALSE(map.contains_weaken(1));
CHECK_FALSE(map.contains_weaken(0));
REQUIRE_FALSE(map.contains_weaken(1));
REQUIRE_FALSE(map.contains_weaken(0));
}
SUBCASE("key match")
SECTION("key match")
{
auto map = test_map({ { 1, 10 }, { 4, 40 } });
CHECK_FALSE(map.contains_weaken(-1));
REQUIRE_FALSE(map.contains_weaken(-1));
CHECK_EQ(map.at_weaken(4), 40); // Exact match
CHECK_EQ(map.at_weaken(0), 10); // First key match
CHECK_EQ(map.at_weaken(7), 40); // Weaken key
REQUIRE(map.at_weaken(4) == 40); // Exact match
REQUIRE(map.at_weaken(0) == 10); // First key match
REQUIRE(map.at_weaken(7) == 40); // Weaken key
}
}
}

View File

@ -4,7 +4,7 @@
//
// The full license is in the file LICENSE, distributed with this software.
#include <doctest/doctest.h>
#include <catch2/catch_all.hpp>
#include <nlohmann/json.hpp>
#include <spdlog/spdlog.h>
@ -23,7 +23,7 @@ hex_str(const std::array<std::byte, size>& bytes)
return util::bytes_to_hex_str(bytes.data(), bytes.data() + bytes.size());
}
TEST_SUITE("validation::tools")
namespace
{
TEST_CASE("sha256sum")
{
@ -32,10 +32,10 @@ TEST_SUITE("validation::tools")
f << "test";
f.close();
auto sha256 = sha256sum(tmp.path());
CHECK_EQ(sha256, "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08");
REQUIRE(sha256 == "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08");
auto md5 = md5sum(tmp.path());
CHECK_EQ(md5, "098f6bcd4621d373cade4e832627b4f6");
REQUIRE(md5 == "098f6bcd4621d373cade4e832627b4f6");
}
TEST_CASE("ed25519_key_hex_to_bytes")
@ -46,22 +46,22 @@ TEST_SUITE("validation::tools")
auto pk_hex = hex_str(pk);
int error = 0;
auto pk_bytes = ed25519_key_hex_to_bytes(pk_hex, error);
REQUIRE_EQ(error, 0);
CHECK_EQ(pk_hex, hex_str(pk_bytes));
REQUIRE(error == 0);
REQUIRE(pk_hex == hex_str(pk_bytes));
spdlog::set_level(spdlog::level::debug);
std::array<std::byte, 5> not_even_key;
pk_hex = hex_str(not_even_key);
pk_bytes = ed25519_key_hex_to_bytes(pk_hex, error);
REQUIRE_EQ(error, 0);
CHECK_FALSE(pk_hex == hex_str(pk_bytes));
REQUIRE(error == 0);
REQUIRE_FALSE(pk_hex == hex_str(pk_bytes));
std::array<std::byte, 6> wrong_size_key;
pk_hex = hex_str(wrong_size_key);
pk_bytes = ed25519_key_hex_to_bytes(pk_hex, error);
REQUIRE_EQ(error, 0);
CHECK_FALSE(pk_hex == hex_str(pk_bytes));
REQUIRE(error == 0);
REQUIRE_FALSE(pk_hex == hex_str(pk_bytes));
spdlog::set_level(spdlog::level::info);
}
@ -77,22 +77,22 @@ TEST_SUITE("validation::tools")
int error = 0;
auto sig_hex = hex_str(sig);
auto sig_bytes = ed25519_sig_hex_to_bytes(sig_hex, error);
REQUIRE_EQ(error, 0);
CHECK_EQ(sig_hex, hex_str(sig_bytes));
REQUIRE(error == 0);
REQUIRE(sig_hex == hex_str(sig_bytes));
spdlog::set_level(spdlog::level::debug);
std::array<std::byte, 5> not_even_sig;
sig_hex = hex_str(not_even_sig);
sig_bytes = ed25519_sig_hex_to_bytes(sig_hex, error);
REQUIRE_EQ(error, 0);
CHECK_FALSE(sig_hex == hex_str(sig_bytes));
REQUIRE(error == 0);
REQUIRE_FALSE(sig_hex == hex_str(sig_bytes));
std::array<std::byte, 6> wrong_size_sig;
sig_hex = hex_str(wrong_size_sig);
sig_bytes = ed25519_sig_hex_to_bytes(sig_hex, error);
REQUIRE_EQ(error, 0);
CHECK_FALSE(sig_hex == hex_str(sig_bytes));
REQUIRE(error == 0);
REQUIRE_FALSE(sig_hex == hex_str(sig_bytes));
spdlog::set_level(spdlog::level::info);
}
@ -115,36 +115,36 @@ protected:
std::array<std::byte, MAMBA_ED25519_SIGSIZE_BYTES> signature;
};
TEST_SUITE("validation::VerifyMsg")
namespace
{
TEST_CASE_FIXTURE(VerifyMsg, "from_bytes")
TEST_CASE_METHOD(VerifyMsg, "from_bytes")
{
CHECK_EQ(verify("Some text.", pk.data(), signature.data()), 1);
REQUIRE(verify("Some text.", pk.data(), signature.data()) == 1);
}
TEST_CASE_FIXTURE(VerifyMsg, "from_hex")
TEST_CASE_METHOD(VerifyMsg, "from_hex")
{
auto signature_hex = hex_str(signature);
auto pk_hex = hex_str(pk);
CHECK_EQ(verify("Some text.", pk_hex, signature_hex), 1);
REQUIRE(verify("Some text.", pk_hex, signature_hex) == 1);
}
TEST_CASE_FIXTURE(VerifyMsg, "wrong_signature")
TEST_CASE_METHOD(VerifyMsg, "wrong_signature")
{
spdlog::set_level(spdlog::level::debug);
auto pk_hex = hex_str(pk);
CHECK_EQ(verify("Some text.", pk_hex, "signature_hex"), 0);
REQUIRE(verify("Some text.", pk_hex, "signature_hex") == 0);
spdlog::set_level(spdlog::level::info);
}
TEST_CASE_FIXTURE(VerifyMsg, "wrong_public_key")
TEST_CASE_METHOD(VerifyMsg, "wrong_public_key")
{
spdlog::set_level(spdlog::level::debug);
auto signature_hex = hex_str(signature);
CHECK_EQ(verify("Some text.", "pk_hex", signature_hex), 0);
REQUIRE(verify("Some text.", "pk_hex", signature_hex) == 0);
spdlog::set_level(spdlog::level::info);
}
}
@ -188,26 +188,26 @@ protected:
std::string data;
};
TEST_SUITE("validation::VerifyGPGMsg")
namespace
{
TEST_CASE_FIXTURE(VerifyGPGMsg, "verify_gpg_hashed_msg_from_bin")
TEST_CASE_METHOD(VerifyGPGMsg, "verify_gpg_hashed_msg_from_bin")
{
int error = 0;
auto bin_signature = ed25519_sig_hex_to_bytes(signature, error);
REQUIRE_EQ(error, 0);
REQUIRE(error == 0);
auto bin_pk = ed25519_key_hex_to_bytes(pk, error);
REQUIRE_EQ(error, 0);
REQUIRE(error == 0);
CHECK_EQ(verify_gpg_hashed_msg(hash, bin_pk.data(), bin_signature.data()), 1);
REQUIRE(verify_gpg_hashed_msg(hash, bin_pk.data(), bin_signature.data()) == 1);
}
TEST_CASE_FIXTURE(VerifyGPGMsg, "verify_gpg_hashed_msg_from_hex")
TEST_CASE_METHOD(VerifyGPGMsg, "verify_gpg_hashed_msg_from_hex")
{
CHECK_EQ(verify_gpg_hashed_msg(hash, pk, signature), 1);
REQUIRE(verify_gpg_hashed_msg(hash, pk, signature) == 1);
}
TEST_CASE_FIXTURE(VerifyGPGMsg, "verify_gpg")
TEST_CASE_METHOD(VerifyGPGMsg, "verify_gpg")
{
CHECK_EQ(verify_gpg(data, trailer, pk, signature), 1);
REQUIRE(verify_gpg(data, trailer, pk, signature) == 1);
}
}

View File

@ -4,16 +4,9 @@
//
// The full license is in the file LICENSE, distributed with this software.
// There are several `CHECK_THROWS_AS` expressions in this file.
// Sometimes they call a method marked as `[[nodiscard]]`.
// This causes compiler warnnings.
// This doctest flag is designed specifically to prevent this warning from happening.
// https://github.com/doctest/doctest/blob/master/doc/markdown/configuration.md#doctest_config_void_cast_expressions
#define DOCTEST_CONFIG_VOID_CAST_EXPRESSIONS
#include <map>
#include <doctest/doctest.h>
#include <catch2/catch_all.hpp>
#include <nlohmann/json.hpp>
#include <spdlog/spdlog.h>
@ -195,59 +188,59 @@ protected:
}
};
TEST_SUITE("validation::v0_6::RootImpl")
namespace
{
TEST_CASE_FIXTURE(RootImplT_v0_6, "ctor_from_path")
TEST_CASE_METHOD(RootImplT_v0_6, "ctor_from_path")
{
v0_6::RootImpl root(trusted_root_file_raw_key());
CHECK_EQ(root.type(), "root");
CHECK_EQ(root.file_ext(), "json");
CHECK_EQ(root.spec_version(), v0_6::SpecImpl("0.6.0"));
CHECK_EQ(root.version(), 1);
REQUIRE(root.type() == "root");
REQUIRE(root.file_ext() == "json");
REQUIRE(root.spec_version() == v0_6::SpecImpl("0.6.0"));
REQUIRE(root.version() == 1);
}
TEST_CASE_FIXTURE(RootImplT_v0_6, "ctor_from_path_pgp_signed")
TEST_CASE_METHOD(RootImplT_v0_6, "ctor_from_path_pgp_signed")
{
v0_6::RootImpl root(trusted_root_file_pgp());
CHECK_EQ(root.type(), "root");
CHECK_EQ(root.file_ext(), "json");
CHECK_EQ(root.spec_version(), v0_6::SpecImpl("0.6.0"));
CHECK_EQ(root.version(), 1);
REQUIRE(root.type() == "root");
REQUIRE(root.file_ext() == "json");
REQUIRE(root.spec_version() == v0_6::SpecImpl("0.6.0"));
REQUIRE(root.version() == 1);
}
TEST_CASE_FIXTURE(RootImplT_v0_6, "ctor_from_json")
TEST_CASE_METHOD(RootImplT_v0_6, "ctor_from_json")
{
v0_6::RootImpl root(root1_json);
CHECK_EQ(root.type(), "root");
CHECK_EQ(root.file_ext(), "json");
CHECK_EQ(root.spec_version(), v0_6::SpecImpl("0.6.0"));
CHECK_EQ(root.version(), 1);
REQUIRE(root.type() == "root");
REQUIRE(root.file_ext() == "json");
REQUIRE(root.spec_version() == v0_6::SpecImpl("0.6.0"));
REQUIRE(root.version() == 1);
}
TEST_CASE_FIXTURE(RootImplT_v0_6, "ctor_from_json_str")
TEST_CASE_METHOD(RootImplT_v0_6, "ctor_from_json_str")
{
v0_6::RootImpl root(root1_json.dump());
CHECK_EQ(root.type(), "root");
CHECK_EQ(root.file_ext(), "json");
CHECK_EQ(root.spec_version(), v0_6::SpecImpl("0.6.0"));
CHECK_EQ(root.version(), 1);
REQUIRE(root.type() == "root");
REQUIRE(root.file_ext() == "json");
REQUIRE(root.spec_version() == v0_6::SpecImpl("0.6.0"));
REQUIRE(root.version() == 1);
}
TEST_CASE_FIXTURE(RootImplT_v0_6, "ctor_from_json_pgp_signed")
TEST_CASE_METHOD(RootImplT_v0_6, "ctor_from_json_pgp_signed")
{
v0_6::RootImpl root(root1_pgp_json);
CHECK_EQ(root.type(), "root");
CHECK_EQ(root.file_ext(), "json");
CHECK_EQ(root.spec_version(), v0_6::SpecImpl("0.6.0"));
CHECK_EQ(root.version(), 1);
REQUIRE(root.type() == "root");
REQUIRE(root.file_ext() == "json");
REQUIRE(root.spec_version() == v0_6::SpecImpl("0.6.0"));
REQUIRE(root.version() == 1);
}
TEST_CASE_FIXTURE(RootImplT_v0_6, "ctor_wrong_filename_spec_version")
TEST_CASE_METHOD(RootImplT_v0_6, "ctor_wrong_filename_spec_version")
{
fs::u8path p = channel_dir->path() / "2.sv1.root.json";
@ -256,10 +249,10 @@ TEST_SUITE("validation::v0_6::RootImpl")
out_file.close();
// "2.sv1.root.json" is not compatible spec version (spec version N)
CHECK_THROWS_AS(v0_6::RootImpl{ p }, role_file_error);
REQUIRE_THROWS_AS(v0_6::RootImpl{ p }, role_file_error);
}
TEST_CASE_FIXTURE(RootImplT_v0_6, "update_from_path")
TEST_CASE_METHOD(RootImplT_v0_6, "update_from_path")
{
using namespace mamba;
@ -272,13 +265,13 @@ TEST_SUITE("validation::v0_6::RootImpl")
auto updated_root = root.update(create_root_update("2.root.json", patch));
auto testing_root = static_cast<v0_6::RootImpl*>(updated_root.get());
CHECK_EQ(testing_root->type(), "root");
CHECK_EQ(testing_root->file_ext(), "json");
CHECK_EQ(testing_root->spec_version(), v0_6::SpecImpl("0.6.0"));
CHECK_EQ(testing_root->version(), 2);
REQUIRE(testing_root->type() == "root");
REQUIRE(testing_root->file_ext() == "json");
REQUIRE(testing_root->spec_version() == v0_6::SpecImpl("0.6.0"));
REQUIRE(testing_root->version() == 2);
}
TEST_CASE_FIXTURE(RootImplT_v0_6, "wrong_version")
TEST_CASE_METHOD(RootImplT_v0_6, "wrong_version")
{
v0_6::RootImpl root(root1_json);
@ -286,10 +279,10 @@ TEST_SUITE("validation::v0_6::RootImpl")
{ "op": "replace", "path": "/signed/version", "value": 3 }
])"_json;
CHECK_THROWS_AS(root.update(create_root_update("2.root.json", patch)), role_metadata_error);
REQUIRE_THROWS_AS(root.update(create_root_update("2.root.json", patch)), role_metadata_error);
}
TEST_CASE_FIXTURE(RootImplT_v0_6, "spec_version")
TEST_CASE_METHOD(RootImplT_v0_6, "spec_version")
{
v0_6::RootImpl root(root1_json);
@ -300,12 +293,12 @@ TEST_SUITE("validation::v0_6::RootImpl")
auto updated_root = root.update(create_root_update("2.root.json", patch));
auto testing_root = static_cast<v0_6::RootImpl*>(updated_root.get());
CHECK_EQ(testing_root->spec_version(), v0_6::SpecImpl("0.6.1"));
CHECK_EQ(testing_root->version(), 2);
CHECK_EQ(testing_root->expires(), root.expires());
REQUIRE(testing_root->spec_version() == v0_6::SpecImpl("0.6.1"));
REQUIRE(testing_root->version() == 2);
REQUIRE(testing_root->expires() == root.expires());
}
TEST_CASE_FIXTURE(RootImplT_v0_6, "upgraded_spec_version")
TEST_CASE_METHOD(RootImplT_v0_6, "upgraded_spec_version")
{
v0_6::RootImpl root(root1_json);
@ -314,7 +307,7 @@ TEST_SUITE("validation::v0_6::RootImpl")
{ "op": "replace", "path": "/signed/metadata_spec_version", "value": "1.0.0" }
])"_json;
CHECK_THROWS_AS(root.update(create_root_update("2.root.json", patch)), spec_version_error);
REQUIRE_THROWS_AS(root.update(create_root_update("2.root.json", patch)), spec_version_error);
nl::json signable_patch = nl::json::parse(
R"([
@ -329,13 +322,13 @@ TEST_SUITE("validation::v0_6::RootImpl")
auto updated_root = root.update(upgrade_to_v1(root, signable_patch));
auto testing_root = dynamic_cast<v1::RootImpl*>(updated_root.get());
REQUIRE_NE(testing_root, nullptr);
CHECK_EQ(testing_root->spec_version(), v0_6::SpecImpl("1.0.17"));
CHECK_EQ(testing_root->version(), 2);
CHECK_LT(testing_root->expires(), root.expires());
REQUIRE(testing_root != nullptr);
REQUIRE(testing_root->spec_version() == v0_6::SpecImpl("1.0.17"));
REQUIRE(testing_root->version() == 2);
REQUIRE(testing_root->expires() < root.expires());
}
TEST_CASE_FIXTURE(RootImplT_v0_6, "equivalent_upgraded_spec_version")
TEST_CASE_METHOD(RootImplT_v0_6, "equivalent_upgraded_spec_version")
{
v0_6::RootImpl root(root1_json);
@ -346,11 +339,11 @@ TEST_SUITE("validation::v0_6::RootImpl")
])"_json;
v1::RootImpl updated_root(upgrade_to_v1(root, signable_patch));
CHECK_EQ(updated_root.spec_version(), v1::SpecImpl("1.0.17"));
CHECK_EQ(updated_root.version(), 1);
REQUIRE(updated_root.spec_version() == v1::SpecImpl("1.0.17"));
REQUIRE(updated_root.version() == 1);
}
TEST_CASE_FIXTURE(RootImplT_v0_6, "wrong_spec_version")
TEST_CASE_METHOD(RootImplT_v0_6, "wrong_spec_version")
{
v0_6::RootImpl root(root1_json);
@ -359,31 +352,31 @@ TEST_SUITE("validation::v0_6::RootImpl")
{ "op": "replace", "path": "/signed/metadata_spec_version", "value": "1.0.0" }
])"_json;
CHECK_THROWS_AS(root.update(create_root_update("2.root.json", patch)), spec_version_error);
REQUIRE_THROWS_AS(root.update(create_root_update("2.root.json", patch)), spec_version_error);
patch = R"([
{ "op": "replace", "path": "/signed/version", "value": 2 },
{ "op": "replace", "path": "/signed/metadata_spec_version", "value": "wrong" }
])"_json;
CHECK_THROWS_AS(root.update(create_root_update("2.root.json", patch)), spec_version_error);
REQUIRE_THROWS_AS(root.update(create_root_update("2.root.json", patch)), spec_version_error);
}
TEST_CASE_FIXTURE(RootImplT_v0_6, "wrong_filename_role")
TEST_CASE_METHOD(RootImplT_v0_6, "wrong_filename_role")
{
v0_6::RootImpl root(root1_json);
CHECK_THROWS_AS(root.update(create_root_update("2.rooot.json")), role_file_error);
REQUIRE_THROWS_AS(root.update(create_root_update("2.rooot.json")), role_file_error);
}
TEST_CASE_FIXTURE(RootImplT_v0_6, "wrong_filename_version")
TEST_CASE_METHOD(RootImplT_v0_6, "wrong_filename_version")
{
v0_6::RootImpl root(root1_json);
CHECK_THROWS_AS(root.update(create_root_update("3.root.json")), role_file_error);
REQUIRE_THROWS_AS(root.update(create_root_update("3.root.json")), role_file_error);
}
TEST_CASE_FIXTURE(RootImplT_v0_6, "wrong_filename_spec_version")
TEST_CASE_METHOD(RootImplT_v0_6, "wrong_filename_spec_version")
{
v0_6::RootImpl root(root1_json);
@ -397,26 +390,26 @@ TEST_SUITE("validation::v0_6::RootImpl")
])"_json;
auto updated_root = root.update(upgrade_to_v1(root, signable_patch));
auto testing_root = dynamic_cast<v1::RootImpl*>(updated_root.get());
REQUIRE_NE(testing_root, nullptr);
CHECK_EQ(testing_root->spec_version(), v0_6::SpecImpl("1.0.0"));
REQUIRE(testing_root != nullptr);
REQUIRE(testing_root->spec_version() == v0_6::SpecImpl("1.0.0"));
// "2.sv2.root.json" is not upgradable spec version (spec version N+1)
nl::json patch = R"([
{ "op": "replace", "path": "/signed/version", "value": 2 }
])"_json;
CHECK_THROWS_AS(root.update(create_root_update("2.sv2.root.json", patch)), role_file_error);
REQUIRE_THROWS_AS(root.update(create_root_update("2.sv2.root.json", patch)), role_file_error);
}
TEST_CASE_FIXTURE(RootImplT_v0_6, "illformed_filename_version")
TEST_CASE_METHOD(RootImplT_v0_6, "illformed_filename_version")
{
v0_6::RootImpl root(root1_json);
CHECK_THROWS_AS(root.update(create_root_update("wrong.root.json")), role_file_error);
CHECK_THROWS_AS(root.update(create_root_update("2..root.json")), role_file_error);
CHECK_THROWS_AS(root.update(create_root_update("2.sv04.root.json")), role_file_error);
REQUIRE_THROWS_AS(root.update(create_root_update("wrong.root.json")), role_file_error);
REQUIRE_THROWS_AS(root.update(create_root_update("2..root.json")), role_file_error);
REQUIRE_THROWS_AS(root.update(create_root_update("2.sv04.root.json")), role_file_error);
}
TEST_CASE_FIXTURE(RootImplT_v0_6, "rollback_attack")
TEST_CASE_METHOD(RootImplT_v0_6, "rollback_attack")
{
v0_6::RootImpl root(root1_json);
@ -424,10 +417,10 @@ TEST_SUITE("validation::v0_6::RootImpl")
{ "op": "replace", "path": "/signed/version", "value": 1 }
])"_json;
CHECK_THROWS_AS(root.update(create_root_update("2.root.json", patch)), rollback_error);
REQUIRE_THROWS_AS(root.update(create_root_update("2.root.json", patch)), rollback_error);
}
TEST_CASE_FIXTURE(RootImplT_v0_6, "wrong_type")
TEST_CASE_METHOD(RootImplT_v0_6, "wrong_type")
{
v0_6::RootImpl root(root1_json);
@ -436,10 +429,10 @@ TEST_SUITE("validation::v0_6::RootImpl")
{ "op": "replace", "path": "/signed/version", "value": 2 }
])"_json;
CHECK_THROWS_AS(root.update(create_root_update("2.root.json", patch)), role_metadata_error);
REQUIRE_THROWS_AS(root.update(create_root_update("2.root.json", patch)), role_metadata_error);
}
TEST_CASE_FIXTURE(RootImplT_v0_6, "missing_type")
TEST_CASE_METHOD(RootImplT_v0_6, "missing_type")
{
v0_6::RootImpl root(root1_json);
@ -448,10 +441,10 @@ TEST_SUITE("validation::v0_6::RootImpl")
{ "op": "replace", "path": "/signed/version", "value": 2 }
])"_json;
CHECK_THROWS_AS(root.update(create_root_update("2.root.json", patch)), role_metadata_error);
REQUIRE_THROWS_AS(root.update(create_root_update("2.root.json", patch)), role_metadata_error);
}
TEST_CASE_FIXTURE(RootImplT_v0_6, "missing_delegations")
TEST_CASE_METHOD(RootImplT_v0_6, "missing_delegations")
{
v0_6::RootImpl root(root1_json);
@ -460,10 +453,10 @@ TEST_SUITE("validation::v0_6::RootImpl")
{ "op": "replace", "path": "/signed/version", "value": 2 }
])"_json;
CHECK_THROWS_AS(root.update(create_root_update("2.root.json", patch)), role_metadata_error);
REQUIRE_THROWS_AS(root.update(create_root_update("2.root.json", patch)), role_metadata_error);
}
TEST_CASE_FIXTURE(RootImplT_v0_6, "missing_delegation")
TEST_CASE_METHOD(RootImplT_v0_6, "missing_delegation")
{
v0_6::RootImpl root(root1_json);
@ -472,10 +465,10 @@ TEST_SUITE("validation::v0_6::RootImpl")
{ "op": "replace", "path": "/signed/version", "value": 2 }
])"_json;
CHECK_THROWS_AS(root.update(create_root_update("2.root.json", patch)), role_metadata_error);
REQUIRE_THROWS_AS(root.update(create_root_update("2.root.json", patch)), role_metadata_error);
}
TEST_CASE_FIXTURE(RootImplT_v0_6, "empty_delegation_pubkeys")
TEST_CASE_METHOD(RootImplT_v0_6, "empty_delegation_pubkeys")
{
v0_6::RootImpl root(root1_json);
@ -484,10 +477,10 @@ TEST_SUITE("validation::v0_6::RootImpl")
{ "op": "replace", "path": "/signed/version", "value": 2 }
])"_json;
CHECK_THROWS_AS(root.update(create_root_update("2.root.json", patch)), role_metadata_error);
REQUIRE_THROWS_AS(root.update(create_root_update("2.root.json", patch)), role_metadata_error);
}
TEST_CASE_FIXTURE(RootImplT_v0_6, "null_role_threshold")
TEST_CASE_METHOD(RootImplT_v0_6, "null_role_threshold")
{
v0_6::RootImpl root(root1_json);
@ -496,10 +489,10 @@ TEST_SUITE("validation::v0_6::RootImpl")
{ "op": "replace", "path": "/signed/version", "value": 2 }
])"_json;
CHECK_THROWS_AS(root.update(create_root_update("2.root.json", patch)), role_metadata_error);
REQUIRE_THROWS_AS(root.update(create_root_update("2.root.json", patch)), role_metadata_error);
}
TEST_CASE_FIXTURE(RootImplT_v0_6, "extra_roles")
TEST_CASE_METHOD(RootImplT_v0_6, "extra_roles")
{
v0_6::RootImpl root(root1_json);
@ -509,10 +502,11 @@ TEST_SUITE("validation::v0_6::RootImpl")
{ "op": "replace", "path": "/signed/version", "value": 2 }
])"_json;
CHECK_THROWS_AS(root.update(create_root_update("2.root.json", patch)), role_metadata_error);
REQUIRE_THROWS_AS(root.update(create_root_update("2.root.json", patch)), role_metadata_error);
}
/*
TEST_CASE_FIXTURE(RootImplT_v06, mirrors_role)
TEST_CASE_METHOD(RootImplT_v06, mirrors_role)
{
json patch = R"([
{ "op": "add", "path":
@ -523,10 +517,10 @@ TEST_SUITE("validation::v0_6::RootImpl")
RootImpl root(create_root_update("2.root.json", patch));
bool mirrors_role_found = (root.roles().find("mirrors") != root.roles().end());
CHECK(mirrors_role_found);
REQUIRE(mirrors_role_found);
}
*/
TEST_CASE_FIXTURE(RootImplT_v0_6, "threshold_not_met")
TEST_CASE_METHOD(RootImplT_v0_6, "threshold_not_met")
{
v0_6::RootImpl root(root1_json);
@ -535,19 +529,19 @@ TEST_SUITE("validation::v0_6::RootImpl")
{ "op": "replace", "path": "/signed/delegations/root/threshold", "value": 2 }
])"_json;
CHECK_THROWS_AS(root.update(create_root_update("2.root.json", patch)), role_error);
REQUIRE_THROWS_AS(root.update(create_root_update("2.root.json", patch)), role_error);
}
TEST_CASE_FIXTURE(RootImplT_v0_6, "expires")
TEST_CASE_METHOD(RootImplT_v0_6, "expires")
{
v0_6::RootImpl root(root1_json);
// expiration is set to now+3600s in 'sign_root'
TimeRef time_ref;
CHECK_FALSE(root.expired(time_ref));
REQUIRE_FALSE(root.expired(time_ref));
time_ref.set(utc_time_now() + 7200);
CHECK(root.expired(time_ref));
REQUIRE(root.expired(time_ref));
nl::json patch = nl::json::parse(
R"([
@ -559,10 +553,10 @@ TEST_SUITE("validation::v0_6::RootImpl")
auto updated_root = root.update(create_root_update("2.root.json", patch));
auto testing_root = static_cast<v0_6::RootImpl*>(updated_root.get());
CHECK_FALSE(testing_root->expired(time_ref));
REQUIRE_FALSE(testing_root->expired(time_ref));
}
TEST_CASE_FIXTURE(RootImplT_v0_6, "timestamp")
TEST_CASE_METHOD(RootImplT_v0_6, "timestamp")
{
v0_6::RootImpl root(root1_json);
@ -572,40 +566,58 @@ TEST_SUITE("validation::v0_6::RootImpl")
{ "op": "replace", "path": "/signed/timestamp", "value": "2021-09-20T07:07:09+0030" },
{ "op": "replace", "path": "/signed/version", "value": 2 }
])");
CHECK_THROWS_AS(root.update(create_root_update("2.root.json", patch)), role_metadata_error);
REQUIRE_THROWS_AS(root.update(create_root_update("2.root.json", patch)), role_metadata_error);
patch = nl::json::parse(R"([
{ "op": "replace", "path": "/signed/timestamp", "value": "2021-09-20T07:07:09D" },
{ "op": "replace", "path": "/signed/version", "value": 2 }
])");
CHECK_THROWS_AS(root.update(create_root_update("2.root.json", patch)), role_metadata_error);
REQUIRE_THROWS_AS(root.update(create_root_update("2.root.json", patch)), role_metadata_error);
patch = nl::json::parse(R"([
{ "op": "replace", "path": "/signed/timestamp", "value": "2021-09-20T07:07:09.000" },
{ "op": "replace", "path": "/signed/version", "value": 2 }
])");
CHECK_THROWS_AS(root.update(create_root_update("2.root.json", patch)), role_metadata_error);
REQUIRE_THROWS_AS(root.update(create_root_update("2.root.json", patch)), role_metadata_error);
}
TEST_CASE_FIXTURE(RootImplT_v0_6, "possible_update_files")
TEST_CASE_METHOD(RootImplT_v0_6, "possible_update_files")
{
v0_6::RootImpl root(root1_json);
auto update_f = root.possible_update_files();
CHECK(update_f[0].string().c_str() == doctest::Contains("2.sv1.root.json"));
CHECK(update_f[1].string().c_str() == doctest::Contains("2.sv0.7.root.json"));
CHECK(update_f[2].string().c_str() == doctest::Contains("2.sv0.6.root.json"));
CHECK(update_f[3].string().c_str() == doctest::Contains("2.root.json"));
REQUIRE_THAT(
update_f[0].string().c_str(),
Catch::Matchers::ContainsSubstring("2.sv1.root.json")
);
REQUIRE_THAT(
update_f[1].string().c_str(),
Catch::Matchers::ContainsSubstring("2.sv0.7.root.json")
);
REQUIRE_THAT(
update_f[2].string().c_str(),
Catch::Matchers::ContainsSubstring("2.sv0.6.root.json")
);
REQUIRE_THAT(update_f[3].string().c_str(), Catch::Matchers::ContainsSubstring("2.root.json"));
nl::json patch = nl::json::parse(R"([
{ "op": "replace", "path": "/signed/version", "value": 2 }
])");
auto updated_root = root.update(create_root_update("2.root.json", patch));
update_f = updated_root->possible_update_files();
CHECK(update_f[0].string().c_str() == doctest::Contains("3.sv1.root.json"));
CHECK(update_f[1].string().c_str() == doctest::Contains("3.sv0.7.root.json"));
CHECK(update_f[2].string().c_str() == doctest::Contains("3.sv0.6.root.json"));
CHECK(update_f[3].string().c_str() == doctest::Contains("3.root.json"));
REQUIRE_THAT(
update_f[0].string().c_str(),
Catch::Matchers::ContainsSubstring("3.sv1.root.json")
);
REQUIRE_THAT(
update_f[1].string().c_str(),
Catch::Matchers::ContainsSubstring("3.sv0.7.root.json")
);
REQUIRE_THAT(
update_f[2].string().c_str(),
Catch::Matchers::ContainsSubstring("3.sv0.6.root.json")
);
REQUIRE_THAT(update_f[3].string().c_str(), Catch::Matchers::ContainsSubstring("3.root.json"));
}
}
@ -620,78 +632,78 @@ protected:
v0_6::SpecImpl spec;
};
TEST_SUITE("validation::v0_6::SpecImpl")
namespace
{
TEST_CASE_FIXTURE(SpecImplT_v06, "ctor")
TEST_CASE_METHOD(SpecImplT_v06, "ctor")
{
v0_6::SpecImpl new_spec("0.6.1");
CHECK_EQ(new_spec.version_str(), "0.6.1");
REQUIRE(new_spec.version_str() == "0.6.1");
}
TEST_CASE_FIXTURE(SpecImplT_v06, "version_str")
TEST_CASE_METHOD(SpecImplT_v06, "version_str")
{
CHECK_EQ(spec.version_str(), "0.6.0");
REQUIRE(spec.version_str() == "0.6.0");
}
TEST_CASE_FIXTURE(SpecImplT_v06, "is_compatible")
TEST_CASE_METHOD(SpecImplT_v06, "is_compatible")
{
CHECK(spec.is_compatible(std::string("0.6.0")));
CHECK(spec.is_compatible(std::string("0.6.1")));
CHECK(spec.is_compatible(std::string("0.6.10")));
REQUIRE(spec.is_compatible(std::string("0.6.0")));
REQUIRE(spec.is_compatible(std::string("0.6.1")));
REQUIRE(spec.is_compatible(std::string("0.6.10")));
// minor version change with major version '0' may be
// backward incompatible
CHECK_FALSE(spec.is_compatible(std::string("0.7.0")));
CHECK_FALSE(spec.is_compatible(std::string("1.0.0")));
CHECK_FALSE(spec.is_compatible(std::string("2.0.0")));
REQUIRE_FALSE(spec.is_compatible(std::string("0.7.0")));
REQUIRE_FALSE(spec.is_compatible(std::string("1.0.0")));
REQUIRE_FALSE(spec.is_compatible(std::string("2.0.0")));
}
TEST_CASE_FIXTURE(SpecImplT_v06, "is_upgrade")
TEST_CASE_METHOD(SpecImplT_v06, "is_upgrade")
{
CHECK(spec.is_upgrade(std::string("0.7.0")));
CHECK(spec.is_upgrade(std::string("1.0.0")));
CHECK(spec.is_upgrade(std::string("1.1.0")));
CHECK(spec.is_upgrade(std::string("1.0.17")));
REQUIRE(spec.is_upgrade(std::string("0.7.0")));
REQUIRE(spec.is_upgrade(std::string("1.0.0")));
REQUIRE(spec.is_upgrade(std::string("1.1.0")));
REQUIRE(spec.is_upgrade(std::string("1.0.17")));
// 2 possible backward incompatible updates
CHECK_FALSE(spec.is_upgrade(std::string("0.8.0")));
CHECK_FALSE(spec.is_upgrade(std::string("2.0.0")));
REQUIRE_FALSE(spec.is_upgrade(std::string("0.8.0")));
REQUIRE_FALSE(spec.is_upgrade(std::string("2.0.0")));
// not an upgrade, compatible version
CHECK_FALSE(spec.is_upgrade(std::string("0.6.1")));
REQUIRE_FALSE(spec.is_upgrade(std::string("0.6.1")));
}
TEST_CASE_FIXTURE(SpecImplT_v06, "upgradable")
TEST_CASE_METHOD(SpecImplT_v06, "upgradable")
{
CHECK(spec.upgradable());
REQUIRE(spec.upgradable());
}
TEST_CASE_FIXTURE(SpecImplT_v06, "compatible_prefix")
TEST_CASE_METHOD(SpecImplT_v06, "compatible_prefix")
{
CHECK_EQ(spec.compatible_prefix(), "0.6");
REQUIRE(spec.compatible_prefix() == "0.6");
}
TEST_CASE_FIXTURE(SpecImplT_v06, "upgrade_prefix")
TEST_CASE_METHOD(SpecImplT_v06, "upgrade_prefix")
{
CHECK(spec.upgrade_prefix()[0].c_str() == doctest::Contains("1"));
CHECK(spec.upgrade_prefix()[1].c_str() == doctest::Contains("0.7"));
REQUIRE_THAT(spec.upgrade_prefix()[0].c_str(), Catch::Matchers::ContainsSubstring("1"));
REQUIRE_THAT(spec.upgrade_prefix()[1].c_str(), Catch::Matchers::ContainsSubstring("0.7"));
}
TEST_CASE_FIXTURE(SpecImplT_v06, "json_key")
TEST_CASE_METHOD(SpecImplT_v06, "json_key")
{
CHECK_EQ(spec.json_key(), "metadata_spec_version");
REQUIRE(spec.json_key() == "metadata_spec_version");
}
TEST_CASE_FIXTURE(SpecImplT_v06, "expiration_json_key")
TEST_CASE_METHOD(SpecImplT_v06, "expiration_json_key")
{
CHECK_EQ(spec.expiration_json_key(), "expiration");
REQUIRE(spec.expiration_json_key() == "expiration");
}
TEST_CASE_FIXTURE(SpecImplT_v06, "canonicalize")
TEST_CASE_METHOD(SpecImplT_v06, "canonicalize")
{
CHECK_EQ(spec.canonicalize(R"({"foo":"bar"})"_json), "{\n \"foo\": \"bar\"\n}");
REQUIRE(spec.canonicalize(R"({"foo":"bar"})"_json) == "{\n \"foo\": \"bar\"\n}");
}
TEST_CASE_FIXTURE(SpecImplT_v06, "signatures")
TEST_CASE_METHOD(SpecImplT_v06, "signatures")
{
nl::json j = R"({
"signatures":
@ -704,10 +716,10 @@ TEST_SUITE("validation::v0_6::SpecImpl")
}
})"_json;
auto sigs = spec.signatures(j);
CHECK_EQ(sigs.size(), 1);
CHECK_EQ(sigs.begin()->keyid, "foo");
CHECK_EQ(sigs.begin()->sig, "baz");
CHECK_EQ(sigs.begin()->pgp_trailer, "bar");
REQUIRE(sigs.size() == 1);
REQUIRE(sigs.begin()->keyid == "foo");
REQUIRE(sigs.begin()->sig == "baz");
REQUIRE(sigs.begin()->pgp_trailer == "bar");
}
}
@ -791,18 +803,18 @@ protected:
}
};
TEST_SUITE("validation::v0_6::KeyMgr")
namespace
{
TEST_CASE_FIXTURE(KeyMgrT_v06, "ctor_from_json")
TEST_CASE_METHOD(KeyMgrT_v06, "ctor_from_json")
{
v0_6::RootImpl root(root1_json);
auto key_mgr = root.create_key_mgr(key_mgr_json);
CHECK_EQ(key_mgr.spec_version(), v0_6::SpecImpl("0.6.0"));
CHECK_EQ(key_mgr.version(), 1);
REQUIRE(key_mgr.spec_version() == v0_6::SpecImpl("0.6.0"));
REQUIRE(key_mgr.version() == 1);
}
TEST_CASE_FIXTURE(KeyMgrT_v06, "ctor_from_json_str")
TEST_CASE_METHOD(KeyMgrT_v06, "ctor_from_json_str")
{
v0_6::RootImpl root(root1_json);
auto key_mgr = v0_6::KeyMgrRole(
@ -811,11 +823,11 @@ TEST_SUITE("validation::v0_6::KeyMgr")
std::make_shared<v0_6::SpecImpl>(v0_6::SpecImpl())
);
CHECK_EQ(key_mgr.spec_version(), v0_6::SpecImpl("0.6.0"));
CHECK_EQ(key_mgr.version(), 1);
REQUIRE(key_mgr.spec_version() == v0_6::SpecImpl("0.6.0"));
REQUIRE(key_mgr.version() == 1);
}
TEST_CASE_FIXTURE(KeyMgrT_v06, "version")
TEST_CASE_METHOD(KeyMgrT_v06, "version")
{
v0_6::RootImpl root(root1_json);
@ -825,8 +837,8 @@ TEST_SUITE("validation::v0_6::KeyMgr")
])"_json;
auto key_mgr = root.create_key_mgr(patched_key_mgr_json(key_mgr_patch));
CHECK_EQ(key_mgr.spec_version(), v0_6::SpecImpl("0.6.0"));
CHECK_EQ(key_mgr.version(), 2);
REQUIRE(key_mgr.spec_version() == v0_6::SpecImpl("0.6.0"));
REQUIRE(key_mgr.version() == 2);
}
{ // Any version is valid, without chaining required
@ -835,12 +847,12 @@ TEST_SUITE("validation::v0_6::KeyMgr")
])"_json;
auto key_mgr = root.create_key_mgr(patched_key_mgr_json(key_mgr_patch));
CHECK_EQ(key_mgr.spec_version(), v0_6::SpecImpl("0.6.0"));
CHECK_EQ(key_mgr.version(), 20);
REQUIRE(key_mgr.spec_version() == v0_6::SpecImpl("0.6.0"));
REQUIRE(key_mgr.version() == 20);
}
}
TEST_CASE_FIXTURE(KeyMgrT_v06, "spec_version")
TEST_CASE_METHOD(KeyMgrT_v06, "spec_version")
{ // spec version as to match exactly 'root' spec version
v0_6::RootImpl root(root1_json);
@ -850,8 +862,8 @@ TEST_SUITE("validation::v0_6::KeyMgr")
])"_json;
auto key_mgr = root.create_key_mgr(patched_key_mgr_json(key_mgr_patch));
CHECK_EQ(key_mgr.spec_version(), v0_6::SpecImpl("0.6.0"));
CHECK_EQ(key_mgr.version(), 1);
REQUIRE(key_mgr.spec_version() == v0_6::SpecImpl("0.6.0"));
REQUIRE(key_mgr.version() == 1);
}
{ // is compatible but not strictly the same as 'root' one
@ -859,7 +871,10 @@ TEST_SUITE("validation::v0_6::KeyMgr")
{ "op": "replace", "path": "/signed/metadata_spec_version", "value": "0.6.1" }
])"_json;
CHECK_THROWS_AS(root.create_key_mgr(patched_key_mgr_json(key_mgr_patch)), spec_version_error);
REQUIRE_THROWS_AS(
root.create_key_mgr(patched_key_mgr_json(key_mgr_patch)),
spec_version_error
);
}
{ // wrong type
@ -867,58 +882,58 @@ TEST_SUITE("validation::v0_6::KeyMgr")
{ "op": "replace", "path": "/signed/metadata_spec_version", "value": 0.6 }
])"_json;
CHECK_THROWS_AS(
REQUIRE_THROWS_AS(
root.create_key_mgr(patched_key_mgr_json(key_mgr_patch)),
role_metadata_error
);
}
}
TEST_CASE_FIXTURE(KeyMgrT_v06, "ctor_from_path")
TEST_CASE_METHOD(KeyMgrT_v06, "ctor_from_path")
{
v0_6::RootImpl root(root1_json);
auto key_mgr = root.create_key_mgr(write_key_mgr_file(key_mgr_json));
CHECK_EQ(key_mgr.spec_version(), v0_6::SpecImpl("0.6.0"));
CHECK_EQ(key_mgr.version(), 1);
REQUIRE(key_mgr.spec_version() == v0_6::SpecImpl("0.6.0"));
REQUIRE(key_mgr.version() == 1);
// TODO: enforce consistency between spec version in filename and metadata
key_mgr = root.create_key_mgr(write_key_mgr_file(key_mgr_json, "20.sv0.6.key_mgr.json"));
CHECK_EQ(key_mgr.spec_version(), v0_6::SpecImpl("0.6.0"));
CHECK_EQ(key_mgr.version(), 1);
REQUIRE(key_mgr.spec_version() == v0_6::SpecImpl("0.6.0"));
REQUIRE(key_mgr.version() == 1);
CHECK_THROWS_AS(root.create_key_mgr(fs::u8path("not_existing")), role_file_error);
REQUIRE_THROWS_AS(root.create_key_mgr(fs::u8path("not_existing")), role_file_error);
CHECK_THROWS_AS(
REQUIRE_THROWS_AS(
root.create_key_mgr(write_key_mgr_file(key_mgr_json, "wrong.json")),
role_file_error
);
CHECK_THROWS_AS(
REQUIRE_THROWS_AS(
root.create_key_mgr(write_key_mgr_file(key_mgr_json, "sv1.key_mgr.json")),
role_file_error
);
CHECK_THROWS_AS(
REQUIRE_THROWS_AS(
root.create_key_mgr(write_key_mgr_file(key_mgr_json, "wrong.sv0.6.key_mgr.json")),
role_file_error
);
}
TEST_CASE_FIXTURE(KeyMgrT_v06, "expires")
TEST_CASE_METHOD(KeyMgrT_v06, "expires")
{
v0_6::RootImpl root(root1_json);
auto key_mgr = root.create_key_mgr(key_mgr_json);
// expiration is set to now+3600s in 'sign_key_mgr'
TimeRef time_ref;
CHECK_FALSE(key_mgr.expired(time_ref));
CHECK_FALSE(root.expired(time_ref));
REQUIRE_FALSE(key_mgr.expired(time_ref));
REQUIRE_FALSE(root.expired(time_ref));
time_ref.set(utc_time_now() + 7200);
CHECK(key_mgr.expired(time_ref));
CHECK(root.expired(time_ref));
REQUIRE(key_mgr.expired(time_ref));
REQUIRE(root.expired(time_ref));
nl::json patch = nl::json::parse(
R"([
@ -928,11 +943,11 @@ TEST_SUITE("validation::v0_6::KeyMgr")
);
key_mgr = root.create_key_mgr(patched_key_mgr_json(patch));
CHECK_FALSE(key_mgr.expired(time_ref));
CHECK(root.expired(time_ref));
REQUIRE_FALSE(key_mgr.expired(time_ref));
REQUIRE(root.expired(time_ref));
}
TEST_CASE_FIXTURE(KeyMgrT_v06, "timestamp")
TEST_CASE_METHOD(KeyMgrT_v06, "timestamp")
{
v0_6::RootImpl root(root1_json);
@ -943,19 +958,19 @@ TEST_SUITE("validation::v0_6::KeyMgr")
{ "op": "replace", "path": "/signed/version", "value": 1 }
])");
CHECK_THROWS_AS(root.create_key_mgr(patched_key_mgr_json(patch)), role_metadata_error);
REQUIRE_THROWS_AS(root.create_key_mgr(patched_key_mgr_json(patch)), role_metadata_error);
patch = nl::json::parse(R"([
{ "op": "replace", "path": "/signed/timestamp", "value": "2021-09-20T07:07:09D" },
{ "op": "replace", "path": "/signed/version", "value": 1 }
])");
CHECK_THROWS_AS(root.create_key_mgr(patched_key_mgr_json(patch)), role_metadata_error);
REQUIRE_THROWS_AS(root.create_key_mgr(patched_key_mgr_json(patch)), role_metadata_error);
patch = nl::json::parse(R"([
{ "op": "replace", "path": "/signed/timestamp", "value": "2021-09-20T07:07:09.000" },
{ "op": "replace", "path": "/signed/version", "value": 1 }
])");
CHECK_THROWS_AS(root.create_key_mgr(patched_key_mgr_json(patch)), role_metadata_error);
REQUIRE_THROWS_AS(root.create_key_mgr(patched_key_mgr_json(patch)), role_metadata_error);
}
}
@ -1114,9 +1129,9 @@ protected:
}
};
TEST_SUITE("validation::v0_6::PkgMgr")
namespace
{
TEST_CASE_FIXTURE(PkgMgrT_v06, "verify_index")
TEST_CASE_METHOD(PkgMgrT_v06, "verify_index")
{
auto key_mgr = root->create_key_mgr(key_mgr_json);
auto pkg_mgr = key_mgr.create_pkg_mgr(pkg_mgr_json);
@ -1124,7 +1139,7 @@ TEST_SUITE("validation::v0_6::PkgMgr")
pkg_mgr.verify_index(signed_repodata_json);
}
TEST_CASE_FIXTURE(PkgMgrT_v06, "corrupted_repodata")
TEST_CASE_METHOD(PkgMgrT_v06, "corrupted_repodata")
{
auto key_mgr = root->create_key_mgr(key_mgr_json);
auto pkg_mgr = key_mgr.create_pkg_mgr(pkg_mgr_json);
@ -1132,10 +1147,13 @@ TEST_SUITE("validation::v0_6::PkgMgr")
nl::json wrong_pkg_patch = R"([
{ "op": "replace", "path": "/packages/test-package1-0.1-0.tar.bz2/version", "value": "0.1.1" }
])"_json;
CHECK_THROWS_AS(pkg_mgr.verify_index(signed_repodata_json.patch(wrong_pkg_patch)), package_error);
REQUIRE_THROWS_AS(
pkg_mgr.verify_index(signed_repodata_json.patch(wrong_pkg_patch)),
package_error
);
}
TEST_CASE_FIXTURE(PkgMgrT_v06, "illformed_repodata")
TEST_CASE_METHOD(PkgMgrT_v06, "illformed_repodata")
{
auto key_mgr = root->create_key_mgr(key_mgr_json);
auto pkg_mgr = key_mgr.create_pkg_mgr(pkg_mgr_json);
@ -1143,7 +1161,7 @@ TEST_SUITE("validation::v0_6::PkgMgr")
nl::json illformed_pkg_patch = R"([
{ "op": "remove", "path": "/signatures"}
])"_json;
CHECK_THROWS_AS(
REQUIRE_THROWS_AS(
pkg_mgr.verify_index(signed_repodata_json.patch(illformed_pkg_patch)),
index_error
);
@ -1192,23 +1210,23 @@ protected:
}
};
TEST_SUITE("validation::v0_6::RepoChecker")
namespace
{
TEST_CASE_FIXTURE(RepoCheckerT, "ctor")
TEST_CASE_METHOD(RepoCheckerT, "ctor")
{
RepoChecker checker(mambatests::context(), m_repo_base_url, m_ref_path);
checker.generate_index_checker();
CHECK_EQ(checker.root_version(), 2);
REQUIRE(checker.root_version() == 2);
}
TEST_CASE_FIXTURE(RepoCheckerT, "verify_index")
TEST_CASE_METHOD(RepoCheckerT, "verify_index")
{
RepoChecker checker(mambatests::context(), m_repo_base_url, m_ref_path);
checker.generate_index_checker();
checker.verify_index(signed_repodata_json);
}
TEST_CASE_FIXTURE(RepoCheckerT, "root_freeze_attack")
TEST_CASE_METHOD(RepoCheckerT, "root_freeze_attack")
{
nl::json patch = nl::json::parse(
R"([
@ -1219,10 +1237,10 @@ TEST_SUITE("validation::v0_6::RepoChecker")
);
write_role(create_root_update_json(patch), channel_dir->path() / "2.root.json");
RepoChecker checker(mambatests::context(), m_repo_base_url, m_ref_path);
CHECK_THROWS_AS(checker.generate_index_checker(), freeze_error);
REQUIRE_THROWS_AS(checker.generate_index_checker(), freeze_error);
}
TEST_CASE_FIXTURE(RepoCheckerT, "key_mgr_freeze_attack")
TEST_CASE_METHOD(RepoCheckerT, "key_mgr_freeze_attack")
{
nl::json patch = nl::json::parse(
R"([
@ -1232,17 +1250,17 @@ TEST_SUITE("validation::v0_6::RepoChecker")
);
write_role(patched_key_mgr_json(patch), channel_dir->path() / "key_mgr.json");
RepoChecker checker(mambatests::context(), m_repo_base_url, m_ref_path);
CHECK_THROWS_AS(checker.generate_index_checker(), freeze_error);
REQUIRE_THROWS_AS(checker.generate_index_checker(), freeze_error);
}
TEST_CASE_FIXTURE(RepoCheckerT, "missing_key_mgr_file")
TEST_CASE_METHOD(RepoCheckerT, "missing_key_mgr_file")
{
fs::remove(channel_dir->path() / "key_mgr.json");
RepoChecker checker(mambatests::context(), m_repo_base_url, m_ref_path);
CHECK_THROWS_AS(checker.generate_index_checker(), fetching_error);
REQUIRE_THROWS_AS(checker.generate_index_checker(), fetching_error);
}
TEST_CASE_FIXTURE(RepoCheckerT, "corrupted_repodata")
TEST_CASE_METHOD(RepoCheckerT, "corrupted_repodata")
{
RepoChecker checker(mambatests::context(), m_repo_base_url, m_ref_path);
@ -1250,10 +1268,13 @@ TEST_SUITE("validation::v0_6::RepoChecker")
{ "op": "replace", "path": "/packages/test-package1-0.1-0.tar.bz2/version", "value": "0.1.1" }
])"_json;
checker.generate_index_checker();
CHECK_THROWS_AS(checker.verify_index(signed_repodata_json.patch(wrong_pkg_patch)), package_error);
REQUIRE_THROWS_AS(
checker.verify_index(signed_repodata_json.patch(wrong_pkg_patch)),
package_error
);
}
TEST_CASE_FIXTURE(RepoCheckerT, "illformed_repodata")
TEST_CASE_METHOD(RepoCheckerT, "illformed_repodata")
{
RepoChecker checker(mambatests::context(), m_repo_base_url, m_ref_path);
@ -1261,7 +1282,7 @@ TEST_SUITE("validation::v0_6::RepoChecker")
{ "op": "remove", "path": "/signatures"}
])"_json;
checker.generate_index_checker();
CHECK_THROWS_AS(
REQUIRE_THROWS_AS(
checker.verify_index(signed_repodata_json.patch(illformed_pkg_patch)),
index_error
);

View File

@ -6,7 +6,7 @@
#include <map>
#include <doctest/doctest.h>
#include <catch2/catch_all.hpp>
#include <nlohmann/json.hpp>
#include <spdlog/spdlog.h>
@ -152,29 +152,29 @@ protected:
}
};
TEST_SUITE("validation::v1::RootImpl")
namespace
{
TEST_CASE_FIXTURE(RootImplT_v1, "ctor_from_path")
TEST_CASE_METHOD(RootImplT_v1, "ctor_from_path")
{
v1::RootImpl root(trusted_root_file());
CHECK_EQ(root.type(), "root");
CHECK_EQ(root.file_ext(), "json");
CHECK_EQ(root.spec_version(), v1::SpecImpl("1.0.17"));
CHECK_EQ(root.version(), 1);
REQUIRE(root.type() == "root");
REQUIRE(root.file_ext() == "json");
REQUIRE(root.spec_version() == v1::SpecImpl("1.0.17"));
REQUIRE(root.version() == 1);
}
TEST_CASE_FIXTURE(RootImplT_v1, "ctor_from_json")
TEST_CASE_METHOD(RootImplT_v1, "ctor_from_json")
{
v1::RootImpl root(root1_json);
CHECK_EQ(root.type(), "root");
CHECK_EQ(root.file_ext(), "json");
CHECK_EQ(root.spec_version(), v1::SpecImpl("1.0.17"));
CHECK_EQ(root.version(), 1);
REQUIRE(root.type() == "root");
REQUIRE(root.file_ext() == "json");
REQUIRE(root.spec_version() == v1::SpecImpl("1.0.17"));
REQUIRE(root.version() == 1);
}
TEST_CASE_FIXTURE(RootImplT_v1, "update_from_path")
TEST_CASE_METHOD(RootImplT_v1, "update_from_path")
{
using namespace mamba;
@ -186,13 +186,13 @@ TEST_SUITE("validation::v1::RootImpl")
auto updated_root = root.update(create_root_update("2.root.json", patch));
auto testing_root = static_cast<v1::RootImpl*>(updated_root.get());
CHECK_EQ(testing_root->type(), "root");
CHECK_EQ(testing_root->file_ext(), "json");
CHECK_EQ(testing_root->spec_version(), v1::SpecImpl("1.0.17"));
CHECK_EQ(testing_root->version(), 2);
REQUIRE(testing_root->type() == "root");
REQUIRE(testing_root->file_ext() == "json");
REQUIRE(testing_root->spec_version() == v1::SpecImpl("1.0.17"));
REQUIRE(testing_root->version() == 2);
}
TEST_CASE_FIXTURE(RootImplT_v1, "ctor_wrong_filename_spec_version")
TEST_CASE_METHOD(RootImplT_v1, "ctor_wrong_filename_spec_version")
{
fs::u8path p = channel_dir->path() / "2.sv0.6.root.json";
@ -201,10 +201,10 @@ TEST_SUITE("validation::v1::RootImpl")
out_file.close();
// "2.sv0.6.root.json" is not compatible spec version (spec version N)
CHECK_THROWS_AS(v1::RootImpl root(p), role_file_error);
REQUIRE_THROWS_AS(v1::RootImpl(p), role_file_error);
}
TEST_CASE_FIXTURE(RootImplT_v1, "wrong_version")
TEST_CASE_METHOD(RootImplT_v1, "wrong_version")
{
v1::RootImpl root(root1_json);
@ -212,10 +212,10 @@ TEST_SUITE("validation::v1::RootImpl")
{ "op": "replace", "path": "/signed/version", "value": 3 }
])"_json;
CHECK_THROWS_AS(root.update(create_root_update("2.root.json", patch)), role_metadata_error);
REQUIRE_THROWS_AS(root.update(create_root_update("2.root.json", patch)), role_metadata_error);
}
TEST_CASE_FIXTURE(RootImplT_v1, "spec_version")
TEST_CASE_METHOD(RootImplT_v1, "spec_version")
{
v1::RootImpl root(root1_json);
@ -227,11 +227,11 @@ TEST_SUITE("validation::v1::RootImpl")
auto updated_root = root.update(create_root_update("2.root.json", patch));
auto testing_root = static_cast<v1::RootImpl*>(updated_root.get());
CHECK_EQ(testing_root->spec_version(), v1::SpecImpl("1.30.10"));
CHECK_EQ(testing_root->version(), 2);
REQUIRE(testing_root->spec_version() == v1::SpecImpl("1.30.10"));
REQUIRE(testing_root->version() == 2);
}
TEST_CASE_FIXTURE(RootImplT_v1, "wrong_spec_version")
TEST_CASE_METHOD(RootImplT_v1, "wrong_spec_version")
{
v1::RootImpl root(root1_json);
@ -239,49 +239,49 @@ TEST_SUITE("validation::v1::RootImpl")
{ "op": "replace", "path": "/signed/spec_version", "value": "2.0.0" }
])"_json;
CHECK_THROWS_AS(root.update(create_root_update("2.root.json", patch)), spec_version_error);
REQUIRE_THROWS_AS(root.update(create_root_update("2.root.json", patch)), spec_version_error);
}
TEST_CASE_FIXTURE(RootImplT_v1, "wrong_filename_role")
TEST_CASE_METHOD(RootImplT_v1, "wrong_filename_role")
{
v1::RootImpl root(root1_json);
nl::json patch = R"([])"_json;
CHECK_THROWS_AS(root.update(create_root_update("2.rooot.json", patch)), role_file_error);
REQUIRE_THROWS_AS(root.update(create_root_update("2.rooot.json", patch)), role_file_error);
}
TEST_CASE_FIXTURE(RootImplT_v1, "wrong_filename_version")
TEST_CASE_METHOD(RootImplT_v1, "wrong_filename_version")
{
v1::RootImpl root(root1_json);
nl::json patch = R"([])"_json;
CHECK_THROWS_AS(root.update(create_root_update("3.root.json", patch)), role_file_error);
REQUIRE_THROWS_AS(root.update(create_root_update("3.root.json", patch)), role_file_error);
}
TEST_CASE_FIXTURE(RootImplT_v1, "wrong_filename_spec_version")
TEST_CASE_METHOD(RootImplT_v1, "wrong_filename_spec_version")
{
v1::RootImpl root(root1_json);
// "2.sv2.root.json" is upgradable spec version (spec version N+1)
// but v2 is NOT implemented yet, so v1::RootImpl is not upgradable
CHECK_THROWS_AS(root.update(create_root_update("2.sv2.root.json")), spec_version_error);
REQUIRE_THROWS_AS(root.update(create_root_update("2.sv2.root.json")), spec_version_error);
// "2.sv3.root.json" is NOT upgradable spec version (spec version N+1)
CHECK_THROWS_AS(root.update(create_root_update("2.sv3.root.json")), role_file_error);
CHECK_THROWS_AS(root.update(create_root_update("2.sv0.6.root.json")), role_file_error);
REQUIRE_THROWS_AS(root.update(create_root_update("2.sv3.root.json")), role_file_error);
REQUIRE_THROWS_AS(root.update(create_root_update("2.sv0.6.root.json")), role_file_error);
}
TEST_CASE_FIXTURE(RootImplT_v1, "illformed_filename_version")
TEST_CASE_METHOD(RootImplT_v1, "illformed_filename_version")
{
v1::RootImpl root(root1_json);
nl::json patch = R"([])"_json;
CHECK_THROWS_AS(root.update(create_root_update("wrong.root.json", patch)), role_file_error);
REQUIRE_THROWS_AS(root.update(create_root_update("wrong.root.json", patch)), role_file_error);
}
TEST_CASE_FIXTURE(RootImplT_v1, "rollback_attack")
TEST_CASE_METHOD(RootImplT_v1, "rollback_attack")
{
v1::RootImpl root(root1_json);
@ -289,10 +289,10 @@ TEST_SUITE("validation::v1::RootImpl")
{ "op": "replace", "path": "/signed/version", "value": 1 }
])"_json;
CHECK_THROWS_AS(root.update(create_root_update("2.root.json", patch)), rollback_error);
REQUIRE_THROWS_AS(root.update(create_root_update("2.root.json", patch)), rollback_error);
}
TEST_CASE_FIXTURE(RootImplT_v1, "wrong_type")
TEST_CASE_METHOD(RootImplT_v1, "wrong_type")
{
v1::RootImpl root(root1_json);
@ -301,10 +301,10 @@ TEST_SUITE("validation::v1::RootImpl")
{ "op": "replace", "path": "/signed/version", "value": 2 }
])"_json;
CHECK_THROWS_AS(root.update(create_root_update("2.root.json", patch)), role_metadata_error);
REQUIRE_THROWS_AS(root.update(create_root_update("2.root.json", patch)), role_metadata_error);
}
TEST_CASE_FIXTURE(RootImplT_v1, "missing_type")
TEST_CASE_METHOD(RootImplT_v1, "missing_type")
{
v1::RootImpl root(root1_json);
@ -313,10 +313,10 @@ TEST_SUITE("validation::v1::RootImpl")
{ "op": "replace", "path": "/signed/version", "value": 2 }
])"_json;
CHECK_THROWS_AS(root.update(create_root_update("2.root.json", patch)), role_metadata_error);
REQUIRE_THROWS_AS(root.update(create_root_update("2.root.json", patch)), role_metadata_error);
}
TEST_CASE_FIXTURE(RootImplT_v1, "missing_keys")
TEST_CASE_METHOD(RootImplT_v1, "missing_keys")
{
v1::RootImpl root(root1_json);
@ -325,10 +325,10 @@ TEST_SUITE("validation::v1::RootImpl")
{ "op": "replace", "path": "/signed/version", "value": 2 }
])"_json;
CHECK_THROWS_AS(root.update(create_root_update("2.root.json", patch)), role_metadata_error);
REQUIRE_THROWS_AS(root.update(create_root_update("2.root.json", patch)), role_metadata_error);
}
TEST_CASE_FIXTURE(RootImplT_v1, "missing_roles")
TEST_CASE_METHOD(RootImplT_v1, "missing_roles")
{
v1::RootImpl root(root1_json);
@ -337,10 +337,10 @@ TEST_SUITE("validation::v1::RootImpl")
{ "op": "replace", "path": "/signed/version", "value": 2 }
])"_json;
CHECK_THROWS_AS(root.update(create_root_update("2.root.json", patch)), role_metadata_error);
REQUIRE_THROWS_AS(root.update(create_root_update("2.root.json", patch)), role_metadata_error);
}
TEST_CASE_FIXTURE(RootImplT_v1, "missing_role")
TEST_CASE_METHOD(RootImplT_v1, "missing_role")
{
v1::RootImpl root(root1_json);
@ -349,10 +349,10 @@ TEST_SUITE("validation::v1::RootImpl")
{ "op": "replace", "path": "/signed/version", "value": 2 }
])"_json;
CHECK_THROWS_AS(root.update(create_root_update("2.root.json", patch)), role_metadata_error);
REQUIRE_THROWS_AS(root.update(create_root_update("2.root.json", patch)), role_metadata_error);
}
TEST_CASE_FIXTURE(RootImplT_v1, "empty_role_keyids")
TEST_CASE_METHOD(RootImplT_v1, "empty_role_keyids")
{
v1::RootImpl root(root1_json);
@ -361,10 +361,10 @@ TEST_SUITE("validation::v1::RootImpl")
{ "op": "replace", "path": "/signed/version", "value": 2 }
])"_json;
CHECK_THROWS_AS(root.update(create_root_update("2.root.json", patch)), role_metadata_error);
REQUIRE_THROWS_AS(root.update(create_root_update("2.root.json", patch)), role_metadata_error);
}
TEST_CASE_FIXTURE(RootImplT_v1, "null_role_threshold")
TEST_CASE_METHOD(RootImplT_v1, "null_role_threshold")
{
v1::RootImpl root(root1_json);
@ -373,10 +373,10 @@ TEST_SUITE("validation::v1::RootImpl")
{ "op": "replace", "path": "/signed/version", "value": 2 }
])"_json;
CHECK_THROWS_AS(root.update(create_root_update("2.root.json", patch)), role_metadata_error);
REQUIRE_THROWS_AS(root.update(create_root_update("2.root.json", patch)), role_metadata_error);
}
TEST_CASE_FIXTURE(RootImplT_v1, "extra_roles")
TEST_CASE_METHOD(RootImplT_v1, "extra_roles")
{
v1::RootImpl root(root1_json);
@ -385,10 +385,10 @@ TEST_SUITE("validation::v1::RootImpl")
{ "op": "replace", "path": "/signed/version", "value": 2 }
])"_json;
CHECK_THROWS_AS(root.update(create_root_update("2.root.json", patch)), role_metadata_error);
REQUIRE_THROWS_AS(root.update(create_root_update("2.root.json", patch)), role_metadata_error);
}
TEST_CASE_FIXTURE(RootImplT_v1, "key_not_found")
TEST_CASE_METHOD(RootImplT_v1, "key_not_found")
{
v1::RootImpl root(root1_json);
@ -397,10 +397,10 @@ TEST_SUITE("validation::v1::RootImpl")
{ "op": "replace", "path": "/signed/version", "value": 2 }
])"_json;
CHECK_THROWS_AS(root.update(create_root_update("2.root.json", patch)), role_metadata_error);
REQUIRE_THROWS_AS(root.update(create_root_update("2.root.json", patch)), role_metadata_error);
}
TEST_CASE_FIXTURE(RootImplT_v1, "mirrors_role")
TEST_CASE_METHOD(RootImplT_v1, "mirrors_role")
{
nl::json patch = R"([
{ "op": "add", "path": "/signed/roles/mirrors", "value": { "keyids": ["c"], "threshold": 1 } },
@ -410,10 +410,10 @@ TEST_SUITE("validation::v1::RootImpl")
const v1::RootImpl root(create_root_update("2.root.json", patch));
const bool mirrors_role_found = root.roles().find("mirrors") != root.roles().cend();
CHECK(mirrors_role_found);
REQUIRE(mirrors_role_found);
}
TEST_CASE_FIXTURE(RootImplT_v1, "threshold_not_met")
TEST_CASE_METHOD(RootImplT_v1, "threshold_not_met")
{
v1::RootImpl root(root1_json);
@ -422,19 +422,19 @@ TEST_SUITE("validation::v1::RootImpl")
{ "op": "replace", "path": "/signed/roles/root/threshold", "value": 2 }
])"_json;
CHECK_THROWS_AS(root.update(create_root_update("2.root.json", patch)), role_error);
REQUIRE_THROWS_AS(root.update(create_root_update("2.root.json", patch)), role_error);
}
TEST_CASE_FIXTURE(RootImplT_v1, "expires")
TEST_CASE_METHOD(RootImplT_v1, "expires")
{
v1::RootImpl root(root1_json);
// expiration is set to now+3600s in 'sign_root'
TimeRef time_ref;
CHECK_FALSE(root.expired(time_ref));
REQUIRE_FALSE(root.expired(time_ref));
time_ref.set(utc_time_now() + 7200);
CHECK(root.expired(time_ref));
REQUIRE(root.expired(time_ref));
nl::json patch = nl::json::parse(
R"([
@ -446,44 +446,56 @@ TEST_SUITE("validation::v1::RootImpl")
auto updated_root = root.update(create_root_update("2.root.json", patch));
auto testing_root = static_cast<v1::RootImpl*>(updated_root.get());
CHECK_FALSE(testing_root->expired(time_ref));
REQUIRE_FALSE(testing_root->expired(time_ref));
patch = nl::json::parse(R"([
{ "op": "replace", "path": "/signed/expires", "value": "2051-10-08T07:07:09+0030" },
{ "op": "replace", "path": "/signed/version", "value": 2 }
])");
CHECK_THROWS_AS(root.update(create_root_update("2.root.json", patch)), role_metadata_error);
REQUIRE_THROWS_AS(root.update(create_root_update("2.root.json", patch)), role_metadata_error);
patch = nl::json::parse(R"([
{ "op": "replace", "path": "/signed/expires", "value": "2051-10-08T07:07:09D" },
{ "op": "replace", "path": "/signed/version", "value": 2 }
])");
CHECK_THROWS_AS(root.update(create_root_update("2.root.json", patch)), role_metadata_error);
REQUIRE_THROWS_AS(root.update(create_root_update("2.root.json", patch)), role_metadata_error);
patch = nl::json::parse(R"([
{ "op": "replace", "path": "/signed/expires", "value": "2051-10-08T07:07:09.000" },
{ "op": "replace", "path": "/signed/version", "value": 2 }
])");
CHECK_THROWS_AS(root.update(create_root_update("2.root.json", patch)), role_metadata_error);
REQUIRE_THROWS_AS(root.update(create_root_update("2.root.json", patch)), role_metadata_error);
}
TEST_CASE_FIXTURE(RootImplT_v1, "possible_update_files")
TEST_CASE_METHOD(RootImplT_v1, "possible_update_files")
{
v1::RootImpl root(root1_json);
auto update_f = root.possible_update_files();
CHECK(update_f[0].string().c_str() == doctest::Contains("2.sv2.root.json"));
CHECK(update_f[1].string().c_str() == doctest::Contains("2.sv1.root.json"));
CHECK(update_f[2].string().c_str() == doctest::Contains("2.root.json"));
REQUIRE_THAT(
update_f[0].string().c_str(),
Catch::Matchers::ContainsSubstring("2.sv2.root.json")
);
REQUIRE_THAT(
update_f[1].string().c_str(),
Catch::Matchers::ContainsSubstring("2.sv1.root.json")
);
REQUIRE_THAT(update_f[2].string().c_str(), Catch::Matchers::ContainsSubstring("2.root.json"));
nl::json patch = nl::json::parse(R"([
{ "op": "replace", "path": "/signed/version", "value": 2 }
])");
auto updated_root = root.update(create_root_update("2.root.json", patch));
update_f = updated_root->possible_update_files();
CHECK(update_f[0].string().c_str() == doctest::Contains("3.sv2.root.json"));
CHECK(update_f[1].string().c_str() == doctest::Contains("3.sv1.root.json"));
CHECK(update_f[2].string().c_str() == doctest::Contains("3.root.json"));
REQUIRE_THAT(
update_f[0].string().c_str(),
Catch::Matchers::ContainsSubstring("3.sv2.root.json")
);
REQUIRE_THAT(
update_f[1].string().c_str(),
Catch::Matchers::ContainsSubstring("3.sv1.root.json")
);
REQUIRE_THAT(update_f[2].string().c_str(), Catch::Matchers::ContainsSubstring("3.root.json"));
}
}
@ -498,73 +510,73 @@ protected:
v1::SpecImpl spec;
};
TEST_SUITE("validation::v1::SpecImpl")
namespace
{
TEST_CASE_FIXTURE(SpecImplT_v1, "ctore")
TEST_CASE_METHOD(SpecImplT_v1, "ctore")
{
v1::SpecImpl new_spec("1.0.0");
CHECK_EQ(new_spec.version_str(), "1.0.0");
REQUIRE(new_spec.version_str() == "1.0.0");
}
TEST_CASE_FIXTURE(SpecImplT_v1, "version_str")
TEST_CASE_METHOD(SpecImplT_v1, "version_str")
{
CHECK_EQ(spec.version_str(), "1.0.17");
REQUIRE(spec.version_str() == "1.0.17");
}
TEST_CASE_FIXTURE(SpecImplT_v1, "is_compatible")
TEST_CASE_METHOD(SpecImplT_v1, "is_compatible")
{
CHECK(spec.is_compatible(std::string("1.0.0")));
CHECK(spec.is_compatible(std::string("1.0.17")));
CHECK(spec.is_compatible(std::string("1.25.10")));
REQUIRE(spec.is_compatible(std::string("1.0.0")));
REQUIRE(spec.is_compatible(std::string("1.0.17")));
REQUIRE(spec.is_compatible(std::string("1.25.10")));
CHECK_FALSE(spec.is_compatible(std::string("2.0.0")));
CHECK_FALSE(spec.is_compatible(std::string("2.0.17")));
CHECK_FALSE(spec.is_compatible(std::string("0.6.0")));
REQUIRE_FALSE(spec.is_compatible(std::string("2.0.0")));
REQUIRE_FALSE(spec.is_compatible(std::string("2.0.17")));
REQUIRE_FALSE(spec.is_compatible(std::string("0.6.0")));
}
TEST_CASE_FIXTURE(SpecImplT_v1, "is_upgrade")
TEST_CASE_METHOD(SpecImplT_v1, "is_upgrade")
{
CHECK(spec.is_upgrade(std::string("2.0.0")));
CHECK(spec.is_upgrade(std::string("2.1.10")));
REQUIRE(spec.is_upgrade(std::string("2.0.0")));
REQUIRE(spec.is_upgrade(std::string("2.1.10")));
CHECK_FALSE(spec.is_upgrade(std::string("0.6.0")));
CHECK_FALSE(spec.is_upgrade(std::string("3.0.0")));
REQUIRE_FALSE(spec.is_upgrade(std::string("0.6.0")));
REQUIRE_FALSE(spec.is_upgrade(std::string("3.0.0")));
// not an upgrade, compatible version
CHECK_FALSE(spec.is_upgrade(std::string("1.0.17")));
CHECK_FALSE(spec.is_upgrade(std::string("1.0.0")));
REQUIRE_FALSE(spec.is_upgrade(std::string("1.0.17")));
REQUIRE_FALSE(spec.is_upgrade(std::string("1.0.0")));
}
TEST_CASE_FIXTURE(SpecImplT_v1, "upgradable")
TEST_CASE_METHOD(SpecImplT_v1, "upgradable")
{
CHECK_FALSE(spec.upgradable());
REQUIRE_FALSE(spec.upgradable());
}
TEST_CASE_FIXTURE(SpecImplT_v1, "compatible_prefix")
TEST_CASE_METHOD(SpecImplT_v1, "compatible_prefix")
{
CHECK_EQ(spec.compatible_prefix(), "1");
REQUIRE(spec.compatible_prefix() == "1");
}
TEST_CASE_FIXTURE(SpecImplT_v1, "upgrade_prefix")
TEST_CASE_METHOD(SpecImplT_v1, "upgrade_prefix")
{
CHECK(spec.upgrade_prefix()[0].c_str() == doctest::Contains("2"));
REQUIRE_THAT(spec.upgrade_prefix()[0].c_str(), Catch::Matchers::ContainsSubstring("2"));
}
TEST_CASE_FIXTURE(SpecImplT_v1, "json_key")
TEST_CASE_METHOD(SpecImplT_v1, "json_key")
{
CHECK_EQ(spec.json_key(), "spec_version");
REQUIRE(spec.json_key() == "spec_version");
}
TEST_CASE_FIXTURE(SpecImplT_v1, "expiration_json_key")
TEST_CASE_METHOD(SpecImplT_v1, "expiration_json_key")
{
CHECK_EQ(spec.expiration_json_key(), "expires");
REQUIRE(spec.expiration_json_key() == "expires");
}
TEST_CASE_FIXTURE(SpecImplT_v1, "canonicalize")
TEST_CASE_METHOD(SpecImplT_v1, "canonicalize")
{
CHECK_EQ(spec.canonicalize(R"({"foo":"bar"})"_json), "{\"foo\":\"bar\"}");
REQUIRE(spec.canonicalize(R"({"foo":"bar"})"_json) == "{\"foo\":\"bar\"}");
}
TEST_CASE_FIXTURE(SpecImplT_v1, "signatures")
TEST_CASE_METHOD(SpecImplT_v1, "signatures")
{
nl::json j = R"({
"signatures":
@ -577,24 +589,24 @@ TEST_SUITE("validation::v1::SpecImpl")
]
})"_json;
auto sigs = spec.signatures(j);
CHECK_EQ(sigs.size(), 1);
CHECK_EQ(sigs.begin()->keyid, "foo");
CHECK_EQ(sigs.begin()->sig, "baz");
CHECK_EQ(sigs.begin()->pgp_trailer, "bar");
REQUIRE(sigs.size() == 1);
REQUIRE(sigs.begin()->keyid == "foo");
REQUIRE(sigs.begin()->sig == "baz");
REQUIRE(sigs.begin()->pgp_trailer == "bar");
}
}
TEST_SUITE("validation::v1::RoleSignature")
namespace
{
// Test serialization/deserialization
TEST_CASE("to_json")
{
RoleSignature s{ "some_key_id", "some_signature", "" };
nl::json j = R"({"keyid": "some_key_id", "sig": "some_signature"})"_json;
CHECK_EQ(j, nl::json(s));
REQUIRE(j == nl::json(s));
s = { "some_key_id", "some_signature", "some_pgp_trailer" };
j = R"({"keyid": "some_key_id", "other_headers": "some_pgp_trailer", "sig": "some_signature"})"_json;
CHECK_EQ(j, nl::json(s));
REQUIRE(j == nl::json(s));
}
}