Crafter.Review/tests/LensTools/main.cpp

42 lines
2.1 KiB
C++
Raw Normal View History

// SPDX-License-Identifier: AGPL-3.0-only
// SPDX-FileCopyrightText: Copyright (C) 2026 Catcrafts®
// The programs a lens is allowed to run are there: every Bash(<program>
// ...:*) entry of the base allowlist (the git verbs included), the shell
// claude's Bash tool runs them with, and node and npx for the Playwright MCP
// server. The suite runs inside the Flatpak build, the sandbox that ships, so
// there every one must resolve on PATH; natively the test names what this
// machine lacks and skips.
#include <unistd.h>
import std;
import Crafter.Review;
namespace fs = std::filesystem;
using namespace Crafter::Review;
int main() {
std::println("lens tools: every program a lens's allowlist names is on PATH");
std::set<std::string> programs = {"bash", "node", "npx"};
for (const std::string& tool : Tools::BaseAllow()) {
if (!tool.starts_with("Bash(") || !tool.ends_with(":*)")) continue;
const std::string prefix = tool.substr(5, tool.size() - 8);
const std::string program = prefix.substr(0, prefix.find(' '));
// A shell builtin, never a file of its own.
if (program != "cd") programs.insert(program);
}
const std::vector<std::string> path = Dyn::Split(Platform::GetEnv("PATH").value_or(""), ":");
std::vector<std::string> missing;
for (const std::string& program : programs) {
const bool found = std::ranges::any_of(path, [&](const std::string& dir) { return !dir.empty() && access((fs::path(dir) / program).c_str(), X_OK) == 0; });
if (!found) missing.push_back(program);
}
const bool shipped = fs::exists("/.flatpak-info");
if (!missing.empty() && !shipped) {
std::println("skipped: not on this machine's PATH: {}", Dyn::Join(missing, ", "));
return 77;
}
const bool ok = missing.empty() && programs.size() >= 20;
std::println("{}every program a lens's allowlist names, its shell and the MCP server's node and npx resolve on PATH ({} programs){}", ok ? " ok " : " FAIL ", programs.size(),
missing.empty() ? std::string() : std::format(" (missing: {})", Dyn::Join(missing, ", ")));
return ok ? 0 : 1;
}