#include import cargoxx.cli; import cargoxx.manifest; import cargoxx.util; import std; using cargoxx::cli::cmd_add; using cargoxx::cli::cmd_new; using cargoxx::util::ErrorCode; namespace manifest = cargoxx::manifest; namespace { auto fresh_dir() -> std::filesystem::path { auto d = std::filesystem::temp_directory_path() / std::format("cargoxx-add-test-{}", std::random_device{}()); std::filesystem::create_directories(d); return d; } auto overlay_path(const std::filesystem::path& dir) -> std::filesystem::path { return dir / "overlay.sqlite"; } auto scaffold(const std::filesystem::path& parent) -> std::filesystem::path { REQUIRE(cmd_new("app", false, parent).has_value()); return parent / "app"; } } // namespace TEST_CASE("cmd_add appends a string-form dependency", "[cli][add]") { auto parent = fresh_dir(); auto root = scaffold(parent); auto r = cmd_add(root, "fmt", "10.2.0", {}, overlay_path(parent)); REQUIRE(r.has_value()); auto m = manifest::parse(root / "Cargoxx.toml"); REQUIRE(m.has_value()); REQUIRE(m->dependencies.size() == 1); REQUIRE(m->dependencies[0].name == "fmt"); REQUIRE(m->dependencies[0].version_spec == "10.2.0"); REQUIRE(m->dependencies[0].components.empty()); } TEST_CASE("cmd_add stores components when provided", "[cli][add]") { auto parent = fresh_dir(); auto root = scaffold(parent); auto r = cmd_add(root, "boost", "1.84.0", {"filesystem", "system"}, overlay_path(parent)); REQUIRE(r.has_value()); auto m = manifest::parse(root / "Cargoxx.toml"); REQUIRE(m.has_value()); REQUIRE(m->dependencies.size() == 1); REQUIRE(m->dependencies[0].name == "boost"); REQUIRE(m->dependencies[0].components == std::vector{"filesystem", "system"}); } TEST_CASE("cmd_add accepts an empty version and stores '*'", "[cli][add]") { auto parent = fresh_dir(); auto root = scaffold(parent); auto r = cmd_add(root, "fmt", "", {}, overlay_path(parent)); REQUIRE(r.has_value()); auto m = manifest::parse(root / "Cargoxx.toml"); REQUIRE(m.has_value()); REQUIRE(m->dependencies.size() == 1); REQUIRE(m->dependencies[0].name == "fmt"); REQUIRE(m->dependencies[0].version_spec == "*"); } TEST_CASE("cmd_add with wildcard version still rejects unknown packages", "[cli][add]") { auto parent = fresh_dir(); auto root = scaffold(parent); auto r = cmd_add(root, "obscurelib", "", {}, overlay_path(parent)); REQUIRE_FALSE(r.has_value()); REQUIRE(r.error().code == ErrorCode::LinkdbUnknownPackage); } TEST_CASE("cmd_add rejects an unknown package", "[cli][add]") { auto parent = fresh_dir(); auto root = scaffold(parent); auto r = cmd_add(root, "obscurelib", "0.0.1", {}, overlay_path(parent)); REQUIRE_FALSE(r.has_value()); REQUIRE(r.error().code == ErrorCode::LinkdbUnknownPackage); } TEST_CASE("cmd_add rejects an already-declared dep", "[cli][add]") { auto parent = fresh_dir(); auto root = scaffold(parent); REQUIRE(cmd_add(root, "fmt", "10.2.0", {}, overlay_path(parent)).has_value()); auto r = cmd_add(root, "fmt", "10.3.0", {}, overlay_path(parent)); REQUIRE_FALSE(r.has_value()); REQUIRE(r.error().code == ErrorCode::ManifestInvalidField); } TEST_CASE("cmd_add rejects componentized package without components", "[cli][add]") { auto parent = fresh_dir(); auto root = scaffold(parent); auto r = cmd_add(root, "boost", "1.84.0", {}, overlay_path(parent)); REQUIRE_FALSE(r.has_value()); REQUIRE(r.error().code == ErrorCode::LinkdbComponentNotSupported); }