@mark1russell7/harness 0.6.0 → 0.7.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
@@ -36,7 +36,7 @@ import "testcontainers";
36
36
  * one side. It is a black hole, a reset or an ICMP unreachable. It can also be a simplex drop, an
37
37
  * MTU drop or netem.
38
38
  *
39
- * These faults are of a replicated group (`Cell.group`), on the part that `Cell.faultAt` names:
39
+ * These faults are of a replicated group (`Cell.group` or `Cell.replicaSet`), on the part that `Cell.faultAt` names:
40
40
  * - `blackhole` drops each segment between the part and each of its peers. `rst` answers each
41
41
  * segment from a peer with a reset, thus the part refuses each connection.
42
42
  * - `partition` is a black hole between the part and some of its peers only (`GroupPlace.cuts`).
@@ -47,8 +47,11 @@ import "testcontainers";
47
47
  * This fault is of an HTTP server:
48
48
  * - `app-stall` injects nothing. The server process holds the reply to the request, because the
49
49
  * request asks for that (`HttpProbe.hold`), while its kernel stays up.
50
+ *
51
+ * This fault is of a replica set (`Cell.replicaSet`):
52
+ * - `step-down` sends `replSetStepDown` to the primary, as a client sends a command.
50
53
  */
51
- type Fault = "blackhole" | "freeze-process" | "rst" | "stall" | "fin" | "unreachable" | "simplex" | "mtu-blackhole" | "netem" | "middlebox-forget" | "proxy-idle" | "toxic" | "server-close" | "partition" | "planned-failover" | "app-stall" | "none";
54
+ type Fault = "blackhole" | "freeze-process" | "rst" | "stall" | "fin" | "unreachable" | "simplex" | "mtu-blackhole" | "netem" | "middlebox-forget" | "proxy-idle" | "toxic" | "server-close" | "partition" | "planned-failover" | "app-stall" | "step-down" | "none";
52
55
  /**
53
56
  * A middlebox form tells what a router does with a flow that it forgot, when a late packet comes:
54
57
  * - `reset-both` sends a reset to the two ends when it forgets the flow.
@@ -158,6 +161,32 @@ interface Group {
158
161
  readonly sentinel: string;
159
162
  };
160
163
  }
164
+ /**
165
+ * A replica set is a replicated group with no external authority, as data: its members elect their
166
+ * own primary. Each member is a container from the same stock image, pinned by digest, in its own
167
+ * network namespace. The client finds the primary by its own monitors. The harness starts the set
168
+ * with the address of each member, and it waits for a primary.
169
+ */
170
+ interface ReplicaSet {
171
+ /** This name is the name of the set, for example `rs0`. */
172
+ readonly name: string;
173
+ /** This image is the stock image of each member, pinned by digest. */
174
+ readonly image: string;
175
+ /** These are the programs of the image: the server and its shell. */
176
+ readonly programs: {
177
+ readonly server: string;
178
+ readonly shell: string;
179
+ };
180
+ /** These are the options of the server of each member, after the name of the set: for example the size of its cache. */
181
+ readonly args?: readonly string[];
182
+ readonly port: number;
183
+ /** These are the names of the members. The first one starts the set. */
184
+ readonly members: readonly string[];
185
+ /** These are the settings of the configuration of the set, as `rs.initiate` takes them: for example `electionTimeoutMillis`. */
186
+ readonly settings: Readonly<Record<string, number>>;
187
+ /** This line tells that a member serves. */
188
+ readonly ready: string;
189
+ }
161
190
  /** A group role is a part of a group by its role at the start of a run: the primary, a replica, or a Sentinel. */
162
191
  type GroupRole = "primary" | "replica" | "sentinel";
163
192
  /**
@@ -166,10 +195,12 @@ type GroupRole = "primary" | "replica" | "sentinel";
166
195
  * - `all`: each other part of the group, and each client. This is the default.
167
196
  * - `group`: the other members and the Sentinels, but not the clients.
168
197
  * - `clients`: the clients, but not the group.
198
+ * - `one`: one other member, in both directions.
199
+ * - `one-way`: one other member, for the segments from the part only.
169
200
  */
170
201
  interface GroupPlace {
171
202
  readonly role: GroupRole;
172
- readonly cuts?: "all" | "group" | "clients";
203
+ readonly cuts?: "all" | "group" | "clients" | "one" | "one-way";
173
204
  }
174
205
  /** A toxic is one toxic of Toxiproxy, as its API takes it. Its toxicity is 1. */
