@mark1russell7/harness 0.14.3 → 0.15.0

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,5 +1,6 @@
1
- import { $ as RunRoute, A as MiddleboxExpectation, B as Reference, C as HopWrite, D as KernelRecord, E as Jitter, F as ProbeEvent, G as RouterHop, H as ReplicaSetStage, I as ProxyHop, J as RunBackup, K as RttRange, L as ProxyTime, M as Observer, N as PinnedImage, O as LineMatch, P as Prediction, Q as RunPart, R as Reconnects, S as HopSignal, T as ImageSource, U as Replies, V as ReplicaSet, W as RequestPrediction, X as RunFabric, Y as RunDrill, Z as RunGroup, _ as GroupPrediction, a as Cluster, at as Stage, b as HopEvent, c as Drill, ct as Target, d as Fabric, dt as WsProbe, et as RunTopology, f as FabricManifest, ft as isHopPlace, g as GroupPlace, h as Group, i as ClientImage, it as ShippedImage, j as MiddleboxForm, k as MiddleboxEvent, l as DriverBand, lt as Topology, m as FaultPlace, n as Cell, nt as SentinelStage, o as ClusterClientAt, ot as StageBand, p as Fault, pt as latestEndOf, q as Run, r as Client, rt as Shipped, s as ClusterStage, st as Subject, t as BuildImage, tt as SentinelEvent, u as DriverStep, ut as Toxic, v as GroupRole, w as HttpProbe, x as HopPlace, y as Hop, z as Recovers } from "./cell-B3-BSTit.js";
1
+ import { $ as ProxyHop, A as ImageSource, At as Subject, B as LoadStream, C as Hop, Ct as RunTopology, D as HopWrite, Dt as ShippedImage, E as HopSignal, Et as Shipped, F as LineCount, Ft as isHopPlace, G as Outcomes, H as MiddleboxExpectation, I as LineMatch, It as latestEndOf, J as PausePrediction, K as Pair, L as LoadBand, M as Kafka, Mt as Topology, N as KafkaPause, Nt as Toxic, O as HostSysctl, Ot as Stage, P as KernelRecord, Pt as WsProbe, Q as ProbeEvent, R as LoadPlan, S as GroupRole, St as RunStream, T as HopPlace, Tt as SentinelStage, U as MiddleboxForm, V as MiddleboxEvent, W as Observer, X as PortsPrediction, Y as PinnedImage, Z as Prediction, _ as Fault, _t as RunFabric, a as ClientCapability, at as Reconnects, b as GroupPlace, bt as RunPause, c as ClusterClientAt, ct as ReplicaSet, d as CountBand, dt as RequestPrediction, et as ProxyTime, f as Drill, ft as RouterHop, g as FabricManifest, gt as RunDrill, h as Fabric, ht as RunBackup, i as Client, it as QueuePrediction, j as Jitter, jt as Target, k as HttpProbe, kt as StageBand, l as ClusterStage, lt as ReplicaSetStage, m as DriverStep, mt as Run, n as CLIENT_CAPABILITIES, nt as QueueConnection, o as ClientImage, ot as Recovers, p as DriverBand, pt as RttRange, q as PauseBand, r as Cell, rt as QueueEnd, s as Cluster, st as Reference, t as BuildImage, tt as QueueBand, u as ConntrackPrediction, ut as Replies, v as FaultPlace, vt as RunGroup, w as HopEvent, wt as SentinelEvent, x as GroupPrediction, xt as RunRoute, y as Group, yt as RunPart, z as LoadPrediction } from "./cell-biffSiEJ.js";
2
2
  import { Quantity } from "@mark1russell7/quantity";
3
+ import { LoadMeasure, Schedule } from "@mark1russell7/rigor-chaos";
3
4
  import { StartedTestContainer } from "testcontainers";
4
5
  //#region src/application.d.ts
5
6
  /**
@@ -135,6 +136,95 @@ interface CallReading {
135
136
  /** This function reads the call that the client sent into the fault: its `call-error` or `data` line after the request. */
136
137
  export declare const callOf: (events: readonly ProbeEvent[], request: ProbeEvent, detected: number | undefined) => CallReading;
137
138
  //#endregion
