wren/val Public Public: anyone can read this; nobody can change it.

forked from benjivers/val

workbenchthis machine
Files 3c63a82833bc2b178340f47c85d7acc2a4952706
1
/**
2
 * How often the arena speaks.
3
 *
4
 * The simulation is 30Hz either way; what is decided here is how much of it
5
 * the browser is told about, which is the difference between a body drawn
6
 * from fifteen samples a second and one drawn from thirty.
7
 */
8
9
import { expect, test } from "bun:test";
10
import { mkdtempSync } from "node:fs";
11
import { tmpdir } from "node:os";
12
import { join } from "node:path";
13
14
process.env.FORGE_APP_DATA ??= mkdtempSync(join(tmpdir(), "app-"));
15
const { advance, attach, broadcastEvery, match, release, seatCount, snapshot } = await import("./arena.ts");
16
17
test("a small room hears every tick, a full one every other", () => {
18
  expect(broadcastEvery(0)).toBe(1);
19
  expect(broadcastEvery(1)).toBe(1);
20
  expect(broadcastEvery(2)).toBe(1);
21
  expect(broadcastEvery(3)).toBe(2);
22
  expect(broadcastEvery(10)).toBe(2);
23
});
24
25
/** A seat that only counts what it was sent. */
26
function listen(session: string) {
27
  const got: string[] = [];
28
  attach(session, match().players[0]!.id, `test-${session}`, session, (data) => got.push(data));
29
  return got;
30
}
31
32
// The arena is one match shared by the whole test run, and another file may
33
// be holding a seat of its own while this one runs; what is checked is that
34
// the loop broadcasts at exactly the cadence the room it is in asks for.
35
test("the loop sends at the cadence the seat count asks for", () => {
36
  const one = listen("rate-a");
37
  const two = listen("rate-b");
38
  const every = broadcastEvery(seatCount());
39
  advance(1);
40
  // Thirty ticks to the second, one snapshot every `every` of them.
41
  expect(one.length).toBe(30 / every);
42
  expect(two.length).toBe(one.length);
43
  release("rate-a", "rate-a");
44
  release("rate-b", "rate-b");
45
});
46
47
test("a full room halves the cadence rather than multiplying the traffic", () => {
48
  const seats = ["rate-c", "rate-d", "rate-e"].map(listen);
49
  expect(seatCount()).toBeGreaterThan(2);
50
  advance(1);
51
  for (const got of seats) expect(got.length).toBe(15);
52
  for (const session of ["rate-c", "rate-d", "rate-e"]) release(session, session);
53
});
54
55
test("a snapshot stays small enough to send thirty times a second", () => {
56
  // The trade is only worth making if the payload is small. Measured over a
57
  // live round it is 3.2-4.5 KiB a seat, mean 3.4 — a hundred KiB a second
58
  // at 30Hz, and at most two seats are sent that much. This is the number
59
  // the pull quotes, so it is checked here rather than assumed; the ceiling
60
  // is loose enough not to fail on a busy tick and tight enough that a
61
  // snapshot which doubled in size would say so.
62
  for (let i = 0; i < 40 && match().phase !== "live"; i++) advance(1);
63
  const bytes = Buffer.byteLength(snapshot(match().players[0]!.id));
64
  expect(bytes).toBeGreaterThan(200);
65
  expect(bytes).toBeLessThan(8000);
66
});
↑↓ navigate ↵ open esc close
↑↓ navigate ↵ open esc close

Keyboard shortcuts