test(cli): a word after format is a glob, not the clean verb

Drives Run() with `format clean` on a staged project whose project file
cannot compile. Both trees must survive, and the run must fail: getting
as far as loading the project is what shows it went on to format rather
than cleaning and exiting 0.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
Jorijn van der Graaf 2026-10-06 18:08:26 +02:00
commit 6dcdad4515
Signed by: jorijnvdgraaf
GPG key ID: 2937E59CDCC1BCFB

View file

@ -29,6 +29,12 @@ namespace {
std::ofstream(root / "keep-me.txt") << "untouched"; std::ofstream(root / "keep-me.txt") << "untouched";
return root; return root;
} }
std::int32_t RunWith(std::vector<std::string> args) {
std::vector<char*> argv;
for (std::string& arg : args) argv.push_back(arg.data());
return Run(static_cast<std::int32_t>(argv.size()), argv.data());
}
} }
int main() { int main() {
@ -71,6 +77,22 @@ int main() {
Check(fs::exists(cwdBin) == cwdBinExisted, "the cwd's bin/ is untouched"); Check(fs::exists(cwdBin) == cwdBinExisted, "the cwd's bin/ is untouched");
} }
{
// `clean` is a verb only where a verb can stand. After `format` it
// is a rule-name glob like any other word, and a glob must never
// delete the build trees. The project file cannot compile, so the
// run fails once it gets as far as loading it — which is the proof
// that it went on to format instead of cleaning and exiting 0.
fs::path root = StageProject("format-glob");
fs::path projectFile = root / "project.cpp";
std::ofstream(projectFile) << "this is not valid C++ at all\n";
const std::int32_t exitCode = RunWith({"crafter-build", "format", "clean", std::format("--project={}", projectFile.string())});
Check(fs::exists(root / "bin" / "app-x86_64-pc-linux-gnu-native-native-0badf00d" / "app"), "`format clean` leaves bin/ alone");
Check(fs::exists(root / "build" / "app-x86_64-pc-linux-gnu-native-native-0badf00d" / "main_impl.o"), "`format clean` leaves build/ alone");
Check(exitCode != 0, "`format clean` goes on to load the project instead of cleaning");
}
if (Failures > 0) { if (Failures > 0) {
std::println(std::cerr, "{} assertions failed", Failures); std::println(std::cerr, "{} assertions failed", Failures);
return 1; return 1;