// SPDX-License-Identifier: LGPL-3.0-only // SPDX-FileCopyrightText: Copyright (C) 2026 Catcrafts® import std; import Crafter.Build; using namespace Crafter; namespace { std::int32_t Failures = 0; void Check(bool cond, std::string_view msg) { if (!cond) { std::println(std::cerr, "FAIL: {}", msg); ++Failures; } } } // Pure-data tests for ApplyStandardArgs and ArgQuery — no build/run, just // confirms the documented arg parsing produces the documented mutations. int main() { // --debug + --target= + --march= + --mtune= { Configuration cfg; cfg.target = "ignored"; std::array raw = { "--debug", "--target=aarch64-linux-gnu", "--march=armv8-a", "--mtune=cortex-a72", }; ApplyStandardArgs(cfg, raw); Check(cfg.debug, "--debug should set cfg.debug"); Check(cfg.target == "aarch64-linux-gnu", "--target= should overwrite cfg.target"); Check(cfg.march == "armv8-a", "--march= should overwrite cfg.march"); Check(cfg.mtune == "cortex-a72", "--mtune= should overwrite cfg.mtune"); } // --sysroot= sets cfg.sysroot (cross-compiles against a foreign root, // e.g. an Alpine aarch64 tree; also picked up by the std.cppm lookup // and the qemu test-runner's QEMU_LD_PREFIX). { Configuration cfg; std::array raw = { "--target=aarch64-alpine-linux-musl", "--sysroot=/opt/alpine-aarch64", }; ApplyStandardArgs(cfg, raw); Check(cfg.sysroot == "/opt/alpine-aarch64", "--sysroot= should set cfg.sysroot"); Check(cfg.target == "aarch64-alpine-linux-musl", "--target= combines with --sysroot="); } // --lib promotes Executable -> LibraryStatic; --shared then promotes to Dynamic. { Configuration cfg; cfg.type = ConfigurationType::Executable; std::array raw = { "--lib" }; ApplyStandardArgs(cfg, raw); Check(cfg.type == ConfigurationType::LibraryStatic, "--lib promotes Exe -> Static"); } { Configuration cfg; cfg.type = ConfigurationType::Executable; // Order shouldn't matter — promotions chain in priority order. std::array raw = { "--shared", "--lib" }; ApplyStandardArgs(cfg, raw); Check(cfg.type == ConfigurationType::LibraryDynamic, "--lib + --shared lands on Dynamic regardless of order"); } { Configuration cfg; cfg.type = ConfigurationType::Executable; std::array raw = { "--shared" }; ApplyStandardArgs(cfg, raw); Check(cfg.type == ConfigurationType::Executable, "--shared alone on Executable is a no-op"); } // ArgQuery is returned over the same args span and exposes Has/Get. { Configuration cfg; std::array raw = { "--timing", "--prefix=/opt/x", "extra" }; ArgQuery q = ApplyStandardArgs(cfg, raw); Check(q.Has("--timing"), "ArgQuery::Has true for present flag"); Check(!q.Has("--missing"), "ArgQuery::Has false for absent flag"); auto prefix = q.Get("--prefix="); Check(prefix.has_value(), "ArgQuery::Get returns a value for known prefix"); Check(prefix.value_or("") == "/opt/x", "ArgQuery::Get returns the substring after ="); Check(!q.Get("--other=").has_value(), "ArgQuery::Get returns nullopt for absent prefix"); } if (Failures > 0) { std::println(std::cerr, "{} assertions failed", Failures); return 1; } return 0; }