/* Crafter® Build Copyright (C) 2026 Catcrafts® Catcrafts.net LGPL-3.0-only. End-to-end Linux→Windows via SSH: the fixture cross-compiles main.cpp for x86_64-w64-mingw32 (V2's existing MinGW build path), the resulting .exe + runtime DLLs (which Build() already copies into the output dir for the mingw target) get scp'd to a Windows host (winvm by default), then ssh runs the .exe under cmd.exe and we capture stdout. Exercises the same build-system features HelloWorld covers, but for the Windows target path. Gated on: - mingw cross-toolchain installed on the host (x86_64-w64-mingw32-g++) - CRAFTER_TEST_WIN_SSH_HOST env var set (defaults to no-skip if "winvm" is reachable, but explicit opt-in keeps CI green by default) */ import std; #include "TestUtil.h" namespace fs = std::filesystem; using namespace TestUtil; namespace { bool ToolPresent(std::string_view name) { std::string cmd = std::format("which {} > /dev/null 2>&1", name); return std::system(cmd.c_str()) == 0; } bool Contains(std::string_view haystack, std::string_view needle) { return haystack.find(needle) != std::string_view::npos; } } int main() { try { const char* hostEnv = std::getenv("CRAFTER_TEST_WIN_SSH_HOST"); if (!hostEnv || !*hostEnv) { std::println("(skipped: set CRAFTER_TEST_WIN_SSH_HOST to enable, e.g. winvm)"); return 0; } std::string host = hostEnv; if (!ToolPresent("x86_64-w64-mingw32-g++")) { std::println("(skipped: mingw cross-toolchain not on PATH)"); return 0; } // Probe the SSH host; skip on transient unreachability rather than fail. std::string probe = std::format( "ssh -o BatchMode=yes -o ConnectTimeout=5 {} \"ver\" > /dev/null 2>&1", host); if (std::system(probe.c_str()) != 0) { std::println("(skipped: ssh {} not reachable)", host); return 0; } fs::path projectRoot = fs::current_path(); fs::path src = projectRoot / "tests" / "fixtures" / "windows-via-ssh"; fs::path crafterBuild = projectRoot / "bin" / "crafter-build"; fs::path work = CopyFixtureToTemp("WindowsViaSsh", src); std::string remoteDir = "C:/temp/crafter-test-winhello"; auto run = RunInDir(work, std::format( "CRAFTER_BUILD_RUNNER_x86_64_w64_mingw32='sshwin:{}:{}' '{}' test", host, remoteDir, crafterBuild.string())); if (run.exitCode != 0) { std::println(std::cerr, "inner runner failed (rc={}):\n{}", run.exitCode, run.output); return 1; } std::string marker = std::format("\xE2\x9C\x85 winhello (sshwin:{})", host); if (!Contains(run.output, marker)) { std::println(std::cerr, "expected marker {:?} not found in inner output:\n{}", marker, run.output); return 1; } return 0; } catch (const std::exception& e) { std::println(std::cerr, "test exception: {}", e.what()); return 1; } }