139
+ //#region src/load.d.ts
140
+ /**
141
+ * The measure and the verdict of an open-loop cell (SYS-68). A client on a schedule sends each
142
+ * arrival at its time, thus a stall counts in each arrival that it delayed. The package rigor-chaos
143
+ * counts each latency from the planned time. The package rigor-bench judges a quantile by a
144
+ * distribution-free interval.
145
+ */
146
+ /** This path is where the client of an open-loop cell finds its schedule. */
147
+ export declare const SCHEDULE_PATH = "/tmp/schedule.json";
148
+ /**
149
+ * This function gives the measure of one run of a schedule from the lines of its client. It gives
150
+ * null when the client did not start the schedule. The first `sent` line of a client is its request
151
+ * before `ready`, and it names no arrival. The end of the run is its last line.
152
+ */
153
+ export declare const loadOf: (events: readonly ProbeEvent[], plan: Schedule) => RunLoad | null;
154
+ /**
155
+ * A run load is the measure of one run of a schedule. `failed` counts the replies with a status
156
+ * outside 200 to 299. Such a reply is a completion, thus its time is in `latency`. The client
157
+ * `schedule` gives no status, and a record from before this field has none: both read as 0.
158
+ */
159
+ type RunLoad = LoadMeasure & {
160
+ readonly failed?: number;
161
+ };
162
+ /** This path is where the client `load` finds its plan. */
163
+ export declare const LOAD_PATH = "/tmp/load.json";
164
+ /** This text is the format of the plan of the client `load`. */
165
+ export declare const LOAD_FORMAT = "systems-load/1";
166
+ /**
167
+ * This function gives the schedule of each stream of a cell, and the text of the plan of the client
168
+ * `load`. It throws for no stream, for two streams with one key and for a stream with no request.
169
+ */
170
+ export declare const loadPlanOf: (streams: readonly LoadStream[]) => {
171
+ readonly streams: readonly RunStream[];
172
+ readonly content: string;
173
+ };
174
+ /**
175
+ * This function gives the measure of each stream of a run of the client `load`, and their pool. Each
176
+ * stream counts its arrivals from 0, thus the lines of a stream are the lines with its key. The pool
177
+ * sums the counts and joins the times, in the order of the streams. It gives null when the client did
178
+ * not start its schedule.
179
+ */
180
+ export declare const streamsLoadOf: (events: readonly ProbeEvent[], streams: readonly RunStream[]) => {
181
+ readonly pool: RunLoad;
182
+ readonly streams: Readonly<Record<string, RunLoad>>;
183
+ } | null;
184
+ /** A load spread is a part of the distribution of one measure of an open-loop cell, over its counted runs. */
185
+ interface LoadSpread {
186
+ readonly p50: Quantity;
187
+ readonly p99: Quantity;
188
+ readonly max: Quantity;
189
+ }
190
+ /**
191
+ * A load verdict sums the schedule of an open-loop cell over its counted runs. `latency` counts from
192
+ * the planned time, and `service` counts from the send: the measure of a closed-loop driver. Each
193
+ * arrival with no reply counts in `latency` at its age at the end of its run, a lower bound.
194
+ */
195
+ interface LoadVerdict {
196
+ readonly planned: number;
197
+ readonly unsent: number;
198
+ readonly unfinished: number;
199
+ /** This count is the replies with a status of a failure, over the counted runs. */
200
+ readonly failed: number;
201
+ readonly latency: LoadSpread | null;
202
+ readonly service: LoadSpread | null;
203
+ readonly lag: LoadSpread | null;
204
+ /** This text is the verdict of each band, in the order of the prediction. */
205
+ readonly bands: readonly string[];
206
+ /** This text is the verdict of the share of failed arrivals, when the prediction has a limit on it. */
207
+ readonly failures?: string;
208
+ }
209
+ /** This record is what the verdict of a cell takes from its load: the runs that broke the schedule, and the sum. */
210
+ interface LoadJudgement {
211
+ readonly holds: boolean;
212
+ readonly outside: ReadonlyArray<{
213
+ readonly run: string;
214
+ readonly why: string;
215
+ }>;
216
+ readonly load: LoadVerdict;
217
+ }
218
+ /**
219
+ * This function judges the load of an open-loop cell over its counted runs. A run that did not keep
220
+ * its schedule measures its driver, not the target, thus it is a finding of that run. Each
221
+ * band reads all the arrivals of the counted runs.
222
+ */
223
+ export declare const loadVerdict: (prediction: LoadPrediction, runs: ReadonlyArray<{
224
+ readonly name: string;
225
+ readonly load: RunLoad | undefined;
226
+ }>) => LoadJudgement;
227
+ //#endregion
138
228
  //#region src/driver.d.ts
139
229
  /**
140
230
  * This module measures a run of a cell whose client is a driver with more than one socket, for
@@ -204,6 +294,103 @@ export declare const referenceOf: (run: Run, from: Reference, role: string, data
204
294
  */
205
295
  export declare const measureDriver: (cell: Cell, run: Run) => Measured;
206
296
  //#endregion
