File: write-ahead-log/test_wal.py

Date: 2026-05-28

Time: 18:15

write-ahead-log/test_wal.py

Purpose

This is the test suite for a Write-Ahead Log (WAL) implementation — the durability primitive described in DDIA Chapter 3. The file validates that WriteAheadLog correctly handles the core WAL contract: every mutation is durably recorded before it's acknowledged, and the log can be replayed to recover state after a crash. It owns the behavioral specification of the WAL through 9 test functions covering the happy path, failure modes, and edge cases.

Key Components

Each test function exercises a distinct WAL capability:

| Function | What it validates |

|---|---|

| test_basic | Full lifecycle: single appends, batch append, checkpoint, replay filtering by sequence number |

| testcrashrecovery | Simulates a crash by opening a second WriteAheadLog instance on the same directory without closing the first — verifies records survive |

| test_corruption | Overwrites the last 5 bytes of a WAL file with 0xFF, then confirms replay recovers only the uncorrupted prefix (1 of 2 records) |

| test_truncation | Calls wal.truncate(2) to discard records with seq <= 2, then verifies only seq=3 survives |

| testrotation | Sets maxfile_size=100 to force multiple .wal files, then checks all 20 records are readable across segments |

| testiterate | Verifies the iterator interface and that appendbatch produces a trailing COMMIT record (4 records total for 1 single + 1 batch of 2) |

| test_empty | Edge case: fresh WAL returns no records and seq=0 |

| testsyncmodes | Smoke test — constructs a WAL in each of "sync", "batch", "none" modes without error |

| testlargevalues | Writes a 100KB value and confirms round-trip fidelity |

Patterns

No test framework. Tests are plain functions with assert statements, run via _main_. Each prints PASSED: ... on success. This is consistent across the DDIA implementations repo — the tests are self-contained scripts, not pytest suites.

Temp directory isolation. Every test uses tempfile.TemporaryDirectory() as a context manager, so WAL files are cleaned up automatically and tests don't interfere with each other.

Crash simulation via re-instantiation. testcrashrecovery doesn't kill a process — it opens a fresh WriteAheadLog on the same directory while the first is still open. This tests that the WAL's on-disk format is self-describing enough to recover without a clean shutdown.

Physical corruption injection. test_corruption seeks to 5 bytes before EOF and writes garbage. This tests the WAL's checksum/integrity mechanism — the implementation must detect the corrupted record and stop replay before it.

Dependencies

Imports:

Imported by:

Flow

When run as python test_wal.py, execution is sequential through all 9 tests. Each test:

1. Creates an isolated temp directory

2. Instantiates WriteAheadLog(dir, sync_mode="sync") — the strictest durability mode

3. Performs writes (append, append_batch)

4. Performs reads (replay, iterate, currentseqnum)

5. Asserts expected record counts, sequence numbers, and field values

6. Calls wal.close() and lets the context manager clean up

The sequence number contract visible from the tests: append returns the assigned seq, starting at 1. appendbatch of 3 items advances the seq by 4 (3 data records + 1 commit marker), bringing the total to 7 in testbasic. checkpoint writes a marker at seq=8.

Invariants

Error Handling

The tests don't exercise explicit error paths (no exception assertions). Error handling is tested implicitly:

Topics to Explore

Beliefs