@mark1russell7/harness 0.14.2 → 0.14.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/build/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
- import { $ as StageBand, A as PinnedImage, B as Replies, C as Jitter, D as MiddleboxExpectation, E as MiddleboxEvent, F as Reconnects, G as RunGroup, H as RouterHop, I as Recovers, J as SentinelEvent, K as RunPart, L as Reference, M as ProbeEvent, N as ProxyHop, O as MiddleboxForm, P as ProxyTime, Q as Stage, R as ReplicaSet, S as ImageSource, T as LineMatch, U as RttRange, V as RequestPrediction, W as Run, X as Shipped, Y as SentinelStage, Z as ShippedImage, _ as HopEvent, a as Cluster, at as isHopPlace, b as HopWrite, c as DriverBand, d as FaultPlace, et as Subject, f as Group, g as Hop, h as GroupRole, i as ClientImage, it as WsProbe, j as Prediction, k as Observer, l as DriverStep, m as GroupPrediction, n as Cell, nt as Topology, o as ClusterClientAt, ot as latestEndOf, p as GroupPlace, q as RunTopology, r as Client, rt as Toxic, s as ClusterStage, t as BuildImage, tt as Target, u as Fault, v as HopPlace, w as KernelRecord, x as HttpProbe, y as HopSignal, z as ReplicaSetStage } from "./cell-BccWKiXh.js";
1
+ import { $ as Replies, A as LineCount, B as Prediction, C as HopSignal, Ct as latestEndOf, D as Jitter, E as ImageSource, F as Observer, G as QueueConnection, H as ProxyHop, I as Outcomes, J as Reconnects, K as QueueEnd, L as Pair, M as MiddleboxEvent, N as MiddleboxExpectation, O as Kafka, P as MiddleboxForm, Q as ReplicaSetStage, R as PinnedImage, S as HopPlace, St as isHopPlace, T as HttpProbe, U as ProxyTime, V as ProbeEvent, W as QueueBand, X as Reference, Y as Recovers, Z as ReplicaSet, _ as GroupPlace, _t as Subject, a as Cluster, at as RunDrill, b as Hop, bt as Toxic, c as CountBand, ct as RunPart, d as DriverStep, dt as SentinelEvent, et as RequestPrediction, f as Fabric, ft as SentinelStage, g as Group, gt as StageBand, h as FaultPlace, ht as Stage, i as ClientImage, it as RunBackup, j as LineMatch, k as KernelRecord, l as Drill, lt as RunRoute, m as Fault, mt as ShippedImage, n as Cell, nt as RttRange, o as ClusterClientAt, ot as RunFabric, p as FabricManifest, pt as Shipped, q as QueuePrediction, r as Client, rt as Run, s as ClusterStage, st as RunGroup, t as BuildImage, tt as RouterHop, u as DriverBand, ut as RunTopology, v as GroupPrediction, vt as Target, w as HopWrite, x as HopEvent, xt as WsProbe, y as GroupRole, yt as Topology, z as PortsPrediction } from "./cell-DZm8zXN4.js";
2
2
  import { Quantity } from "@mark1russell7/quantity";
3
- import "testcontainers";
3
+ import { StartedTestContainer } from "testcontainers";
4
4
  //#region src/application.d.ts
5
5
  /**
6
6
  * This module reads the acts of the program of the observer: its heartbeat, its drop of the
@@ -204,6 +204,74 @@ export declare const referenceOf: (run: Run, from: Reference, role: string, data
204
204
  */
205
205
  export declare const measureDriver: (cell: Cell, run: Run) => Measured;
206
206
  //#endregion
207
+ //#region src/recovery.d.ts
208
+ /**
209
+ * This module holds the pure parts of a recovery drill. These are the scripts of the shell, the reader
210
+ * of the output of `bsondump`, and the set check of a recovery. It has no container, thus unit tests
211
+ * run it. `drill.ts` does the drill on a lab.
212
+ *
213
+ * A dump with `--oplog` reads the oplog from the start of the dump to its end. A slice reads the
214
+ * oplog after the last entry of the backup before it. Thus the backups together hold each write up
215
+ * to the last entry of the last backup, and no write after it. One writer sends the writes one at a
216
+ * time, thus the highest sequence number is also the latest write.
217
+ */
218
+ /** This size is one document of generated data. A tenant holds as many documents as its size needs. */
219
+ export declare const SEED_DOCUMENT = 65536;
220
+ /** This count is how far the lost writes can be from the writes after the last backup: the writes in flight at the fault. */
221
+ export declare const LOSS_MARGIN = 2;
222
+ /** This function gives the time of a drill from the start of the backups to the fault, in seconds. */
223
+ export declare const drillSpan: (drill: Drill) => number;
224
+ /**
225
+ * This script writes the generated data of each tenant into the collection `tenants`. Each write
226
+ * waits for `copies` members, thus each member holds the data when the script ends.
227
+ */
228
+ export declare const seedScript: (drill: Drill, copies: number) => string;
229
+ /** This script prints the hash of the collection `tenants`. It takes locks, thus a run reads it with no writer. */
230
+ export declare const HASH_SCRIPT: string;
231
+ /** This function gives the hash from the output of `HASH_SCRIPT`. */
232
+ export declare const hashOf: (text: string) => string;
233
+ /** This function gives the command of a server with no set, on its own port. A client of the set cannot reach that server, and a restore writes to it. */
234
+ export declare const standaloneCommand: (set: ReplicaSet, port: number) => string;
235
+ /**
236
+ * This script waits for the end of the server of a box, and it can stop the server first. `kill -0`
237
+ * also succeeds on a zombie, and the shell of the box can leave its child as a zombie for a long
238
+ * time. Thus the script reads the state of the process, and a zombie has ended.
239
+ */
240
+ export declare const stopScript: (terminate: boolean) => string;
241
+ /** An oplog time is the `ts` of an oplog entry: a time in seconds, and the count of the entry in that second. */
242
+ interface OplogTime {
243
+ readonly t: number;
244
+ readonly i: number;
245
+ }
246
+ /** An oplog read is what an oplog file holds: its last entry, and the highest sequence number that it inserts. */
247
+ interface OplogRead {
248
+ readonly last: OplogTime | null;
249
+ readonly highest: number | null;
250
+ }
251
+ /** This function reads an oplog file from the output of `bsondump`. Only an insert into `cells.w` is a write of a client. */
252
+ export declare const readOplog: (text: string) => OplogRead;
253
+ /** This function gives the highest sequence number of the file of the writes in a dump, from the output of `bsondump`, or null. */
254
+ export declare const highestHeld: (text: string) => number | null;
255
+ /** This function gives the query of a slice of the oplog: each entry after an oplog time, in Extended JSON. */
256
+ export declare const sliceQuery: (after: OplogTime) => string;
257
+ /** A recovery measurement is what a drill found, beside the writes of the run. */
258
+ interface RecoveryMeasured {
259
+ /** This time is from the reply to the last accepted write that the store kept to the fault, or null with no such write. */
260
+ readonly rpo: Quantity | null;
261
+ /** This time is `rpo` less the age of the drill: what a schedule adds to its interval. It is null for a control and for an election. */
262
+ readonly excess: Quantity | null;
263
+ /** These are the accepted writes that the store lost, below a write that it kept. A restore must leave none. */
264
+ readonly holes: readonly number[];
265
+ /** This count is the number of accepted writes after the last write of the last backup, or null without a backup. */
266
+ readonly afterBackup: number | null;
267
+ /** This flag tells if the tenants have the same data after the recovery, or null when that is not known. */
268
+ readonly sameData: boolean | null;
269
+ }
270
+ /** This function gives the measurement of a drill, from its run. `t0` is the fault. */
271
+ export declare const recoveryOf: (drill: Drill, run: Run, t0: number) => RecoveryMeasured;
272
+ /** This function gives the findings of a drill: each rule of a recovery that its run broke. */
273
+ export declare const recoveryFindings: (measured: RecoveryMeasured, writes: Writes) => string[];
274
+ //#endregion
207
275
  //#region src/timeline.d.ts
208
276
  /**
209
277
  * This module measures a run of a group cell. It gives the first write that a primary accepted
@@ -227,6 +295,9 @@ interface ErrorOnTheWay {
227
295
  * of a split brain. It is null when the group did not converge after the run.
228
296
  * - `unknown` are the writes that the client sent and did not see accepted: an error, or no answer.
229
297
  * `held` tells if the group kept each one, or null when it did not converge.
298
+ * - `duplicates` has one entry for each extra copy that the group holds: a write held three times
299
+ * has two entries. It is null when the group did not converge. A key holds one copy by
300
+ * construction, thus only a list can show a copy.
230
301
  */
