test: broaden self-test coverage beyond the compile smoke test
All checks were successful
CI / build-test-release (pull_request) Successful in 7m26s
All checks were successful
CI / build-test-release (pull_request) Successful in 7m26s
The suite had only HelloWorld, which built and exited an empty exe. Add in-process tests covering each public surface area users actually touch: - StaticLib / ModuleInterface / DependencyLink — Build() against fixtures for libraries, project-local module interfaces, and cross-config module deps with link verification (runs the built exe). - ShaderCompile — drives Shader::Compile directly, validates SPIR-V magic + Check() idempotency. - StandardArgs — covers --debug, --target=, --march=, --mtune=, --lib/--shared promotions, and ArgQuery::Has / Get. - TestRunnerSpec — FromSpec parse rules, ForTarget routing for host, wasm32-wasip1, aarch64-linux-gnu (+ sysroot QEMU_LD_PREFIX), i686 → qemu-i386 rewrite, mingw → wine on Linux hosts, FromEnv. - VariantId — confirms type / debug / sysroot / defines / compileFlags / target / march all perturb the cache key, plus PcmDir routing. - WasiBrowserRuntime — calls EnableWasiBrowserRuntime, asserts the three cfg.files entries get registered and index.html had its template placeholder substituted. - RunSingleTestExit — drives RunSingleTest against tiny sh scripts and pins the documented exit-code mapping (0/77/non-zero) and the Cmd-prefix runner path. Closes #12. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
603840879d
commit
124c2285f9
16 changed files with 794 additions and 0 deletions
115
tests/TestRunnerSpec/main.cpp
Normal file
115
tests/TestRunnerSpec/main.cpp
Normal file
|
|
@ -0,0 +1,115 @@
|
|||
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 {
|
||||
int failures = 0;
|
||||
|
||||
void Check(bool cond, std::string_view msg) {
|
||||
if (!cond) {
|
||||
std::println(std::cerr, "FAIL: {}", msg);
|
||||
++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);
|
||||
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.
|
||||
const char* name = "CRAFTER_BUILD_RUNNER_fake_target_for_unit_test";
|
||||
setenv(name, "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>");
|
||||
unsetenv(name);
|
||||
TestRunner fallback = TestRunner::FromEnv("fake-target-for-unit-test", TestRunner::Local());
|
||||
Check(fallback.IsLocal(), "FromEnv falls back when env var is unset");
|
||||
}
|
||||
|
||||
if (failures > 0) {
|
||||
std::println(std::cerr, "{} assertions failed", failures);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue