Skip to content

Testing Helpers

chumicro_timing.testing provides deterministic fakes for host-side tests.

Usage with Heartbeat

Pass a FakeTicks instance as the ticks parameter to Heartbeat. Then use FakeTicks.ticks_ms() to get timestamps for poll() and FakeTicks.advance() to move time forward:

from chumicro_timing import Heartbeat
from chumicro_timing.testing import FakeTicks

def test_heartbeat_fires_after_period() -> None:
    """Heartbeat fires exactly when the period elapses."""
    fake = FakeTicks()
    heartbeat = Heartbeat(period_ms=100, ticks=fake)

    now = fake.ticks_ms()
    assert heartbeat.poll(now) is False

    fake.advance(99)
    now = fake.ticks_ms()
    assert heartbeat.poll(now) is False

    fake.advance(1)
    now = fake.ticks_ms()
    assert heartbeat.poll(now) is True
    # Timer has been reset — next poll returns False
    assert heartbeat.poll(now) is False

Usage from other libraries

Libraries that depend on chumicro-timing can import FakeTicks directly:

# In another library's test file
from chumicro_timing.testing import FakeTicks

This follows the project convention from Decision 0010: libraries that expose injectable services ship their own test fakes.

API Reference

chumicro_timing.testing

Test helpers for libraries that depend on chumicro-timing.

Provides deterministic fakes that replace the real tick functions, allowing host-side tests to control time without wall-clock waits.

Ships with the library per Decision 0010 so downstream consumers import ready-made fakes rather than inventing ad-hoc mocks.

Example
from chumicro_timing.testing import FakeTicks

fake = FakeTicks()
heartbeat = Heartbeat(period_ms=100, ticks=fake)
fake.advance(100)
assert heartbeat.poll(fake.ticks_ms()) is True

FakeTicks models the full tick contract including the 2²⁹ ms wraparound period. Values returned by ticks_ms() are always in [0 .. 2**29 - 1], and ticks_diff uses ring arithmetic — so tests will catch code that accidentally uses plain subtraction instead of ticks_diff.

FakeTicks

Deterministic tick source for host-side tests.

Replaces the real ticks_ms / ticks_diff / ticks_add contract with values that only move when advance() is called explicitly. Models the 2²⁹ ms wraparound period so downstream code is tested against the real tick semantics.

current_ms property writable

Return the raw internal counter (unmasked).

Prefer ticks_ms() for values that match the production contract. This property exists for backward compatibility and for tests that need to inspect the raw counter.

__init__(start_ms=0)

Create a fake tick source starting at start_ms.

Parameters:

Name Type Description Default
start_ms int

Initial tick value (masked to the tick period).

0

advance(amount_ms)

Move the clock forward by amount_ms milliseconds.

Parameters:

Name Type Description Default
amount_ms int

Milliseconds to advance.

required

ticks_ms()

Return the current fake tick value in [0 .. 2**29 - 1].

ticks_diff(end, start)

Wraparound-safe signed difference endstart.

Uses the same ring arithmetic as the real ticks_diff.

Parameters:

Name Type Description Default
end int

Later tick value.

required
start int

Earlier tick value.

required

Returns:

Type Description
int

Signed difference in milliseconds.

ticks_add(ticks_val, delta)

Wraparound-safe addition of delta to a tick value.

Matches the real ticks_add behavior, including raising OverflowError for deltas at or beyond the half-period.

Parameters:

Name Type Description Default
ticks_val int

Base tick value.

required
delta int

Milliseconds to add.

required

Returns:

Type Description
int

Wrapped tick value in [0 .. 2**29 - 1].

Raises:

Type Description
OverflowError

If delta is outside (-228 .. 228).