test(run): the store rules, stacks and memory, and the review fixes, check by check
StoreRules (23 checks), StacksMemory (24) and ReviewFixes (19), each a test of its own. Run and SlotsPlan now have seams that start as the real ones: appReady, probe, query, bypassesRls, migrationsAtHead, migrationsDrift, treeDrift, promptFor, runPass, resumable, instrumentPreflight, and a Machine for SlotsPlan. MigrationsAtHead is split out of MigrationsDrift for it; the HEAD side is still worked out once per tree and base. The Postgres stand-in and the raw broker call move to tests/Common, shared by PgWire and ReviewFixes. ReviewFixes runs this binary as `sql`, and a real server that resets every connection makes the startup message either fail to go out or never get its answer - a DbError either way. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
0f803d90bd
commit
dd0929b705
8 changed files with 1328 additions and 185 deletions
|
|
@ -76,11 +76,21 @@ export namespace Crafter::Review::Run {
|
|||
// Below 500 is ok.
|
||||
std::pair<bool, std::string> AppReady(std::string_view url, std::string_view path = "/", double timeout = 10);
|
||||
|
||||
// The machine's memory as SlotsPlan reads it (the tests give their own).
|
||||
struct Machine {
|
||||
std::function<std::optional<std::int64_t>()> available;
|
||||
std::function<std::int64_t()> reserve;
|
||||
};
|
||||
// `slots`: how many stacks to bring up - as many as free memory holds,
|
||||
// and no more than the range's browser passes can use at once - and the
|
||||
// commands for the ones not up yet. (want, commands).
|
||||
std::pair<std::int64_t, std::vector<std::string>> SlotsPlan(const Json& cfg, const std::filesystem::path& repo, const std::optional<std::filesystem::path>& artifact = std::nullopt,
|
||||
const std::optional<std::filesystem::path>& scratchRoot = std::nullopt, const Log& log = {});
|
||||
const std::optional<std::filesystem::path>& scratchRoot = std::nullopt, const Log& log = {}, const Machine& machine = {});
|
||||
|
||||
// ({version: path} of the migrations at the range HEAD, the range's added
|
||||
// or changed migrations, {path: fingerprint at HEAD} of those).
|
||||
using MigrationsHead = std::tuple<std::map<std::string, std::string>, std::vector<std::string>, std::map<std::string, std::string>>;
|
||||
using QueryResult = std::pair<std::vector<std::string>, std::vector<std::vector<std::optional<std::string>>>>;
|
||||
|
||||
class Run {
|
||||
public:
|
||||
|
|
@ -108,6 +118,7 @@ export namespace Crafter::Review::Run {
|
|||
std::map<std::string, std::string> DbLenses(std::span<const std::string> lensFiles) const;
|
||||
void InstrumentPreflight(std::span<const std::string> lensFiles);
|
||||
static std::optional<std::string> MigrationVersion(std::string_view file);
|
||||
MigrationsHead MigrationsAtHead();
|
||||
// (problem, note): the migrations at the range HEAD against the ones
|
||||
// the database applied.
|
||||
std::pair<std::optional<std::string>, std::optional<std::string>> MigrationsDrift(const std::string& url);
|
||||
|
|
@ -226,10 +237,26 @@ export namespace Crafter::Review::Run {
|
|||
std::vector<Json> seats;
|
||||
std::map<std::filesystem::path, Json> envMarkers;
|
||||
std::set<std::pair<std::string, std::string>> envSkips;
|
||||
std::map<std::pair<std::string, std::string>, std::tuple<std::map<std::string, std::string>, std::vector<std::string>, std::map<std::string, std::string>>> migCache;
|
||||
std::map<std::pair<std::string, std::string>, MigrationsHead> migCache;
|
||||
// The log every line goes to (the tests put their own here).
|
||||
Log log;
|
||||
|
||||
// ---- the seams a test replaces ---------------------------------------------
|
||||
// Each starts as the real one; the methods call through these.
|
||||
std::function<std::pair<bool, std::string>(std::string_view url, std::string_view path)> appReady;
|
||||
std::function<std::pair<bool, std::string>(std::string_view url)> probe;
|
||||
std::function<QueryResult(std::string_view url, std::string_view sql)> query;
|
||||
std::function<std::optional<bool>(std::string_view url)> bypassesRls;
|
||||
std::function<MigrationsHead()> migrationsAtHead;
|
||||
std::function<std::pair<std::optional<std::string>, std::optional<std::string>>(const std::string& url)> migrationsDrift;
|
||||
std::function<std::optional<std::string>()> treeDrift;
|
||||
std::function<std::pair<std::filesystem::path, std::string>(const Json& job)> promptFor;
|
||||
std::function<std::pair<Json, Json>(const Json& job, const std::string& prompt, const std::filesystem::path& systemPath, std::string_view schema, std::int64_t maxTurns, std::int64_t timeoutMin,
|
||||
bool persist)>
|
||||
runPass;
|
||||
std::function<std::optional<Json>(const std::string& name, const std::string& lensFile, std::string_view title)> resumable;
|
||||
std::function<void(std::span<const std::string> lensFiles)> instrumentPreflight;
|
||||
|
||||
private:
|
||||
// What exec_job's threads share with the pool's: the system files,
|
||||
// the lens layers, the jobs run.
|
||||
|
|
|
|||
Loading…
Reference in a new issue