Files
kte/tests/TestRunner.cc
T
Claude a33c1759e7 Swap: chunked checkpoints for large buffers; scaled thresholds; single replay
- A checkpoint larger than one record (16 MiB) is written as CHKPT_BEGIN
  [size u64, CRC-32], CHKPT_DATA chunks and CHKPT_END. Replay assembles it
  and applies it only when complete with the size and CRC matching; an
  unfinished one is a torn tail (valid_bytes stops before it). Buffers
  over 16 MiB could not be checkpointed before: a lost record left their
  journal behind for good, and they were never compacted. Records are
  written as segments straight from the snapshot. Header version 2;
  version 1 journals are still read.
- Checkpoint thresholds scale with the buffer size (edits of half its
  size; the timer only after a sixteenth; compaction at twice its size;
  gap retries spaced by size), and a checkpoint that would compact is
  written straight into the compacted journal instead of being appended
  and then copied.
- The recovery prompt keeps the content it replayed for its preview and
  installs it on 'y', instead of replaying the journal a second time.
- A base file over 64 MiB gets its CRC from the writer thread before it
  creates the journal (it had none, so touching such a file made its
  journal unusable for recovery).
- kte_tests takes optional name substrings to run a subset of tests.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015rcVQiiWyTzoNrsvLSaAfB
2026-09-24 09:16:04 -07:00

52 lines
1.5 KiB
C++

#include "Test.h"
#include <iostream>
#include <chrono>
#include <string>
#include <vector>
// Usage: kte_tests [substring...] runs the tests whose names contain any of
// the substrings (all tests when none are given).
int
main(int argc, char **argv)
{
using namespace std::chrono;
auto &reg = ktet::registry();
std::vector<std::string> filters(argv + 1, argv + argc);
auto selected = [&filters](const std::string &name) {
if (filters.empty())
return true;
for (const auto &f: filters)
if (name.find(f) != std::string::npos)
return true;
return false;
};
std::cout << "kte unit tests: " << reg.size() << " test(s)\n";
int failed = 0;
auto t0 = steady_clock::now();
for (const auto &tc: reg) {
if (!selected(tc.name))
continue;
auto ts = steady_clock::now();
try {
tc.fn();
auto te = steady_clock::now();
auto ms = duration_cast<milliseconds>(te - ts).count();
std::cout << "[ OK ] " << tc.name << " (" << ms << " ms)\n";
} catch (const ktet::AssertionFailure &e) {
++failed;
std::cerr << "[FAIL] " << tc.name << " -> " << e.msg << "\n";
} catch (const std::exception &e) {
++failed;
std::cerr << "[EXCP] " << tc.name << " -> " << e.what() << "\n";
} catch (...) {
++failed;
std::cerr << "[EXCP] " << tc.name << " -> unknown exception\n";
}
}
auto t1 = steady_clock::now();
auto total_ms = duration_cast<milliseconds>(t1 - t0).count();
std::cout << "Done in " << total_ms << " ms. Failures: " << failed << "\n";
return failed == 0 ? 0 : 1;
}