Crafter.Build/tests/TestRunnerSpec/main.cpp

117 lines
4.5 KiB
C++
Raw Normal View History

2026-07-23 01:24:42 +02:00
// SPDX-License-Identifier: LGPL-3.0-only
// SPDX-FileCopyrightText: Copyright (C) 2026 Catcrafts®
import std;
import Crafter.Build;
using namespace Crafter;
// POSIX env helpers — libc++ exports only std::getenv via `import std`, so
// forward-declare the setters we need against the C library directly. The
// test only runs on POSIX hosts (the project.cpp gates new tests by
// x86_64-pc-linux-gnu) so we don't need a Windows alternative here.
extern "C" int setenv(const char* name, const char* value, int overwrite);
extern "C" int unsetenv(const char* name);
namespace {
2026-07-23 01:24:42 +02:00
std::int32_t Failures = 0;
void Check(bool cond, std::string_view msg) {
if (!cond) {
std::println(std::cerr, "FAIL: {}", msg);
2026-07-23 01:24:42 +02:00
++Failures;
}
}
}
// Pure-data tests for TestRunner factories. No tests are actually executed;
// we just confirm the routing tables in ForTarget / FromSpec / FromEnv.
int main() {
// FromSpec: empty -> nullopt; recognized -> populated; garbage -> throws.
{
auto empty = TestRunner::FromSpec("");
Check(!empty.has_value(), "FromSpec(\"\") returns nullopt");
}
{
auto local = TestRunner::FromSpec("local");
Check(local.has_value() && local->IsLocal(), "FromSpec(\"local\") returns Local");
Check(local.has_value() && local->name == "local", "Local name is 'local'");
}
{
auto cmd = TestRunner::FromSpec("cmd:wasmtime");
Check(cmd.has_value(), "FromSpec(\"cmd:wasmtime\") returns a runner");
Check(cmd.has_value() && cmd->name == "cmd:wasmtime", "Cmd name carries the binary");
Check(cmd.has_value() && cmd->exec.find("wasmtime") != std::string::npos, "Cmd exec carries the binary");
Check(cmd.has_value() && !cmd->probe.empty(), "Cmd probe is set so harness can detect missing tools");
}
{
bool threw = false;
try {
(void)TestRunner::FromSpec("garbage");
} catch (const std::exception&) {
threw = true;
}
Check(threw, "FromSpec rejects unrecognized non-empty specs");
}
// ForTarget routing.
{
Configuration cfg;
cfg.target = HostTarget();
TestRunner r = TestRunner::ForTarget(cfg);
Check(r.IsLocal(), "ForTarget(host) is Local");
}
{
Configuration cfg;
cfg.target = "wasm32-wasip1";
TestRunner r = TestRunner::ForTarget(cfg);
Check(r.name == "cmd:wasmtime", "ForTarget(wasm32-wasip1) routes through wasmtime");
}
{
Configuration cfg;
cfg.target = "aarch64-linux-gnu";
TestRunner r = TestRunner::ForTarget(cfg);
Check(r.name == "cmd:qemu-aarch64", "ForTarget(aarch64-linux-gnu) routes through qemu-aarch64");
}
{
Configuration cfg;
cfg.target = "i686-linux-gnu";
TestRunner r = TestRunner::ForTarget(cfg);
Check(r.name == "cmd:qemu-i386", "ForTarget(i686-linux-gnu) rewrites arch to i386");
}
{
// Sysroot propagates to QEMU_LD_PREFIX so the dynamic linker is reachable.
Configuration cfg;
cfg.target = "aarch64-linux-gnu";
cfg.sysroot = "/opt/alarm-sysroot";
TestRunner r = TestRunner::ForTarget(cfg);
2026-07-23 01:24:42 +02:00
Check(r.exec.find("QEMU_LD_PREFIX=/opt/alarm-sysroot") != std::string::npos, "ForTarget propagates sysroot to QEMU_LD_PREFIX");
}
{
// From a Linux host the only sensible way to run x86_64-w64-mingw32 is wine.
Configuration cfg;
cfg.target = "x86_64-w64-mingw32";
TestRunner r = TestRunner::ForTarget(cfg);
if (HostTarget().find("linux") != std::string::npos) {
Check(r.name == "wine", "ForTarget(mingw) on Linux host uses wine");
}
}
// FromEnv: when the env var is set, it wins over the fallback.
{
// Use a unique fake triple so we don't stomp on a real env var the
// CI/dev shell may have set.
2026-07-23 01:24:42 +02:00
const std::string name = "CRAFTER_BUILD_RUNNER_fake_target_for_unit_test";
setenv(name.c_str(), "cmd:fake-tool", 1);
TestRunner r = TestRunner::FromEnv("fake-target-for-unit-test", TestRunner::Local());
Check(r.name == "cmd:fake-tool", "FromEnv reads CRAFTER_BUILD_RUNNER_<target>");
2026-07-23 01:24:42 +02:00
unsetenv(name.c_str());
TestRunner fallback = TestRunner::FromEnv("fake-target-for-unit-test", TestRunner::Local());
Check(fallback.IsLocal(), "FromEnv falls back when env var is unset");
}
2026-07-23 01:24:42 +02:00
if (Failures > 0) {
std::println(std::cerr, "{} assertions failed", Failures);
return 1;
}
return 0;
}