[M2] add SQLite overlay + add_manual
This commit is contained in:
@@ -13,4 +13,5 @@ cargoxx_add_test(manifest_parse)
|
||||
cargoxx_add_test(manifest_write)
|
||||
cargoxx_add_test(layout_discovery)
|
||||
cargoxx_add_test(linkdb_lookup)
|
||||
cargoxx_add_test(linkdb_overlay)
|
||||
cargoxx_add_test(cmd_new)
|
||||
|
||||
@@ -10,15 +10,31 @@ using cargoxx::linkdb::expand_targets;
|
||||
using cargoxx::linkdb::substitute_components;
|
||||
using cargoxx::util::ErrorCode;
|
||||
|
||||
TEST_CASE("Database::open loads the curated linkdb", "[linkdb]") {
|
||||
auto r = Database::open();
|
||||
namespace {
|
||||
|
||||
auto fresh_overlay() -> std::filesystem::path {
|
||||
auto d = std::filesystem::temp_directory_path() /
|
||||
std::format("cargoxx-linkdb-test-{}", std::random_device{}());
|
||||
std::filesystem::create_directories(d);
|
||||
return d / "overlay.sqlite";
|
||||
}
|
||||
|
||||
auto open_db() -> Database {
|
||||
auto r = Database::open(fresh_overlay());
|
||||
REQUIRE(r.has_value());
|
||||
return std::move(*r);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
TEST_CASE("Database::open loads the curated linkdb", "[linkdb]") {
|
||||
auto db = open_db();
|
||||
(void)db;
|
||||
}
|
||||
|
||||
TEST_CASE("resolve returns the curated recipe for fmt 10", "[linkdb]") {
|
||||
auto db = Database::open();
|
||||
REQUIRE(db.has_value());
|
||||
auto rec = db->resolve("fmt", "10.2.0");
|
||||
auto db = open_db();
|
||||
auto rec = db.resolve("fmt", "10.2.0");
|
||||
REQUIRE(rec.has_value());
|
||||
REQUIRE(rec->nixpkgs_attr == "fmt_10");
|
||||
REQUIRE(rec->find_package == "fmt CONFIG REQUIRED");
|
||||
@@ -27,25 +43,22 @@ TEST_CASE("resolve returns the curated recipe for fmt 10", "[linkdb]") {
|
||||
}
|
||||
|
||||
TEST_CASE("resolve returns the older fmt recipe for fmt 8", "[linkdb]") {
|
||||
auto db = Database::open();
|
||||
REQUIRE(db.has_value());
|
||||
auto rec = db->resolve("fmt", "8.1.0");
|
||||
auto db = open_db();
|
||||
auto rec = db.resolve("fmt", "8.1.0");
|
||||
REQUIRE(rec.has_value());
|
||||
REQUIRE(rec->nixpkgs_attr == "fmt_8");
|
||||
}
|
||||
|
||||
TEST_CASE("resolve fails for an unknown package", "[linkdb]") {
|
||||
auto db = Database::open();
|
||||
REQUIRE(db.has_value());
|
||||
auto rec = db->resolve("obscurelib", "0.0.1");
|
||||
auto db = open_db();
|
||||
auto rec = db.resolve("obscurelib", "0.0.1");
|
||||
REQUIRE_FALSE(rec.has_value());
|
||||
REQUIRE(rec.error().code == ErrorCode::LinkdbUnknownPackage);
|
||||
}
|
||||
|
||||
TEST_CASE("resolve substitutes boost components", "[linkdb]") {
|
||||
auto db = Database::open();
|
||||
REQUIRE(db.has_value());
|
||||
auto rec = db->resolve("boost", "1.84.0", {"filesystem", "system"});
|
||||
auto db = open_db();
|
||||
auto rec = db.resolve("boost", "1.84.0", {"filesystem", "system"});
|
||||
REQUIRE(rec.has_value());
|
||||
REQUIRE(rec->find_package == "Boost REQUIRED COMPONENTS filesystem system");
|
||||
REQUIRE(rec->targets ==
|
||||
@@ -54,26 +67,23 @@ TEST_CASE("resolve substitutes boost components", "[linkdb]") {
|
||||
|
||||
TEST_CASE("resolve fails when a componentized package gets no components",
|
||||
"[linkdb]") {
|
||||
auto db = Database::open();
|
||||
REQUIRE(db.has_value());
|
||||
auto rec = db->resolve("boost", "1.84.0");
|
||||
auto db = open_db();
|
||||
auto rec = db.resolve("boost", "1.84.0");
|
||||
REQUIRE_FALSE(rec.has_value());
|
||||
REQUIRE(rec.error().code == ErrorCode::LinkdbComponentNotSupported);
|
||||
}
|
||||
|
||||
TEST_CASE("resolve fails when components are passed to a non-componentized package",
|
||||
"[linkdb]") {
|
||||
auto db = Database::open();
|
||||
REQUIRE(db.has_value());
|
||||
auto rec = db->resolve("fmt", "10.2.0", {"core"});
|
||||
auto db = open_db();
|
||||
auto rec = db.resolve("fmt", "10.2.0", {"core"});
|
||||
REQUIRE_FALSE(rec.has_value());
|
||||
REQUIRE(rec.error().code == ErrorCode::LinkdbComponentNotSupported);
|
||||
}
|
||||
|
||||
TEST_CASE("resolve handles wildcard versions", "[linkdb]") {
|
||||
auto db = Database::open();
|
||||
REQUIRE(db.has_value());
|
||||
auto rec = db->resolve("openssl", "3.2.0");
|
||||
auto db = open_db();
|
||||
auto rec = db.resolve("openssl", "3.2.0");
|
||||
REQUIRE(rec.has_value());
|
||||
REQUIRE(rec->find_package == "OpenSSL REQUIRED");
|
||||
REQUIRE(rec->targets ==
|
||||
@@ -81,8 +91,7 @@ TEST_CASE("resolve handles wildcard versions", "[linkdb]") {
|
||||
}
|
||||
|
||||
TEST_CASE("resolve covers all 25 curated packages", "[linkdb]") {
|
||||
auto db = Database::open();
|
||||
REQUIRE(db.has_value());
|
||||
auto db = open_db();
|
||||
|
||||
struct Sample {
|
||||
std::string name;
|
||||
@@ -118,7 +127,7 @@ TEST_CASE("resolve covers all 25 curated packages", "[linkdb]") {
|
||||
};
|
||||
|
||||
for (const auto& s : samples) {
|
||||
auto rec = db->resolve(s.name, s.version, s.components);
|
||||
auto rec = db.resolve(s.name, s.version, s.components);
|
||||
INFO("resolving " << s.name);
|
||||
REQUIRE(rec.has_value());
|
||||
REQUIRE_FALSE(rec->nixpkgs_attr.empty());
|
||||
|
||||
153
tests/linkdb_overlay.cpp
Normal file
153
tests/linkdb_overlay.cpp
Normal file
@@ -0,0 +1,153 @@
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
|
||||
import cargoxx.linkdb;
|
||||
import cargoxx.util;
|
||||
import std;
|
||||
|
||||
using cargoxx::linkdb::Database;
|
||||
using cargoxx::linkdb::Recipe;
|
||||
using cargoxx::util::ErrorCode;
|
||||
|
||||
namespace {
|
||||
|
||||
auto fresh_overlay() -> std::filesystem::path {
|
||||
auto d = std::filesystem::temp_directory_path() /
|
||||
std::format("cargoxx-overlay-test-{}", std::random_device{}());
|
||||
std::filesystem::create_directories(d);
|
||||
return d / "overlay.sqlite";
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
TEST_CASE("open creates the overlay schema and file", "[linkdb][overlay]") {
|
||||
auto path = fresh_overlay();
|
||||
auto db = Database::open(path);
|
||||
REQUIRE(db.has_value());
|
||||
REQUIRE(std::filesystem::exists(path));
|
||||
}
|
||||
|
||||
TEST_CASE("add_manual then resolve returns the manual recipe",
|
||||
"[linkdb][overlay]") {
|
||||
auto db = Database::open(fresh_overlay());
|
||||
REQUIRE(db.has_value());
|
||||
|
||||
Recipe r{
|
||||
.nixpkgs_attr = "obscurelib",
|
||||
.find_package = "obscurelib CONFIG REQUIRED",
|
||||
.targets = {"obscurelib::obscurelib"},
|
||||
.source = "manual",
|
||||
};
|
||||
REQUIRE(db->add_manual("obscurelib", "*", r).has_value());
|
||||
|
||||
auto got = db->resolve("obscurelib", "1.0.0");
|
||||
REQUIRE(got.has_value());
|
||||
REQUIRE(got->nixpkgs_attr == "obscurelib");
|
||||
REQUIRE(got->find_package == "obscurelib CONFIG REQUIRED");
|
||||
REQUIRE(got->targets == std::vector<std::string>{"obscurelib::obscurelib"});
|
||||
REQUIRE(got->source == "manual");
|
||||
}
|
||||
|
||||
TEST_CASE("manual entry overrides curated for the same package",
|
||||
"[linkdb][overlay]") {
|
||||
auto db = Database::open(fresh_overlay());
|
||||
REQUIRE(db.has_value());
|
||||
|
||||
Recipe override_r{
|
||||
.nixpkgs_attr = "fmt_pinned",
|
||||
.find_package = "fmt CONFIG REQUIRED",
|
||||
.targets = {"fmt::fmt"},
|
||||
.source = "manual",
|
||||
};
|
||||
REQUIRE(db->add_manual("fmt", ">=10.0.0", override_r).has_value());
|
||||
|
||||
auto got = db->resolve("fmt", "10.2.0");
|
||||
REQUIRE(got.has_value());
|
||||
REQUIRE(got->nixpkgs_attr == "fmt_pinned");
|
||||
REQUIRE(got->source == "manual");
|
||||
}
|
||||
|
||||
TEST_CASE("manual entry is constrained by version_range",
|
||||
"[linkdb][overlay]") {
|
||||
auto db = Database::open(fresh_overlay());
|
||||
REQUIRE(db.has_value());
|
||||
|
||||
Recipe r{
|
||||
.nixpkgs_attr = "fmt_v11_only",
|
||||
.find_package = "fmt CONFIG REQUIRED",
|
||||
.targets = {"fmt::fmt"},
|
||||
.source = "manual",
|
||||
};
|
||||
REQUIRE(db->add_manual("fmt", ">=11.0.0", r).has_value());
|
||||
|
||||
// 10.x falls outside the manual range and falls through to curated
|
||||
auto curated = db->resolve("fmt", "10.2.0");
|
||||
REQUIRE(curated.has_value());
|
||||
REQUIRE(curated->source == "curated");
|
||||
REQUIRE(curated->nixpkgs_attr == "fmt_10");
|
||||
|
||||
// 11.x matches the manual range
|
||||
auto manual = db->resolve("fmt", "11.0.0");
|
||||
REQUIRE(manual.has_value());
|
||||
REQUIRE(manual->source == "manual");
|
||||
REQUIRE(manual->nixpkgs_attr == "fmt_v11_only");
|
||||
}
|
||||
|
||||
TEST_CASE("manual recipes persist across reopen", "[linkdb][overlay]") {
|
||||
auto path = fresh_overlay();
|
||||
|
||||
{
|
||||
auto db = Database::open(path);
|
||||
REQUIRE(db.has_value());
|
||||
Recipe r{
|
||||
.nixpkgs_attr = "persistlib",
|
||||
.find_package = "persistlib CONFIG REQUIRED",
|
||||
.targets = {"persistlib::persistlib"},
|
||||
.source = "manual",
|
||||
};
|
||||
REQUIRE(db->add_manual("persistlib", "*", r).has_value());
|
||||
}
|
||||
|
||||
auto db = Database::open(path);
|
||||
REQUIRE(db.has_value());
|
||||
auto got = db->resolve("persistlib", "0.0.1");
|
||||
REQUIRE(got.has_value());
|
||||
REQUIRE(got->nixpkgs_attr == "persistlib");
|
||||
REQUIRE(got->source == "manual");
|
||||
}
|
||||
|
||||
TEST_CASE("resolve with components on a manual recipe is rejected",
|
||||
"[linkdb][overlay]") {
|
||||
auto db = Database::open(fresh_overlay());
|
||||
REQUIRE(db.has_value());
|
||||
|
||||
Recipe r{
|
||||
.nixpkgs_attr = "weirdlib",
|
||||
.find_package = "weirdlib CONFIG REQUIRED",
|
||||
.targets = {"weirdlib::weirdlib"},
|
||||
.source = "manual",
|
||||
};
|
||||
REQUIRE(db->add_manual("weirdlib", "*", r).has_value());
|
||||
|
||||
auto got = db->resolve("weirdlib", "1.0.0", {"some_component"});
|
||||
REQUIRE_FALSE(got.has_value());
|
||||
REQUIRE(got.error().code == ErrorCode::LinkdbComponentNotSupported);
|
||||
}
|
||||
|
||||
TEST_CASE("Database is move-constructible without leaking the handle",
|
||||
"[linkdb][overlay]") {
|
||||
auto db = Database::open(fresh_overlay());
|
||||
REQUIRE(db.has_value());
|
||||
Database moved = std::move(*db);
|
||||
|
||||
Recipe r{
|
||||
.nixpkgs_attr = "movelib",
|
||||
.find_package = "movelib CONFIG REQUIRED",
|
||||
.targets = {"movelib::movelib"},
|
||||
.source = "manual",
|
||||
};
|
||||
REQUIRE(moved.add_manual("movelib", "*", r).has_value());
|
||||
|
||||
auto got = moved.resolve("movelib", "1.0.0");
|
||||
REQUIRE(got.has_value());
|
||||
REQUIRE(got->source == "manual");
|
||||
}
|
||||
Reference in New Issue
Block a user