231
302
  interface Writes {
232
303
  readonly sent: number;
@@ -237,6 +308,18 @@ interface Writes {
237
308
  readonly n: number;
238
309
  readonly held: boolean | null;
239
310
  }>;
311
+ readonly duplicates?: readonly number[] | null;
312
+ /** These are the counts of a pair (`Cell.pair`), from its two final reads. */
313
+ readonly sets?: PairSets;
314
+ }
315
+ /** These are the counts that the bands of `Outcomes` judge: each one has the same name there. */
316
+ interface PairSets {
317
+ readonly unknown: number;
318
+ readonly kept: number;
319
+ readonly stranded: number;
320
+ readonly absent: number;
321
+ readonly missing: number;
322
+ readonly warnings: number;
240
323
  }
241
324
  /** A group measurement is what one run of a group cell measured, beside its time. */
242
325
  interface GroupMeasured {
@@ -249,6 +332,8 @@ interface GroupMeasured {
249
332
  readonly errors: readonly ErrorOnTheWay[];
250
333
  /** These are the delays of the stamps of the observer after the writes of the Sentinels, for a calibration. */
251
334
  readonly lags?: readonly Quantity[];
335
+ /** This is what a recovery drill measured, for a drill only. */
336
+ readonly recovery?: RecoveryMeasured;
252
337
  }
253
338
  /** This function gives the time of each stage of a timeline from an instant: the first announcement of each, after the instant. */
254
339
  export declare const stagesOf: (timeline: readonly SentinelEvent[], from: number) => Partial<Record<Stage, Quantity>>;
@@ -336,6 +421,78 @@ interface GroupReading {
336
421
  */
337
422
  export declare const measureGroup: (cell: Cell, run: Run) => GroupReading;
338
423
  //#endregion
424
+ //#region src/ports.d.ts
425
+ /** This record is what a run of a port cell measured. */
426
+ interface PortsReading {
427
+ /** This count is the rounds of the run, each destination once. */
428
+ readonly rounds: number;
429
+ /** This record gives the count of searches for each count of connects, by that count. */
430
+ readonly counts: Readonly<Record<string, number>>;
431
+ /** These offsets from the low port are the ports that the run used, in rising order. */
432
+ readonly seen: readonly number[];
433
+ /** These errnos ended the searches of the run, each one time. */
434
+ readonly errnos: readonly string[];
435
+ /** This time is the longest connect that failed. */
436
+ readonly refusal: Quantity;
437
+ /** This time is from the `closing` line to the first `freed` line. */
438
+ readonly firstFreed: Quantity | null;
439
+ /** This time is from the `closing` line to the last `freed` line. */
440
+ readonly lastFreed: Quantity | null;
441
+ /** This count is the `freed` lines of the run. */
442
+ readonly freed: number;
443
+ /** This count is the connects that failed before the last `freed` line. */
444
+ readonly tries: number;
445
+ }
446
+ /**
447
+ * This function reads one run of a port cell. The `round` lines give each search. The `closing` and
448
+ * `freed` lines give when each held port comes back. The records of the prober give the
449
+ * retransmissions.
450
+ */
451
+ export declare const measurePorts: (run: Run, expected: PortsPrediction) => Measured;
452
+ //#endregion
453
+ //#region src/queue.d.ts
454
+ /** This record is what one connection of a queue cell did, from its lines and the records of its socket. */
455
+ interface QueueConnectionReading {
456
+ readonly name: string;
457
+ readonly connected: boolean;
458
+ /** These times are the waits of the SYN. The first one counts from the dial. */
459
+ readonly syns: readonly Quantity[];
460
+ /** These times are the waits of each SYN-ACK sent again. The first one counts from the dial. */
461
+ readonly synAcks: readonly Quantity[];
462
+ /** This count is the segments that the socket sent again. */
463
+ readonly retransmissions: number;
464
+ readonly errno: string | null;
465
+ /** This time is from the line of the prediction to the end of the connection. It is null for a live connection, or with no prediction. */
466
+ readonly ended: Quantity | null;
467
+ /** This time is from the last retransmission to the end of the connection. */
468
+ readonly afterLast: Quantity | null;
469
+ /** This count is the segments of the socket with no acknowledgment at the end of the run. */
470
+ readonly unacked: number | null;
471
+ }
472
+ /** This record is what a run of a queue cell measured. The counts are the changes in the run. */
473
+ interface QueueReading {
474
+ readonly max: number;
475
+ readonly held: number;
476
+ readonly connected: number;
477
+ readonly overflows: number;
478
+ readonly drops: number;
479
+ readonly cookies: number;
480
+ readonly timeouts: number;
481
+ readonly resets: number;
482
+ readonly drained: number;
483
+ /** This time is from the first dial of the burst to the last `TCPTimeouts` of the prediction. */
484
+ readonly expiry: Quantity | null;
485
+ /** This time is from the first dial of the burst to the rise of the count of the queue. */
486
+ readonly rise: Quantity | null;
487
+ readonly connections: readonly QueueConnectionReading[];
488
+ }
489
+ /**
490
+ * This function reads one run of a queue cell. The client lines give the connections and the
491
+ * counters at the two ends of the run. The target lines give the count of the queue. The records of
492
+ * the prober give the waits of each socket.
493
+ */
494
+ export declare const measureQueue: (run: Run, expected: QueuePrediction) => Measured;
495
+ //#endregion
339
496
  //#region src/verdict.d.ts
340
497
  /** This function gives the words of the outcome of a second request: its connection, a retry, and its end. */
341
498
  export declare const requestWords: (outcome: {
@@ -435,6 +592,8 @@ interface Verdict {
435
592
  readonly median: Quantity | null;
436
593
  /** This interval is the order-statistic interval of the median at 95 %, or the whole range for fewer than six runs. */
437
594
  readonly medianInterval: Interval | null;
595
+ /** This time is the slowest reply of a cell that measures a distribution. A closed loop hides the sends in a stall, thus a quantile is a lower bound, and this maximum is not. */
596
+ readonly slowest?: Quantity;
438
597
  /** This record is the sum of what reordering did in each counted run of a measurement-only cell. */
439
598
  readonly reordering?: Reordering;
440
599
  /** This record is the time of the proxy of a calibration cell, in each direction. */
@@ -505,6 +664,8 @@ interface StageVerdict {
505
664
  * - `unknown` counts the writes whose outcome the client did not see, and how many the group kept.
506
665
  * - `errors` are the errors on the way: the runs that met each, and the median of its first time.
507
666
  * - `lags` is the spread of the delays of the stamps, for a calibration.
667
+ * - `duplicates` counts the extra copies that the group holds, in each run. A cell with no band of
668
+ * copies has no such count.
508
669
  */
509
670
  interface GroupVerdict {
510
671
  readonly stages: readonly StageVerdict[];
@@ -529,6 +690,12 @@ interface GroupVerdict {
529
690
  readonly first: Quantity;
530
691
  }>;
531
692
  readonly lags?: Spread | null;
693
+ readonly duplicates?: {
694
+ readonly runs: number;
695
+ readonly total: number;
696
+ readonly median: number | null;
697
+ readonly max: number | null;
698
+ };
532
699
  }
533
700
  /**
534
701
  * This function gives the value at quantile p of sorted values, by nearest rank: x_(⌈p·n⌉). It is
@@ -640,6 +807,10 @@ interface Measured {
640
807
  readonly crossings?: Crossings;
641
808
  /** This record is what a run of a group cell measured: the stages of its timeline, and what became of each write. */
642
809
  readonly group?: GroupMeasured;
810
+ /** This record is what a run of a queue cell measured: the count of the queue, its counters, and each connection. */
811
+ readonly queue?: QueueReading;
812
+ /** This record is what a run of a port cell measured: the count of each search, and when each port came back. */
813
+ readonly ports?: PortsReading;
643
814
  /** This record is what the second request of an HTTP client met, for a cell whose prediction says it. */
644
815
  readonly request?: RequestReading | null;
645
816
  /** This record is the time of each later band of a driver cell (`DriverBand.then`). */
@@ -761,10 +932,293 @@ export declare const jitterOf: (cell: Cell, run: Run) => Jitter;
761
932
  */
762
933
  export declare const requestOf: (events: readonly ProbeEvent[]) => RequestReading | null;
763
934
  //#endregion
935
+ //#region src/fabric.d.ts
936
+ /**
937
+ * A fabric is a routed network between the client and the target, on layer E3 (docs/S7.md). Four
938
+ * routers of FRRouting, two leaves and two spines, run real BGP over veth pairs that containerlab
939
+ * makes. The client hangs off leaf1 and the target off leaf2. The path between them goes through
940
+ * spine1 by a weight, and spine2 holds the other path. A cell silences spine1, and the routes of
941
+ * the leaves move to spine2 when a detector of the routers fires.
942
+ *
943
+ * This file holds the plan of the fabric as pure functions, and `openFabric` that starts it. A lab
944
+ * opens a fabric with `Topology.fabric`. Thus the client, the target, the prober and the verdict
945
+ * stay the same as on layer E1. The fabric needs a Linux host with containerlab and sudo.
946
+ */
947
+ /** This image is FRRouting 10.7.1, pinned by digest. */
948
+ export declare const FRR_IMAGE = "quay.io/frrouting/frr:10.7.1@sha256:e995beaa50fdc9edb35eadcfefa29b7f062cc06f2b812613789b68fa541554d2";
949
+ /** This device is the side of the fabric in the client and in the target. Docker keeps eth0. */
950
+ export declare const FABRIC_DEVICE = "eth1";
951
+ /** This address is the client on its network behind leaf1. */
952
+ export declare const FABRIC_CLIENT = "10.1.0.2";
953
+ /** This address is the target on its network behind leaf2. */
954
+ export declare const FABRIC_TARGET = "10.2.0.2";
955
+ /** A router is one box of the fabric, as data. */
956
+ interface Router {
957
+ readonly name: string;
958
+ readonly as: number;
959
+ readonly id: string;
960
+ readonly interfaces: Readonly<Record<string, string>>;
961
+ readonly neighbors: ReadonlyArray<{
962
+ readonly address: string;
963
+ readonly as: number;
964
+ readonly weight?: number;
965
+ }>;
966
+ /** This prefix is the network behind a leaf, which its BGP advertises. */
967
+ readonly network?: string;
968
+ /** This prefix is the network behind the other leaf. A move is a change of its route. */
969
+ readonly remote?: string;
970
+ }
971
+ /** These are the routers. Each leaf prefers spine1 by a weight of 100, thus the path of each run is known. */
972
+ export declare const ROUTERS: readonly Router[];
973
+ /** This text is the `daemons` file of each router: BGP and BFD, on top of what FRRouting always starts. */
974
+ export declare const DAEMONS: string;
975
+ /**
976
+ * This function gives the configuration of a router. Graceful restart is off: after a hold expiry,
977
+ * a helper can keep the stale routes, and the move that a cell measures does not come.
978
+ * `maximum-paths 1` keeps one path, thus a move is one change of one route.
979
+ */
980
+ export declare const frrConf: (router: Router, fabric: Fabric) => string;
981
+ /**
982
+ * This function gives the topology file of containerlab. The client and the target are containers
983
+ * of the lab, and the fabric adds a device to each. Each link has the MTU of a Docker network, thus
984
+ * a segment is as long as on layer E1. The default of containerlab is 9500. The management network
985
+ * belongs to the lab, and Docker chooses its subnet.
986
+ */
987
+ export declare const topologyOf: (lab: string, dir: string, client: string, target: string) => string;
988
+ /** A route line is one line of `ip -ts -o monitor route`, with its time on the wall clock in ms. */
989
+ interface RouteLine {
990
+ readonly wall: number;
991
+ readonly deleted: boolean;
992
+ readonly prefix: string;
993
+ readonly via: string | null;
994
+ readonly dev: string | null;
995
+ }
996
+ /** This function reads a line of `ip -ts -o monitor route`, or it gives null for another line. The clock of a container is UTC. */
997
+ export declare const routeLine: (text: string) => RouteLine | null;
998
+ /** A clock pair is one instant on the monotonic clock in ns and on the wall clock in ms. */
999
+ interface ClockPair {
1000
+ readonly mono: number;
1001
+ readonly wall: number;
1002
+ }
1003
+ /**
1004
+ * This function takes a time on the wall clock to the monotonic clock. The harness runs on the host
1005
+ * of the containers, thus `process.hrtime` reads the CLOCK_MONOTONIC of the injector and the
1006
+ * prober. The error of the pair is approximately 1 ms, the step of `Date.now`.
1007
+ */
1008
+ export declare const monotonicAt: (wall: number, pair: ClockPair) => number;
1009
+ /** This function gives the state of the BGP sessions from `show bgp neighbors json`. */
1010
+ export declare const sessionsOf: (json: string) => {
1011
+ readonly up: number;
1012
+ readonly established: number;
1013
+ };
1014
+ /** These are the views of a leaf that tell if a run can start on it. */
1015
+ interface LeafViews {
1016
+ readonly neighbors: string;
1017
+ /** This text is the kernel's route to the far network, from `ip -o route show`. */
1018
+ readonly route: string;
1019
+ /** This text is `show bgp ipv4 unicast PREFIX json`. */
1020
+ readonly paths: string;
1021
+ /** This text is `show bfd peers json`, or null when the fabric has no BFD. */
1022
+ readonly bfd: string | null;
1023
+ }
1024
+ /**
1025
+ * This function tells what a leaf still lacks before a run, or it gives null. The two sessions must
1026
+ * be up and the route must be on spine1. Spine2 must hold the other path. Without these, the fault
1027
+ * of a run acts on another path, or nothing can take over.
1028
+ */
1029
+ export declare const leafLacks: (views: LeafViews) => string | null;
1030
+ /**
1031
+ * This function gives the later move of the leaves after an instant: for each leaf, the first route
1032
+ * to its far network that leaves spine1. It gives null when a leaf has no move. The later move ends
1033
+ * the outage in the two directions.
1034
+ */
1035
+ export declare const laterMove: (routes: readonly RunRoute[], after: number) => number | null;
1036
+ /** A fabric lab is the open fabric of a lab. */
1037
+ interface FabricLab {
1038
+ /** These are the lines of the route monitors of the leaves, on the monotonic clock. */
1039
+ readonly routes: readonly RunRoute[];
1040
+ /** This method drops each packet of spine1 in one commit, and the links stay up. */
1041
+ silence(): Promise<{
1042
+ t0: number;
1043
+ t1: number;
1044
+ }>;
1045
+ /** This method ends a silence. */
1046
+ clear(): Promise<{
1047
+ t0: number;
1048
+ t1: number;
1049
+ }>;
1050
+ /** This method waits until each leaf is on spine1 with each session up. */
1051
+ ready(): Promise<void>;
1052
+ /** This method gives the count of established sessions of each leaf so far. */
1053
+ sessions(): Promise<Readonly<Record<string, number>>>;
1054
+ /** This method gives the record of the fabric for a manifest. */
1055
+ manifest(): FabricManifest;
1056
+ /** This method destroys the routers. */
1057
+ close(): Promise<void>;
1058
+ }
1059
+ /** These are the parts of a lab that a fabric uses. */
1060
+ interface FabricParts {
1061
+ readonly fabric: Fabric;
1062
+ readonly image: string;
1063
+ readonly client: StartedTestContainer;
1064
+ readonly server: StartedTestContainer;
1065
+ readonly admin: StartedTestContainer;
1066
+ readonly injector: StartedTestContainer;
1067
+ readonly opened: StartedTestContainer[];
1068
+ readonly output: (container: StartedTestContainer, argv: string[]) => Promise<string>;
1069
+ }
1070
+ /**
1071
+ * This function deploys the routers of a lab and joins the client and the target to them. It also
1072
+ * starts the sidecars: the injector of spine1 and a route monitor on each leaf. The caller stops the
1073
+ * sidecars with the other containers of the lab, and it calls `close` first.
1074
+ */
1075
+ export declare const openFabric: (parts: FabricParts) => Promise<FabricLab>;
1076
+ //#endregion
1077
+ //#region src/image.d.ts
1078
+ /** These are the names of the images that the harness ships. */
1079
+ export declare const SHIPPED_NAMES: readonly [Shipped, ...Shipped[]];
1080
+ /** This function gives the source of a shipped image. */
1081
+ export declare const shippedSource: (name: Shipped) => ImageSource;
1082
+ /** This function gives the version of the package of the harness, from its package.json. */
1083
+ export declare const harnessVersion: () => string;
1084
+ /**
1085
+ * These are the clients that the harness ships, by their names (`Client`): the image of each, and
1086
+ * its command. A cell that names a client gets this image and this command.
1087
+ */
1088
+ export declare const SHIPPED_CLIENTS: Readonly<Record<Client, ClientImage>>;
1089
+ /** These are the names of the clients that the harness ships. */
1090
+ export declare const CLIENT_NAMES: readonly [Client, ...Client[]];
1091
+ /** This function gives the command of a program of a subject by its role. It fails when the subject has no such program. */
1092
+ export declare const programOf: (subject: Subject, role: string) => readonly string[];
1093
+ /**
1094
+ * This function gives the client of a subject for a cell (`Cell.client`): the image of the subject,
1095
+ * with the command of a program. A client that the harness ships goes by its name, thus its records
1096
+ * stay the same.
1097
+ */
1098
+ export declare const subjectClient: (subject: Subject, role?: string) => Client | ClientImage;
1099
+ /** This pattern matches an image pinned by digest: a name, a tag or none, then `@sha256:` and 64 hex digits. */
1100
+ export declare const PINNED: RegExp;
1101
+ /** This pattern matches the repository of a tag that the harness builds. Its parts are lower case, with `/` between them. */
1102
+ export declare const REPOSITORY: RegExp;
1103
+ /** This function tells if a path stays in its context: relative, with `/` between its parts, and no `..`. */
1104
+ export declare const inContext: (path: string) => boolean;
1105
+ /**
1106
+ * This function gives the problems of the source of an image, as data. A pinned image names a
1107
+ * digest. A build names a repository, a context, and paths that stay in the context. A shipped image
1108
+ * is one that the harness ships.
1109
+ */
1110
+ export declare const imageProblems: (source: ImageSource) => string[];
1111
+ /**
1112
+ * This function gives the problems of a subject, as data. A subject has a name and a base that a
1113
+ * digest pins. Its image source has no problems, and each of its programs is a command.
1114
+ */
1115
+ export declare const subjectProblems: (subject: Subject) => string[];
1116
+ /**
1117
+ * This function gives each `FROM` of a Dockerfile that no digest pins. A `FROM` of an earlier stage
1118
+ * by its name, or of `scratch`, needs no digest. A base from an `ARG` has no digest that the harness
1119
+ * can read, thus it is in the list too.
1120
+ */
1121
+ export declare const unpinnedBases: (dockerfile: string) => string[];
1122
+ /**
1123
+ * This function gives each base of a Dockerfile, in the sequence of the file. A base is the image of
1124
+ * a `FROM` that is not `scratch` or an earlier stage by its name.
1125
+ */
1126
+ export declare const basesOf: (dockerfile: string) => string[];
1127
+ /**
1128
+ * This function gives each manifest of packages in a context (`package.json`, `Cargo.toml`) that
1129
+ * has no lockfile in its folder or in a folder above it. The paths are the paths in the context.
1130
+ */
1131
+ export declare const unlockedManifests: (paths: readonly string[]) => string[];
1132
+ /**
1133
+ * An image plan tells how the harness gets the image of a source. It is a pull of an image by its
1134
+ * name, or a build of a context. A build has its tag, its Dockerfile, and each file with its path.
1135
+ */
1136
+ type ImagePlan = {
1137
+ readonly kind: "pull";
1138
+ readonly image: string;
1139
+ } | {
1140
+ readonly kind: "build";
1141
+ readonly tag: string;
1142
+ readonly dockerfile: string;
1143
+ readonly files: ReadonlyArray<{
1144
+ readonly file: string;
1145
+ readonly at: string;
1146
+ }>;
1147
+ /** This record tells what the image holds, for the manifest of a run. */
1148
+ readonly record: BuildRecord;
1149
+ };
1150
+ /**
1151
+ * A build record tells what an image that the harness builds holds, for the manifest of a run. The
1152
+ * tag is a sha256 of each file of the context. The bases are pinned by digest, and each lockfile
1153
+ * has its sha256. Thus the record pins each program of the image. The versions are the part that a
1154
+ * person reads.
1155
+ */
1156
+ interface BuildRecord {
1157
+ readonly tag: string;
1158
+ /** These are the bases of its Dockerfile, each pinned by digest (`basesOf`). */
1159
+ readonly bases: readonly string[];
1160
+ /** These are the lockfiles of its context by their path, each with the sha256 of its content (`locksOf`). */
1161
+ readonly locks: Readonly<Record<string, string>>;
1162
+ /** These are the versions of the packages that its manifests name directly, by their names (`versionsOf`). */
1163
+ readonly versions: Readonly<Record<string, string>>;
1164
+ }
1165
+ /**
1166
+ * This function gives the plan of the image of a source. A stock image by its name, or a pinned
1167
+ * image, is a pull. A build or a shipped image is a build. Its tag is its name, then 12 digits of a
1168
+ * sha256. The sha256 reads the path of the Dockerfile, and the path and the content of each file.
1169
+ * Thus a changed program cannot operate as an old one.
1170
+ *
1171
+ * A build fails before it starts on a problem of its source. It also fails on a `FROM` that no
1172
+ * digest pins, and on a manifest of packages without a lockfile.
1173
+ */
1174
+ export declare const planOf: (source: string | ImageSource) => ImagePlan;
1175
+ /**
1176
+ * This function gives an image that a lab can start, from its source. It is the name of a stock
1177
+ * image or of a pinned image, which the lab pulls, or the tag of a build. A build goes through the CLI
1178
+ * of Docker.
1179
+ */
1180
+ export declare const imageOf: (source: string | ImageSource) => Promise<string>;
1181
+ /**
1182
+ * This function gives the build record of the image of a source, for the manifest of a run. A
1183
+ * stock image by its name, or a pinned image, is a pull, and it has no build record.
1184
+ */
1185
+ export declare const buildRecordOf: (source: string | ImageSource) => BuildRecord | undefined;
1186
+ /** This function gives the image of the harness: the prober, the TCP client, the injector and the namespace admin. */
1187
+ export declare const harnessImage: () => Promise<string>;
1188
+ /** This function gives the image of the Node client. */
1189
+ export declare const nodeClientImage: () => Promise<string>;
1190
+ /** This function gives the image of the router. */
1191
+ export declare const routerImage: () => Promise<string>;
1192
+ /** This function gives the image of the Go HTTP client. */
1193
+ export declare const goHttpImage: () => Promise<string>;
1194
+ /** This function gives the image of the Node HTTP clients. */
1195
+ export declare const nodeHttpImage: () => Promise<string>;
1196
+ /** This function gives the image of the MongoDB client. */
1197
+ export declare const mongoClientImage: () => Promise<string>;
1198
+ /** This function gives the image of the PostgreSQL client. */
1199
+ export declare const pgClientImage: () => Promise<string>;
1200
+ /** This function gives the image of the client of HikariCP over pgjdbc. */
1201
+ export declare const hikariClientImage: () => Promise<string>;
1202
+ /** This function gives the image of the RabbitMQ client: amqplib, with the client and the admin of a cluster cell. */
1203
+ export declare const amqpClientImage: () => Promise<string>;
1204
+ /** This function gives the image of the Kafka client: kafka-clients on Java, with the client and the admin of a Kafka cell. */
1205
+ export declare const kafkaClientImage: () => Promise<string>;
1206
+ /** This function gives the image of the gRPC client of the harness: grpc-js 1.14.6 on Node 24.21.0, with its client. */
1207
+ export declare const grpcClientImage: () => Promise<string>;
1208
+ /**
1209
+ * This function gives the source of the image that a target operates. It is the image of its
1210
+ * subject (`Target.subject`), or its stock image.
1211
+ */
1212
+ export declare const targetSourceOf: (target: Target) => string | ImageSource;
1213
+ /** This function gives the image that a target operates: the image of its subject, or its stock image. */
1214
+ export declare const targetImageOf: (target: Target) => Promise<string>;
1215
+ //#endregion
764
1216
  //#region src/substrate.d.ts
765
1217
  /**
766
1218
  * A layer is a rung of the laboratory (`docs/S7.md`). E1 is containers on one kernel, and E2 is a
767
- * cluster of containers on one kernel. The other layers do not have a runner at this time.
1219
+ * cluster of containers on one kernel. A lab with `Topology.fabric` writes E3: routers in containers.
1220
+ * A lab in a guest of QEMU writes E4 (`substrateHere`). The other layers do not have a runner at this
1221
+ * time.
768
1222
  */
769
1223
  type Layer = "E0" | "E1" | "E2" | "E3" | "E4" | "E5" | "E6";
770
1224
  /** A cloud is where the runner operates. GitHub can schedule a standard Linux job on Azure or on AWS. */
@@ -804,6 +1258,27 @@ export declare const cloudOf: (vendor: string | null) => Cloud;
804
1258
  export declare const readHost: (root?: string, env?: Readonly<Record<string, string | undefined>>, kernel?: string) => Host;
805
1259
  /** This function gives the substrate of a layer on a host. */
806
1260
  export declare const substrateOn: (layer: Layer, host?: Host) => Substrate;
1261
+ /**
1262
+ * This function gives the substrate of a lab at this place. A guest cannot read its own runner: its
1263
+ * DMI vendor is QEMU, and `ImageOS` is not set. Thus the runner writes its host to `LAB_RUNNER`, and
1264
+ * the guest keeps only its own kernel and HZ. A value of that variable makes the layer E4.
1265
+ */
1266
+ export declare const substrateHere: (layer: Layer, host?: Host, env?: Readonly<Record<string, string | undefined>>) => Substrate;
1267
+ /** A CPU reading is two counters of `/proc/stat`, in ticks of the clock. */
1268
+ interface CpuTime {
1269
+ /** This count is the time that the host gave to another guest while this one had work. */
1270
+ readonly steal: number;
1271
+ /** This count is the sum of all states of each CPU. */
1272
+ readonly total: number;
1273
+ }
1274
+ /** This function reads the CPU time of this machine, or gives null without `/proc/stat`. `root` is for tests. */
1275
+ export declare const readCpu: (root?: string) => CpuTime | null;
1276
+ /**
1277
+ * This function gives the share of the CPU time between two readings that the host took. The share
1278
+ * goes from zero to one. It is null if no tick passed. A guest sees only the host above it. On a hosted
1279
+ * runner that host is itself a guest, and this number does not show the contention of the layer below it.
1280
+ */
1281
+ export declare const stealShare: (before: CpuTime, after: CpuTime) => number | null;
807
1282
  /** A part of a record that can hold a substrate: a manifest of the harness, or the fields of a kind manifest. */
808
1283
  interface SubstrateSource {
809
1284
  readonly substrate?: Substrate;
@@ -865,6 +1340,8 @@ interface FaultOptions {
865
1340
  readonly code?: "host" | "net" | "port" | "admin";
866
1341
  /** This length is the longest segment in bytes that an MTU drop lets through. */
867
1342
  readonly above?: number;
1343
+ /** These are the addresses that the rule faces, in place of the peer of its place. */
1344
+ readonly peers?: readonly string[];
868
1345
  }
869
1346
  /**
870
1347
  * A fault side is the namespace that gets the rules of a fault: the namespace of the peer of the
@@ -901,6 +1378,8 @@ interface Manifest {
901
1378
  readonly docker: string;
902
1379
  /** This block tells the layer, the cloud and the kernel of the record. A record from before it reads through `substrateOf`. */
903
1380
  readonly substrate?: Substrate;
1381
+ /** This record is the fabric of a cell with `Topology.fabric`. */
1382
+ readonly fabric?: FabricManifest;
904
1383
  /** This record is the target, and its settings as it read them back. */
905
1384
  readonly target: {
906
1385
  readonly image: string;
@@ -915,11 +1394,20 @@ interface Manifest {
915
1394
  readonly files?: Readonly<Record<string, string>>;
916
1395
  /** This line is the first line of a target that writes them: a server that tells its settings as it reads them. */
917
1396
  readonly first?: ProbeEvent;
1397
+ /** This record tells what the image of a target holds when the harness builds it: the image of a subject (`buildRecordOf`). */
1398
+ readonly build?: BuildRecord;
918
1399
  };
1400
+ /**
1401
+ * This record is the harness: its image, the id of that image and its Alpine packages. It also
1402
+ * has the version of the package of the harness, and the build of its image. The record of a
1403
+ * cell gives the commit of the code that operated.
1404
+ */
919
1405
  readonly harness: {
920
1406
  readonly image: string;
921
1407
  readonly id: string;
922
1408
  readonly packages: string[];
1409
+ readonly version?: string;
1410
+ readonly build?: BuildRecord;
923
1411
  };
924
1412
  /**
925
1413
  * This record is the client of each run: the TCP client of the harness, a driver, or an image that
@@ -929,6 +1417,7 @@ interface Manifest {
929
1417
  readonly kind: Client | "image";
930
1418
  readonly image: string;
931
1419
  readonly source?: ImageSource;
1420
+ readonly build?: BuildRecord;
932
1421
  };
933
1422
  /** These are the namespaces that the prober watched, by inode. */
934
1423
  readonly netns: {
@@ -994,8 +1483,17 @@ interface Agent {
994
1483
  exec(argv: readonly string[]): Promise<string>;
995
1484
  stop(): Promise<void>;
996
1485
  }
1486
+ /** A sibling is a server that a lab starts on the network of the target, for example a standby. */
1487
+ interface Sibling {
1488
+ readonly ip: string;
1489
+ readonly netns: number;
1490
+ /** This method starts a command in the sibling, and gives its standard output. */
1491
+ exec(argv: readonly string[]): Promise<string>;
1492
+ }
997
1493
  /** A lab is one environment: the target, the client, the hops of a topology, the injectors and the prober. */
998
1494
  interface Lab {
1495
+ /** This address is the address of the target on its own network. */
1496
+ readonly serverIp: string;
999
1497
  /** This address is the address that the client connects to: the target, or the first proxy of a topology. */
1000
1498
  readonly targetIp: string;
1001
1499
  /** This port is the port that the client connects to. */
@@ -1026,6 +1524,10 @@ interface Lab {
1026
1524
  agent(image: string, command: readonly string[], options?: {
1027
1525
  readonly pid?: boolean;
1028
1526
  }): Promise<Agent>;
1527
+ /** This method starts a sibling, and waits for a line of its log. */
1528
+ sibling(image: string, command: readonly string[], ready: string): Promise<Sibling>;
1529
+ /** This method starts a command in the target, and gives its standard output. */
1530
+ exec(argv: readonly string[]): Promise<string>;
1029
1531
  /** These are all the records that the prober wrote, in sequence. */
1030
1532
  readonly kernel: readonly KernelRecord[];
1031
1533
  /** This method sets the sysctls of the client namespace through its privileged sidecar, and reads them back. */
@@ -1086,6 +1588,8 @@ interface Lab {
1086
1588
  * independent of the run before it.
1087
1589
  */
1088
1590
  forget(): Promise<void>;
1591
+ /** This part is the routed fabric of a lab with `Topology.fabric`. */
1592
+ readonly fabric?: FabricLab;
1089
1593
  /** This method freezes the target with the cgroup freezer: its process stops, and its kernel continues to answer. */
1090
1594
  freeze(): Promise<void>;
1091
1595
  thaw(): Promise<void>;
@@ -1152,6 +1656,20 @@ export declare const hzOf: (first: {
1152
1656
  now: number;
1153
1657
  jiffies: number;
1154
1658
  }) => string | null;
1659
+ /** This function gives the build record of a source as a part of a manifest: `{ build }`, or nothing for an image that the harness pulls. */
1660
+ export declare const buildOf: (source: Parameters<typeof buildRecordOf>[0]) => {
1661
+ readonly build?: BuildRecord;
1662
+ };
1663
+ /** This function gives the version of the harness and the build of its image, as a part of the harness record of a manifest. */
1664
+ export declare const harnessRecord: () => {
1665
+ readonly version: string;
1666
+ readonly build?: BuildRecord;
1667
+ };
1668
+ /**
1669
+ * This function gives the record of the client of a run that the harness ships, for a manifest:
1670
+ * its kind, its image, and its build.
1671
+ */
1672
+ export declare const shippedClientRecord: (kind: Client, image: string) => Manifest["client"];
1155
1673
  /** This function gives the device of a route from its line in `ip -o route get`: "10.0.0.2 dev eth0 src …". */
1156
1674
  export declare const deviceOf: (route: string) => string;
1157
1675
  /**
@@ -1176,111 +1694,108 @@ export declare const deviceOf: (route: string) => string;
1176
1694
  */
1177
1695
  export declare const openLab: (target: Target, kind?: Client | ClientImage, topology?: Topology) => Promise<Lab>;
1178
1696
  //#endregion
1179
- //#region src/image.d.ts
1180
- /** These are the names of the images that the harness ships. */
1181
- export declare const SHIPPED_NAMES: readonly [Shipped, ...Shipped[]];
1182
- /**
1183
- * These are the clients that the harness ships, by their names (`Client`): the image of each, and
1184
- * its command. A cell that names a client gets this image and this command.
1185
- */
1186
- export declare const SHIPPED_CLIENTS: Readonly<Record<Client, ClientImage>>;
1187
- /** These are the names of the clients that the harness ships. */
1188
- export declare const CLIENT_NAMES: readonly [Client, ...Client[]];
1189
- /** This function gives the command of a program of a subject by its role. It fails when the subject has no such program. */
1190
- export declare const programOf: (subject: Subject, role: string) => readonly string[];
1191
- /**
1192
- * This function gives the client of a subject for a cell (`Cell.client`): the image of the subject,
1193
- * with the command of a program. A client that the harness ships goes by its name, thus its records
1194
- * stay the same.
1195
- */
1196
- export declare const subjectClient: (subject: Subject, role?: string) => Client | ClientImage;
1197
- /** This pattern matches an image pinned by digest: a name, a tag or none, then `@sha256:` and 64 hex digits. */
1198
- export declare const PINNED: RegExp;
1199
- /** This pattern matches the repository of a tag that the harness builds. Its parts are lower case, with `/` between them. */
1200
- export declare const REPOSITORY: RegExp;
1201
- /** This function tells if a path stays in its context: relative, with `/` between its parts, and no `..`. */
1202
- export declare const inContext: (path: string) => boolean;
1203
- /**
1204
- * This function gives the problems of the source of an image, as data. A pinned image names a
1205
- * digest. A build names a repository, a context, and paths that stay in the context. A shipped image
1206
- * is one that the harness ships.
1207
- */
1208
- export declare const imageProblems: (source: ImageSource) => string[];
1209
- /**
1210
- * This function gives the problems of a subject, as data. A subject has a name and a base that a
1211
- * digest pins. Its image source has no problems, and each of its programs is a command.
1212
- */
1213
- export declare const subjectProblems: (subject: Subject) => string[];
1214
- /**
1215
- * This function gives each `FROM` of a Dockerfile that no digest pins. A `FROM` of an earlier stage
1216
- * by its name, or of `scratch`, needs no digest. A base from an `ARG` has no digest that the harness
1217
- * can read, thus it is in the list too.
1218
- */
1219
- export declare const unpinnedBases: (dockerfile: string) => string[];
1220
- /**
1221
- * This function gives each manifest of packages in a context (`package.json`, `Cargo.toml`) that
1222
- * has no lockfile in its folder or in a folder above it. The paths are the paths in the context.
1223
- */
1224
- export declare const unlockedManifests: (paths: readonly string[]) => string[];
1697
+ //#region src/standby.d.ts
1698
+ /** This text is the line of the log of a standby that serves reads (src/backend/postmaster/postmaster.c:3740). */
1699
+ export declare const STANDBY_READY: string;
1700
+ /** This text is the write of the client, with its sequence number. */
1701
+ export declare const INSERT: string;
1702
+ /** This function gives the command of a standby: a base backup of the primary, then the server in recovery. */
1703
+ export declare const standbyCommand: (primary: string) => string[];
1704
+ /** This command starts the old primary again, after the stop of each of its processes. Its crash recovery runs before the wait ends. */
1705
+ export declare const RESTART: readonly string[];
1706
+ /** This function reads the output of a query for sequence numbers into a sorted list. */
1707
+ export declare const numbersOf: (text: string) => number[];
1708
+ /** This function gives the arguments of the client of a run. */
1709
+ export declare const pairArgs: (cell: Cell, lab: Pick<Lab, "targetIp" | "targetPort">) => string[];
1710
+ /** This function gives the instants of the cancels of a hold, in ns from the fault: equal parts of the hold. */
1711
+ export declare const cancelsOf: (pair: Pair, holdNs: number) => number[];
1712
+ /**
1713
+ * This function opens the pair of an environment. The table comes first and the standby next: the
1714
+ * base backup has it. A synchronous standby is named last, thus no setup step waits for it.
1715
+ */
1716
+ export declare const openStandby: (lab: Lab, cell: Cell) => Promise<Sibling>;
1717
+ /**
1718
+ * This function does one run of a pair. A dry run writes and stops, with no fault: the warm-up of the
1719
+ * environment. It removes its rows, thus the numbers of the run start on an empty table.
1720
+ */
1721
+ export declare const pairOnce: (lab: Lab, standby: Sibling, cell: Cell, environment: number, index: number, dry?: boolean) => Promise<Run>;
1722
+ //#endregion
1723
+ //#region src/locks.d.ts
1225
1724
  /**
1226
- * An image plan tells how the harness gets the image of a source. It is a pull of an image by its
1227
- * name, or a build of a context. A build has its tag, its Dockerfile, and each file with its path.
1725
+ * This module reads the lockfiles of a build context for the manifest of a run. A lockfile pins each
1726
+ * package that a build installs, thus its sha256 pins the packages that the image holds. The
1727
+ * versions of the packages that each manifest names directly are the part that a person reads.
1228
1728
  */
1229
- type ImagePlan = {
1230
- readonly kind: "pull";
1231
- readonly image: string;
1232
- } | {
1233
- readonly kind: "build";
1234
- readonly tag: string;
1235
- readonly dockerfile: string;
1236
- readonly files: ReadonlyArray<{
1237
- readonly file: string;
1238
- readonly at: string;
1239
- }>;
1240
- };
1241
- /**
1242
- * This function gives the plan of the image of a source. A stock image by its name, or a pinned
1243
- * image, is a pull. A build or a shipped image is a build. Its tag is its name, then 12 digits of a
1244
- * sha256. The sha256 reads the path of the Dockerfile, and the path and the content of each file.
1245
- * Thus a changed program cannot operate as an old one.
1246
- *
1247
- * A build fails before it starts on a problem of its source. It also fails on a `FROM` that no
1248
- * digest pins, and on a manifest of packages without a lockfile.
1249
- */
1250
- export declare const planOf: (source: string | ImageSource) => ImagePlan;
1729
+ /** A context file is a file of a build context: its path in the context, and its content. */
1730
+ interface ContextFile {
1731
+ readonly at: string;
1732
+ readonly content: Buffer | string;
1733
+ }
1251
1734
  /**
1252
- * This function gives an image that a lab can start, from its source. It is the name of a stock
1253
- * image or of a pinned image, which the lab pulls, or the tag of a build. A build goes through the CLI
1254
- * of Docker.
1255
- */
1256
- export declare const imageOf: (source: string | ImageSource) => Promise<string>;
1257
- /** This function gives the image of the harness: the prober, the TCP client, the injector and the namespace admin. */
1258
- export declare const harnessImage: () => Promise<string>;
1259
- /** This function gives the image of the Node client. */
1260
- export declare const nodeClientImage: () => Promise<string>;
1261
- /** This function gives the image of the router. */
1262
- export declare const routerImage: () => Promise<string>;
1263
- /** This function gives the image of the Go HTTP client. */
1264
- export declare const goHttpImage: () => Promise<string>;
1265
- /** This function gives the image of the Node HTTP clients. */
1266
- export declare const nodeHttpImage: () => Promise<string>;
1267
- /** This function gives the image of the MongoDB client. */
1268
- export declare const mongoClientImage: () => Promise<string>;
1269
- /** This function gives the image of the PostgreSQL client. */
1270
- export declare const pgClientImage: () => Promise<string>;
1271
- /** This function gives the image of the client of HikariCP over pgjdbc. */
1272
- export declare const hikariClientImage: () => Promise<string>;
1273
- /** This function gives the image of the RabbitMQ client: amqplib, with the client and the admin of a cluster cell. */
1274
- export declare const amqpClientImage: () => Promise<string>;
1275
- /** This function gives the image of the gRPC client of the harness: grpc-js 1.14.6 on Node 24.21.0, with its client. */
1276
- export declare const grpcClientImage: () => Promise<string>;
1735
+ * These are the names of the lockfiles that the harness records. A `go.mod` is the lockfile of a Go
1736
+ * module, because its `require` lines give exact versions. For them, Go selects the same packages
1737
+ * each time, and its checksum database examines each package.
1738
+ */
1739
+ export declare const LOCK_NAMES: ReadonlySet<string>;
1740
+ /** This function gives each lockfile of a context by its path, with the sha256 of its content in hex. */
1741
+ export declare const locksOf: (files: readonly ContextFile[]) => Record<string, string>;
1742
+ /** This function gives the version of each direct dependency of an npm lockfile (lockfileVersion 2 or 3). */
1743
+ export declare const npmVersions: (lock: string) => Record<string, string>;
1744
+ /**
1745
+ * This function gives the version of each direct dependency of the root package of a Cargo.lock: the
1746
+ * package that the Cargo.toml beside it names. An entry of a dependency list is a name, or a name
1747
+ * and a version when the lock holds two versions of that name.
1748
+ */
1749
+ export declare const cargoVersions: (lock: string, manifest: string) => Record<string, string>;
1750
+ /** This function gives the version of each direct requirement of a go.mod. A requirement that is `// indirect` is not direct. */
1751
+ export declare const goVersions: (mod: string) => Record<string, string>;
1752
+ /** This function gives the version of each jar of a list of jars by their SHA-256: `<hex> HikariCP-7.1.0.jar` gives HikariCP 7.1.0. */
1753
+ export declare const jarVersions: (list: string) => Record<string, string>;
1754
+ /**
1755
+ * This function gives the version of each package that the manifests of a context name directly,
1756
+ * by its name. It reads each npm lockfile, Cargo.lock, go.mod and list of jars. A package of a
1757
+ * workspace in the context is a package of the image too, with the version of its package.json.
1758
+ * Such a package has a name and a version, and it is not private. The record has the sha256 of
1759
+ * the lockfile of a pnpm, yarn or bun workspace (`locksOf`). This function does not read versions
1760
+ * from such a lockfile.
1761
+ */
1762
+ export declare const versionsOf: (files: readonly ContextFile[]) => Record<string, string>;
1763
+ //#endregion
1764
+ //#region src/pins.d.ts
1765
+ /**
1766
+ * This function gives each problem of a manifest that stops it from pinning the programs of its
1767
+ * run. An empty list means that the manifest pins each program.
1768
+ * - the target: an image by its digest, or the build of a subject with its build record and its base
1769
+ * by digest.
1770
+ * - the harness: the version of its package, and the build record of its image.
1771
+ * - the client: an image by its digest, or a build with its build record.
1772
+ * - each hop: an image by its digest, or the tag of a build and the id of its image.
1773
+ */
1774
+ export declare const manifestProblems: (manifest: Manifest) => string[];
1775
+ /** This function gives the problem of the commit of a record: no commit, or a text that is not a commit of git. */
1776
+ export declare const commitProblems: (commit: string | undefined) => string[];
1777
+ /** The code of a record is the commit of the checkout that operated, and if its tracked files had changes. */
1778
+ interface RecordCode {
1779
+ readonly commit: string;
1780
+ readonly dirty: boolean;
1781
+ }
1782
+ /** These are the parts of a record that tell if it pins the programs of its runs. */
1783
+ interface Pinnable {
1784
+ readonly code?: RecordCode | undefined;
1785
+ readonly manifests: readonly Manifest[];
1786
+ /** A local debug run marks its record so. No page reads such a record. */
1787
+ readonly debug?: boolean | undefined;
1788
+ }
1789
+ /** This problem is the problem of a checkout with changes: its commit does not hold the code that operated. */
1790
+ export declare const DIRTY = "the checkout has changes to tracked files that no commit holds";
1791
+ /** This problem is the problem of a record of a local debug run. */
1792
+ export declare const DEBUG = "the record is of a local debug run, and no page reads it";
1277
1793
  /**
1278
- * This function gives the source of the image that a target operates. It is the image of its
1279
- * subject (`Target.subject`), or its stock image.
1794
+ * This function gives each problem that stops a record from pinning the programs of its runs. A
1795
+ * record with a problem is not a record (SYS-101). The writer of the cells refuses it, and the read
1796
+ * of a schedule refuses it. A commit with changes to tracked files is not a pin.
1280
1797
  */
1281
- export declare const targetSourceOf: (target: Target) => string | ImageSource;
1282
- /** This function gives the image that a target operates: the image of its subject, or its stock image. */
1283
- export declare const targetImageOf: (target: Target) => Promise<string>;
1798
+ export declare const recordProblems: (record: Pinnable) => string[];
1284
1799
  //#endregion
1285
1800
  //#region src/group.d.ts
1286
1801
  /**
@@ -1357,8 +1872,8 @@ export declare const memberConfig: (group: Group, primary: string | null) => str
1357
1872
  export declare const sentinelConfig: (group: Group, primary: string) => string;
1358
1873
  /**
1359
1874
  * This function gives the peers that a fault on a part cuts it from, by their addresses. `all` is
1360
- * each other part and the client, `group` is the other parts, and `clients` is the client. `one`
1361
- * and `one-way` are the first other member. The observer is not a peer, thus the timeline of the
1875
+ * each other part and the client, `group` is the other parts, and `clients` and `to-clients` are
1876
+ * the client. `one` and `one-way` are the first other member. The observer is not a peer, thus the timeline of the
1362
1877
  * group stays whole.
1363
1878
  */
1364
1879
  export declare const peersOf: (parts: {
@@ -1527,6 +2042,12 @@ interface ReplicaSetLab {
1527
2042
  signal(part: string, signal: "KILL" | "STOP" | "CONT", at?: number): Promise<Stamp>;
1528
2043
  /** This method starts the server of a member again, after a fin. */
1529
2044
  restart(member: string): Promise<void>;
2045
+ /** This method runs a command in the box of a member, and gives its output. */
2046
+ exec(member: string, argv: string[]): Promise<string>;
2047
+ /** This method runs a script of the shell on a member, against its own server only, and gives its output. Another port reads a server with no set. */
2048
+ script(member: string, script: string, port?: number): Promise<string>;
2049
+ /** This method runs a command on the backup host of a drill, and gives its output. A lab without that host refuses it. */
2050
+ vault(argv: string[]): Promise<string>;
1530
2051
  /** This method sends replSetStepDown to the primary. */
1531
2052
  stepDown(primary: string): Promise<Stamp>;
1532
2053
  /** This method removes the TCP metrics of the client namespace: each run starts from a kernel that keeps nothing. */
@@ -1550,8 +2071,9 @@ export declare const STEP_DOWN: {
1550
2071
  * - an injector sidecar for each member, in its network and process namespaces.
1551
2072
  * - a client that holds its own network namespace, with a privileged sidecar for its sysctls.
1552
2073
  * - the prober, which watches the namespace of the client.
2074
+ * - a backup host for a recovery drill: the stock image, for its tools, with no server.
1553
2075
  */
1554
- export declare const openReplicaSetLab: (set: ReplicaSet) => Promise<ReplicaSetLab>;
2076
+ export declare const openReplicaSetLab: (set: ReplicaSet, backups?: boolean) => Promise<ReplicaSetLab>;
1555
2077
  /** This function gives the arguments of the client of a replica set cell: each member, and the stream of writes. */
1556
2078
  export declare const replicaSetArgs: (cell: Cell, members: Readonly<Record<string, RunPart>>) => string[];
1557
2079
  /**
@@ -1569,6 +2091,18 @@ export declare const replicaSetArgs: (cell: Cell, members: Readonly<Record<strin
1569
2091
  */
1570
2092
  export declare const replicaSetOnce: (lab: ReplicaSetLab, cell: Cell, environment: number, index: number) => Promise<Run>;
1571
2093
  //#endregion
2094
+ //#region src/drill.d.ts
2095
+ /**
2096
+ * This function does one run of a recovery drill:
2097
+ * - The set converges, and it loses its writes. The tenants get their data, and a hash reads it.
2098
+ * - The client writes until its stream is steady. A control stops it here.
2099
+ * - The backups go, each at its interval. The fault comes at the age of the newest backup.
2100
+ * - An election continues the same client. A restore stops the client, and it starts a second one.
2101
+ * - The set converges again. The writes that it then holds tell which writes it kept, and a second
2102
+ * hash tells if the tenants have the same data.
2103
+ */
2104
+ export declare const drillOnce: (lab: ReplicaSetLab, cell: Cell, environment: number, index: number) => Promise<Run>;
2105
+ //#endregion
1572
2106
  //#region src/cluster.d.ts
1573
2107
  /**
1574
2108
  * This module is the lab of a cluster of RabbitMQ with one quorum queue. The members of the queue
@@ -1639,6 +2173,7 @@ export declare const clusterViewOf: (cluster: Cluster, rows: readonly StatusRow[
1639
2173
  * This function gives the peers that a fault on a node cuts it from. `all` is each other node and the
1640
2174
  * client, `group` is the other nodes, and `clients` is the client. `one` is the first other node in
1641
2175
  * the sequence of the cluster, and `one-way` is the same node for the segments from the part only.
2176
+ * `to-clients` is the client, for the segments from the part only.
1642
2177
  */
1643
2178
  export declare const clusterCutOf: (cluster: Cluster, members: Readonly<Record<string, RunPart>>, client: string, part: string, cuts: NonNullable<GroupPlace["cuts"]>) => Cut;
1644
2179
  /** A wall stamp is the wall clock in ns around a command of a node: the run puts it on the monotonic clock. */
@@ -1739,6 +2274,106 @@ export declare const restamped: (line: NodeLine, events: readonly ProbeEvent[])
1739
2274
  */
1740
2275
  export declare const clusterOnce: (lab: ClusterLab, cell: Cell, environment: number, index: number) => Promise<Run>;
1741
2276
  //#endregion
2277
+ //#region src/kafka.d.ts
2278
+ /** This function gives the node id of a name. A broker has its place in the list from 1, and the controller has the id after them. */
2279
+ export declare const nodeIdOf: (kafka: Kafka, name: string) => number;
2280
+ /**
2281
+ * This function gives the variable of a server property for the image. The wrapper of the image
2282
+ * reverses this map (KafkaDockerWrapper.scala:188-203). After the prefix `KAFKA_`, `___` is a
2283
+ * hyphen, `__` is an underscore and `_` is a dot.
2284
+ */
2285
+ export declare const envOf: (property: string) => string;
2286
+ /** This function gives the environment of a broker. */
2287
+ export declare const brokerEnv: (kafka: Kafka, name: string) => Record<string, string>;
2288
+ /** This function gives the environment of the controller. The start script of the image stops on an advertised listener here (configure:43-48). */
2289
+ export declare const controllerEnv: (kafka: Kafka) => Record<string, string>;
2290
+ /** A partition view is the output of the command `view` of the admin. Without a topic it has only the brokers. */
2291
+ interface PartitionView {
2292
+ readonly brokers: readonly number[];
2293
+ readonly leader?: number | null;
2294
+ readonly isr?: readonly number[];
2295
+ readonly replicas?: readonly number[];
2296
+ }
2297
+ /**
2298
+ * This function judges a view of a partition: its leader, and if the group is healthy. A healthy
2299
+ * group has each broker not fenced, one leader, and each broker in the in-sync replicas.
2300
+ */
2301
+ export declare const kafkaViewOf: (kafka: Kafka, view: PartitionView) => GroupView;
2302
+ /**
2303
+ * This function gives the peers that a fault on a broker cuts it from. Only `group` has a law: the
2304
+ * other brokers and the controller, and the client keeps its route to the broker.
2305
+ */
2306
+ export declare const kafkaCutOf: (kafka: Kafka, members: Readonly<Record<string, RunPart>>, controller: RunPart, part: string, cuts: NonNullable<GroupPlace["cuts"]>) => Cut;
2307
+ /** This function gives the addresses that the client and the admin bootstrap from. */
2308
+ export declare const bootstrapOf: (kafka: Kafka) => string;
2309
+ /** This function gives the name of the topic of a run. A warm-up has the index -1. */
2310
+ export declare const topicOf: (environment: number, index: number) => string;
2311
+ /** A Kafka lab is one environment of a Kafka cell. */
2312
+ interface KafkaLab {
2313
+ readonly kafka: Kafka;
2314
+ readonly clientIp: string;
2315
+ readonly members: Readonly<Record<string, RunPart>>;
2316
+ readonly controller: RunPart;
2317
+ readonly netns: {
2318
+ readonly client: number;
2319
+ };
2320
+ /** These are all the records that the prober wrote, in sequence. */
2321
+ readonly kernel: readonly KernelRecord[];
2322
+ /** These are the last raw lines of the console of each node, for the diagnosis of a lab: at most RAW_TAIL of each. */
2323
+ readonly raw: Readonly<Record<string, readonly string[]>>;
2324
+ /** This method sets the sysctls of the client namespace through its privileged sidecar, and reads them back. */
2325
+ sysctl(values: Readonly<Record<string, string>>): Promise<Record<string, string>>;
2326
+ /** This method waits until each broker is not fenced. */
2327
+ brokersUp(within?: number): Promise<void>;
2328
+ /** This method makes the topic of a run. */
2329
+ create(topic: string): Promise<void>;
2330
+ /** This method waits until the partition is whole and calm, and gives the name of the broker of its leader. */
2331
+ converge(topic: string, within?: number): Promise<string>;
2332
+ /** This method gives the sequence numbers that the partition holds, one entry for each copy. */
2333
+ holds(topic: string): Promise<number[]>;
2334
+ /** This method starts the client of a run, with the arguments of `ClientKafka`. */
2335
+ client(args: readonly string[]): Promise<GroupClient>;
2336
+ /** This method applies a network fault between a broker and some of its peers, at once or at an instant of the VM. */
2337
+ fault(kind: GroupNetworkFault, part: string, cuts: NonNullable<GroupPlace["cuts"]>, at?: number): Promise<Stamp>;
2338
+ /** This method removes a network fault, at once or at an instant of the VM. */
2339
+ lift(kind: GroupNetworkFault, part: string, cuts: NonNullable<GroupPlace["cuts"]>, at?: number): Promise<Stamp>;
2340
+ /** This method removes the TCP metrics of the client namespace: each run starts from a kernel that keeps nothing. */
2341
+ forget(): Promise<void>;
2342
+ /** This method waits for the next clock line of the prober, which gives the count of lost records. */
2343
+ settle(): Promise<number | null>;
2344
+ manifest(sysctls: Readonly<Record<string, string>>): Promise<Manifest>;
2345
+ close(): Promise<void>;
2346
+ }
2347
+ /**
2348
+ * This function opens one environment of a Kafka cell:
2349
+ * - one new network, with each node, the client and the commander on it.
2350
+ * - the controller first, then each broker: the stock image with its own command. The brokers
2351
+ * register with the controller, thus they need it first.
2352
+ * - an injector sidecar for each node, in its network and process namespaces.
2353
+ * - a client that holds its own network namespace, with a privileged sidecar for its sysctls.
2354
+ * - the prober, which watches the namespace of the client.
2355
+ */
2356
+ export declare const openKafkaLab: (kafka: Kafka) => Promise<KafkaLab>;
2357
+ /**
2358
+ * This time is how long a run continues after its lift. The record then shows the step-down of the
2359
+ * leader and the writes after it. It has no source. It is above the largest step-down of the
2360
+ * law, which is approximately 2 s after the lift.
2361
+ */
2362
+ export declare const KAFKA_TAIL_MS = 1e4;
2363
+ /** This function gives the arguments of the client of a Kafka cell: the topic, the writers, the stream of writes and the settings. */
2364
+ export declare const kafkaArgs: (cell: Cell, topic: string) => string[];
2365
+ /**
2366
+ * This function does one run of a Kafka cell:
2367
+ * - Each broker is up, the topic of the run exists, and its partition is whole. The client starts,
2368
+ * and its stream of writes gets steady.
2369
+ * - The fault cuts the leader from the other brokers and the controller, and it lifts at its instant
2370
+ * in the VM. The client keeps its route to the leader, thus only the group knows of the cut.
2371
+ * - The run waits for the lift and for the tail after it.
2372
+ * - Each fault goes, the client stops, and the partition converges again. The admin then reads
2373
+ * the whole partition, thus the record tells which writes the group kept.
2374
+ */
2375
+ export declare const kafkaOnce: (lab: KafkaLab, cell: Cell, environment: number, index: number) => Promise<Run>;
2376
+ //#endregion
1742
2377
  //#region src/run.d.ts
1743
2378
  /** A cell result is a cell with its manifests, its runs, their measurements and its verdict. */
1744
2379
  interface CellResult {
@@ -1787,5 +2422,5 @@ export declare const spread: (runs: number, environments: number) => number[];
1787
2422
  */
1788
2423
  export declare const runCell: (cell: Cell, say?: (line: string) => void) => Promise<CellResult>;
1789
2424
  //#endregion
1790
- export { type Agent, type BuildImage, type CallReading, type Cell, type CellResult, type Client, type ClientImage, type Cloud, type Cluster, type ClusterClientAt, type ClusterLab, type ClusterStage, type Crossings, type Cut, type Decision, type DriverBand, type DriverSocket, type DriverStep, type DriverStepTime, type ErrorOnTheWay, type Fault, type FaultPlace, type FaultSide, type Group, type GroupClient, type GroupLab, type GroupMeasured, type GroupNetworkFault, type GroupPlace, type GroupPrediction, type GroupReading, type GroupRole, type GroupVerdict, type GroupView, type Hop, type HopEvent, type HopPlace, type HopSignal, type HopWrite, type Host, type HttpProbe, type ImagePlan, type ImageSource, type Interval, type Jitter, type KernelRecord, type Lab, type Layer, type LineMatch, type Manifest, type ManifestHop, type Measured, type MemberLine, type MiddleboxEvent, type MiddleboxExpectation, type MiddleboxForm, type NetworkFault, type NodeLine, type Observer, type Outcome, type Pairing, type PinnedImage, type Prediction, type Probe, type ProbeEvent, type ProgramEvent, type ProxyHop, type ProxyTime, type ReconnectReading, type ReconnectVerdict, type Reconnects, type Recovers, type Reference, type Reordering, type ReplicaSet, type ReplicaSetLab, type ReplicaSetStage, type Replies, type RequestPrediction, type RequestReading, type RouterHop, type RttRange, type Run, type RunGroup, type RunPart, type RunTopology, type SentinelEvent, type SentinelStage, type Shipped, type ShippedImage, type SocketPlace, type Spread, type Stage, type StageBand, type StageVerdict, type Stamp, type Status, type StatusRow, type Subject, type Substrate, type SubstrateSource, type Target, type Topology, type Toxic, type Verdict, type WallStamp, type Writes, type WsProbe, isHopPlace, latestEndOf };
2425
+ export { type Agent, type BuildImage, type BuildRecord, type CallReading, type Cell, type CellResult, type Client, type ClientImage, type ClockPair, type Cloud, type Cluster, type ClusterClientAt, type ClusterLab, type ClusterStage, type ContextFile, type CountBand, type Crossings, type Cut, type Decision, type Drill, type DriverBand, type DriverSocket, type DriverStep, type DriverStepTime, type ErrorOnTheWay, type Fabric, type FabricLab, type FabricManifest, type FabricParts, type Fault, type FaultPlace, type FaultSide, type Group, type GroupClient, type GroupLab, type GroupMeasured, type GroupNetworkFault, type GroupPlace, type GroupPrediction, type GroupReading, type GroupRole, type GroupVerdict, type GroupView, type Hop, type HopEvent, type HopPlace, type HopSignal, type HopWrite, type Host, type HttpProbe, type ImagePlan, type ImageSource, type Interval, type Jitter, type Kafka, type KafkaLab, type KernelRecord, type Lab, type Layer, type LeafViews, type LineCount, type LineMatch, type Manifest, type ManifestHop, type Measured, type MemberLine, type MiddleboxEvent, type MiddleboxExpectation, type MiddleboxForm, type NetworkFault, type NodeLine, type Observer, type OplogRead, type OplogTime, type Outcome, type Outcomes, type Pair, type PairSets, type Pairing, type PartitionView, type Pinnable, type PinnedImage, type PortsPrediction, type PortsReading, type Prediction, type Probe, type ProbeEvent, type ProgramEvent, type ProxyHop, type ProxyTime, type QueueBand, type QueueConnection, type QueueConnectionReading, type QueueEnd, type QueuePrediction, type QueueReading, type ReconnectReading, type ReconnectVerdict, type Reconnects, type RecordCode, type Recovers, type RecoveryMeasured, type Reference, type Reordering, type ReplicaSet, type ReplicaSetLab, type ReplicaSetStage, type Replies, type RequestPrediction, type RequestReading, type RouteLine, type RouterHop, type RttRange, type Run, type RunBackup, type RunDrill, type RunFabric, type RunGroup, type RunPart, type RunRoute, type RunTopology, type SentinelEvent, type SentinelStage, type Shipped, type ShippedImage, type Sibling, type SocketPlace, type Spread, type Stage, type StageBand, type StageVerdict, type Stamp, type Status, type StatusRow, type Subject, type Substrate, type SubstrateSource, type Target, type Topology, type Toxic, type Verdict, type WallStamp, type Writes, type WsProbe, isHopPlace, latestEndOf };
1791
2426
  //# sourceMappingURL=index.d.ts.map