aboutsummaryrefslogtreecommitdiffziptar.gz
path: root/docs/notes/test-gotchas.md
blob: 496f3236decae0fa205b51659e7cc3fdf12066ef (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# Test gotchas

Traps met while writing Core tests. Add one when a flaky or misleading test
cost real time.

## Allocation tests (`GC.GetAllocatedBytesForCurrentThread`)

- **The counter can jump by one allocation context (~8 KB)** under parallel
  test load — seen as `8200 B` where the same window normally reads `128 B`
  (2026-09-25, ~2 in 25 build+test runs). Not reproducible in isolation or
  with an in-test GC-pressure thread. A budget below ~8 KB must measure
  several windows and take the quietest (`AmbienceDirector_SteadyState…`);
  a real per-event allocation shows in every window.
- **`foreach` over an interface (`IReadOnlyList<T>`, `IEnumerable<T>`) boxes
  the enumerator** — 32–40 B per loop. Hot paths index instead
  (`CombatSystem.HitSphere`, `Overlaps`). `List<T>` / arrays typed concretely
  are fine.
- **Undrained buffers grow in doublings** in headless tests (`_sounds`,
  notices, damage events cap at a max but grow to it first): one-off spikes of
  0.5–1 KB mid-window are that, not a leak. Budget per tick over ≥ 1000 ticks
  or drain like the Desktop does.
- Tests run on Debug builds: Core code is never JIT-optimised there, so tiered
  compilation / escape analysis don't change what Core allocates.

## Timing tests (`Stopwatch`)

- A build server or parallel tests can steal the CPU for one measurement:
  take the best of several runs (`AudioSpeedTests.RealtimeFactor`). A real
  slowdown lowers all of them (checked with a `Thread.Sleep` mutant).