297
+ //#region src/conntrack.d.ts
298
+ /** This record is the end of a connect that found no entry at its start. */
299
+ interface StallReading {
300
+ readonly errno: string;
301
+ readonly time: Quantity;
302
+ /** This count is the rise of the field `drop` of the conntrack statistics during the connect. */
303
+ readonly drops: number;
304
+ /** This count is the rise of `TCPRetransFail` during the connect. */
305
+ readonly retransFail: number;
306
+ }
307
+ /** This record is what a run of a conntrack cell measured. */
308
+ interface ConntrackReading {
309
+ /** This count is the flows that the client holds at its `full` line. */
310
+ readonly flows: number;
311
+ /** This count is what the namespace of the client reads at that line. */
312
+ readonly count: number;
313
+ /** This count is what the namespace of the target reads while the client holds its flows. */
314
+ readonly neighbor: number | null;
315
+ readonly stall: StallReading | null;
316
+ /** This time is from the `closing` line to the first fall of the count. */
317
+ readonly firstFall: Quantity | null;
318
+ /** This time is from the `closing` line to the zero of the count. */
319
+ readonly zero: Quantity | null;
320
+ /** This count is what the namespace reads after each side closes. */
321
+ readonly closed: number | null;
322
+ /** This count is the lowest that the poll of the count read. */
323
+ readonly lowest: number | null;
324
+ /** This count is what the namespace reads after a connect that got a slot. */
325
+ readonly after: number | null;
326
+ }
327
+ /**
328
+ * This function reads one run of a conntrack cell from the lines of its client and its target. An
329
+ * `unsettled` line makes the run void. The entries of the run before it were still in the table, thus
330
+ * the run did not start from an empty table.
331
+ */
332
+ export declare const measureConntrack: (run: Run, expected: ConntrackPrediction) => Measured;
333
+ //#endregion
334
+ //#region src/pause.d.ts
335
+ /**
336
+ * This module reads one run of a paused consumer against its law. Two members of a group each hold
337
+ * one partition. A SIGSTOP stops the first member while it holds a batch, and a SIGCONT ends that
338
+ * stop. Three sources give the reading: the lines of each member, the log lines of the brokers, and
339
+ * the stamps of the injector.
340
+ *
341
+ * The broker writes its log on the clock of the wall, and the members and the injector use the
342
+ * monotonic clock. The `start` line of a member has both clocks, thus it converts a log line.
343
+ */
344
+ /** A commit reading is the first commit of the stopped member after the stop. */
345
+ interface PauseCommit {
346
+ readonly acked: boolean;
347
+ /** This name is the class of the error of the commit. It is null for a commit that the broker acknowledged. */
348
+ readonly name: string | null;
349
+ readonly message: string | null;
350
+ /** This number is the epoch that the member held at the commit. */
351
+ readonly epoch: number | null;
352
+ }
353
+ /** A pause reading is what one run of a paused consumer measured. Each offset is the next offset to read, as a commit names it. */
354
+ interface PauseReading {
355
+ /** This number is the partition of the stopped member before the stop. */
356
+ readonly partition: number;
357
+ /** This time is from the stop to the log line of the broker that removes the member. It is null when no such line came. */
358
+ readonly fence: Quantity | null;
359
+ /** This time is from the stop to the first report of the partition by the other member. It is null when no report came. */
360
+ readonly takeover: Quantity | null;
361
+ readonly commit: PauseCommit | null;
362
+ /** This number is the epoch at the last acknowledged commit before the stop. */
363
+ readonly epochBefore: number | null;
364
+ /** This offset is the last acknowledged commit of the stopped member before the stop. */
365
+ readonly lastAck: number;
366
+ /** This offset is the first offset of the partition that the other member read after the stop. */
367
+ readonly otherFirst: number | null;
368
+ /** This offset is the last acknowledged commit of the other member on the partition, before the commit of the stopped member. */
369
+ readonly otherLast: number | null;
370
+ /** This time is from the end of the stop to the new epoch of the member. It is null when no new epoch came. */
371
+ readonly rejoin: Quantity | null;
372
+ /** This value tells if the stopped member reported the partition again between the end of the stop and its commit. */
373
+ readonly reassigned: boolean;
374
+ /** This offset is the committed offset that the member read after its commit. */
375
+ readonly committed: number | null;
376
+ /** This offset is what the first commit after the stop names for the partition. */
377
+ readonly stale: number | null;
378
+ }
379
+ /** This function gives the time of a log line on the monotonic clock of a member, in ns, from the `start` line of that member. It is null for a line with no stamp. */
380
+ export declare const logTimeOf: (line: string, start: ProbeEvent) => number | null;
381
+ /**
382
+ * This function tells if the two members can take the fault. Each member holds one partition, the
383
+ * two partitions differ, and the first member has two acknowledged commits on its partition after its
384
+ * last change. Thus the first member reads and commits at a steady rate.
385
+ */
386
+ export declare const pauseReady: (first: readonly ProbeEvent[], other: readonly ProbeEvent[]) => boolean;
387
+ /** This function tells if a log line of a broker tells that a member left a group, under either protocol. */
388
+ export declare const isFenceLine: (line: string) => boolean;
389
+ /** This function tells if a fence line names a group. The two protocols write the name in different words. */
390
+ export declare const namesGroup: (line: string, group: string) => boolean;
391
+ /** This function reads one run of a paused consumer against its law. */
392
+ export declare const measurePause: (run: Run, prediction: PausePrediction) => Measured;
393
+ //#endregion
207
394
  //#region src/recovery.d.ts
208
395
  /**
209
396
  * This module holds the pure parts of a recovery drill. These are the scripts of the shell, the reader
@@ -295,6 +482,9 @@ interface ErrorOnTheWay {
295
482
  * of a split brain. It is null when the group did not converge after the run.
296
483
  * - `unknown` are the writes that the client sent and did not see accepted: an error, or no answer.
297
484
  * `held` tells if the group kept each one, or null when it did not converge.
485
+ * - `duplicates` has one entry for each extra copy that the group holds: a write held three times
486
+ * has two entries. It is null when the group did not converge. A key holds one copy by
487
+ * construction, thus only a list can show a copy.
298
488
  */
299
489
  interface Writes {
300
490
  readonly sent: number;
@@ -305,6 +495,18 @@ interface Writes {
305
495
  readonly n: number;
306
496
  readonly held: boolean | null;
307
497
  }>;
498
+ readonly duplicates?: readonly number[] | null;
499
+ /** These are the counts of a pair (`Cell.pair`), from its two final reads. */
500
+ readonly sets?: PairSets;
501
+ }
502
+ /** These are the counts that the bands of `Outcomes` judge: each one has the same name there. */
503
+ interface PairSets {
504
+ readonly unknown: number;
505
+ readonly kept: number;
506
+ readonly stranded: number;
507
+ readonly absent: number;
508
+ readonly missing: number;
509
+ readonly warnings: number;
308
510
  }
309
511
  /** A group measurement is what one run of a group cell measured, beside its time. */
