Class TimeRenderingHelpers
- Namespace
- TimeAssertions
- Assembly
- TimeAssertions.dll
Formatting utilities for rendering elapsed durations and timing budgets in human-readable form for assertion-failure messages. Pure; no I/O; allocation-conscious.
public static class TimeRenderingHelpers
- Inheritance
-
TimeRenderingHelpers
- Inherited Members
Methods
FormatActiveTimerAtLeastShortfall(IReadOnlyList<ActiveTimerInfo>, int)
Formats the failure message for HasActiveTimers() and
HasAtLeastActiveTimerCount(count): the minimum that was required and the actual count,
followed by each active timer's schedule in deterministic order (by due time, then period).
When no timers are active the schedule list is omitted.
public static string FormatActiveTimerAtLeastShortfall(IReadOnlyList<ActiveTimerInfo> active, int minimum)
Parameters
activeIReadOnlyList<ActiveTimerInfo>The timers active when the assertion ran.
minimumintThe minimum active-timer count that was required. Must be non-negative.
Returns
- string
A multi-line human-readable summary in InvariantCulture, with a grep-friendly
(minimum=N, actual=M)trailer on the headline.
Exceptions
- ArgumentNullException
activeis null.- ArgumentOutOfRangeException
minimumis negative.
FormatActiveTimerCountMismatch(IReadOnlyList<ActiveTimerInfo>, int)
Formats the failure message for HasActiveTimerCount(expected): the expected and actual
active-timer counts, followed by each active timer's schedule in deterministic order (by due
time, then period). When no timers are active the schedule list is omitted.
public static string FormatActiveTimerCountMismatch(IReadOnlyList<ActiveTimerInfo> active, int expected)
Parameters
activeIReadOnlyList<ActiveTimerInfo>The timers active when the assertion ran.
expectedintThe expected active-timer count that was not met. Must be non-negative.
Returns
- string
A multi-line human-readable summary in InvariantCulture, with a grep-friendly
(expected=N, actual=M)trailer on the headline.
Exceptions
- ArgumentNullException
activeis null.- ArgumentOutOfRangeException
expectedis negative.
FormatActiveTimerLeak(IReadOnlyList<ActiveTimerInfo>)
Formats the failure message for HasNoActiveTimers(): names each timer that remained
active by the schedule it was created with (or last changed to), so a leak failure reports
which timers survived rather than a bare count. Survivors are listed in a
deterministic order (by due time, then period) so the message is snapshot-stable.
public static string FormatActiveTimerLeak(IReadOnlyList<ActiveTimerInfo> survivors)
Parameters
survivorsIReadOnlyList<ActiveTimerInfo>The timers still active when the assertion ran. Expected non-empty: the assertion only renders a failure when at least one timer leaked.
Returns
- string
A multi-line human-readable summary in InvariantCulture, with a grep-friendly
(count=N)trailer on the headline.
Exceptions
- ArgumentNullException
survivorsis null.
FormatActiveTimerSurvivors(IReadOnlyList<ActiveTimerInfo>)
Formats the schedule list of the timers that survived a poll-until-clear deadline, for the
failure message of HasNoActiveTimersEventually(...) / HasActiveTimerCountEventually(...).
Returns each survivor's schedule on its own indented line, sorted by due time then period for
deterministic (snapshot-stable) output, prefixed with a grep-friendly (count=N) trailer.
The caller supplies the headline (which names the timeout); this renders only the survivor list.
public static string FormatActiveTimerSurvivors(IReadOnlyList<ActiveTimerInfo> survivors)
Parameters
survivorsIReadOnlyList<ActiveTimerInfo>The timers still active when the deadline elapsed.
Returns
- string
A multi-line string in InvariantCulture beginning with the
(count=N)trailer, followed by one indented schedule line per survivor. Empty survivors render the trailer alone.
Exceptions
- ArgumentNullException
survivorsis null.
FormatBudgetOverrun(TimeSpan, TimeSpan)
Formats a budget-overrun summary: actual elapsed, the budget that was exceeded, and the
excess. Used in .WithinTimeBudget(...) failure messages.
public static string FormatBudgetOverrun(TimeSpan elapsed, TimeSpan budget)
Parameters
elapsedTimeSpanThe wall-clock duration the assertion's evaluator took.
budgetTimeSpanThe configured timing budget.
Returns
- string
A multi-line human-readable summary.
Remarks
The rendered string carries two forms in parallel: a human-readable prose
(completed in 1.2s: exceeded budget of 500ms by 747ms) and a grep-friendly
fixed-unit parenthetical ((elapsed=1247ms, budget=500ms, overrun=747ms)). The
parenthetical lets CI log scrapers and triage tooling extract the three numbers
without parsing the human-readable prose around them.
FormatDuration(TimeSpan)
Formats a TimeSpan as a compact human-readable duration string. Picks the
most appropriate unit based on magnitude:
sub-millisecond → microseconds (e.g. "123μs"),
sub-second → milliseconds (e.g. "247ms"),
sub-minute → seconds with one decimal (e.g. "1.2s"),
otherwise → minutes:seconds (e.g. "1:30").
public static string FormatDuration(TimeSpan duration)
Parameters
durationTimeSpanThe duration to format.
Returns
- string
A compact human-readable duration string in InvariantCulture.
FormatNextTimerDueMismatch(TimeSpan?, TimeSpan, TimeSpan)
Formats the failure message for HasNextTimerDueApproximately(expected, tolerance): the
expected due time, the allowed tolerance, and either the observed next-timer due time and how
far it fell outside tolerance, or a note that no enabled timer was pending.
public static string FormatNextTimerDueMismatch(TimeSpan? actual, TimeSpan expected, TimeSpan tolerance)
Parameters
actualTimeSpan?The observed next-timer due time, or null when no enabled timer is pending.
expectedTimeSpanThe expected next-timer due time.
toleranceTimeSpanThe allowed absolute tolerance around
expected. Must be non-negative.
Returns
- string
A single-line human-readable summary in InvariantCulture.
Remarks
The rendered shape pins a one-line headline followed by a grep-friendly fixed-unit
parenthetical ((expected=Xms, tolerance=Yms, actual=Zms, delta=Wms)) so CI log scrapers
can extract the numbers without parsing the prose, analogous to
FormatBudgetOverrun(TimeSpan, TimeSpan). When no enabled timer is pending the parenthetical reads
(expected=Xms, tolerance=Yms, actual=none).
Exceptions
- ArgumentOutOfRangeException
toleranceis negative.
FormatNextTimerDueOutOfRange(TimeSpan?, TimeSpan, TimeSpan)
Formats the failure message for HasPendingTimerDueWithin(min, max): the inclusive
range, and either the observed next-timer due time, or a note that no enabled timer was
pending.
public static string FormatNextTimerDueOutOfRange(TimeSpan? actual, TimeSpan min, TimeSpan max)
Parameters
actualTimeSpan?The observed next-timer due time, or null when no enabled timer is pending.
minTimeSpanThe inclusive lower bound of the expected due-time range.
maxTimeSpanThe inclusive upper bound of the expected due-time range.
Returns
- string
A single-line human-readable summary in InvariantCulture.
Remarks
The rendered shape pins a one-line headline followed by a grep-friendly fixed-unit
parenthetical ((min=Xms, max=Yms, actual=Zms)); when no enabled timer is pending the
parenthetical reads (min=Xms, max=Yms, actual=none).
FormatNoTimerFired(long, IReadOnlyList<ActiveTimerInfo>)
Formats the failure message for HasNoTimerFired(): the observed cumulative fire count
that should have been zero, followed by the still-active timers with their per-timer fire
counts (when any remain active).
public static string FormatNoTimerFired(long actual, IReadOnlyList<ActiveTimerInfo> active)
Parameters
actuallongThe observed cumulative fire count. Expected greater than zero: the assertion only renders a failure when at least one callback fired.
activeIReadOnlyList<ActiveTimerInfo>The timers still active when the assertion ran.
Returns
- string
A human-readable summary in InvariantCulture, with a grep-friendly
(expected=0, actual=M)trailer on the headline.
Exceptions
- ArgumentNullException
activeis null.
FormatRateLimitViolation(IReadOnlyList<DateTimeOffset>, int, TimeSpan, TimeSpan)
Formats a rate-limit violation summary for the failure message of
WasInvokedAtMostOncePer(...). Names the first violating consecutive pair by
index, the observed gap, and the configured minimum interval.
public static string FormatRateLimitViolation(IReadOnlyList<DateTimeOffset> timestamps, int violatingIndex, TimeSpan gap, TimeSpan interval)
Parameters
timestampsIReadOnlyList<DateTimeOffset>The invocation-timestamp sequence the assertion examined.
violatingIndexintThe zero-based index of the second timestamp in the violating pair. The pair is (
timestamps[violatingIndex - 1],timestamps[violatingIndex]).gapTimeSpanThe observed gap between the two timestamps.
intervalTimeSpanThe configured minimum interval that was violated.
Returns
- string
A multi-line human-readable summary in InvariantCulture.
Remarks
The rendered shape pins a one-line headline with the violation index and gap,
followed by the two violating timestamps in ISO 8601 round-trip form, and a
grep-friendly fixed-unit parenthetical (analogous to
FormatBudgetOverrun(TimeSpan, TimeSpan)'s (elapsed=, budget=, overrun=) trailer)
so CI log scrapers can extract the numbers without parsing the prose.
Exceptions
- ArgumentNullException
timestampsis null.- ArgumentOutOfRangeException
violatingIndexis less than1or greater than or equal to: the pair (timestamps.Counttimestamps[violatingIndex - 1],timestamps[violatingIndex]) must reference two in-range entries.
FormatTimerFireCountMismatch(long, int, IReadOnlyList<ActiveTimerInfo>)
Formats the failure message for HasTimerFiredCount(expected): the expected and actual
cumulative fire counts across every timer the provider created, followed by the still-active
timers with their per-timer fire counts (when any remain active). The count is cumulative and
survives disposal, so a mismatch with an empty active list still reports the totals.
public static string FormatTimerFireCountMismatch(long actual, int expected, IReadOnlyList<ActiveTimerInfo> active)
Parameters
actuallongThe observed cumulative fire count.
expectedintThe expected fire count that was not met. Must be non-negative.
activeIReadOnlyList<ActiveTimerInfo>The timers still active when the assertion ran.
Returns
- string
A human-readable summary in InvariantCulture, with a grep-friendly
(expected=N, actual=M)trailer on the headline.
Exceptions
- ArgumentNullException
activeis null.- ArgumentOutOfRangeException
expectedis negative.
FormatTimerFireShortfall(long, int, IReadOnlyList<ActiveTimerInfo>)
Formats the failure message for HasTimerFiredAtLeast(minimum): the required minimum and
the actual cumulative fire count, followed by the still-active timers with their per-timer fire
counts (when any remain active). The liveness counterpart used when timing jitter makes an
exact fire count brittle.
public static string FormatTimerFireShortfall(long actual, int minimum, IReadOnlyList<ActiveTimerInfo> active)
Parameters
actuallongThe observed cumulative fire count.
minimumintThe minimum fire count that was required. Must be non-negative.
activeIReadOnlyList<ActiveTimerInfo>The timers still active when the assertion ran.
Returns
- string
A human-readable summary in InvariantCulture, with a grep-friendly
(minimum=N, actual=M)trailer on the headline.
Exceptions
- ArgumentNullException
activeis null.- ArgumentOutOfRangeException
minimumis negative.