fold/tests/unit/test_batch_safety_observer.cpp
trvon 2dcbdbc75d
feat: harden Fold quality guard
Preserve source, binary, and runtime evidence boundaries while making precision and performance regressions reproducible.

- decompose analysis orchestration into bounded modules
- add differential, metamorphic, organic, and Yams change-time gates
- fix detector, P-Code, fuzz sanitizer, and report identity precision
2026-07-13 15:05:35 -04:00

73 lines
2.3 KiB
C++

#include <catch2/catch_test_macros.hpp>
#include <chrono>
#include "fold/symbolic/batch_safety_observer.hpp"
namespace {
class RecordingObserver final : public fold::SafetyObserver {
public:
void onDivision(const z3::expr&, const z3::expr&, const fold::ir::Expr&, const fold::ir::Expr&,
const z3::expr&, const fold::ir::SourceLoc&, bool, unsigned,
const fold::DefUseContext*, const fold::SymbolicEnv*) override {
++divisions;
}
void onFree(const z3::expr&, const fold::ir::Expr&, const z3::expr&, const fold::ir::SourceLoc&,
bool, bool) override {
++frees;
}
int divisions = 0;
int frees = 0;
};
} // namespace
TEST_CASE("BatchSafetyObserver defers expensive hazard hooks", "[symbolic][observer]") {
z3::context context;
const z3::expr lhs = context.bv_val(12, 32);
const z3::expr rhs = context.bv_val(3, 32);
const z3::expr path = context.bool_val(true);
const fold::ir::Expr expression;
const fold::ir::SourceLoc location;
RecordingObserver recording;
fold::BatchSafetyObserver batch(&recording);
batch.onDivision(lhs, rhs, expression, expression, path, location, true, 32);
CHECK(recording.divisions == 0);
CHECK(batch.pending() == 1);
batch.flush();
CHECK(recording.divisions == 1);
CHECK(batch.pending() == 0);
}
TEST_CASE("BatchSafetyObserver preserves immediate stateful hooks", "[symbolic][observer]") {
z3::context context;
const z3::expr pointer = context.bv_val(1, 64);
const z3::expr path = context.bool_val(true);
RecordingObserver recording;
fold::BatchSafetyObserver batch(&recording);
batch.onFree(pointer, {}, path, {}, true, false);
CHECK(recording.frees == 1);
CHECK(batch.pending() == 0);
}
TEST_CASE("BatchSafetyObserver drops pending work after its deadline", "[symbolic][observer]") {
z3::context context;
const z3::expr value = context.bv_val(1, 32);
const z3::expr path = context.bool_val(true);
RecordingObserver recording;
fold::BatchSafetyObserver batch(&recording);
batch.onDivision(value, value, {}, {}, path, {}, true, 32);
batch.setDeadline(std::chrono::steady_clock::now() - std::chrono::milliseconds(1));
batch.flush();
CHECK(recording.divisions == 0);
CHECK(batch.pending() == 0);
CHECK(batch.deadlineHit());
}