Crafter.Build/tests/WasmVariants/main.cpp
Jorijn van der Graaf 8892154b28
Some checks failed
CI / build-test-release (push) Failing after 7m15s
linting
2026-07-23 01:24:42 +02:00

117 lines
5.2 KiB
C++

// SPDX-License-Identifier: LGPL-3.0-only
// SPDX-FileCopyrightText: Copyright (C) 2026 Catcrafts®
import std;
import Crafter.Build;
namespace fs = std::filesystem;
using namespace Crafter;
extern "C" int setenv(const char* name, const char* value, int overwrite);
// Covers the browser-wasm variant plumbing that does NOT require a wasm
// toolchain run: EnableWasiRelaxedSimdVariant's registration, the
// variants.json manifest EnableWasiBrowserRuntime emits, and the VariantId
// perturbation that keeps each variant's objects in their own build dir. The
// actual multi-.wasm production is exercised by a real wasm build (manual /
// integration), not here — same boundary the WasiBrowserRuntime test draws.
namespace {
std::int32_t Failures = 0;
void Check(bool cond, std::string_view msg) {
if (!cond) { std::println(std::cerr, "FAIL: {}", msg); ++Failures; }
}
}
int main() {
// ── EnableWasiRelaxedSimdVariant: registration + idempotency ──────────
{
Configuration cfg;
cfg.target = "wasm32-wasip1";
EnableWasiRelaxedSimdVariant(cfg);
Check(cfg.wasmVariants.size() == 1, "one variant registered");
if (!cfg.wasmVariants.empty()) {
const WasmVariant& v = cfg.wasmVariants.front();
Check(v.label == "relaxed-simd", "label is relaxed-simd");
Check(v.flags.size() == 1 && v.flags.front() == "-mrelaxed-simd", "flag is -mrelaxed-simd");
Check(v.probes.size() == 1 && v.probes.front() == "relaxed-simd", "probe is relaxed-simd");
}
EnableWasiRelaxedSimdVariant(cfg);
Check(cfg.wasmVariants.size() == 1, "second call is idempotent");
}
// ── wasmVariantFlags perturbs VariantId / BuildDir / BinDir ──────────
// Configuration owns move-only members (unique_ptr<Module>), so build the
// two cases independently rather than copying.
{
auto make = [] {
Configuration c;
c.path = "/tmp/wasm-variant-id-test";
c.name = "wv"; c.outputName = "wv";
c.target = "wasm32-wasip1";
c.type = ConfigurationType::Executable;
return c;
};
Configuration a = make();
Configuration b = make();
b.wasmVariantFlags = {"-mrelaxed-simd"};
Check(a.VariantId() != b.VariantId(), "wasmVariantFlags perturbs VariantId");
Check(a.BuildDir() != b.BuildDir(), "wasmVariantFlags perturbs BuildDir");
Check(a.BinDir() != b.BinDir(), "wasmVariantFlags perturbs BinDir");
}
// ── variants.json manifest contents ──────────────────────────────────
{
fs::path repoWasi = fs::current_path() / "wasi-runtime";
fs::path systemHome = "/usr/local/share/crafter-build";
if (fs::exists(repoWasi / "runtime.js")) {
setenv("CRAFTER_BUILD_HOME", fs::current_path().c_str(), 1);
} else if (fs::exists(systemHome / "wasi-runtime" / "runtime.js")) {
setenv("CRAFTER_BUILD_HOME", systemHome.c_str(), 1);
} else {
std::println(std::cerr, "wasi-runtime assets not found; skipping manifest check");
return Failures ? 1 : 77;
}
Configuration cfg;
cfg.path = fs::temp_directory_path() / "crafter-build-wasm-variants-test";
cfg.name = "wvhelper";
cfg.outputName = "wvhelper";
cfg.target = "wasm32-wasip1";
cfg.type = ConfigurationType::Executable;
std::error_code ec;
fs::remove_all(cfg.path, ec);
fs::create_directories(cfg.path);
EnableWasiRelaxedSimdVariant(cfg);
EnableWasiBrowserRuntime(cfg);
const fs::path* variants = nullptr;
for (const fs::path& f : cfg.files) {
if (f.filename() == "variants.json") variants = &f;
}
Check(variants != nullptr, "variants.json registered");
if (variants) {
std::ifstream vin(*variants);
std::string j{std::istreambuf_iterator<char>(vin), std::istreambuf_iterator<char>()};
// relaxed-simd entry, with its labelled url + probe.
Check(j.find("\"label\":\"relaxed-simd\"") != std::string::npos, "manifest has relaxed-simd label");
Check(j.find("\"wvhelper.relaxed-simd.wasm\"") != std::string::npos, "manifest has labelled url");
Check(j.find("\"relaxed-simd\"") != std::string::npos, "manifest has relaxed-simd probe");
// baseline fallback entry.
Check(j.find("\"wvhelper.wasm\"") != std::string::npos, "manifest has baseline url");
// The relaxed-simd variant must precede the baseline so the runtime
// prefers it when probes pass.
auto relaxedPos = j.find("relaxed-simd");
auto baselinePos = j.find("\"wvhelper.wasm\"");
Check(relaxedPos != std::string::npos && baselinePos != std::string::npos && relaxedPos < baselinePos, "relaxed-simd entry precedes baseline");
}
fs::remove_all(cfg.path, ec);
}
if (Failures > 0) {
std::println(std::cerr, "{} assertions failed", Failures);
return 1;
}
return 0;
}