/* Crafter® Build Copyright (C) 2026 Catcrafts® Catcrafts.net LGPL-3.0-only. */ import std; #include "TestUtil.h" namespace fs = std::filesystem; using namespace TestUtil; namespace { bool Contains(std::string_view haystack, std::string_view needle) { return haystack.find(needle) != std::string_view::npos; } std::string PickQemu() { if (const char* v = std::getenv("CRAFTER_TEST_QEMU"); v && *v) return v; return "qemu-x86_64"; } bool QemuPresent(const std::string& qemu) { std::string cmd = std::format("which {} > /dev/null 2>&1", qemu); return std::system(cmd.c_str()) == 0; } } int main() { try { std::string qemu = PickQemu(); if (!QemuPresent(qemu)) { std::println("(skipped: {} not on PATH)", qemu); return 0; } fs::path projectRoot = fs::current_path(); fs::path src = projectRoot / "tests" / "fixtures" / "qemu-runner"; fs::path crafterBuild = projectRoot / "bin" / "crafter-build"; fs::path work = CopyFixtureToTemp("QemuUser", src); // Tell the inner crafter-build to use qemu for the host triple via the // FromEnv mechanism that the fixture's project.cpp opted into. auto run = RunInDir(work, std::format( "CRAFTER_BUILD_RUNNER_x86_64_pc_linux_gnu='qemu:{}' '{}' test", qemu, crafterBuild.string())); if (run.exitCode != 0) { std::println(std::cerr, "inner runner failed (rc={}):\n{}", run.exitCode, run.output); return 1; } if (!Contains(run.output, std::format("\xE2\x9C\x85 Hello (qemu:{})", qemu))) { std::println(std::cerr, "expected '✅ Hello (qemu:{})' marker not found in inner output:\n{}", qemu, run.output); return 1; } return 0; } catch (const std::exception& e) { std::println(std::cerr, "test exception: {}", e.what()); return 1; } }