Files
cargoxx/tests/exec_run.cpp

79 lines
2.5 KiB
C++

#include <catch2/catch_test_macros.hpp>
import cargoxx.exec;
import cargoxx.util;
import std;
using cargoxx::exec::ExecOptions;
using cargoxx::exec::ExecResult;
using cargoxx::exec::run;
using cargoxx::util::ErrorCode;
TEST_CASE("run captures stdout from echo", "[exec]") {
auto r = run("echo", {"hello", "world"});
REQUIRE(r.has_value());
REQUIRE(r->exit_code == 0);
REQUIRE(r->stdout_text == "hello world\n");
REQUIRE(r->stderr_text.empty());
}
TEST_CASE("run returns 0 for true", "[exec]") {
auto r = run("true", {});
REQUIRE(r.has_value());
REQUIRE(r->exit_code == 0);
}
TEST_CASE("run returns non-zero for false", "[exec]") {
auto r = run("false", {});
REQUIRE(r.has_value());
REQUIRE(r->exit_code != 0);
}
TEST_CASE("run reports ExecToolNotFound for missing program", "[exec]") {
auto r = run("definitely-not-a-real-command-xyz-12345", {});
REQUIRE_FALSE(r.has_value());
REQUIRE(r.error().code == ErrorCode::ExecToolNotFound);
}
TEST_CASE("run honors cwd", "[exec]") {
auto cwd = std::filesystem::temp_directory_path();
auto r = run("pwd", {}, ExecOptions{.cwd = cwd});
REQUIRE(r.has_value());
REQUIRE(r->exit_code == 0);
// pwd may print the canonical path; at minimum the result starts with /tmp
// (or whatever the temp dir's prefix is)
REQUIRE_FALSE(r->stdout_text.empty());
}
TEST_CASE("run captures stderr", "[exec]") {
auto r = run("ls", {"/this/path/does/not/exist/cargoxx-xyz"});
REQUIRE(r.has_value());
REQUIRE(r->exit_code != 0);
REQUIRE_FALSE(r->stderr_text.empty());
}
TEST_CASE("run propagates env_overrides", "[exec]") {
auto r = run("env", {}, ExecOptions{
.env_overrides = {{"CARGOXX_TEST_VAR", "lemonade"}},
});
REQUIRE(r.has_value());
REQUIRE(r->exit_code == 0);
REQUIRE(r->stdout_text.find("CARGOXX_TEST_VAR=lemonade") != std::string::npos);
}
TEST_CASE("run enforces a timeout", "[exec]") {
auto r = run("sleep", {"5"},
ExecOptions{.timeout = std::chrono::seconds{1}});
REQUIRE_FALSE(r.has_value());
REQUIRE(r.error().code == ErrorCode::ExecCommandFailed);
}
TEST_CASE("run handles many output bytes without deadlocking", "[exec]") {
// 64 KiB of zeros — exercises pipe-pumping past the typical 4 KiB buffer
// without producing unbounded output.
auto r = run("dd", {"if=/dev/zero", "bs=1024", "count=64", "status=none"});
REQUIRE(r.has_value());
REQUIRE(r->exit_code == 0);
REQUIRE(r->stdout_text.size() == 64 * 1024);
}