// Step 1966: SelectionJustificationLog // // t1: append and size // t2: findByDomain returns matching entries only // t3: findByLibrary filters correctly // t4: findByTask returns correct entries // t5: clear resets the log; entries() ordering preserved #include "SelectionJustificationLog.h" #include namespace ws = whetstone; static int p = 0, f = 0; #define T(n) { std::cout << " " << #n << "... "; } #define P() { std::cout << "PASS\n"; ++p; } #define F(m) { std::cout << "FAIL: " << m << "\n"; ++f; } #define C(c, m) if (!(c)) { F(m); return; } static ws::SelectionJustificationLog makeLog() { ws::SelectionJustificationLog log; log.append({"t1", "serialization.json", "nlohmann_json", 0.92f, "nlohmann_json scores 0.92 vs protobuf at 0.60", "2026-03-02"}); log.append({"t2", "compute.matrix", "cublas", 0.99f, "cublas scores 0.99 vs numpy at 0.95", "2026-03-02"}); log.append({"t3", "serialization.json", "serde_json", 0.98f, "serde_json scores 0.98 (only qualified)", "2026-03-02"}); log.append({"t4", "compute.statistics", "numpy", 0.93f, "numpy scores 0.93 (only qualified library)", "2026-03-02"}); return log; } void t1() { T(append_and_size); ws::SelectionJustificationLog log; C(log.size() == 0, "empty initially"); log.append({"t1", "serialization.json", "nlohmann_json", 0.92f, "j", "2026-03-02"}); C(log.size() == 1, "size 1 after append"); log.append({"t2", "compute.matrix", "cublas", 0.99f, "j", "2026-03-02"}); C(log.size() == 2, "size 2 after second append"); C(log.entries().size() == 2, "entries() matches size"); P(); } void t2() { T(findByDomain_filters_correctly); auto log = makeLog(); auto json_entries = log.findByDomain("serialization.json"); C(json_entries.size() == 2, "2 serialization.json entries"); C(json_entries[0].taskId == "t1", "first is t1"); C(json_entries[1].taskId == "t3", "second is t3"); auto none = log.findByDomain("network.async"); C(none.empty(), "no entries for network.async"); P(); } void t3() { T(findByLibrary_filters_correctly); auto log = makeLog(); auto cublas = log.findByLibrary("cublas"); C(cublas.size() == 1, "1 cublas entry"); C(cublas[0].operationDomain == "compute.matrix", "correct domain"); auto numpy = log.findByLibrary("numpy"); C(numpy.size() == 1, "1 numpy entry"); C(numpy[0].capabilityScore == 0.93f, "correct score"); P(); } void t4() { T(findByTask_returns_correct_entry); auto log = makeLog(); auto t2 = log.findByTask("t2"); C(t2.size() == 1, "1 t2 entry"); C(t2[0].selectedLibrary == "cublas", "cublas for t2"); auto missing = log.findByTask("t99"); C(missing.empty(), "no t99 entry"); P(); } void t5() { T(clear_resets_and_ordering_preserved); auto log = makeLog(); C(log.size() == 4, "4 entries before clear"); log.clear(); C(log.size() == 0, "empty after clear"); C(log.entries().empty(), "entries() empty after clear"); // Re-append and verify ordering preserved log.append({"a", "serialization.json", "nlohmann_json", 0.92f, "j", "2026-03-02"}); log.append({"b", "compute.matrix", "cublas", 0.99f, "j", "2026-03-02"}); C(log.entries()[0].taskId == "a", "first entry preserved"); C(log.entries()[1].taskId == "b", "second entry preserved"); P(); } int main() { std::cout << "Step 1966: SelectionJustificationLog\n"; t1(); t2(); t3(); t4(); t5(); std::cout << "\n" << p << "/" << (p + f) << " passed\n"; return f > 0 ? 1 : 0; }