@mark1russell7/harness 0.9.0 → 0.10.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/README.md +1 -0
- package/build/index.d.ts +7 -1
- package/build/index.js +10 -4
- package/build/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -208,6 +208,7 @@ Each run starts from kernels that keep nothing from the run before it (`lab.forg
|
|
|
208
208
|
- Each wait goes from a `reconnecting` line, where the program starts its timer, to its next `dial` line, where it makes the socket. A wait outside its band, widened by δ_abs, is a finding. A try that did not come is a finding too.
|
|
209
209
|
- The kernel gives the time from the detection to the first SYN of a new socket (`syn`). It also gives the time to the first new socket in ESTABLISHED (`established`).
|
|
210
210
|
- It also gives the time from each `dial` line to its SYN (`connects`): the work of the program before connect(2).
|
|
211
|
+
- A measurement-only prediction can give `reconnects` too. The end of its connection has no band, but each wait has one. A wait outside its band is a finding of its run, and the verdict names that run. The decision stays `measured`.
|
|
211
212
|
- **A call in flight of a WebSocket client** (`callOf`). The run gives its error or its reply, and the time from the detection to its end.
|
|
212
213
|
- **A stream.** In a stream (`probe.mode` is `stream`), the client sends `count` requests. The run keeps the time from each send to the last byte of its reply (`samples`). A record without `replied` lines gives the time to the first data.
|
|
213
214
|
- **Reordering.** A measurement-only run also gives what reordering, duplicates and losses did (`reordering`). At the client, it counts the arrivals beyond a hole and the arrivals of data that it had already, against `rcv_nxt`. From the sender, it gives the most SACKed and lost segments, the DSACKs, the fast retransmissions, and the reordering degree and count of the kernel.
|
package/build/index.d.ts
CHANGED
|
@@ -426,7 +426,8 @@ interface Reconnects {
|
|
|
426
426
|
* A cell whose outcome is a distribution, for example under netem loss, has no band. Its
|
|
427
427
|
* prediction is `detects: null` with the reason, and its runs are measurements only. A
|
|
428
428
|
* measurement-only cell that names a reference (`from`) also records the time from it to the end
|
|
429
|
-
* of the connection, or to the last data.
|
|
429
|
+
* of the connection, or to the last data. It can also give the waits of the reconnect after that
|
|
430
|
+
* end (`reconnects`).
|
|
430
431
|
*
|
|
431
432
|
* For a group cell, the band is the first write that a primary accepts after the fault, and its
|
|
432
433
|
* errno is `OK`. `group` tells which primary, and the stages of the group on the way.
|
|
@@ -491,6 +492,11 @@ type Prediction = {
|
|
|
491
492
|
readonly ends?: "own-close";
|
|
492
493
|
readonly group?: GroupPrediction;
|
|
493
494
|
readonly request?: RequestPrediction;
|
|
495
|
+
/**
|
|
496
|
+
* These are the waits of the reconnect after the end of the connection, from the document of
|
|
497
|
+
* the client. The end has no band, but each wait has one. A wait outside its band is a finding of its run.
|
|
498
|
+
*/
|
|
499
|
+
readonly reconnects?: Reconnects;
|
|
494
500
|
};
|
|
495
501
|
/** A target is the server that a cell connects to: a stock image. */
|
|
496
502
|
interface Target {
|
package/build/index.js
CHANGED
|
@@ -329,13 +329,15 @@ const verdictOfBand = (prediction, runs, delta = NOISE) => {
|
|
|
329
329
|
}
|
|
330
330
|
const outcomes = [...kinds].map(([kind, n]) => `${n} ${kind}`).join(", ");
|
|
331
331
|
const timed = times.length === 0 ? "no time" : `median ${s(middle(times)).value} s from ${prediction.from}, range [${s(times[0]).value}, ${s(times.at(-1)).value}] s`;
|
|
332
|
+
const missed = outside.filter((each) => counted.some((run) => name(run) === each.run && run.reconnect !== void 0));
|
|
333
|
+
const late = missed.length === 0 ? "" : ` ${missed.length} runs had a wait of the reconnect outside its band.`;
|
|
332
334
|
return {
|
|
333
335
|
...empty,
|
|
334
336
|
decision: "measured",
|
|
335
337
|
band: null,
|
|
336
|
-
outside:
|
|
338
|
+
outside: missed,
|
|
337
339
|
median: times.length === 0 ? null : s(middle(times)),
|
|
338
|
-
why: `${counted.length} runs measured: ${outcomes}; ${timed}
|
|
340
|
+
why: `${counted.length} runs measured: ${outcomes}; ${timed}.${late} ${prediction.why}`
|
|
339
341
|
};
|
|
340
342
|
}
|
|
341
343
|
const samples = counted.flatMap((run) => (run.samples ?? []).map((sample) => valueIn(sample, "s"))).sort((a, b) => a - b);
|
|
@@ -1674,10 +1676,14 @@ const measureSocket = (cell, run) => {
|
|
|
1674
1676
|
toward: "target"
|
|
1675
1677
|
}
|
|
1676
1678
|
}, run)) };
|
|
1679
|
+
const reconnect = prediction.reconnects === void 0 || ended === void 0 ? void 0 : reconnectOf(run, ended, cookie, drop?.line.t ?? ended);
|
|
1680
|
+
const late = reconnect === void 0 || prediction.reconnects === void 0 ? null : reconnectFinding(prediction.reconnects, reconnect, noiseOf(cell));
|
|
1677
1681
|
return {
|
|
1678
1682
|
...base,
|
|
1679
1683
|
...nothing,
|
|
1680
1684
|
...chain,
|
|
1685
|
+
...reconnect === void 0 ? {} : { reconnect },
|
|
1686
|
+
finding: late,
|
|
1681
1687
|
outcome: ended !== void 0 ? outcome : { kind: "answered" },
|
|
1682
1688
|
...from === void 0 || until === void 0 ? {} : { elapsed: between(from, until) },
|
|
1683
1689
|
noticed: prediction.from === void 0 ? null : noticed,
|
|
@@ -4154,7 +4160,7 @@ const probeArgs = (cell, lab) => {
|
|
|
4154
4160
|
];
|
|
4155
4161
|
if (probe.ws !== void 0) {
|
|
4156
4162
|
const { ws } = probe;
|
|
4157
|
-
const waits = (prediction.detects
|
|
4163
|
+
const waits = (prediction.detects !== false ? prediction.reconnects?.waits ?? [] : []).reduce((sum, wait) => sum + valueIn(wait.high, "s"), 0);
|
|
4158
4164
|
args.push("--websocket", ws.socket);
|
|
4159
4165
|
args.push("--heartbeat", ws.heartbeat === null ? "off" : "on");
|
|
4160
4166
|
if (ws.heartbeat !== null) args.push("--heartbeat-interval-ms", String(valueIn(ws.heartbeat.interval, "ms")), "--heartbeat-timeout-ms", String(valueIn(ws.heartbeat.timeout, "ms")), "--heartbeat-misses", String(ws.heartbeat.misses));
|
|
@@ -4531,7 +4537,7 @@ const once = async (lab, cell, environment, index, dry = false) => {
|
|
|
4531
4537
|
if (toxicFirst) await lab.toxic(null);
|
|
4532
4538
|
}
|
|
4533
4539
|
if (cell.fault === "freeze-process" && !server && cell.probe.mode !== "idle") await probe.until(["data"], 5e3).catch(() => void 0);
|
|
4534
|
-
const expected = cell.prediction.detects
|
|
4540
|
+
const expected = cell.prediction.detects !== false ? cell.prediction.reconnects : void 0;
|
|
4535
4541
|
if (expected !== void 0) {
|
|
4536
4542
|
const waits = expected.waits.reduce((sum, wait) => sum + valueIn(wait.high, "s"), 0);
|
|
4537
4543
|
await dials(probe, 1 + expected.waits.length, waits * 2e3 + 5e3);
|