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:
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 — tick-domain tests:
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 end − start.
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 |
Raises:
| Type | Description |
|---|---|
OverflowError
|
If delta is outside (-228 .. 228). |