310
512
  interface GroupMeasured {
@@ -406,6 +608,78 @@ interface GroupReading {
406
608
  */
407
609
  export declare const measureGroup: (cell: Cell, run: Run) => GroupReading;
408
610
  //#endregion
611
+ //#region src/ports.d.ts
612
+ /** This record is what a run of a port cell measured. */
613
+ interface PortsReading {
614
+ /** This count is the rounds of the run, each destination once. */
615
+ readonly rounds: number;
616
+ /** This record gives the count of searches for each count of connects, by that count. */
617
+ readonly counts: Readonly<Record<string, number>>;
618
+ /** These offsets from the low port are the ports that the run used, in rising order. */
619
+ readonly seen: readonly number[];
620
+ /** These errnos ended the searches of the run, each one time. */
621
+ readonly errnos: readonly string[];
622
+ /** This time is the longest connect that failed. */
623
+ readonly refusal: Quantity;
624
+ /** This time is from the `closing` line to the first `freed` line. */
625
+ readonly firstFreed: Quantity | null;
626
+ /** This time is from the `closing` line to the last `freed` line. */
627
+ readonly lastFreed: Quantity | null;
628
+ /** This count is the `freed` lines of the run. */
629
+ readonly freed: number;
630
+ /** This count is the connects that failed before the last `freed` line. */
631
+ readonly tries: number;
632
+ }
633
+ /**
634
+ * This function reads one run of a port cell. The `round` lines give each search. The `closing` and
635
+ * `freed` lines give when each held port comes back. The records of the prober give the
636
+ * retransmissions.
637
+ */
638
+ export declare const measurePorts: (run: Run, expected: PortsPrediction) => Measured;
639
+ //#endregion
640
+ //#region src/queue.d.ts
641
+ /** This record is what one connection of a queue cell did, from its lines and the records of its socket. */
642
+ interface QueueConnectionReading {
643
+ readonly name: string;
644
+ readonly connected: boolean;
645
+ /** These times are the waits of the SYN. The first one counts from the dial. */
646
+ readonly syns: readonly Quantity[];
647
+ /** These times are the waits of each SYN-ACK sent again. The first one counts from the dial. */
648
+ readonly synAcks: readonly Quantity[];
649
+ /** This count is the segments that the socket sent again. */
650
+ readonly retransmissions: number;
651
+ readonly errno: string | null;
652
+ /** 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. */
653
+ readonly ended: Quantity | null;
654
+ /** This time is from the last retransmission to the end of the connection. */
655
+ readonly afterLast: Quantity | null;
656
+ /** This count is the segments of the socket with no acknowledgment at the end of the run. */
657
+ readonly unacked: number | null;
658
+ }
659
+ /** This record is what a run of a queue cell measured. The counts are the changes in the run. */
660
+ interface QueueReading {
661
+ readonly max: number;
662
+ readonly held: number;
663
+ readonly connected: number;
664
+ readonly overflows: number;
665
+ readonly drops: number;
666
+ readonly cookies: number;
667
+ readonly timeouts: number;
668
+ readonly resets: number;
669
+ readonly drained: number;
670
+ /** This time is from the first dial of the burst to the last `TCPTimeouts` of the prediction. */
671
+ readonly expiry: Quantity | null;
672
+ /** This time is from the first dial of the burst to the rise of the count of the queue. */
673
+ readonly rise: Quantity | null;
674
+ readonly connections: readonly QueueConnectionReading[];
675
+ }
676
+ /**
677
+ * This function reads one run of a queue cell. The client lines give the connections and the
678
+ * counters at the two ends of the run. The target lines give the count of the queue. The records of
679
+ * the prober give the waits of each socket.
680
+ */
681
+ export declare const measureQueue: (run: Run, expected: QueuePrediction) => Measured;
682
+ //#endregion
409
683
  //#region src/verdict.d.ts
410
684
  /** This function gives the words of the outcome of a second request: its connection, a retry, and its end. */
411
685
  export declare const requestWords: (outcome: {
@@ -509,6 +783,8 @@ interface Verdict {
509
783
  readonly slowest?: Quantity;
510
784
  /** This record is the sum of what reordering did in each counted run of a measurement-only cell. */
511
785
  readonly reordering?: Reordering;
786
+ /** This record is the load of an open-loop cell over its counted runs. */
787
+ readonly load?: LoadVerdict;
512
788
  /** This record is the time of the proxy of a calibration cell, in each direction. */
513
789
  readonly proxy?: {
514
790
  readonly hop: string;
@@ -577,6 +853,8 @@ interface StageVerdict {
577
853
  * - `unknown` counts the writes whose outcome the client did not see, and how many the group kept.
578
854
  * - `errors` are the errors on the way: the runs that met each, and the median of its first time.
579
855
  * - `lags` is the spread of the delays of the stamps, for a calibration.
856
+ * - `duplicates` counts the extra copies that the group holds, in each run. A cell with no band of
857
+ * copies has no such count.
580
858
  */
581
859
  interface GroupVerdict {
582
860
  readonly stages: readonly StageVerdict[];
@@ -601,6 +879,12 @@ interface GroupVerdict {
601
879
  readonly first: Quantity;
602
880
  }>;
603
881
  readonly lags?: Spread | null;
882
+ readonly duplicates?: {
883
+ readonly runs: number;
884
+ readonly total: number;
885
+ readonly median: number | null;
886
+ readonly max: number | null;
887
+ };
604
888
  }
605
889
  /**
606
890
  * This function gives the value at quantile p of sorted values, by nearest rank: x_(⌈p·n⌉). It is
@@ -688,6 +972,8 @@ interface Measured {
688
972
  * sample is the time from its send to the first data after it.
689
973
  */
690
974
  readonly samples?: readonly Quantity[];
975
+ /** This measure is the run of an open-loop cell against its schedule (`Run.schedule`), with its failed replies. Its times are in ms. */
976
+ readonly load?: RunLoad;
691
977
  /** This count is the number of keepalive probes that the kernel sent. */
692
978
  readonly probes: number;
693
979
  /** This count is the number of segments that the kernel sent again. */
@@ -712,6 +998,12 @@ interface Measured {
712
998
  readonly crossings?: Crossings;
713
999
  /** This record is what a run of a group cell measured: the stages of its timeline, and what became of each write. */
714
1000
  readonly group?: GroupMeasured;
1001
+ /** This record is what a run of a queue cell measured: the count of the queue, its counters, and each connection. */
1002
+ readonly queue?: QueueReading;
1003
+ /** This record is what a run of a port cell measured: the count of each search, and when each port came back. */
1004
+ readonly ports?: PortsReading;
1005
+ /** This record is what a run of a conntrack cell measured: the flows, the count, and when a slot came back. */
1006
+ readonly conntrack?: ConntrackReading;
715
1007
  /** This record is what the second request of an HTTP client met, for a cell whose prediction says it. */
716
1008
  readonly request?: RequestReading | null;
717
1009
  /** This record is the time of each later band of a driver cell (`DriverBand.then`). */
@@ -740,6 +1032,8 @@ interface Measured {
740
1032
  * reader can check each pairing of the run again.
741
1033
  */
742
1034
  readonly pairing?: Pairing;
1035
+ /** This record is what a run of a paused consumer measured. */
1036
+ readonly pause?: PauseReading;
743
1037
  /** This text is the reason that the run cannot count, or null. A void run is not a pass and not a finding. */
744
1038
  readonly void: string | null;
745
1039
  /** This text tells what in the run disagrees with the prediction, other than its timing, or null. */
@@ -1102,6 +1396,8 @@ export declare const pgClientImage: () => Promise<string>;
1102
1396
  export declare const hikariClientImage: () => Promise<string>;
1103
1397
  /** This function gives the image of the RabbitMQ client: amqplib, with the client and the admin of a cluster cell. */
1104
1398
  export declare const amqpClientImage: () => Promise<string>;
1399
+ /** This function gives the image of the Kafka client: kafka-clients on Java, with the client and the admin of a Kafka cell. */
1400
+ export declare const kafkaClientImage: () => Promise<string>;
1105
1401
  /** 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. */
1106
1402
  export declare const grpcClientImage: () => Promise<string>;
1107
1403
  /**
@@ -1239,6 +1535,8 @@ interface FaultOptions {
1239
1535
  readonly code?: "host" | "net" | "port" | "admin";
1240
1536
  /** This length is the longest segment in bytes that an MTU drop lets through. */
1241
1537
  readonly above?: number;
1538
+ /** These are the addresses that the rule faces, in place of the peer of its place. */
1539
+ readonly peers?: readonly string[];
1242
1540
  }
1243
1541
  /**
1244
1542
  * A fault side is the namespace that gets the rules of a fault: the namespace of the peer of the
@@ -1260,6 +1558,14 @@ interface ManifestHop {
1260
1558
  /** These are the sysctls of the namespace of the hop, as read back after the harness set them. */
1261
1559
  readonly sysctls: Readonly<Record<string, string>>;
1262
1560
  }
1561
+ /** This record is one sysctl of the host for one environment, as the harness read it. */
1562
+ interface HostSetting {
1563
+ readonly name: string;
1564
+ readonly before: string;
1565
+ readonly set: string;
1566
+ /** This value is the read after the restore. It is null until the restore. */
1567
+ readonly restored: string | null;
1568
+ }
1263
1569
  /** A manifest is what a lab records about its machine, its images and its settings. */
1264
1570
  interface Manifest {
1265
1571
  readonly kernel: string;
@@ -1313,6 +1619,7 @@ interface Manifest {
1313
1619
  readonly client: {
1314
1620
  readonly kind: Client | "image";
1315
1621
  readonly image: string;
1622
+ readonly capabilities?: readonly ClientCapability[];
1316
1623
  readonly source?: ImageSource;
1317
1624
  readonly build?: BuildRecord;
1318
1625
  };
@@ -1324,6 +1631,8 @@ interface Manifest {
1324
1631
  };
1325
1632
  /** These are the sysctls of the client namespace, as read back after the harness set them. */
1326
1633
  readonly sysctls: Readonly<Record<string, string>>;
1634
+ /** These are the sysctls of the host that the cell set: each value before, as set, and as restored. */
1635
+ readonly host?: readonly HostSetting[];
1327
1636
  /** These are the hops of a topology, in sequence from the client. */
1328
1637
  readonly hops?: readonly ManifestHop[];
1329
1638
  /** These are the parts of a group, with their settings as each part read them back. */
@@ -1380,8 +1689,17 @@ interface Agent {
1380
1689
  exec(argv: readonly string[]): Promise<string>;
1381
1690
  stop(): Promise<void>;
1382
1691
  }
1692
+ /** A sibling is a server that a lab starts on the network of the target, for example a standby. */
1693
+ interface Sibling {
1694
+ readonly ip: string;
1695
+ readonly netns: number;
1696
+ /** This method starts a command in the sibling, and gives its standard output. */
1697
+ exec(argv: readonly string[]): Promise<string>;
1698
+ }
1383
1699
  /** A lab is one environment: the target, the client, the hops of a topology, the injectors and the prober. */
1384
1700
  interface Lab {
1701
+ /** This address is the address of the target on its own network. */
1702
+ readonly serverIp: string;
1385
1703
  /** This address is the address that the client connects to: the target, or the first proxy of a topology. */
1386
1704
  readonly targetIp: string;
1387
1705
  /** This port is the port that the client connects to. */
@@ -1412,6 +1730,10 @@ interface Lab {
1412
1730
  agent(image: string, command: readonly string[], options?: {
1413
1731
  readonly pid?: boolean;
1414
1732
  }): Promise<Agent>;
1733
+ /** This method starts a sibling, and waits for a line of its log. */
1734
+ sibling(image: string, command: readonly string[], ready: string): Promise<Sibling>;
1735
+ /** This method starts a command in the target, and gives its standard output. */
1736
+ exec(argv: readonly string[]): Promise<string>;
1415
1737
  /** These are all the records that the prober wrote, in sequence. */
1416
1738
  readonly kernel: readonly KernelRecord[];
1417
1739
  /** This method sets the sysctls of the client namespace through its privileged sidecar, and reads them back. */
@@ -1420,6 +1742,12 @@ interface Lab {
1420
1742
  configure(values: Readonly<Record<string, string>>): Promise<Record<string, string>>;
1421
1743
  /** This method sets the sysctls of the target namespace through a privileged sidecar there, and reads them back. */
1422
1744
  targetSysctl(values: Readonly<Record<string, string>>): Promise<Record<string, string>>;
1745
+ /** This method runs each command in the namespace of the client and in the namespace of the target. */
1746
+ namespaceSetup(commands: readonly (readonly string[])[]): Promise<void>;
1747
+ /** This method sets sysctls of the host through a privileged sidecar on the network of the host, and reads them back. */
1748
+ hostSysctl(settings: readonly HostSysctl[]): Promise<void>;
1749
+ /** This method puts back each value that `hostSysctl` changed, once, and gives the record of each. Closing the lab also does it. */
1750
+ restoreHost(): Promise<readonly HostSetting[]>;
1423
1751
  /**
1424
1752
  * This method applies a fault between the client and the target, by default from the namespace
1425
1753
  * of the target. The fault is a black hole, or a reset that answers the next segment of the
@@ -1497,7 +1825,11 @@ interface Lab {
1497
1825
  t0: number;
1498
1826
  t1: number;
1499
1827
  } | null>;
1500
- probe(args: readonly string[]): Promise<Probe>;
1828
+ /** This method starts the client with `args`. Each file is in its container before it starts. */
1829
+ probe(args: readonly string[], files?: ReadonlyArray<{
1830
+ readonly content: string;
1831
+ readonly target: string;
1832
+ }>): Promise<Probe>;
1501
1833
  /**
1502
1834
  * This method waits for the next clock line of the prober, which gives the count of lost
1503
1835
  * records. It gives null when no clock line comes in 5 s, because then nothing tells the count.
@@ -1578,6 +1910,32 @@ export declare const deviceOf: (route: string) => string;
1578
1910
  */
1579
1911
  export declare const openLab: (target: Target, kind?: Client | ClientImage, topology?: Topology) => Promise<Lab>;
1580
1912
  //#endregion
1913
+ //#region src/standby.d.ts
1914
+ /** This text is the line of the log of a standby that serves reads (src/backend/postmaster/postmaster.c:3740). */
1915
+ export declare const STANDBY_READY: string;
1916
+ /** This text is the write of the client, with its sequence number. */
1917
+ export declare const INSERT: string;
1918
+ /** This function gives the command of a standby: a base backup of the primary, then the server in recovery. */
1919
+ export declare const standbyCommand: (primary: string) => string[];
1920
+ /** This command starts the old primary again, after the stop of each of its processes. Its crash recovery runs before the wait ends. */
1921
+ export declare const RESTART: readonly string[];
1922
+ /** This function reads the output of a query for sequence numbers into a sorted list. */
1923
+ export declare const numbersOf: (text: string) => number[];
1924
+ /** This function gives the arguments of the client of a run. */
1925
+ export declare const pairArgs: (cell: Cell, lab: Pick<Lab, "targetIp" | "targetPort">) => string[];
1926
+ /** This function gives the instants of the cancels of a hold, in ns from the fault: equal parts of the hold. */
1927
+ export declare const cancelsOf: (pair: Pair, holdNs: number) => number[];
1928
+ /**
1929
+ * This function opens the pair of an environment. The table comes first and the standby next: the
1930
+ * base backup has it. A synchronous standby is named last, thus no setup step waits for it.
1931
+ */
1932
+ export declare const openStandby: (lab: Lab, cell: Cell) => Promise<Sibling>;
1933
+ /**
1934
+ * This function does one run of a pair. A dry run writes and stops, with no fault: the warm-up of the
1935
+ * environment. It removes its rows, thus the numbers of the run start on an empty table.
1936
+ */
1937
+ export declare const pairOnce: (lab: Lab, standby: Sibling, cell: Cell, environment: number, index: number, dry?: boolean) => Promise<Run>;
1938
+ //#endregion
1581
1939
  //#region src/locks.d.ts
1582
1940
  /**
1583
1941
  * This module reads the lockfiles of a build context for the manifest of a run. A lockfile pins each
@@ -1632,6 +1990,28 @@ export declare const versionsOf: (files: readonly ContextFile[]) => Record<strin
1632
1990
  export declare const manifestProblems: (manifest: Manifest) => string[];
1633
1991
  /** This function gives the problem of the commit of a record: no commit, or a text that is not a commit of git. */
1634
1992
  export declare const commitProblems: (commit: string | undefined) => string[];
1993
+ /** The code of a record is the commit of the checkout that operated, and if its tracked files had changes. */
1994
+ interface RecordCode {
1995
+ readonly commit: string;
1996
+ readonly dirty: boolean;
1997
+ }
1998
+ /** These are the parts of a record that tell if it pins the programs of its runs. */
1999
+ interface Pinnable {
2000
+ readonly code?: RecordCode | undefined;
2001
+ readonly manifests: readonly Manifest[];
2002
+ /** A local debug run marks its record so. No page reads such a record. */
2003
+ readonly debug?: boolean | undefined;
2004
+ }
2005
+ /** This problem is the problem of a checkout with changes: its commit does not hold the code that operated. */
2006
+ export declare const DIRTY = "the checkout has changes to tracked files that no commit holds";
2007
+ /** This problem is the problem of a record of a local debug run. */
2008
+ export declare const DEBUG = "the record is of a local debug run, and no page reads it";
2009
+ /**
2010
+ * This function gives each problem that stops a record from pinning the programs of its runs. A
2011
+ * record with a problem is not a record (SYS-101). The writer of the cells refuses it, and the read
2012
+ * of a schedule refuses it. A commit with changes to tracked files is not a pin.
2013
+ */
2014
+ export declare const recordProblems: (record: Pinnable) => string[];
1635
2015
  //#endregion
1636
2016
  //#region src/group.d.ts
1637
2017
  /**
@@ -1708,8 +2088,8 @@ export declare const memberConfig: (group: Group, primary: string | null) => str
1708
2088
  export declare const sentinelConfig: (group: Group, primary: string) => string;
1709
2089
  /**
1710
2090
  * This function gives the peers that a fault on a part cuts it from, by their addresses. `all` is
1711
- * each other part and the client, `group` is the other parts, and `clients` is the client. `one`
1712
- * and `one-way` are the first other member. The observer is not a peer, thus the timeline of the
2091
+ * each other part and the client, `group` is the other parts, and `clients` and `to-clients` are
2092
+ * the client. `one` and `one-way` are the first other member. The observer is not a peer, thus the timeline of the
1713
2093
  * group stays whole.
1714
2094
  */
1715
2095
  export declare const peersOf: (parts: {
@@ -2009,6 +2389,7 @@ export declare const clusterViewOf: (cluster: Cluster, rows: readonly StatusRow[
2009
2389
  * This function gives the peers that a fault on a node cuts it from. `all` is each other node and the
2010
2390
  * client, `group` is the other nodes, and `clients` is the client. `one` is the first other node in
2011
2391
  * the sequence of the cluster, and `one-way` is the same node for the segments from the part only.
2392
+ * `to-clients` is the client, for the segments from the part only.
2012
2393
  */
2013
2394
  export declare const clusterCutOf: (cluster: Cluster, members: Readonly<Record<string, RunPart>>, client: string, part: string, cuts: NonNullable<GroupPlace["cuts"]>) => Cut;
2014
2395
  /** A wall stamp is the wall clock in ns around a command of a node: the run puts it on the monotonic clock. */
@@ -2109,6 +2490,129 @@ export declare const restamped: (line: NodeLine, events: readonly ProbeEvent[])
2109
2490
  */
2110
2491
  export declare const clusterOnce: (lab: ClusterLab, cell: Cell, environment: number, index: number) => Promise<Run>;
2111
2492
  //#endregion
2493
+ //#region src/kafka.d.ts
2494
+ /** 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. */
2495
+ export declare const nodeIdOf: (kafka: Kafka, name: string) => number;
2496
+ /**
2497
+ * This function gives the variable of a server property for the image. The wrapper of the image
2498
+ * reverses this map (KafkaDockerWrapper.scala:188-203). After the prefix `KAFKA_`, `___` is a
2499
+ * hyphen, `__` is an underscore and `_` is a dot.
2500
+ */
2501
+ export declare const envOf: (property: string) => string;
2502
+ /** This function gives the environment of a broker. */
2503
+ export declare const brokerEnv: (kafka: Kafka, name: string) => Record<string, string>;
2504
+ /** This function gives the environment of the controller. The start script of the image stops on an advertised listener here (configure:43-48). */
2505
+ export declare const controllerEnv: (kafka: Kafka) => Record<string, string>;
2506
+ /** A partition view is the output of the command `view` of the admin. Without a topic it has only the brokers. */
2507
+ interface PartitionView {
2508
+ readonly brokers: readonly number[];
2509
+ readonly leader?: number | null;
2510
+ readonly isr?: readonly number[];
2511
+ readonly replicas?: readonly number[];
2512
+ }
2513
+ /**
2514
+ * This function judges a view of a partition: its leader, and if the group is healthy. A healthy
2515
+ * group has each broker not fenced, one leader, and each broker in the in-sync replicas.
2516
+ */
2517
+ export declare const kafkaViewOf: (kafka: Kafka, view: PartitionView) => GroupView;
2518
+ /**
2519
+ * This function gives the peers that a fault on a broker cuts it from. Only `group` has a law: the
2520
+ * other brokers and the controller, and the client keeps its route to the broker.
2521
+ */
2522
+ export declare const kafkaCutOf: (kafka: Kafka, members: Readonly<Record<string, RunPart>>, controller: RunPart, part: string, cuts: NonNullable<GroupPlace["cuts"]>) => Cut;
2523
+ /** This function gives the addresses that the client and the admin bootstrap from. */
2524
+ export declare const bootstrapOf: (kafka: Kafka) => string;
2525
+ /** This function gives the name of the topic of a run. A warm-up has the index -1. */
2526
+ export declare const topicOf: (environment: number, index: number) => string;
2527
+ /** A Kafka member is one member of a consumer group. A signal goes from a sidecar in its process namespace. */
2528
+ interface KafkaMember extends GroupClient {
2529
+ /** This method sends a signal to the process of the member, at once or at an instant of the VM. The injector stamps it. */
2530
+ signal(signal: "STOP" | "CONT", at?: number): Promise<Stamp>;
2531
+ }
2532
+ /** A Kafka lab is one environment of a Kafka cell. */
2533
+ interface KafkaLab {
2534
+ readonly kafka: Kafka;
2535
+ readonly clientIp: string;
2536
+ readonly members: Readonly<Record<string, RunPart>>;
2537
+ readonly controller: RunPart;
2538
+ readonly netns: {
2539
+ readonly client: number;
2540
+ };
2541
+ /** These are all the records that the prober wrote, in sequence. */
2542
+ readonly kernel: readonly KernelRecord[];
2543
+ /** These are the last raw lines of the console of each node, for the diagnosis of a lab: at most RAW_TAIL of each. */
2544
+ readonly raw: Readonly<Record<string, readonly string[]>>;
2545
+ /** This method sets the sysctls of the client namespace through its privileged sidecar, and reads them back. */
2546
+ sysctl(values: Readonly<Record<string, string>>): Promise<Record<string, string>>;
2547
+ /** This method waits until each broker is not fenced. */
2548
+ brokersUp(within?: number): Promise<void>;
2549
+ /** These are the log lines of the brokers that tell that a member left a group (`isFenceLine`), in sequence. */
2550
+ readonly fences: readonly string[];
2551
+ /** This method makes the topic of a run, with one partition or more. */
2552
+ create(topic: string, partitions?: number): Promise<void>;
2553
+ /** This method writes `count` records in each partition of a topic, each acknowledged by each in-sync replica. */
2554
+ fill(topic: string, partitions: number, count: number): Promise<void>;
2555
+ /** This method starts one member of a consumer group, with the arguments of `ConsumerKafka` after the bootstrap. */
2556
+ consumer(args: readonly string[]): Promise<KafkaMember>;
2557
+ /** This method waits until the partition is whole and calm, and gives the name of the broker of its leader. */
2558
+ converge(topic: string, within?: number): Promise<string>;
2559
+ /** This method gives the sequence numbers that the partition holds, one entry for each copy. */
2560
+ holds(topic: string): Promise<number[]>;
2561
+ /** This method starts the client of a run, with the arguments of `ClientKafka`. */
2562
+ client(args: readonly string[]): Promise<GroupClient>;
2563
+ /** This method applies a network fault between a broker and some of its peers, at once or at an instant of the VM. */
2564
+ fault(kind: GroupNetworkFault, part: string, cuts: NonNullable<GroupPlace["cuts"]>, at?: number): Promise<Stamp>;
2565
+ /** This method removes a network fault, at once or at an instant of the VM. */
2566
+ lift(kind: GroupNetworkFault, part: string, cuts: NonNullable<GroupPlace["cuts"]>, at?: number): Promise<Stamp>;
2567
+ /** This method removes the TCP metrics of the client namespace: each run starts from a kernel that keeps nothing. */
2568
+ forget(): Promise<void>;
2569
+ /** This method waits for the next clock line of the prober, which gives the count of lost records. */
2570
+ settle(): Promise<number | null>;
2571
+ manifest(sysctls: Readonly<Record<string, string>>): Promise<Manifest>;
2572
+ close(): Promise<void>;
2573
+ }
2574
+ /**
2575
+ * This function opens one environment of a Kafka cell:
2576
+ * - one new network, with each node, the client and the commander on it.
2577
+ * - the controller first, then each broker: the stock image with its own command. The brokers
2578
+ * register with the controller, thus they need it first.
2579
+ * - an injector sidecar for each node, in its network and process namespaces.
2580
+ * - a client that holds its own network namespace, with a privileged sidecar for its sysctls.
2581
+ * - the prober, which watches the namespace of the client.
2582
+ */
2583
+ export declare const openKafkaLab: (kafka: Kafka) => Promise<KafkaLab>;
2584
+ /**
2585
+ * This time is how long a run continues after its lift. The record then shows the step-down of the
2586
+ * leader and the writes after it. It has no source. It is above the largest step-down of the
2587
+ * law, which is approximately 2 s after the lift.
2588
+ */
2589
+ export declare const KAFKA_TAIL_MS = 1e4;
2590
+ /** This function gives the arguments of the client of a Kafka cell: the topic, the writers, the stream of writes and the settings. */
2591
+ export declare const kafkaArgs: (cell: Cell, topic: string) => string[];
2592
+ /**
2593
+ * This function does one run of a Kafka cell:
2594
+ * - Each broker is up, the topic of the run exists, and its partition is whole. The client starts,
2595
+ * and its stream of writes gets steady.
2596
+ * - The fault cuts the leader from the other brokers and the controller, and it lifts at its instant
2597
+ * in the VM. The client keeps its route to the leader, thus only the group knows of the cut.
2598
+ * - The run waits for the lift and for the tail after it.
2599
+ * - Each fault goes, the client stops, and the partition converges again. The admin then reads
2600
+ * the whole partition, thus the record tells which writes the group kept.
2601
+ */
2602
+ export declare const kafkaOnce: (lab: KafkaLab, cell: Cell, environment: number, index: number) => Promise<Run>;
2603
+ /**
2604
+ * This function does one run of a paused consumer:
2605
+ * - The topic of the run has two partitions, each with records that a run does not finish.
2606
+ * - Two members join one group, and the run waits until each member holds one partition and the
2607
+ * first member has two commits on its partition.
2608
+ * - A SIGSTOP stops the first member while it holds its next batch, and a SIGCONT ends the stop
2609
+ * after the hold of the cell. The run then waits for the tail.
2610
+ *
2611
+ * The fault is null when the members did not get one partition each. The measure then voids the run.
2612
+ * The law reads no kernel record, thus a lost record does not void this run.
2613
+ */
2614
+ export declare const kafkaPauseOnce: (lab: KafkaLab, cell: Cell, environment: number, index: number) => Promise<Run>;
2615
+ //#endregion
2112
2616
  //#region src/run.d.ts
2113
2617
  /** A cell result is a cell with its manifests, its runs, their measurements and its verdict. */
2114
2618
  interface CellResult {
@@ -2157,5 +2661,5 @@ export declare const spread: (runs: number, environments: number) => number[];
2157
2661
  */
2158
2662
  export declare const runCell: (cell: Cell, say?: (line: string) => void) => Promise<CellResult>;
2159
2663
  //#endregion
2160
- 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 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 KernelRecord, type Lab, type Layer, type LeafViews, 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 Pairing, type PinnedImage, type Prediction, type Probe, type ProbeEvent, type ProgramEvent, type ProxyHop, type ProxyTime, type ReconnectReading, type ReconnectVerdict, type Reconnects, 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 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 };
2664
+ export { type Agent, type BuildImage, type BuildRecord, CLIENT_CAPABILITIES, type CallReading, type Cell, type CellResult, type Client, type ClientCapability, type ClientImage, type ClockPair, type Cloud, type Cluster, type ClusterClientAt, type ClusterLab, type ClusterStage, type ConntrackPrediction, type ConntrackReading, 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 HostSetting, type HostSysctl, type HttpProbe, type ImagePlan, type ImageSource, type Interval, type Jitter, type Kafka, type KafkaLab, type KafkaMember, type KafkaPause, type KernelRecord, type Lab, type Layer, type LeafViews, type LineCount, type LineMatch, type LoadBand, type LoadJudgement, type LoadPlan, type LoadPrediction, type LoadSpread, type LoadStream, type LoadVerdict, 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 PauseBand, type PauseCommit, type PausePrediction, type PauseReading, 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 RunLoad, type RunPart, type RunPause, type RunRoute, type RunStream, type RunTopology, type SentinelEvent, type SentinelStage, type Shipped, type ShippedImage, type Sibling, type SocketPlace, type Spread, type Stage, type StageBand, type StageVerdict, type StallReading, 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 };
2161
2665
  //# sourceMappingURL=index.d.ts.map