[M5+] add resolver::devbox_resolve (search.devbox.sh)

This commit is contained in:
2026-05-10 12:09:58 +00:00
parent afe1856e11
commit df2c25b559
7 changed files with 295 additions and 0 deletions

View File

@@ -33,3 +33,5 @@ cargoxx_add_test(conan_probe_live)
cargoxx_add_test(vcpkg_probe_parse)
cargoxx_add_test(vcpkg_probe_live)
cargoxx_add_test(verify_link_unit)
cargoxx_add_test(devbox_resolve_parse)
cargoxx_add_test(devbox_resolve_live)

View File

@@ -0,0 +1,44 @@
// Network-gated integration test for resolver::devbox_resolve.
#include <catch2/catch_test_macros.hpp>
import cargoxx.resolver;
import cargoxx.util;
import std;
namespace {
auto network_tests_enabled() -> bool {
auto* env = std::getenv("CARGOXX_NETWORK_TESTS");
return env != nullptr && std::string_view{env} == "1";
}
} // namespace
TEST_CASE("devbox_resolve returns a commit_hash for fmt 10.2.1",
"[resolver][network]") {
if (!network_tests_enabled()) {
SKIP("CARGOXX_NETWORK_TESTS != 1");
}
auto r = cargoxx::resolver::devbox_resolve("fmt", "10.2.1");
REQUIRE(r.has_value());
REQUIRE(r->name == "fmt");
REQUIRE(r->version == "10.2.1");
REQUIRE(r->commit_hash.size() == 40); // git sha
// attr_paths should at minimum include the package name itself.
REQUIRE(std::ranges::find(r->attr_paths, std::string{"fmt"}) !=
r->attr_paths.end());
}
TEST_CASE("devbox_resolve returns ResolutionUnknownPackage on 404",
"[resolver][network]") {
if (!network_tests_enabled()) {
SKIP("CARGOXX_NETWORK_TESTS != 1");
}
auto r = cargoxx::resolver::devbox_resolve(
"definitely_not_a_real_pkg_cargoxx_xyzzy", "1.0");
REQUIRE_FALSE(r.has_value());
INFO("error msg: " << r.error().message);
REQUIRE(r.error().code ==
cargoxx::util::ErrorCode::ResolutionUnknownPackage);
}

View File

@@ -0,0 +1,85 @@
#include <catch2/catch_test_macros.hpp>
import cargoxx.resolver;
import cargoxx.util;
import std;
using cargoxx::resolver::parse_devbox_resolve;
using cargoxx::util::ErrorCode;
TEST_CASE("parse_devbox_resolve extracts the canonical fields",
"[resolver][devbox]") {
// Trimmed shape of the real response for `fmt 10.2.1` from
// https://search.devbox.sh/v1/resolve?name=fmt&version=10.2.1
constexpr std::string_view input = R"({
"commit_hash": "f4b140d5b253f5e2a1ff4e5506edbf8267724bde",
"version": "10.2.1",
"name": "fmt",
"attr_paths": ["fmt"]
})";
auto r = parse_devbox_resolve(input);
REQUIRE(r.has_value());
REQUIRE(r->name == "fmt");
REQUIRE(r->version == "10.2.1");
REQUIRE(r->commit_hash == "f4b140d5b253f5e2a1ff4e5506edbf8267724bde");
REQUIRE(r->attr_paths == std::vector<std::string>{"fmt"});
}
TEST_CASE("parse_devbox_resolve falls back to systems.<plat>.commit_hash",
"[resolver][devbox]") {
// Older / partial responses omit the top-level commit_hash but still
// ship per-system entries.
constexpr std::string_view input = R"({
"name": "spdlog",
"version": "1.13.0",
"systems": {
"x86_64-linux": {
"commit_hash": "abc123def456",
"attr_paths": ["spdlog"]
}
}
})";
auto r = parse_devbox_resolve(input);
REQUIRE(r.has_value());
REQUIRE(r->commit_hash == "abc123def456");
REQUIRE(r->attr_paths == std::vector<std::string>{"spdlog"});
}
TEST_CASE("parse_devbox_resolve fails on missing commit_hash",
"[resolver][devbox]") {
constexpr std::string_view input = R"({
"name": "fmt",
"version": "10.2.1"
})";
auto r = parse_devbox_resolve(input);
REQUIRE_FALSE(r.has_value());
REQUIRE(r.error().code == ErrorCode::ResolutionVersionNotFound);
}
TEST_CASE("parse_devbox_resolve fails on garbage input", "[resolver][devbox]") {
auto r = parse_devbox_resolve("not-json");
REQUIRE_FALSE(r.has_value());
REQUIRE(r.error().code == ErrorCode::ResolutionNetworkError);
}
TEST_CASE("parse_devbox_resolve fails on non-object root", "[resolver][devbox]") {
auto r = parse_devbox_resolve("[]");
REQUIRE_FALSE(r.has_value());
REQUIRE(r.error().code == ErrorCode::ResolutionNetworkError);
}
TEST_CASE("parse_devbox_resolve tolerates an empty attr_paths array",
"[resolver][devbox]") {
constexpr std::string_view input = R"({
"name": "fmt",
"version": "10.2.1",
"commit_hash": "abc",
"attr_paths": []
})";
auto r = parse_devbox_resolve(input);
REQUIRE(r.has_value());
REQUIRE(r->attr_paths.empty());
REQUIRE(r->commit_hash == "abc");
}