Crafter.Build/tests/WasiBrowserRuntime/main.cpp

97 lines
4.1 KiB
C++
Raw Normal View History

import std;
import Crafter.Build;
namespace fs = std::filesystem;
using namespace Crafter;
// POSIX env helper — std::setenv is non-standard. Linux-only is fine here;
// project.cpp gates this test on x86_64-pc-linux-gnu.
extern "C" int setenv(const char* name, const char* value, int overwrite);
// EnableWasiBrowserRuntime stamps runtime.js, a generated index.html, and a
// files.json manifest onto cfg.files so the build step copies them next to
// the .wasm. We don't run the wasm build here (avoids requiring wasi-sdk +
// the wasi-libc++ PCM rebuild on top of every test); we just verify the
// helper produced the right artifacts and registered them on the config.
int main() {
Configuration cfg;
cfg.path = fs::temp_directory_path() / "crafter-build-wasi-runtime-test";
cfg.name = "wasi-helper";
cfg.outputName = "wasi-helper";
cfg.target = "wasm32-wasip1";
cfg.type = ConfigurationType::Executable;
std::error_code ec;
fs::remove_all(cfg.path, ec);
fs::create_directories(cfg.path);
// EnableWasiBrowserRuntime looks up runtime.js + index.html.in under
// GetCrafterBuildHome()/wasi-runtime. The test binary lives in
// bin/<variant>/, so the auto-detect walks parents and won't find a
// share/crafter-build/Crafter.Build.cppm anchor — point CRAFTER_BUILD_HOME
// at the repo root (cwd when crafter-build test runs) so it picks up
// ./wasi-runtime/. Probe both repo root and the system-installed share
// dir to also work from a packaged checkout.
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 near {} or {}",
repoWasi.string(), systemHome.string());
return 77; // skipped — environmental, not a code defect
}
EnableWasiBrowserRuntime(cfg);
// Three files registered: runtime.js, generated index.html, files.json.
if (cfg.files.size() != 3) {
std::println(std::cerr, "expected 3 cfg.files entries, got {}", cfg.files.size());
for (const auto& f : cfg.files) std::println(std::cerr, " - {}", f.string());
return 1;
}
auto findByName = [&](std::string_view name) -> const fs::path* {
for (const fs::path& f : cfg.files) {
if (f.filename() == name) return &f;
}
return nullptr;
};
const fs::path* runtimeJs = findByName("runtime.js");
const fs::path* indexHtml = findByName("index.html");
const fs::path* manifest = findByName("files.json");
if (!runtimeJs) { std::println(std::cerr, "runtime.js not registered"); return 1; }
if (!indexHtml) { std::println(std::cerr, "index.html not registered"); return 1; }
if (!manifest) { std::println(std::cerr, "files.json not registered"); return 1; }
// The generated index.html and manifest live under the project's build/
// wasi-runtime/<name>/ directory and must actually exist on disk.
if (!fs::exists(*indexHtml)) {
std::println(std::cerr, "index.html not produced at {}", indexHtml->string());
return 1;
}
if (!fs::exists(*manifest)) {
std::println(std::cerr, "files.json not produced at {}", manifest->string());
return 1;
}
// The template's {{WASM}} placeholder should have been replaced with
// the configured outputName.
std::ifstream in(*indexHtml);
std::string html{std::istreambuf_iterator<char>(in), std::istreambuf_iterator<char>()};
if (html.find("wasi-helper.wasm") == std::string::npos) {
std::println(std::cerr, "index.html missing wasi-helper.wasm reference");
return 1;
}
if (html.find("{{WASM}}") != std::string::npos) {
std::println(std::cerr, "index.html still contains unreplaced {{WASM}} placeholder");
return 1;
}
fs::remove_all(cfg.path, ec);
return 0;
}