~/moonraft▊

Ledger

258 tests,
none unaccounted for

How the port stands against the reference implementation's own unit-test suite. The target is etcd-io/raft pinned at 26647d5; the scope is that repository minus the database beside it (mvcc, watch, lease, gRPC).

This page audits the unit-test side. The scripted side — 41 scenarios replayed block by block — is recorded in the porting notes, and all 41 match byte for byte.

Method

Mechanical, so it can be falsified

The reference tree's test functions were extracted from the pinned commit with two commands:

grep -rhoE '^func (Test[A-Za-z0-9_]+)\(t \*testing\.T\)' --include=*_test.go . \
  | sed 's/func //;s/(t \*testing.T)//' | sort

That yields 258 Test* functions. Each is matched against this repository by the convention the port follows: a MoonBit test carries the reference name at the front of its own name, or names it in the comment above.

// TestRawNodeStep: RawNode.Step handles every network message.
test "TestRawNodeStep every network payload routes through Step" { … }

A test's provenance is therefore visible in moon test output rather than buried in a mapping file. Benchmark* functions are not in this count; the three the port names are in src/cmd/benchmark.

Result

Every test has a disposition

DispositionCount
Carried by a test of the same name199
N/A — out of scope, reason below9
Covered by the scripted scenarios and by tests named after the behaviour50
Total reference Test*258

No reference test is unaccounted for, and the 50 are grouped below with the file that covers each group — so a wrong grouping is one grep away from being caught.

Out of scope

The nine that cannot be translated

Three reasons are admissible: a language-level concurrency shell, a benchmark, and a memory-layout assertion. Only the first and the third occur here.

Reference testWhy not
TestProtoMemorySizes It asserts the byte size of message fields under the reference language's struct layout. MoonBit's data model has no comparable layout to assert, and nothing in the protocol depends on one.
TestNodeStop, TestNodeStepUnblock The goroutine-and-channel shell around the core: a Ready loop in a goroutine, a stop channel, a proposal queue. The port has no such shell — RawNode is the same state machine driven by the caller — so there is no lifecycle to stop or unblock.
TestNodeCommitPaginationAfterRestart Same shell: it restarts a goroutine and counts the readies it hands out. Its substance — a committed batch paginated across readies, and the applied cursor surviving a restart — is carried by TestRawNodeCommitPaginationAfterRestart, which is translated.
TestNetworkDrop, TestNetworkDelay The test network is a goroutine per node behind a channel; these two drive that shell's drop and delay knobs. The port's Cluster covers the same two faults — set_drop, set_delay — deterministically, and both are exercised throughout the property and scenario tests.
TestBasicProgress, TestPause, TestRestart They assert on the progress of the goroutine-backed node, which the port does not have. The state they inspect — a Progress advancing, a paused follower, a node resumed from storage — is asserted directly in the tracker's progress tests, the replicate_pause script, and TestRawNodeRestart.

Covered without a same-named test

The fifty, by area

These behaviours are exercised — through the scripts, and through tests named after what they check rather than after the function they came from.

Election timing

TestFollowerStartElection, TestFollowerElectionTimeoutRandomized, TestCandidateElectionTimeoutRandomized, TestFollowersElectionTimeoutNonconflict, TestCandidatesElectionTimeoutNonconflict, TestPastElectionTimeout — covered by the randomised-timeout band test, the pinned-timeout tick test, and the campaign and prevote scripts.

One-round elections and their losers

TestCandidateConcede, TestSingleNodeCandidate, TestSingleNodePreCandidate, TestCandidateSelfVoteAfterLostElection, and the pre-vote variant, TestCandidateDeliversPreCandidateSelfVoteAfterBecomingCandidate — covered by the election, election-contention and pre-vote property tests, the vote-record test, and the single_node script.

Stale and duplicated messages

TestOldMessages, TestAllServerStepdown — covered by the stale-term and step-dispatch tests, and by the scripts' ignored-message blocks.

Replication and proposals

TestLogReplication, TestProposal, TestProposalByProxy, TestLeaderMsgAppSelfAckAfterTermChange — covered by the replication, forwarding and idempotent-append tests, and the async_storage_writes scripts.

Heartbeats

TestBcastBeat, TestRecvMsgBeat — covered by the replicate_pause and heartbeat_resp_recovers_from_probing scripts.

Flow control

TestProgressFlowControl, TestProgressPaused, TestProgressResumeByHeartbeatResp — covered by replicate_pause (a full in-flight window), probe_and_replicate, and the tracker's progress tests.

Learners

TestLearnerPromotion, TestLearnerLogReplication, TestLearnerReceiveSnapshot — covered by the learners-next test and the two auto-add scripts.

Snapshots

TestProvideSnap, TestIgnoreProvidingSnap, TestRestoreFromSnapMsg, TestRestoreIgnoreSnapshot — covered by the snapshot, snapshot-RPC and snapshot-scenario tests, and the snapshot_succeed_via_app_resp scripts.

Membership

TestAddLearner, TestRemoveNode, TestStepConfig, TestStepIgnoreConfig, TestConfChangeCheckBeforeCampaign, TestConfChangeV2CheckBeforeCampaign — covered by the configuration, cluster and pending-change tests, and the nine confchange scripts.

Leadership transfer

TestLeaderTransferTimeout, TestLeaderTransferRemoveNode, TestLeaderTransferDemoteNode, TestLeaderTransferToNonExistingNode, TestTransferNonMember — covered by the transfer tests (a transfer to a non-member is a no-op; an incomplete transfer aborts after an election timeout) and the confchange_v2_replace_leader scripts.

Read index and leases

TestReadOnlyForNewLeader, TestReadOnlyOptionLease, TestReadOnlyWithLearner, TestRaftFreesReadOnlyMem — covered by the read-only and read-index-queue tests: lease-based reads, safe reads with a learner, and lease reads without a quorum.

Check-quorum disruption

TestDisruptiveFollower, TestDisruptiveFollowerPreVote — covered by the check-quorum test (a leased follower drops a pre-vote) and the checkquorum script.

The scripted drivers themselves

TestDataDriven, TestConfChangeDataDriven, TestInteraction — covered by the port's own interpreter and the two scoreboards that replay all 41 scripts.

Why a ledger

Counts are mechanical; judgement is named

The counts above are two commands over the pinned tree and src/. The fifty rows are the part that needs judgement, so they are grouped and each group names what covers it. If a group is wrong, it is wrong in a way one grep exposes — which is the point.