175
206
  interface Toxic {
@@ -185,8 +216,11 @@ interface Toxic {
185
216
  * send of the client. A FIN counts from the change of state of the socket of the peer when its
186
217
  * process dies (`peer-closed`). A toxic of Toxiproxy counts from the start of its commit, as the
187
218
  * injector stamps it (`fault`).
219
+ *
220
+ * A client that starts into a fault counts from its `connecting` line, or from its first line
221
+ * without one (`client-start`).
188
222
  */
189
- type Reference = "last-received" | "first-retransmission" | "request-sent" | "peer-closed" | "fault";
223
+ type Reference = "last-received" | "first-retransmission" | "request-sent" | "peer-closed" | "fault" | "client-start";
190
224
  /**
191
225
  * This prediction tells when a connection moves again after a stall. That occurs at the first
192
226
  * firing of its retransmission timer after the stall stops, and its reply comes back one round
@@ -245,8 +279,18 @@ interface ProxyTime {
245
279
  * failover and the election. Then the selection of a replica, the promotion, the switch to the new
246
280
  * primary, and the conversion of the old primary into a replica.
247
281
  */
248
- type Stage = "+sdown" | "+odown" | "+try-failover" | "+elected-leader" | "+selected-slave" | "+promoted-slave" | "+switch-master" | "+convert-to-slave";
249
- /** A stage band is when the first Sentinel announces a stage, from the reference of the cell. */
282
+ type SentinelStage = "+sdown" | "+odown" | "+try-failover" | "+elected-leader" | "+selected-slave" | "+promoted-slave" | "+switch-master" | "+convert-to-slave";
283
+ /**
284
+ * A replica set stage is one step of the timeline of a replica set after a fault. A line of the log
285
+ * of a member marks it, or a line of the client. The stages are a member that marks the primary
286
+ * DOWN, the start of an election and its win, and the end of the catch-up. Then come the first
287
+ * write of the new primary and the step-down of the old one. The client's lines give its discovery
288
+ * of the new primary, the write-off of the old one, and the first write that a primary accepts.
289
+ */
290
+ type ReplicaSetStage = "member-down" | "election-start" | "elected" | "caught-up" | "writable" | "old-primary-steps-down" | "discovered" | "written-off" | "first-write";
291
+ /** A stage is one step of the timeline of a group: of a group under Sentinels, or of a replica set. */
292
+ type Stage = SentinelStage | ReplicaSetStage;
293
+ /** A stage band is when the first part announces a stage, from the reference of the cell. */
250
294
  interface StageBand {
251
295
  readonly stage: Stage;
252
296
  readonly low: Quantity;
@@ -260,6 +304,7 @@ interface StageBand {
260
304
  * stamps of the observer (`stamps`).
261
305
  * - `errors` are the errors that the client must meet on the way, each with the band of its
262
306
  * first occurrence. An example is the error of the offline queue when it gives up.
307
+ * - `quiet` are the stages that must not occur after the fault. Each one that a run shows is a finding.
263
308
  */
264
309
  interface GroupPrediction {
265
310
  readonly lands: "new" | "same";
@@ -271,6 +316,7 @@ interface GroupPrediction {
271
316
  readonly low: Quantity;
272
317
  readonly high: Quantity;
273
318
  }>;
319
+ readonly quiet?: readonly Stage[];
274
320
  }
275
321
  /**
276
322
  * A middlebox expectation tells what the router of a topology does with the flow in the window of
@@ -298,6 +344,59 @@ interface RequestPrediction {
298
344
  readonly error: string | null;
299
345
  readonly pending?: true;
300
346
  }
347
+ /**
348
+ * A line match is a line of the client that a driver band waits for. It has the `ev` of the line,
349
+ * and the value of each field that it names. A dotted name is a field in a field, for example
350
+ * `failure.name`. `name` is the field that names the error of the line, for its outcome.
351
+ */
352
+ interface LineMatch {
353
+ readonly ev: string;
354
+ readonly where?: Readonly<Record<string, string | number | boolean>>;
355
+ readonly name?: string;
356
+ }
357
+ /**
358
+ * A driver step is one more band of a driver after the band of its cell. An example is the error
359
+ * of the retry after the interruption. It has its own reference on a socket of the driver, its
360
+ * line, and its band. A run whose step is outside its band, or absent, has a finding.
361
+ */
362
+ interface DriverStep {
363
+ readonly what: string;
364
+ /** This name is the name of the error of the line, or OK. */
365
+ readonly name: string;
366
+ /** This role is the socket of the reference. Without it, the socket is the socket of the band of the cell. */
367
+ readonly socket?: string;
368
+ readonly from: Reference;
369
+ readonly ends: LineMatch;
370
+ readonly low: Quantity;
371
+ readonly high: Quantity;
372
+ }
373
+ /**
374
+ * A driver band is a band of a cell whose client is a driver with more than one socket, for
375
+ * example the MongoDB driver. It names the socket of the reference, and the line that ends the
376
+ * band:
377
+ * - `socket` is the role of the socket, as the client names it in its `socket` lines. The socket
378
+ * `server` is the socket of the target for the first connection of the pool.
379
+ * - `ends` is the line of the client that marks the detection. Without it, the detection is the
380
+ * report of the kernel on the socket: an error, or the end of the file.
381
+ * - `reply` is the line of a reply that a silent prediction times (`replies`), with its reference.
382
+ * - `quiet` are the lines that must not occur after the fault, in the window of the prediction.
383
+ * - `then` are the later bands, each one a test of its own.
384
+ *
385
+ * A band whose line ends it is a timer of the driver. Its `last-received` is the last segment with
386
+ * data that its socket received or sent. The idle timer of a Node socket starts again at each read
387
+ * and each write. A band of the kernel counts from the last segment of any kind that the socket
388
+ * received.
389
+ */
390
+ interface DriverBand {
391
+ readonly socket: string;
392
+ readonly ends?: LineMatch;
393
+ readonly reply?: {
394
+ readonly from: Reference;
395
+ readonly ends: LineMatch;
396
+ };
397
+ readonly quiet?: readonly LineMatch[];
398
+ readonly then?: readonly DriverStep[];
399
+ }
301
400
  /**
302
401
  * A prediction is what a cell predicts. Either a detection occurs in an interval [T_lo, T_hi]
303
402
  * after the reference event, or nothing detects the fault in a window. Nothing detects a stall
@@ -318,6 +417,8 @@ interface RequestPrediction {
318
417
  *
319
418
  * For an HTTP cell, `request` tells what the second request meets. The errno `CLOSED` is a close
320
419
  * of the observer itself: its pool closes an idle connection, a FIN that it sends.
420
+ *
421
+ * A band of a driver (`driver`) counts from a socket of the driver to a line of the client.
321
422
  */
322
423
  type Prediction = {
323
424
  readonly detects: true;
@@ -337,6 +438,7 @@ type Prediction = {
337
438
  readonly through?: readonly ProxyTime[];
338
439
  readonly group?: GroupPrediction;
339
440
  readonly request?: RequestPrediction;
441
+ readonly driver?: DriverBand;
340
442
  } | {
341
443
  readonly detects: false;
342
444
  readonly window: Quantity;
@@ -347,6 +449,7 @@ type Prediction = {
347
449
  readonly through?: readonly ProxyTime[];
348
450
  readonly group?: GroupPrediction;
349
451
  readonly request?: RequestPrediction;
452
+ readonly driver?: DriverBand;
350
453
  } | {
351
454
  readonly detects: null;
352
455
  readonly window: Quantity;
@@ -390,13 +493,19 @@ interface Target {
390
493
  * output, on CLOCK_MONOTONIC. Each run then keeps its lines (`Run.server`).
391
494
  */
392
495
  readonly lines?: true;
496
+ /**
497
+ * This name is the server process, as /proc/PID/comm holds it. With it, a freeze of the target
498
+ * stops this process with SIGSTOP from a sidecar in its process namespace, and the injector
499
+ * stamps it. SIGCONT then thaws it. Without it, the freeze is the cgroup freezer, with no stamps.
500
+ */
501
+ readonly program?: string;
393
502
  }
394
503
  /**
395
504
  * A client is what the runs of a cell use: the TCP client of the harness, or a driver on its
396
505
  * socket. The HTTP clients are the `http.Transport` of Go (`go-http`), the `http.Agent` of Node
397
- * (`http-agent`) and an HTTP/1.1 `Client` of undici (`undici`).
506
+ * (`http-agent`) and an HTTP/1.1 `Client` of undici (`undici`). The MongoDB driver is `mongodb`.
398
507
  */
399
- type Client = "tcp" | "ioredis" | "go-http" | "http-agent" | "undici";
508
+ type Client = "tcp" | "ioredis" | "go-http" | "http-agent" | "undici" | "mongodb";
400
509
  /**
401
510
  * An HTTP probe is the workload of an HTTP client. The first request is a GET of the root. The
402
511
  * second request follows the mode of the probe: after the signal (`inflight`), or after a gap
@@ -466,13 +575,19 @@ interface Cell {
466
575
  */
467
576
  readonly request?: string;
468
577
  /**
469
- * This driver replaces the TCP client of the harness, with its own options. It is ioredis 6 on
470
- * Node, whose keepAlive is the keepalive delay of the socket. The driver then ignores `keepalive`
471
- * and `userTimeout`.
578
+ * This driver replaces the TCP client of the harness, with its own options. The driver then
579
+ * ignores `keepalive` and `userTimeout`:
580
+ * - ioredis 6 on Node, whose keepAlive is the keepalive delay of the socket.
581
+ * - the MongoDB driver on Node, against the replica set `set`. Its operation is a write, or
582
+ * the read of a long document (`read-long`). `Cell.driverOptions` are its options.
472
583
  */
473
584
  readonly driver?: {
474
585
  readonly name: "ioredis";
475
586
  readonly keepAlive: Quantity;
587
+ } | {
588
+ readonly name: "mongodb";
589
+ readonly set: string;
590
+ readonly op?: "write" | "read-long";
476
591
  };
477
592
  /** This workload is the workload of an HTTP client (`Cell.client` is an HTTP client). The client then ignores `keepalive` and `userTimeout`. */
478
593
  readonly http?: HttpProbe;
@@ -530,12 +645,28 @@ interface Cell {
530
645
  * record, and the group does not read it.
531
646
  */
532
647
  readonly group?: Group;
533
- /** This time is how long a fault on a group holds after its commit. The injector then lifts it at that instant, on the clock of the VM. */
648
+ /**
649
+ * This replica set replaces the target: a replicated group whose members elect their own
650
+ * primary. The client is then the MongoDB driver, and it writes a stream of sequence numbers.
651
+ * `target` stays for the record, and the set does not read it.
652
+ */
653
+ readonly replicaSet?: ReplicaSet;
654
+ /**
655
+ * This time is how long a fault on a group holds after its commit. The injector then lifts it at
656
+ * that instant, on the clock of the VM. On a direct pair, a frozen target thaws after it.
657
+ */
534
658
  readonly hold?: Quantity;
535
659
  /** This flag makes a planned failover coordinated: `SENTINEL FAILOVER <group> COORDINATED`. */
536
660
  readonly coordinated?: boolean;
537
- /** These are options of ioredis over its defaults, for the client of a group. A cell at the defaults has none. */
661
+ /**
662
+ * These are options of the driver over its defaults: of ioredis for the client of a group, or of
663
+ * the MongoDB driver for its client. A cell at the defaults has none.
664
+ */
538
665
  readonly driverOptions?: Readonly<Record<string, unknown>>;
666
+ /** This write concern is the w of each write of the MongoDB client. Without it, it is majority. */
667
+ readonly writeConcern?: "majority" | 1;
668
+ /** This flag makes the fault hold before the client starts. The client then meets it at its first selection. */
669
+ readonly before?: boolean;
539
670
  /** This count is the number of runs of the cell (11), across new environments (two at least). */
540
671
  readonly runs: number;
541
672
  readonly environments: number;
@@ -639,7 +770,11 @@ interface RunGroup {
639
770
  readonly primary: string;
640
771
  /** This name is the part that got the fault, or null for a fault on the whole group. */
641
772
  readonly at: string | null;
642
- /** These are the lines of the observer of the Sentinels from the start to the end of the run. */
773
+ /**
774
+ * These are the lines of the timeline from the start to the end of the run. For a group under
775
+ * Sentinels, they are the lines of the observer of the Sentinels. For a replica set, they are
776
+ * the log lines of the members (`ev` "mongod"), with their times on the monotonic clock.
777
+ */
643
778
  readonly timeline: readonly SentinelEvent[];
644
779
  /** This name is the member that was the primary when the group converged after the run, or null when it did not converge. */
645
780
  readonly after: string | null;
@@ -662,14 +797,76 @@ interface RunTopology {
662
797
  }>>;
663
798
  }
664
799
  //#endregion
800
+ //#region src/driver.d.ts
801
+ /**
802
+ * This module measures a run of a cell whose client is a driver with more than one socket, for
803
+ * example the MongoDB driver. Its monitor, its pool and its round-trip pinger each have their own
804
+ * socket, and the client names each socket by its role. A band counts from an event of one socket,
805
+ * as the kernel records it. It ends at a line of the client, or at the report of the kernel on
806
+ * that socket.
807
+ */
808
+ /** A driver socket is one socket of the driver in a run: its role, its local address, its server, and when it opened and ended. */
809
+ interface DriverSocket {
810
+ readonly role: string;
811
+ readonly local: string;
812
+ readonly server: string;
813
+ readonly opened: number;
814
+ readonly ended: number | null;
815
+ }
816
+ /** A driver step time is the time of one later band of a run. It is null when its line did not come. */
817
+ interface DriverStepTime {
818
+ readonly what: string;
819
+ readonly name: string | null;
820
+ readonly elapsed: Quantity | null;
821
+ }
822
+ /** This function gives the value of a field of a line by its name. A dotted name is a field in a field. */
823
+ export declare const fieldOf: (line: unknown, path: string) => unknown;
824
+ /** This function tells if a line of the client matches a line match: its `ev`, and each field that the match names. */
825
+ export declare const matches: (line: ProbeEvent, match: LineMatch) => boolean;
826
+ /** This function gives the sockets of the driver in a run, from the `socket` and `socket-end` lines of the client. */
827
+ export declare const socketsOf: (events: readonly ProbeEvent[]) => DriverSocket[];
828
+ /**
829
+ * This function finds the socket of a role at an instant. The pool's socket is the first one, which
830
+ * the client names in its `connected` line. Each other role has the latest socket that opened at
831
+ * the instant or before it.
832
+ */
833
+ export declare const socketAt: (events: readonly ProbeEvent[], role: string, at: number) => DriverSocket | undefined;
834
+ /**
835
+ * This function gives the instant of a reference in a run, on a socket of the driver:
836
+ * - `last-received`: the last segment that the socket received before the fault held. A band of
837
+ * the kernel counts from the last segment of any kind. A band that a line ends is a timer of
838
+ * the driver. It counts from the last segment with data that the socket received or sent.
839
+ * - `request-sent`: the send of the operation into the fault, the second `sent` line.
840
+ * - `first-retransmission`: the first retransmission of the RTO timer on the socket.
841
+ * - `peer-closed`: the change of state of the socket of the target, when its process dies.
842
+ * - `fault`: the start of the commit of the fault. `client-start`: the `connecting` line.
843
+ */
844
+ export declare const referenceOf: (run: Run, from: Reference, role: string, data: boolean) => number | undefined;
845
+ /**
846
+ * This function reads one run of a driver cell.
847
+ * - The band of the cell counts from its reference on its socket. It ends at its line, or at the
848
+ * report of the kernel on that socket.
849
+ * - Each later band (`then`) gets the same test. A later band outside its band, or absent, is a finding.
850
+ * - A line that the prediction names as quiet, after the fault and in its window, is a finding.
851
+ * So is a flow of an open socket of the driver that a router forgot, for a silent prediction.
852
+ * - A silent prediction can time a reply (`reply`), and the verdict tests it against `replies`.
853
+ *
854
+ * A run is void when the prober lost records, or when the client did not get its first reply. It
855
+ * is also void when the operation went out before the fault held. A late lift of a hold and a
856
+ * keepalive probe before the fault also make it void. So do a delayed timer and a round trip
857
+ * above the assumption.
858
+ */
859
+ export declare const measureDriver: (cell: Cell, run: Run) => Measured;
860
+ //#endregion
665
861
  //#region src/timeline.d.ts
666
862
  /**
667
863
  * This module measures a run of a group cell. It gives the first write that a primary accepted
668
- * after the fault, and the timeline of the group as its Sentinels announced it. It also gives what
864
+ * after the fault, and the timeline of the group. The Sentinels of a group announce its timeline.
865
+ * The logs of the members of a replica set and its client tell it. The module also gives what
669
866
  * became of each write.
670
867
  */
671
- /** These are the stages of a timeline, in their sequence after a fault. */
672
- export declare const STAGES: readonly Stage[];
868
+ /** These are the stages of a timeline under Sentinels, in their sequence after a fault. */
869
+ export declare const STAGES: readonly SentinelStage[];
673
870
  /** An error on the way is one kind of error that the client met after the fault. It has its first time from the fault, and its count. */
674
871
  interface ErrorOnTheWay {
675
872
  readonly name: string;
@@ -708,6 +905,30 @@ interface GroupMeasured {
708
905
  }
709
906
  /** This function gives the time of each stage of a timeline from an instant: the first announcement of each, after the instant. */
710
907
  export declare const stagesOf: (timeline: readonly SentinelEvent[], from: number) => Partial<Record<Stage, Quantity>>;
908
+ /** These are the stages of the timeline of a replica set, in their usual sequence after a fault. */
909
+ export declare const REPLICA_SET_STAGES: readonly ReplicaSetStage[];
910
+ /**
911
+ * A member mark is how a log line of mongod marks a stage: by its id, or by its message. The
912
+ * message is the fallback for a version whose ids differ. `at` tells where the line comes from:
913
+ * the old primary, or another member.
914
+ */
915
+ interface MemberMark {
916
+ readonly ids: readonly number[];
917
+ readonly message: RegExp;
918
+ readonly at: "old" | "other";
919
+ }
920
+ /** These are the log lines of mongod that mark each stage of a member. */
921
+ export declare const MEMBER_MARKS: Readonly<Record<Exclude<ReplicaSetStage, "discovered" | "written-off" | "first-write">, MemberMark>>;
922
+ /**
923
+ * This function gives the time of each stage of a replica set from an instant, in a run. The stages
924
+ * of the members come from their log lines (`ev` "mongod"), whose times the lab puts on the
925
+ * monotonic clock. The stages of the client come from its lines:
926
+ * - `discovered`: a member other than the old primary becomes RSPrimary in the view of the client.
927
+ * - `written-off`: the first heartbeat of the client to the old primary that fails.
928
+ * - `first-write`: the first write that a primary accepts, of a write that the client sent after
929
+ * the commit of the fault (`sentAfter`). It is on a new primary when `lands` is `new`.
930
+ */
931
+ export declare const replicaSetStagesOf: (run: Run, from: number, sentAfter: number, lands: "new" | "same") => Partial<Record<Stage, Quantity>>;
711
932
  /** This function gives what became of each write of a run, from the lines of the client and the keys that the group kept. */
712
933
  export declare const writesOf: (run: Run, after: number, primary: string) => Writes;
713
934
  /** This function gives the errors that the client met after an instant: each kind, its first time, and its count. */
@@ -737,7 +958,10 @@ interface GroupReading {
737
958
  * - The reference is the start of the commit of the fault, as the injector stamped it. For a
738
959
  * stall, it is the first write into the fault, as for the stall of a direct pair.
739
960
  * - The outcome is the first write that a primary accepted after the fault. The prediction says
740
- * which primary: a new one, or the same one after the lift.
961
+ * which primary: a new one, or the same one after the lift. In a replica set, it is the first
962
+ * accepted write of a write that the client sent after the commit of the fault.
963
+ * - The stages come from the Sentinels, or from the logs of the members of a replica set and the
964
+ * lines of its client (`replicaSetStagesOf`).
741
965
  * - Its time is the last segment with data that the client's socket to that primary received
742
966
  * before the client saw the acceptance. The stamp of the client is the fallback.
743
967
  * - A run is void when the prober lost records, or when the client did not become ready. It is
@@ -826,6 +1050,10 @@ interface Measured {
826
1050
  readonly group?: GroupMeasured;
827
1051
  /** This record is what the second request of an HTTP client met, for a cell whose prediction says it. */
828
1052
  readonly request?: RequestReading | null;
1053
+ /** This record is the time of each later band of a driver cell (`DriverBand.then`). */
1054
+ readonly driver?: {
1055
+ readonly steps: readonly DriverStepTime[];
1056
+ };
829
1057
  /** This text is the reason that the run cannot count, or null. A void run is not a pass and not a finding. */
830
1058
  readonly void: string | null;
831
1059
  /** This text tells what in the run disagrees with the prediction, other than its timing, or null. */
@@ -1069,6 +1297,8 @@ export declare const routerImage: () => Promise<string>;
1069
1297
  export declare const goHttpImage: () => Promise<string>;
1070
1298
  /** This function gives the image of the Node HTTP clients. */
1071
1299
  export declare const nodeHttpImage: () => Promise<string>;
1300
+ /** This function gives the image of the MongoDB client. */
1301
+ export declare const mongoClientImage: () => Promise<string>;
1072
1302
  /**
1073
1303
  * This time is the interval of the listing of a router, when its hop does not set one. A listing
1074
1304
  * evicts each expired flow that it walks past, and the DESTROY event of that flow follows.
@@ -1304,6 +1534,15 @@ interface Lab {
1304
1534
  /** This method freezes the target with the cgroup freezer: its process stops, and its kernel continues to answer. */
1305
1535
  freeze(): Promise<void>;
1306
1536
  thaw(): Promise<void>;
1537
+ /**
1538
+ * This method sends a signal to the server process of the target (`Target.program`), at once or
1539
+ * at an instant of the VM. A sidecar in the network and process namespaces of the target sends
1540
+ * it, and the injector stamps it. The lab starts that sidecar at the first signal.
1541
+ */
1542
+ signal(signal: "STOP" | "CONT" | "KILL", at?: number): Promise<{
1543
+ t0: number;
1544
+ t1: number;
1545
+ }>;
1307
1546
  probe(args: readonly string[]): Promise<Probe>;
1308
1547
  /**
1309
1548
  * This method waits for the next clock line of the prober, which gives the count of lost
@@ -1491,6 +1730,157 @@ export declare const subscriptionsOf: (timeline: readonly SentinelEvent[]) => Se
1491
1730
  */
1492
1731
  export declare const groupOnce: (lab: GroupLab, cell: Cell, environment: number, index: number) => Promise<Run>;
1493
1732
  //#endregion
1733
+ //#region src/replset.d.ts
1734
+ /**
1735
+ * This module is the lab of a replica set: a replicated group with no external authority, whose
1736
+ * members elect their own primary. It opens one environment for a replica set cell, for the runs
1737
+ * of the cell. Each member is a container from the stock image of the set, in its own network
1738
+ * namespace. An injector sidecar shares its network and process namespaces.
1739
+ *
1740
+ * The client of each run is the MongoDB driver, which finds the primary with its own monitors. The
1741
+ * timeline comes from the log of each member and from the lines of the client. The prober watches
1742
+ * the namespace of the client.
1743
+ */
1744
+ /**
1745
+ * A member line is one log line of a member, as mongod writes it in JSON. `real` is its time on
1746
+ * the wall clock in ms, and `t` is its time on the monotonic clock. The run gives `t` from the
1747
+ * clock lines of its client.
1748
+ */
1749
+ interface MemberLine extends SentinelEvent {
1750
+ readonly ev: "mongod";
1751
+ readonly member: string;
1752
+ readonly real: number;
1753
+ readonly id: number;
1754
+ readonly c: string;
1755
+ readonly msg: string;
1756
+ readonly attr: Readonly<Record<string, unknown>>;
1757
+ }
1758
+ /** These are the components of the log of mongod that a run keeps: replication, its heartbeats, the elections, the rollbacks and the commands. */
1759
+ export declare const KEPT: ReadonlySet<string>;
1760
+ /** This function reads one log line of a member, or gives null for a line of another component or a line that is not JSON. */
1761
+ export declare const memberLineOf: (member: string, text: string) => MemberLine | null;
1762
+ /**
1763
+ * This function gives the offset of the wall clock from the monotonic clock, in ns, from the clock
1764
+ * lines of a client. Each line pairs its stamp with the wall clock in whole ms, which truncates.
1765
+ * Thus each pair is the offset or less, and the largest pair is the nearest. It is null without a clock line.
1766
+ */
1767
+ export declare const clockOffsetOf: (events: readonly ProbeEvent[]) => number | null;
1768
+ /** This function puts the log lines of the members on the monotonic clock, with the offset of a client. */
1769
+ export declare const onMonotonic: (log: readonly MemberLine[], offset: number | null) => MemberLine[];
1770
+ /** A cut is the peers that a network fault on a part cuts it from, by their addresses, and the direction of the rules. */
1771
+ interface Cut {
1772
+ readonly peers: readonly string[];
1773
+ readonly direction?: "out";
1774
+ }
1775
+ /**
1776
+ * This function gives the peers that a fault on a member of a replica set cuts it from. `all` is
1777
+ * each other member and the client, `group` is the other members, and `clients` is the client.
1778
+ * `one` is the first other member in the sequence of the set, and `one-way` is the same member for
1779
+ * the segments from the part only.
1780
+ */
1781
+ export declare const cutOf: (set: ReplicaSet, members: Readonly<Record<string, RunPart>>, client: string, part: string, cuts: NonNullable<GroupPlace["cuts"]>) => Cut;
1782
+ /** This function gives the command of the server of each member. The server is the child of a shell, thus a fin can stop it and the container stays up. */
1783
+ export declare const memberCommand: (set: ReplicaSet) => string;
1784
+ /** This function gives the script of the shell that starts the set: each member by its address, and the settings of the set. */
1785
+ export declare const initiateScript: (set: ReplicaSet, ips: Readonly<Record<string, string>>) => string;
1786
+ /** This script prints the view of a member: itself, if it accepts writes, and the state of each member as it sees them. */
1787
+ export declare const STATUS_SCRIPT: string;
1788
+ /** A status is the view of one member, as `STATUS_SCRIPT` prints it. */
1789
+ interface Status {
1790
+ readonly me: string;
1791
+ readonly writable: boolean;
1792
+ readonly members: ReadonlyArray<{
1793
+ readonly name: string;
1794
+ readonly state: string;
1795
+ readonly health: number;
1796
+ readonly optime: number | null;
1797
+ }>;
1798
+ }
1799
+ /**
1800
+ * This function judges the view of a member: the primary of the set, and if the set is healthy.
1801
+ * The set is healthy when the member is the one primary and accepts writes. Each other member must
1802
+ * be a healthy secondary at the optime of the primary.
1803
+ */
1804
+ export declare const statusViewOf: (set: ReplicaSet, ips: Readonly<Record<string, string>>, status: Status) => GroupView;
1805
+ /** A replica set lab is one environment of a replica set cell. */
1806
+ interface ReplicaSetLab {
1807
+ readonly set: ReplicaSet;
1808
+ readonly clientIp: string;
1809
+ readonly members: Readonly<Record<string, RunPart>>;
1810
+ readonly netns: {
1811
+ readonly client: number;
1812
+ };
1813
+ /** These are all the records that the prober wrote, in sequence. */
1814
+ readonly kernel: readonly KernelRecord[];
1815
+ /** These are the log lines of the members that a run keeps, in the sequence of their arrival, with `t` at 0. */
1816
+ readonly log: readonly MemberLine[];
1817
+ /** This method sets the sysctls of the client namespace through its privileged sidecar, and reads them back. */
1818
+ sysctl(values: Readonly<Record<string, string>>): Promise<Record<string, string>>;
1819
+ /** This method waits until the set is whole and calm, and gives the name of its primary. */
1820
+ converge(within?: number): Promise<string>;
1821
+ /** This method removes each write from the set, and waits until each member has the removal. */
1822
+ flush(primary: string): Promise<void>;
1823
+ /**
1824
+ * This method lets each secondary stand for election again (`rs.freeze(0)`). A step-down holds its
1825
+ * old primary out of the elections for `STEP_DOWN.seconds`. Without it, a run inherits that hold.
1826
+ */
1827
+ unfreeze(primary: string): Promise<void>;
1828
+ /** This method gives the sequence numbers that the set holds, from its primary. */
1829
+ holds(primary: string): Promise<number[]>;
1830
+ /** This method gives the member that has a role in the set, when `primary` is the primary. */
1831
+ partOf(role: GroupRole, primary: string): string;
1832
+ /** This method starts the client of a run, with the arguments of `client-mongo.mjs`. */
1833
+ client(args: readonly string[]): Promise<GroupClient>;
1834
+ /** This method applies a network fault between a member and some of its peers, at once or at an instant of the VM. */
1835
+ fault(kind: GroupNetworkFault, part: string, cuts: NonNullable<GroupPlace["cuts"]>, at?: number): Promise<Stamp>;
1836
+ /** This method removes a network fault, at once or at an instant of the VM. */
1837
+ lift(kind: GroupNetworkFault, part: string, cuts: NonNullable<GroupPlace["cuts"]>, at?: number): Promise<Stamp>;
1838
+ /** This method sends a signal to the server process of a member, at once or at an instant of the VM. */
1839
+ signal(part: string, signal: "KILL" | "STOP" | "CONT", at?: number): Promise<Stamp>;
1840
+ /** This method starts the server of a member again, after a fin. */
1841
+ restart(member: string): Promise<void>;
1842
+ /** This method sends replSetStepDown to the primary. */
1843
+ stepDown(primary: string): Promise<Stamp>;
1844
+ /** This method removes the TCP metrics of the client namespace: each run starts from a kernel that keeps nothing. */
1845
+ forget(): Promise<void>;
1846
+ /** This method waits for the next clock line of the prober, which gives the count of lost records. */
1847
+ settle(): Promise<number | null>;
1848
+ manifest(sysctls: Readonly<Record<string, string>>): Promise<Manifest>;
1849
+ close(): Promise<void>;
1850
+ }
1851
+ /** These are the arguments of replSetStepDown: the time that the old primary cannot stand again, and the wait for a secondary to catch up. */
1852
+ export declare const STEP_DOWN: {
1853
+ readonly seconds: 60;
1854
+ readonly catchUp: 10;
1855
+ };
1856
+ /**
1857
+ * This function opens one environment of a replica set cell:
1858
+ * - one new network, with each member, the client and the sender of a step-down on it.
1859
+ * - each member: the stock image, its server as the child of a shell. A log consumer reads its
1860
+ * JSON log. The first member starts the set with the address of each member, and the lab
1861
+ * waits for a primary.
1862
+ * - an injector sidecar for each member, in its network and process namespaces.
1863
+ * - a client that holds its own network namespace, with a privileged sidecar for its sysctls.
1864
+ * - the prober, which watches the namespace of the client.
1865
+ */
1866
+ export declare const openReplicaSetLab: (set: ReplicaSet) => Promise<ReplicaSetLab>;
1867
+ /** This function gives the arguments of the client of a replica set cell: each member, and the stream of writes. */
1868
+ export declare const replicaSetArgs: (cell: Cell, members: Readonly<Record<string, RunPart>>) => string[];
1869
+ /**
1870
+ * This function does one run of a replica set cell:
1871
+ * - The set converges, and its writes go. The client finds the primary with its monitors, and its
1872
+ * stream of writes gets steady.
1873
+ * - The fault occurs on its member, as the primary of this run makes the roles. A fault with a
1874
+ * hold lifts at its instant in the VM. A stall lifts at its length after the first write into
1875
+ * it. A step-down is replSetStepDown to the primary.
1876
+ * - The run waits for its outcome: the first accepted write of a write sent after the commit of
1877
+ * the fault. It is on a new primary, or on any primary. Then the run waits for the end of the
1878
+ * hold, thus the record shows what the set did in the whole hold.
1879
+ * - Each fault goes, the client stops, and the set converges again. The writes that it then holds
1880
+ * tell which writes it kept. The log lines of the members go onto the monotonic clock.
1881
+ */
1882
+ export declare const replicaSetOnce: (lab: ReplicaSetLab, cell: Cell, environment: number, index: number) => Promise<Run>;
1883
+ //#endregion
1494
1884
  //#region src/run.d.ts
1495
1885
  /** A cell result is a cell with its manifests, its runs, their measurements and its verdict. */
1496
1886
  interface CellResult {
@@ -1539,5 +1929,5 @@ export declare const spread: (runs: number, environments: number) => number[];
1539
1929
  */
1540
1930
  export declare const runCell: (cell: Cell, say?: (line: string) => void) => Promise<CellResult>;
1541
1931
  //#endregion
1542
- export type { Agent, Cell, CellResult, Client, ClientImage, Crossings, Decision, ErrorOnTheWay, Fault, FaultPlace, FaultSide, Group, GroupClient, GroupLab, GroupMeasured, GroupNetworkFault, GroupPlace, GroupPrediction, GroupReading, GroupRole, GroupVerdict, GroupView, Hop, HopPlace, HttpProbe, Interval, KernelRecord, Lab, Manifest, ManifestHop, Measured, MiddleboxEvent, MiddleboxExpectation, MiddleboxForm, NetworkFault, Observer, Outcome, Prediction, Probe, ProbeEvent, ProxyHop, ProxyTime, Recovers, Reference, Reordering, Replies, RequestPrediction, RequestReading, RouterHop, RttRange, Run, RunGroup, RunPart, RunTopology, SentinelEvent, SocketPlace, Spread, Stage, StageBand, StageVerdict, Stamp, Target, Topology, Toxic, Verdict, Writes };
1932
+ export type { Agent, Cell, CellResult, Client, ClientImage, Crossings, Cut, Decision, DriverBand, DriverSocket, DriverStep, DriverStepTime, ErrorOnTheWay, Fault, FaultPlace, FaultSide, Group, GroupClient, GroupLab, GroupMeasured, GroupNetworkFault, GroupPlace, GroupPrediction, GroupReading, GroupRole, GroupVerdict, GroupView, Hop, HopPlace, HttpProbe, Interval, KernelRecord, Lab, LineMatch, Manifest, ManifestHop, Measured, MemberLine, MiddleboxEvent, MiddleboxExpectation, MiddleboxForm, NetworkFault, Observer, Outcome, Prediction, Probe, ProbeEvent, ProxyHop, ProxyTime, Recovers, Reference, Reordering, ReplicaSet, ReplicaSetLab, ReplicaSetStage, Replies, RequestPrediction, RequestReading, RouterHop, RttRange, Run, RunGroup, RunPart, RunTopology, SentinelEvent, SentinelStage, SocketPlace, Spread, Stage, StageBand, StageVerdict, Stamp, Status, Target, Topology, Toxic, Verdict, Writes };
1543
1933
  //# sourceMappingURL=index.d.ts.map