@systemfsoftware/stryker-js 15.0.0 → 16.0.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/CHANGELOG.md +44 -0
- package/README.md +12 -6
- package/dist/{Run.schema-B1HZugu9.d.mts → Run.schema-CgcTsB1w.d.mts} +1 -1
- package/dist/{RunEnvironment.service-B1bsWOQ9.d.mts → RunEnvironment.service-F8LgeCqh.d.mts} +90 -18
- package/dist/config.d.mts +2 -2
- package/dist/config.mjs +1 -1
- package/dist/events.d.mts +1 -1
- package/dist/{index-Cf9G6kA8.d.mts → index-DEphx668.d.mts} +11 -2
- package/dist/index.d.mts +11 -6
- package/dist/index.mjs +3 -2
- package/dist/main.mjs +2077 -1350
- package/dist/{merge-config-zsGl1aWc.mjs → merge-config-BYhhPA7r.mjs} +12 -5
- package/dist/{merge-config-BdQdK3PM.d.mts → merge-config-b06M-Ccx.d.mts} +2 -2
- package/dist/promises.d.mts +2 -2
- package/dist/promises.mjs +1 -1
- package/dist/{run-stages-aBT_QAfO.mjs → run-stages-k4L7ymmp.mjs} +570 -254
- package/package.json +10 -10
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { t as __exportAll$4 } from "./rolldown-runtime-8H4AJuhK.mjs";
|
|
2
|
-
import { a as MutatorCatalog_exports, c as Plugin_exports, d as TestRunner_exports, f as Trace_exports$1, i as Mutant_exports, l as Report_exports, n as mergeConfigs, o as MutatorProvider_exports, r as Checker_exports, s as Options_exports, t as mergeConfig, u as Reporter_exports } from "./merge-config-
|
|
2
|
+
import { a as MutatorCatalog_exports, c as Plugin_exports, d as TestRunner_exports, f as Trace_exports$1, i as Mutant_exports, l as Report_exports, n as mergeConfigs, o as MutatorProvider_exports, r as Checker_exports, s as Options_exports, t as mergeConfig, u as Reporter_exports } from "./merge-config-BYhhPA7r.mjs";
|
|
3
3
|
import { n as StageError, t as PrepareError } from "./Run.schema-DuaneDGd.mjs";
|
|
4
4
|
import { Blueprint, Cell, Handle, Sandwich, Workflow } from "@systemfsoftware/effect-cell-types";
|
|
5
5
|
import * as S from "effect/Schema";
|
|
@@ -28,12 +28,12 @@ import * as Path from "effect/Path";
|
|
|
28
28
|
import * as Stream from "effect/Stream";
|
|
29
29
|
import * as Config from "effect/Config";
|
|
30
30
|
import * as Clock from "effect/Clock";
|
|
31
|
-
import * as Exit from "effect/Exit";
|
|
32
31
|
import * as Layer from "effect/Layer";
|
|
33
32
|
import * as Queue from "effect/Queue";
|
|
34
33
|
import * as Scope from "effect/Scope";
|
|
35
34
|
import * as HashMap from "effect/HashMap";
|
|
36
35
|
import * as MutableHashMap from "effect/MutableHashMap";
|
|
36
|
+
import * as Exit from "effect/Exit";
|
|
37
37
|
import * as api from "@opentelemetry/api";
|
|
38
38
|
import * as Headers from "effect/http/Headers";
|
|
39
39
|
import * as Tracer from "effect/Tracer";
|
|
@@ -46,7 +46,6 @@ import * as HashSet from "effect/HashSet";
|
|
|
46
46
|
import * as PubSub from "effect/PubSub";
|
|
47
47
|
import * as SynchronizedRef from "effect/SynchronizedRef";
|
|
48
48
|
import * as RpcClient from "effect/rpc/RpcClient";
|
|
49
|
-
import * as Schedule from "effect/Schedule";
|
|
50
49
|
import * as DateTime from "effect/DateTime";
|
|
51
50
|
import * as Ref from "effect/Ref";
|
|
52
51
|
import * as Sink from "effect/Sink";
|
|
@@ -60,6 +59,7 @@ import * as NodeCrypto from "@effect/platform-node-shared/NodeCrypto";
|
|
|
60
59
|
import * as Crypto from "effect/Crypto";
|
|
61
60
|
import * as ChildProcess from "effect/process/ChildProcess";
|
|
62
61
|
import * as ChildProcessSpawner from "effect/process/ChildProcessSpawner";
|
|
62
|
+
import * as Deferred from "effect/Deferred";
|
|
63
63
|
import * as FiberSet from "effect/FiberSet";
|
|
64
64
|
import { RpcClientError } from "effect/rpc/RpcClientError";
|
|
65
65
|
import * as Socket from "effect/socket/Socket";
|
|
@@ -185,7 +185,32 @@ const PluginLoadFailureReason = Schema.Union([
|
|
|
185
185
|
Schema.TaggedStruct("InvalidContribution", { detail: Schema.String }),
|
|
186
186
|
Schema.TaggedStruct("ImportFailed", { cause: Schema.Unknown })
|
|
187
187
|
]);
|
|
188
|
-
const
|
|
188
|
+
const ShardPlanVersion = S.Literal(1);
|
|
189
|
+
const ShardProject = S.Struct({
|
|
190
|
+
project: S.String,
|
|
191
|
+
mutants: S.Array(S.String)
|
|
192
|
+
});
|
|
193
|
+
const Shard = S.Struct({
|
|
194
|
+
index: S.Int,
|
|
195
|
+
count: S.Int,
|
|
196
|
+
predictedSeconds: S.Finite,
|
|
197
|
+
projects: S.Array(ShardProject)
|
|
198
|
+
});
|
|
199
|
+
const labelOf = (shard) => `${shard.index}/${shard.count}`;
|
|
200
|
+
const shardLabelsAreUnique = S.makeFilter((shards) => {
|
|
201
|
+
const duplicated = Mutant_exports.duplicatedValue(shards.map(labelOf));
|
|
202
|
+
return duplicated === void 0 ? void 0 : `shard plan shards share the label "${duplicated}"`;
|
|
203
|
+
}, { arbitraryConstraint: { uniqueBy: labelOf } });
|
|
204
|
+
const ShardPlan = S.Struct({
|
|
205
|
+
version: ShardPlanVersion,
|
|
206
|
+
targetSeconds: S.Finite,
|
|
207
|
+
shards: S.Array(Shard).check(shardLabelsAreUnique),
|
|
208
|
+
matrix: S.Struct({ include: S.Array(S.Struct({
|
|
209
|
+
shard: S.String,
|
|
210
|
+
predictedSeconds: S.Finite
|
|
211
|
+
})) })
|
|
212
|
+
});
|
|
213
|
+
const StreamSchemaVersion = S.Literal("6.0");
|
|
189
214
|
const RunPhase = S.Literals([
|
|
190
215
|
"prepare",
|
|
191
216
|
"instrument",
|
|
@@ -203,8 +228,18 @@ var PhaseEntered = class extends S.TaggedClass()("phase", {
|
|
|
203
228
|
phase: RunPhase,
|
|
204
229
|
elapsedMs: Report_exports.NonNegativeFinite
|
|
205
230
|
}) {};
|
|
206
|
-
var PlanKnown = class extends S.TaggedClass()("plan", {
|
|
207
|
-
|
|
231
|
+
var PlanKnown = class extends S.TaggedClass()("plan", {
|
|
232
|
+
total: Report_exports.NonNegativeInt,
|
|
233
|
+
shardPlan: S.NullOr(ShardPlan)
|
|
234
|
+
}) {};
|
|
235
|
+
const WorkerRole = S.Literals(["testRunner", "checker"]);
|
|
236
|
+
var WorkerReported = class extends S.TaggedClass()("worker", {
|
|
237
|
+
schemaVersion: StreamSchemaVersion,
|
|
238
|
+
role: WorkerRole,
|
|
239
|
+
index: Report_exports.NonNegativeInt,
|
|
240
|
+
startupMs: Report_exports.NonNegativeFinite
|
|
241
|
+
}) {};
|
|
242
|
+
const MutantCost$1 = S.Struct({
|
|
208
243
|
fixedOverheadMs: Report_exports.NonNegativeFinite,
|
|
209
244
|
testBodyMs: Report_exports.NonNegativeFinite,
|
|
210
245
|
testsExecuted: Report_exports.NonNegativeInt,
|
|
@@ -226,7 +261,7 @@ var RunMutantTestedEvent = class extends S.TaggedClass()("mutantTested", {
|
|
|
226
261
|
completed: Report_exports.NonNegativeInt,
|
|
227
262
|
total: Report_exports.NonNegativeInt,
|
|
228
263
|
static: S.Boolean,
|
|
229
|
-
cost: S.NullOr(MutantCost)
|
|
264
|
+
cost: S.NullOr(MutantCost$1)
|
|
230
265
|
}) {};
|
|
231
266
|
const RunMutantTested = S.TaggedStruct("mutant", {
|
|
232
267
|
id: Mutant_exports.MutantId,
|
|
@@ -238,7 +273,7 @@ const RunMutantTested = S.TaggedStruct("mutant", {
|
|
|
238
273
|
completed: Report_exports.NonNegativeInt,
|
|
239
274
|
total: Report_exports.NonNegativeInt,
|
|
240
275
|
static: S.Boolean,
|
|
241
|
-
cost: S.NullOr(MutantCost)
|
|
276
|
+
cost: S.NullOr(MutantCost$1)
|
|
242
277
|
}).pipe(S.decodeTo(S.toType(RunMutantTestedEvent), {
|
|
243
278
|
decode: SchemaGetter.transform((line) => RunMutantTestedEvent.make({
|
|
244
279
|
id: line.id,
|
|
@@ -290,6 +325,7 @@ const VerdictMutant = S.Struct({
|
|
|
290
325
|
});
|
|
291
326
|
const RunScope = S.Literals(["full", "diff"]);
|
|
292
327
|
const MutantSetPolicy = S.Literals(["default", "full"]);
|
|
328
|
+
const IncrementalMode = S.Literals(["incremental", "full"]);
|
|
293
329
|
const PhaseDurations = S.Struct({
|
|
294
330
|
prepare: Report_exports.NonNegativeFinite,
|
|
295
331
|
instrument: Report_exports.NonNegativeFinite,
|
|
@@ -300,6 +336,10 @@ const StaticVerdict = S.Struct({
|
|
|
300
336
|
count: Report_exports.NonNegativeInt,
|
|
301
337
|
costMs: Report_exports.NonNegativeFinite
|
|
302
338
|
});
|
|
339
|
+
const Budget = S.Struct({
|
|
340
|
+
predictedSeconds: Report_exports.NonNegativeFinite,
|
|
341
|
+
actualSeconds: Report_exports.NonNegativeFinite
|
|
342
|
+
});
|
|
303
343
|
var VerdictReached = class extends S.TaggedClass()("verdict", {
|
|
304
344
|
schemaVersion: StreamSchemaVersion,
|
|
305
345
|
runId: RunId,
|
|
@@ -312,8 +352,10 @@ var VerdictReached = class extends S.TaggedClass()("verdict", {
|
|
|
312
352
|
mutants: S.Array(VerdictMutant),
|
|
313
353
|
scope: RunScope,
|
|
314
354
|
mutantSetPolicy: MutantSetPolicy,
|
|
355
|
+
incrementalMode: S.optionalKey(IncrementalMode),
|
|
315
356
|
phaseDurations: S.NullOr(PhaseDurations),
|
|
316
|
-
static: S.NullOr(StaticVerdict)
|
|
357
|
+
static: S.NullOr(StaticVerdict),
|
|
358
|
+
budget: Budget
|
|
317
359
|
}) {};
|
|
318
360
|
const FrameworkContributionRow = S.Struct({
|
|
319
361
|
name: S.String,
|
|
@@ -360,6 +402,10 @@ var ReuseReported = class extends S.TaggedClass()("reuse", {
|
|
|
360
402
|
ran: Report_exports.NonNegativeInt,
|
|
361
403
|
refused: ReuseRefusals
|
|
362
404
|
}) {};
|
|
405
|
+
var TceReported = class extends S.TaggedClass()("tce", {
|
|
406
|
+
equivalentToOriginal: Report_exports.NonNegativeInt,
|
|
407
|
+
duplicateAtSite: Report_exports.NonNegativeInt
|
|
408
|
+
}) {};
|
|
363
409
|
var MutantDetailReported = class extends S.TaggedClass()("mutant-detail", {
|
|
364
410
|
id: Mutant_exports.MutantId,
|
|
365
411
|
status: Mutant_exports.MutantStatusSchema,
|
|
@@ -385,27 +431,37 @@ var HelpRendered = class extends S.TaggedClass()("help", {
|
|
|
385
431
|
code: S.Literals([0]),
|
|
386
432
|
help: S.String
|
|
387
433
|
}) {};
|
|
434
|
+
const RefusalRule = S.Literal("mutation-runs-on-main-ci");
|
|
435
|
+
var Refused = class extends S.TaggedClass()("refused", {
|
|
436
|
+
schemaVersion: StreamSchemaVersion,
|
|
437
|
+
rule: RefusalRule,
|
|
438
|
+
message: S.String
|
|
439
|
+
}) {};
|
|
388
440
|
const RunEvent = Object.assign(S.Union([
|
|
389
441
|
RunStarted,
|
|
390
442
|
PhaseEntered,
|
|
391
443
|
PlanKnown,
|
|
444
|
+
WorkerReported,
|
|
392
445
|
RunMutantTested,
|
|
393
446
|
Heartbeat,
|
|
394
447
|
PluginsReported,
|
|
395
448
|
FormatRegistryResolved,
|
|
396
449
|
SkippedReported,
|
|
397
450
|
ReuseReported,
|
|
451
|
+
TceReported,
|
|
398
452
|
MutantDetailReported,
|
|
399
453
|
FeedbackReported,
|
|
400
454
|
VerdictReached,
|
|
401
455
|
RunFailed,
|
|
402
|
-
HelpRendered
|
|
456
|
+
HelpRendered,
|
|
457
|
+
Refused
|
|
403
458
|
]), { QUEUE_BOUND: 256 });
|
|
404
459
|
const RunEventWireLine = S.String.pipe(S.decodeTo(S.fromJsonString(RunEvent), {
|
|
405
460
|
decode: SchemaGetter$1.transform((line) => line.replace(/\n$/, "")),
|
|
406
461
|
encode: SchemaGetter$1.transform((json) => `${json}\n`)
|
|
407
462
|
}));
|
|
408
463
|
var RunEvent_exports = /* @__PURE__ */ __exportAll$3({
|
|
464
|
+
Budget: () => Budget,
|
|
409
465
|
FeedbackJudgment: () => FeedbackJudgment,
|
|
410
466
|
FeedbackReported: () => FeedbackReported,
|
|
411
467
|
FormatClaimShadowingRow: () => FormatClaimShadowingRow,
|
|
@@ -415,7 +471,8 @@ var RunEvent_exports = /* @__PURE__ */ __exportAll$3({
|
|
|
415
471
|
FrameworkModuleRow: () => FrameworkModuleRow,
|
|
416
472
|
Heartbeat: () => Heartbeat,
|
|
417
473
|
HelpRendered: () => HelpRendered,
|
|
418
|
-
|
|
474
|
+
IncrementalMode: () => IncrementalMode,
|
|
475
|
+
MutantCost: () => MutantCost$1,
|
|
419
476
|
MutantDetailReported: () => MutantDetailReported,
|
|
420
477
|
MutantSetPolicy: () => MutantSetPolicy,
|
|
421
478
|
PhaseDurations: () => PhaseDurations,
|
|
@@ -423,6 +480,8 @@ var RunEvent_exports = /* @__PURE__ */ __exportAll$3({
|
|
|
423
480
|
PlanKnown: () => PlanKnown,
|
|
424
481
|
PluginLoadFailureReason: () => PluginLoadFailureReason,
|
|
425
482
|
PluginsReported: () => PluginsReported,
|
|
483
|
+
RefusalRule: () => RefusalRule,
|
|
484
|
+
Refused: () => Refused,
|
|
426
485
|
ReuseRefusals: () => ReuseRefusals,
|
|
427
486
|
ReuseReported: () => ReuseReported,
|
|
428
487
|
RunEvent: () => RunEvent,
|
|
@@ -438,10 +497,13 @@ var RunEvent_exports = /* @__PURE__ */ __exportAll$3({
|
|
|
438
497
|
SkippedReported: () => SkippedReported,
|
|
439
498
|
StaticVerdict: () => StaticVerdict,
|
|
440
499
|
StreamSchemaVersion: () => StreamSchemaVersion,
|
|
500
|
+
TceReported: () => TceReported,
|
|
441
501
|
VerdictLocation: () => VerdictLocation,
|
|
442
502
|
VerdictMutant: () => VerdictMutant,
|
|
443
503
|
VerdictReached: () => VerdictReached,
|
|
444
|
-
VerdictThresholds: () => VerdictThresholds
|
|
504
|
+
VerdictThresholds: () => VerdictThresholds,
|
|
505
|
+
WorkerReported: () => WorkerReported,
|
|
506
|
+
WorkerRole: () => WorkerRole
|
|
445
507
|
});
|
|
446
508
|
const SpanName = S.String.check(S.isPattern(/^[A-Za-z][A-Za-z0-9_-]*(?:\.[A-Za-z][A-Za-z0-9_-]*)*$/u, { expected: "a dot-separated span name whose segments start with a letter, such as \"stryker.checker.check\"" })).pipe(S.brand("SpanName"));
|
|
447
509
|
const SpanAttributeKey = S.String.check(S.isPattern(/^[A-Za-z][A-Za-z0-9_.-]*$/u, { expected: "an attribute key starting with a letter, such as \"stryker.checker.name\"" })).pipe(S.brand("SpanAttributeKey"));
|
|
@@ -688,74 +750,6 @@ const Spans = {
|
|
|
688
750
|
name: "stryker.load_config",
|
|
689
751
|
attributes: {}
|
|
690
752
|
},
|
|
691
|
-
mergeReports: {
|
|
692
|
-
name: "stryker.merge_reports",
|
|
693
|
-
attributes: {}
|
|
694
|
-
},
|
|
695
|
-
mergeReportsCollectPartDirs: {
|
|
696
|
-
name: "stryker.merge_reports.collect_part_dirs",
|
|
697
|
-
attributes: {}
|
|
698
|
-
},
|
|
699
|
-
mergeReportsDirectoryExists: {
|
|
700
|
-
name: "stryker.merge_reports.directory_exists",
|
|
701
|
-
attributes: {}
|
|
702
|
-
},
|
|
703
|
-
mergeReportsEncodeReport: {
|
|
704
|
-
name: "stryker.merge_reports.encode_report",
|
|
705
|
-
attributes: {}
|
|
706
|
-
},
|
|
707
|
-
mergeReportsFail: {
|
|
708
|
-
name: "stryker.merge_reports.fail",
|
|
709
|
-
attributes: {}
|
|
710
|
-
},
|
|
711
|
-
mergeReportsGather: {
|
|
712
|
-
name: "stryker.merge_reports.gather",
|
|
713
|
-
attributes: {}
|
|
714
|
-
},
|
|
715
|
-
mergeReportsListNames: {
|
|
716
|
-
name: "stryker.merge_reports.list_names",
|
|
717
|
-
attributes: {}
|
|
718
|
-
},
|
|
719
|
-
mergeReportsPutFile: {
|
|
720
|
-
name: "stryker.merge_reports.put_file",
|
|
721
|
-
attributes: {}
|
|
722
|
-
},
|
|
723
|
-
mergeReportsReadPart: {
|
|
724
|
-
name: "stryker.merge_reports.read_part",
|
|
725
|
-
attributes: {}
|
|
726
|
-
},
|
|
727
|
-
mergeReportsReadText: {
|
|
728
|
-
name: "stryker.merge_reports.read_text",
|
|
729
|
-
attributes: {}
|
|
730
|
-
},
|
|
731
|
-
mergeReportsRefuseCommand: {
|
|
732
|
-
name: "stryker.merge_reports.refuse_command",
|
|
733
|
-
attributes: {}
|
|
734
|
-
},
|
|
735
|
-
mergeReportsRefuseParts: {
|
|
736
|
-
name: "stryker.merge_reports.refuse_parts",
|
|
737
|
-
attributes: {}
|
|
738
|
-
},
|
|
739
|
-
mergeReportsRenderHtml: {
|
|
740
|
-
name: "stryker.merge_reports.render_html",
|
|
741
|
-
attributes: {}
|
|
742
|
-
},
|
|
743
|
-
mergeReportsWriteAbsent: {
|
|
744
|
-
name: "stryker.merge_reports.write_absent",
|
|
745
|
-
attributes: {}
|
|
746
|
-
},
|
|
747
|
-
mergeReportsWriteFiles: {
|
|
748
|
-
name: "stryker.merge_reports.write_files",
|
|
749
|
-
attributes: {}
|
|
750
|
-
},
|
|
751
|
-
mergeReportsWriteHtml: {
|
|
752
|
-
name: "stryker.merge_reports.write_html",
|
|
753
|
-
attributes: {}
|
|
754
|
-
},
|
|
755
|
-
mergeReportsWriteMerged: {
|
|
756
|
-
name: "stryker.merge_reports.write_merged",
|
|
757
|
-
attributes: {}
|
|
758
|
-
},
|
|
759
753
|
mutantRun: {
|
|
760
754
|
name: "stryker.mutant_run",
|
|
761
755
|
attributes: {}
|
|
@@ -10244,6 +10238,48 @@ const resolveConfig = Workflow.make({
|
|
|
10244
10238
|
})
|
|
10245
10239
|
});
|
|
10246
10240
|
//#endregion
|
|
10241
|
+
//#region src/atomic-write.cell.ts
|
|
10242
|
+
const writeFileAtomic = Effect$1.fn(SpanTaxonomy_exports.Spans.mutationReportingWriteAtomic.name)(function* (ports, file, content) {
|
|
10243
|
+
const directory = ports.path.dirname(file);
|
|
10244
|
+
yield* ports.fs.makeDirectory(directory, { recursive: true });
|
|
10245
|
+
const temp = yield* ports.fs.makeTempFile({
|
|
10246
|
+
directory,
|
|
10247
|
+
prefix: `${ports.path.basename(file)}.`,
|
|
10248
|
+
suffix: ".tmp"
|
|
10249
|
+
});
|
|
10250
|
+
yield* Effect$1.gen(function* () {
|
|
10251
|
+
yield* ports.fs.writeFileString(temp, content);
|
|
10252
|
+
yield* ports.fs.rename(temp, file);
|
|
10253
|
+
}).pipe(Effect$1.onExit((exit) => Exit.isSuccess(exit) ? Effect$1.void : ports.fs.remove(temp).pipe(Effect$1.ignore)));
|
|
10254
|
+
});
|
|
10255
|
+
//#endregion
|
|
10256
|
+
//#region src/mutant-cost.ts
|
|
10257
|
+
const executedTestBodyMsOf = (executedTests) => executedTests.reduce((total, test) => total + test.timeSpentMs, 0);
|
|
10258
|
+
const testBodyMsOf = (result) => Match$1.value(result).pipe(Match$1.when({ status: "killed" }, (killed) => executedTestBodyMsOf(killed.executedTests)), Match$1.when({ status: "survived" }, (survived) => executedTestBodyMsOf(survived.executedTests)), Match$1.orElse(() => 0));
|
|
10259
|
+
const bodyTimeWithinWall = (elapsedMs, testBodyMs) => Math.min(testBodyMs, elapsedMs);
|
|
10260
|
+
const costTotalMsOf = (cost) => cost === void 0 ? void 0 : cost.fixedOverheadMs + cost.testBodyMs;
|
|
10261
|
+
const mutantCostOf = (input) => {
|
|
10262
|
+
const testBodyMs = bodyTimeWithinWall(input.elapsedMs, input.testBodyMs);
|
|
10263
|
+
return {
|
|
10264
|
+
fixedOverheadMs: input.elapsedMs - testBodyMs,
|
|
10265
|
+
testBodyMs,
|
|
10266
|
+
testsExecuted: input.testsExecuted,
|
|
10267
|
+
shared: input.shared
|
|
10268
|
+
};
|
|
10269
|
+
};
|
|
10270
|
+
//#endregion
|
|
10271
|
+
//#region src/budget.ts
|
|
10272
|
+
const MILLIS_PER_SECOND = 1e3;
|
|
10273
|
+
const costMsOf = (result) => costTotalMsOf(result.cost) ?? 0;
|
|
10274
|
+
const predictedSecondsOf = (results, concurrency) => {
|
|
10275
|
+
const lanes = concurrency > 0 ? concurrency : 1;
|
|
10276
|
+
return Arr.reduce(results, 0, (total, result) => total + costMsOf(result)) / lanes / MILLIS_PER_SECOND;
|
|
10277
|
+
};
|
|
10278
|
+
const budgetOf$1 = (input) => ({
|
|
10279
|
+
predictedSeconds: input.planPredictedSeconds ?? predictedSecondsOf(input.results, input.concurrency),
|
|
10280
|
+
actualSeconds: input.actualSeconds
|
|
10281
|
+
});
|
|
10282
|
+
//#endregion
|
|
10247
10283
|
//#region src/build-reproducers.workflow.ts
|
|
10248
10284
|
const CONTEXT_LINES = 3;
|
|
10249
10285
|
const maxOf$1 = (left, right) => Boolean$1$1.match(left < right, {
|
|
@@ -10315,7 +10351,7 @@ const fileNameOrder = Order.mapInput(Order.String, (reproducer) => reproducer.fi
|
|
|
10315
10351
|
const idOrder$1 = Order.mapInput(Order.String, (reproducer) => reproducer.id);
|
|
10316
10352
|
const reproducersOf = (report) => Arr.sort(Arr.flatMap(Object.entries(report.files), ([fileName, file]) => Arr.map(file.mutants, (mutant) => reproducerOf(fileName, file.source, mutant))), Order.combine(fileNameOrder, idOrder$1));
|
|
10317
10353
|
const mutantsOf = (report) => Arr.flatMap(Object.values(report.files), (file) => file.mutants);
|
|
10318
|
-
const decide$
|
|
10354
|
+
const decide$24 = (command) => {
|
|
10319
10355
|
const mutants = mutantsOf(command.report);
|
|
10320
10356
|
return Boolean$1$1.match(mutants.length === 0, {
|
|
10321
10357
|
onTrue: () => NoMutantsToReproduce.make({}),
|
|
@@ -10326,7 +10362,7 @@ const buildReproducers = Workflow.make({
|
|
|
10326
10362
|
command: BuildReproducersCommand,
|
|
10327
10363
|
decision: BuildReproducersDecision,
|
|
10328
10364
|
error: S.Never,
|
|
10329
|
-
decide: (command) => Result.succeed(decide$
|
|
10365
|
+
decide: (command) => Result.succeed(decide$24(command))
|
|
10330
10366
|
});
|
|
10331
10367
|
//#endregion
|
|
10332
10368
|
//#region src/checkpoint-mutants.workflow.ts
|
|
@@ -10350,7 +10386,7 @@ var CheckpointMutantsCommand = class extends S.TaggedClass()("CheckpointMutantsC
|
|
|
10350
10386
|
};
|
|
10351
10387
|
const settledByIdOf = (settled) => HashMap.fromIterable(settled.map((row) => [row.mutant.id, row]));
|
|
10352
10388
|
const rowOf = (mutant, settledById) => Option$1.getOrElse(HashMap.get(settledById, mutant.id), () => CheckpointPendingMutant.make({ mutant }));
|
|
10353
|
-
const decide$
|
|
10389
|
+
const decide$23 = (command) => {
|
|
10354
10390
|
const settledById = settledByIdOf(command.settled);
|
|
10355
10391
|
return Result.succeed(command.plannedMutants.map((mutant) => rowOf(mutant, settledById)));
|
|
10356
10392
|
};
|
|
@@ -10358,7 +10394,7 @@ const checkpointMutants = Workflow.make({
|
|
|
10358
10394
|
command: CheckpointMutantsCommand,
|
|
10359
10395
|
decision: S.Array(CheckpointMutantRow),
|
|
10360
10396
|
error: S.Never,
|
|
10361
|
-
decide: decide$
|
|
10397
|
+
decide: decide$23
|
|
10362
10398
|
});
|
|
10363
10399
|
//#endregion
|
|
10364
10400
|
//#region src/classify-exit.workflow.ts
|
|
@@ -10407,7 +10443,7 @@ const verdictExitClass = (score, breakingThreshold) => Match$1.valueTags(score,
|
|
|
10407
10443
|
onSome: (threshold) => Match$1.value(percentage < threshold).pipe(Match$1.when(true, () => "VerdictFail"), Match$1.when(false, () => null), Match$1.exhaustive)
|
|
10408
10444
|
})
|
|
10409
10445
|
});
|
|
10410
|
-
const decide$
|
|
10446
|
+
const decide$22 = (command) => Option$1.match(Option$1.fromNullishOr(verdictExitClass(command.score, command.breakingThreshold)), {
|
|
10411
10447
|
onNone: () => Option$1.match(precedenceOf(command.pending), {
|
|
10412
10448
|
onNone: () => Result.succeed(ExitPassed.make({})),
|
|
10413
10449
|
onSome: (exitClass) => Result.succeed(decisionOf$3(exitClass))
|
|
@@ -10418,7 +10454,7 @@ const classifyExit = Workflow.make({
|
|
|
10418
10454
|
command: ClassifyExitCommand,
|
|
10419
10455
|
decision: ClassifyExitDecision,
|
|
10420
10456
|
error: S.Never,
|
|
10421
|
-
decide: decide$
|
|
10457
|
+
decide: decide$22
|
|
10422
10458
|
});
|
|
10423
10459
|
//#endregion
|
|
10424
10460
|
//#region src/IncrementalDiff.schema.ts
|
|
@@ -10480,6 +10516,61 @@ const ReuseReportSchema = S.Struct({
|
|
|
10480
10516
|
testFiles: S.optional(ReuseTestFilesSchema)
|
|
10481
10517
|
});
|
|
10482
10518
|
//#endregion
|
|
10519
|
+
//#region src/MutantCost.schema.ts
|
|
10520
|
+
const MutantCost = S.Struct({
|
|
10521
|
+
predictedMs: S.Finite,
|
|
10522
|
+
actualMs: S.NullOr(S.Finite),
|
|
10523
|
+
coveringTests: S.Int
|
|
10524
|
+
});
|
|
10525
|
+
const MutantCosts = S.Record(Mutant_exports.MutantId, MutantCost);
|
|
10526
|
+
const MutantCostSubject = S.Struct({
|
|
10527
|
+
id: Mutant_exports.MutantId,
|
|
10528
|
+
static: S.optional(S.Boolean)
|
|
10529
|
+
});
|
|
10530
|
+
S.Struct({
|
|
10531
|
+
subject: MutantCostSubject,
|
|
10532
|
+
staticCoverage: S.optional(S.Record(S.String, Report_exports.NonNegativeFinite)),
|
|
10533
|
+
allTestTimesMs: S.Array(Report_exports.NonNegativeFinite),
|
|
10534
|
+
coveringTestTimesMs: S.Array(Report_exports.NonNegativeFinite),
|
|
10535
|
+
executedActualMs: S.optional(Report_exports.NonNegativeFinite),
|
|
10536
|
+
priorActualMs: S.optional(Report_exports.NonNegativeFinite),
|
|
10537
|
+
fixedOverheadMs: Report_exports.NonNegativeFinite
|
|
10538
|
+
});
|
|
10539
|
+
S.Struct({
|
|
10540
|
+
subjects: S.Array(MutantCostSubject),
|
|
10541
|
+
staticCoverage: S.optional(S.Record(S.String, Report_exports.NonNegativeFinite)),
|
|
10542
|
+
allTestTimesMs: S.Array(Report_exports.NonNegativeFinite),
|
|
10543
|
+
coveringTestTimesMsByMutantId: S.Record(S.String, S.Array(Report_exports.NonNegativeFinite)),
|
|
10544
|
+
executedActualMsByMutantId: S.Record(S.String, Report_exports.NonNegativeFinite),
|
|
10545
|
+
priorActualMsByMutantId: S.Record(S.String, Report_exports.NonNegativeFinite),
|
|
10546
|
+
fixedOverheadMs: Report_exports.NonNegativeFinite
|
|
10547
|
+
});
|
|
10548
|
+
//#endregion
|
|
10549
|
+
//#region src/mutant-cost-model.ts
|
|
10550
|
+
const staticHitCountOf = (staticCoverage, id) => Option$1.getOrElse(Option$1.flatMap(Option$1.fromNullishOr(staticCoverage), (coverage) => Record$1.get(coverage, id)), () => 0);
|
|
10551
|
+
const hasStaticHit = (staticCoverage, id) => staticCoverage === void 0 || staticHitCountOf(staticCoverage, id) > 0;
|
|
10552
|
+
const runsWholeSuite$1 = (input) => input.subject.static === true || hasStaticHit(input.staticCoverage, input.subject.id);
|
|
10553
|
+
const coveringTimesOf = (input) => runsWholeSuite$1(input) ? input.allTestTimesMs : input.coveringTestTimesMs;
|
|
10554
|
+
const actualMsOf = (input) => Option$1.getOrElse(Option$1.firstSomeOf([Option$1.fromNullishOr(input.executedActualMs), Option$1.fromNullishOr(input.priorActualMs)]), () => null);
|
|
10555
|
+
const mutantCostOfCase = (input) => {
|
|
10556
|
+
const coveringTimes = coveringTimesOf(input);
|
|
10557
|
+
return {
|
|
10558
|
+
predictedMs: input.fixedOverheadMs + coveringTimes.reduce((total, time) => total + time, 0),
|
|
10559
|
+
actualMs: actualMsOf(input),
|
|
10560
|
+
coveringTests: coveringTimes.length
|
|
10561
|
+
};
|
|
10562
|
+
};
|
|
10563
|
+
const caseOfSubject = (input, subject) => ({
|
|
10564
|
+
subject,
|
|
10565
|
+
staticCoverage: input.staticCoverage,
|
|
10566
|
+
allTestTimesMs: input.allTestTimesMs,
|
|
10567
|
+
coveringTestTimesMs: Option$1.getOrElse(Record$1.get(input.coveringTestTimesMsByMutantId, subject.id), () => []),
|
|
10568
|
+
executedActualMs: Option$1.getOrUndefined(Record$1.get(input.executedActualMsByMutantId, subject.id)),
|
|
10569
|
+
priorActualMs: Option$1.getOrUndefined(Record$1.get(input.priorActualMsByMutantId, subject.id)),
|
|
10570
|
+
fixedOverheadMs: input.fixedOverheadMs
|
|
10571
|
+
});
|
|
10572
|
+
const mutantCostsOf = (input) => Object.fromEntries(input.subjects.map((subject) => [subject.id, mutantCostOfCase(caseOfSubject(input, subject))]));
|
|
10573
|
+
//#endregion
|
|
10483
10574
|
//#region src/mutation-reporting.schema.ts
|
|
10484
10575
|
var ManifestUnreadable = class extends Schema.TaggedError()("ManifestUnreadable", {
|
|
10485
10576
|
specifier: Schema.String,
|
|
@@ -10741,7 +10832,7 @@ var WorkerLauncher = class extends Context.Service()("@systemfsoftware/stryker-j
|
|
|
10741
10832
|
//#endregion
|
|
10742
10833
|
//#region src/worker-client.blueprint.ts
|
|
10743
10834
|
const TypeId$10 = Symbol.for("~systemfsoftware/stryker-js/WorkerClient");
|
|
10744
|
-
const
|
|
10835
|
+
const WORKER_BOOT_TIMEOUT = Duration.seconds(30);
|
|
10745
10836
|
const WorkerClients = () => Blueprint.make()(TypeId$10).steps({
|
|
10746
10837
|
steps: {},
|
|
10747
10838
|
targets: { scoped: Effect$1.fnUntraced(function* (params) {
|
|
@@ -10755,7 +10846,11 @@ const WorkerClients = () => Blueprint.make()(TypeId$10).steps({
|
|
|
10755
10846
|
tempDirPrefix: params.tempDirPrefix,
|
|
10756
10847
|
env: params.env
|
|
10757
10848
|
});
|
|
10758
|
-
const
|
|
10849
|
+
const bootTimedOut = () => Effect$1.fail(WorkerBootTimeoutError.make({ pid: worker.pid }));
|
|
10850
|
+
const protocol = yield* worker.pipe(clientLayer, Layer.build, Effect$1.raceFirst(worker.exited), Effect$1.timeoutOrElse({
|
|
10851
|
+
duration: WORKER_BOOT_TIMEOUT,
|
|
10852
|
+
orElse: bootTimedOut
|
|
10853
|
+
}), Effect$1.catchTag("SocketError", bootTimedOut));
|
|
10759
10854
|
const traceContext = yield* Layer.build(Trace_exports.layerTraceContextClient);
|
|
10760
10855
|
return yield* RpcClient.make(params.rpcs).pipe(Effect$1.provideContext(Context.merge(protocol, traceContext)));
|
|
10761
10856
|
}) }
|
|
@@ -11032,21 +11127,6 @@ S.Literal("mutation-part.json");
|
|
|
11032
11127
|
S.Literal("mutation-stream.jsonl");
|
|
11033
11128
|
const ReportFileNames = S.Record(S.String, Mutant_exports.CanonicalFileName);
|
|
11034
11129
|
//#endregion
|
|
11035
|
-
//#region src/mutant-cost.ts
|
|
11036
|
-
const executedTestBodyMsOf = (executedTests) => executedTests.reduce((total, test) => total + test.timeSpentMs, 0);
|
|
11037
|
-
const testBodyMsOf = (result) => Match$1.value(result).pipe(Match$1.when({ status: "killed" }, (killed) => executedTestBodyMsOf(killed.executedTests)), Match$1.when({ status: "survived" }, (survived) => executedTestBodyMsOf(survived.executedTests)), Match$1.orElse(() => 0));
|
|
11038
|
-
const bodyTimeWithinWall = (elapsedMs, testBodyMs) => Math.min(testBodyMs, elapsedMs);
|
|
11039
|
-
const costTotalMsOf = (cost) => cost === void 0 ? void 0 : cost.fixedOverheadMs + cost.testBodyMs;
|
|
11040
|
-
const mutantCostOf = (input) => {
|
|
11041
|
-
const testBodyMs = bodyTimeWithinWall(input.elapsedMs, input.testBodyMs);
|
|
11042
|
-
return {
|
|
11043
|
-
fixedOverheadMs: input.elapsedMs - testBodyMs,
|
|
11044
|
-
testBodyMs,
|
|
11045
|
-
testsExecuted: input.testsExecuted,
|
|
11046
|
-
shared: input.shared
|
|
11047
|
-
};
|
|
11048
|
-
};
|
|
11049
|
-
//#endregion
|
|
11050
11130
|
//#region src/reporting/static-verdict.ts
|
|
11051
11131
|
const costOrZero = (cost) => Option$1.getOrElse(Option$1.fromUndefinedOr(costTotalMsOf(cost)), () => 0);
|
|
11052
11132
|
const staticVerdictOf = (results) => {
|
|
@@ -11073,8 +11153,10 @@ var VerdictEnvelope = class extends S.Class("VerdictEnvelope")({
|
|
|
11073
11153
|
mutants: S.Array(RunEvent_exports.VerdictMutant),
|
|
11074
11154
|
scope: RunEvent_exports.RunScope,
|
|
11075
11155
|
mutantSetPolicy: RunEvent_exports.MutantSetPolicy,
|
|
11156
|
+
incrementalMode: RunEvent_exports.IncrementalMode,
|
|
11076
11157
|
phaseDurations: S.NullOr(RunEvent_exports.PhaseDurations),
|
|
11077
|
-
static: S.NullOr(RunEvent_exports.StaticVerdict)
|
|
11158
|
+
static: S.NullOr(RunEvent_exports.StaticVerdict),
|
|
11159
|
+
budget: RunEvent_exports.Budget
|
|
11078
11160
|
}) {};
|
|
11079
11161
|
//#endregion
|
|
11080
11162
|
//#region src/reporting/verdict-envelope.ts
|
|
@@ -11113,6 +11195,11 @@ const runIdTextOf = (now) => {
|
|
|
11113
11195
|
};
|
|
11114
11196
|
const generateRunId = (now) => RunEvent_exports.RunId.make(runIdTextOf(now));
|
|
11115
11197
|
const isActionableStatus = S.is(Mutant_exports.ActionableStatusSchema);
|
|
11198
|
+
const ZERO_BUDGET = RunEvent_exports.Budget.make({
|
|
11199
|
+
predictedSeconds: 0,
|
|
11200
|
+
actualSeconds: 0
|
|
11201
|
+
});
|
|
11202
|
+
const budgetOf = (report) => Option$1.getOrElse(Option$1.flatMap(Option$1.fromUndefinedOr(report["budget"]), (raw) => S.decodeUnknownOption(RunEvent_exports.Budget)(raw)), () => ZERO_BUDGET);
|
|
11116
11203
|
const actionableMutants = (files) => Arr.flatMap(Object.entries(files), ([file, fileResult]) => Arr.map(Arr.filter(fileResult.mutants, (mutant) => isActionableStatus(mutant.status)), (mutant) => RunEvent_exports.VerdictMutant.make({
|
|
11117
11204
|
id: mutant.id,
|
|
11118
11205
|
file,
|
|
@@ -11121,13 +11208,17 @@ const actionableMutants = (files) => Arr.flatMap(Object.entries(files), ([file,
|
|
|
11121
11208
|
replacement: mutant.replacement ?? null,
|
|
11122
11209
|
status: mutant.status
|
|
11123
11210
|
})));
|
|
11211
|
+
const reusesVerdicts = (config) => config.incremental === true && config.force !== true;
|
|
11212
|
+
const incrementalModeOf = (decoded) => Option$1.exists(decoded, reusesVerdicts) ? "incremental" : "full";
|
|
11124
11213
|
const embeddedConfig = (report) => {
|
|
11125
11214
|
const JsonReporterSchema = S.Struct({ fileName: S.String });
|
|
11126
11215
|
const MutatorSchema = S.StructWithRest(S.Struct({ mutantSetPolicy: S.optional(RunEvent_exports.MutantSetPolicy) }), [S.Record(S.String, S.Unknown)]);
|
|
11127
11216
|
const EmbeddedConfigSchema = S.StructWithRest(S.Struct({
|
|
11128
11217
|
jsonReporter: S.optional(JsonReporterSchema),
|
|
11129
11218
|
mutator: S.optional(MutatorSchema),
|
|
11130
|
-
since: S.optional(S.String)
|
|
11219
|
+
since: S.optional(S.String),
|
|
11220
|
+
incremental: S.optional(S.Boolean),
|
|
11221
|
+
force: S.optional(S.Boolean)
|
|
11131
11222
|
}), [S.Record(S.String, S.Unknown)]);
|
|
11132
11223
|
const decoded = S.decodeUnknownOption(EmbeddedConfigSchema)(report.config);
|
|
11133
11224
|
const jsonReporter = Option$1.flatMap(decoded, (config) => Option$1.fromUndefinedOr(config.jsonReporter));
|
|
@@ -11136,12 +11227,13 @@ const embeddedConfig = (report) => {
|
|
|
11136
11227
|
return {
|
|
11137
11228
|
jsonReporterFileName: Option$1.getOrUndefined(Option$1.map(jsonReporter, (reporter) => reporter.fileName)),
|
|
11138
11229
|
mutantSetPolicy: Option$1.getOrElse(mutantSetPolicy, () => "default"),
|
|
11139
|
-
scope: Option$1.isSome(since) ? "diff" : "full"
|
|
11230
|
+
scope: Option$1.isSome(since) ? "diff" : "full",
|
|
11231
|
+
incrementalMode: incrementalModeOf(decoded)
|
|
11140
11232
|
};
|
|
11141
11233
|
};
|
|
11142
11234
|
const buildVerdictEnvelope = dual((args) => args.length === 8, (report, mode, signal, runId, basePath, pathService, phaseDurations, staticVerdict) => {
|
|
11143
11235
|
const metrics = Report_exports.metricsFromMutants(Arr.flatMap(Object.values(report.files), (file) => file.mutants));
|
|
11144
|
-
const { jsonReporterFileName, mutantSetPolicy, scope } = embeddedConfig(report);
|
|
11236
|
+
const { jsonReporterFileName, mutantSetPolicy, scope, incrementalMode } = embeddedConfig(report);
|
|
11145
11237
|
return VerdictEnvelope.make({
|
|
11146
11238
|
schemaVersion: RunEvent_exports.StreamSchemaVersion.literal,
|
|
11147
11239
|
runId,
|
|
@@ -11161,14 +11253,33 @@ const buildVerdictEnvelope = dual((args) => args.length === 8, (report, mode, si
|
|
|
11161
11253
|
mutants: actionableMutants(report.files),
|
|
11162
11254
|
scope,
|
|
11163
11255
|
mutantSetPolicy,
|
|
11256
|
+
incrementalMode,
|
|
11164
11257
|
phaseDurations: Option$1.getOrNull(phaseDurations),
|
|
11165
|
-
static: staticVerdict
|
|
11258
|
+
static: staticVerdict,
|
|
11259
|
+
budget: budgetOf(report)
|
|
11166
11260
|
});
|
|
11167
11261
|
});
|
|
11168
11262
|
//#endregion
|
|
11169
11263
|
//#region src/run-events.service.ts
|
|
11170
11264
|
var RunEvents = class extends Context.Service()("@systemfsoftware/stryker-js/run-events.service/RunEvents") {};
|
|
11171
11265
|
var RunIdentity = class extends Context.Service()("@systemfsoftware/stryker-js/run-events.service/RunIdentity") {};
|
|
11266
|
+
var WorkerReports = class extends Context.Service()("@systemfsoftware/stryker-js/run-events.service/WorkerReports") {};
|
|
11267
|
+
const WorkerReportsLive = Layer.effect(WorkerReports, Effect$1.gen(function* () {
|
|
11268
|
+
const queue = yield* RunEvents;
|
|
11269
|
+
const counters = {
|
|
11270
|
+
testRunner: yield* Ref.make(0),
|
|
11271
|
+
checker: yield* Ref.make(0)
|
|
11272
|
+
};
|
|
11273
|
+
return WorkerReports.of({ report: (role, startupMs) => Effect$1.gen(function* () {
|
|
11274
|
+
const index = yield* Ref.getAndUpdate(counters[role], (current) => current + 1);
|
|
11275
|
+
yield* Queue.offer(queue, RunEvent_exports.WorkerReported.make({
|
|
11276
|
+
schemaVersion: RunEvent_exports.StreamSchemaVersion.literal,
|
|
11277
|
+
role,
|
|
11278
|
+
index,
|
|
11279
|
+
startupMs
|
|
11280
|
+
}));
|
|
11281
|
+
}) });
|
|
11282
|
+
}));
|
|
11172
11283
|
//#endregion
|
|
11173
11284
|
//#region src/phase-durations.ts
|
|
11174
11285
|
const elapsedOf = (marks, phase) => Option$1.map(Arr.findFirst(marks, (mark) => mark.phase === phase), (mark) => mark.elapsedMs);
|
|
@@ -11225,7 +11336,7 @@ const strykerOutputFilesOf = (options) => [
|
|
|
11225
11336
|
];
|
|
11226
11337
|
//#endregion
|
|
11227
11338
|
//#region package.json
|
|
11228
|
-
var version = "
|
|
11339
|
+
var version = "16.0.0";
|
|
11229
11340
|
//#endregion
|
|
11230
11341
|
//#region src/stryker-package.schema.ts
|
|
11231
11342
|
var StrykerPackage = class extends S.Class("StrykerPackage")({
|
|
@@ -11373,6 +11484,8 @@ var MutationReporting = class MutationReporting extends Context.Service()("@syst
|
|
|
11373
11484
|
};
|
|
11374
11485
|
return MutationReporting.of({
|
|
11375
11486
|
reportCheckFailure: (mutant, result) => reportCheckFailure(mutant, result),
|
|
11487
|
+
reportIgnored: (mutant, result) => reportIgnored(mutant, result),
|
|
11488
|
+
reportNoCoverage: (mutant) => reportNoCoverage(mutant),
|
|
11376
11489
|
reportMutantRunResult: (mutant, result) => mapRunResult(mutant, result),
|
|
11377
11490
|
reportAll: (input) => reportAll(deps, input),
|
|
11378
11491
|
checkpoint: (input, plannedMutants) => checkpoint(deps, input, plannedMutants)
|
|
@@ -11395,6 +11508,8 @@ const reportMutant = (mutant, status, outcome = {}) => Effect$1.succeed({
|
|
|
11395
11508
|
});
|
|
11396
11509
|
const reportMutantStatus = (mutant, status, statusReason) => reportMutant(mutant, status, { statusReason: statusReason ?? mutant.statusReason });
|
|
11397
11510
|
const reportCheckFailure = (mutant, result) => reportMutantStatus(mutant, "CompileError", result.reason);
|
|
11511
|
+
const reportIgnored = (mutant, result) => reportMutantStatus(mutant, "Ignored", result.reason);
|
|
11512
|
+
const reportNoCoverage = (mutant) => reportMutantStatus(mutant, "NoCoverage");
|
|
11398
11513
|
const reasonedOutcomeOf = (reason) => Option$1.match(Option$1.fromNullishOr(reason), {
|
|
11399
11514
|
onNone: () => ({}),
|
|
11400
11515
|
onSome: (present) => ({ statusReason: present })
|
|
@@ -11618,6 +11733,11 @@ const mutationTestReport = Effect$1.fn(SpanTaxonomy_exports.Spans.mutationReport
|
|
|
11618
11733
|
const { files, testFiles, identities } = yield* assembleReport(deps, input, results);
|
|
11619
11734
|
const dependencies = yield* discoverDependencies(deps);
|
|
11620
11735
|
const config = yield* S.encodeEffect(S.fromJsonString(S.Unknown))(input.options).pipe(Effect$1.flatMap(S.decodeEffect(S.fromJsonString(S.Record(S.String, S.Json)))), Effect$1.orDie);
|
|
11736
|
+
const budget = budgetOf$1({
|
|
11737
|
+
results,
|
|
11738
|
+
concurrency: input.concurrency,
|
|
11739
|
+
actualSeconds: ((yield* Clock.currentTimeMillis) - input.runStartedAt) / 1e3
|
|
11740
|
+
});
|
|
11621
11741
|
return {
|
|
11622
11742
|
report: {
|
|
11623
11743
|
files,
|
|
@@ -11629,7 +11749,8 @@ const mutationTestReport = Effect$1.fn(SpanTaxonomy_exports.Spans.mutationReport
|
|
|
11629
11749
|
framework: {
|
|
11630
11750
|
...STRYKER_FRAMEWORK,
|
|
11631
11751
|
dependencies
|
|
11632
|
-
}
|
|
11752
|
+
},
|
|
11753
|
+
budget
|
|
11633
11754
|
},
|
|
11634
11755
|
identities
|
|
11635
11756
|
};
|
|
@@ -11670,27 +11791,49 @@ const emitVerdict = Effect$1.fn(SpanTaxonomy_exports.Spans.mutationReportingEmit
|
|
|
11670
11791
|
mutants: envelope.mutants,
|
|
11671
11792
|
scope: envelope.scope,
|
|
11672
11793
|
mutantSetPolicy: envelope.mutantSetPolicy,
|
|
11794
|
+
incrementalMode: envelope.incrementalMode,
|
|
11673
11795
|
phaseDurations: envelope.phaseDurations,
|
|
11674
|
-
static: envelope.static
|
|
11796
|
+
static: envelope.static,
|
|
11797
|
+
budget: envelope.budget
|
|
11675
11798
|
}));
|
|
11676
11799
|
});
|
|
11677
11800
|
const dryRunCoverageFieldOf = (testCoverage) => Option$1.match(Option$1.fromUndefinedOr(testCoverage.dryRunCoverage), {
|
|
11678
11801
|
onNone: () => ({}),
|
|
11679
11802
|
onSome: (dryRunCoverage) => ({ dryRunCoverage })
|
|
11680
11803
|
});
|
|
11804
|
+
const testTimesOf = (tests) => Arr.map([...tests], (test) => test.timeSpentMs);
|
|
11805
|
+
const executedEntryOf = (result) => Option$1.match(Option$1.fromUndefinedOr(result.cost), {
|
|
11806
|
+
onNone: () => [],
|
|
11807
|
+
onSome: (cost) => [[result.id, costTotalMsOf(cost) ?? 0]]
|
|
11808
|
+
});
|
|
11809
|
+
const priorEntryOf = (entry) => entry[1].actualMs === null ? [] : [[entry[0], entry[1].actualMs]];
|
|
11810
|
+
const priorCostsOf = (report) => Option$1.getOrElse(Option$1.flatMap(Option$1.fromNullishOr(report), (present) => Option$1.fromNullishOr(present.costs)), () => ({}));
|
|
11811
|
+
const mutantCostModelOf = (input, results) => ({
|
|
11812
|
+
subjects: Arr.map(results, (result) => ({
|
|
11813
|
+
id: result.id,
|
|
11814
|
+
static: result.static
|
|
11815
|
+
})),
|
|
11816
|
+
staticCoverage: input.testCoverage.staticCoverage,
|
|
11817
|
+
allTestTimesMs: Arr.map([...input.testCoverage.testsById], ([, test]) => test.timeSpentMs),
|
|
11818
|
+
coveringTestTimesMsByMutantId: Object.fromEntries([...input.testCoverage.testsByMutantId].map(([mutantId, tests]) => [mutantId, testTimesOf(tests)])),
|
|
11819
|
+
executedActualMsByMutantId: Object.fromEntries(Arr.flatMap(results, executedEntryOf)),
|
|
11820
|
+
priorActualMsByMutantId: Object.fromEntries(Arr.flatMap(Object.entries(priorCostsOf(input.project.incrementalReport)), priorEntryOf)),
|
|
11821
|
+
fixedOverheadMs: input.timeOverheadMs
|
|
11822
|
+
});
|
|
11823
|
+
const costsOf = (input, results) => mutantCostsOf(mutantCostModelOf(input, results));
|
|
11681
11824
|
const writeIncrementalReport = Effect$1.fn(SpanTaxonomy_exports.Spans.mutationReportingWriteIncrementalReport.name)(function* (deps, input, report, identities) {
|
|
11682
|
-
yield* deps.fs.makeDirectory(deps.path.dirname(input.options.incrementalFile), { recursive: true });
|
|
11683
11825
|
const runInputsDigest = yield* runInputsDigestOf(deps.fs, deps.path, input.basePath, input.options);
|
|
11684
11826
|
const json = yield* S.encodeEffect(S.fromJsonString(S.Unknown, { space: 2 }))({
|
|
11685
|
-
incrementalVersion: "
|
|
11686
|
-
verdictSemanticsVersion:
|
|
11827
|
+
incrementalVersion: "3",
|
|
11828
|
+
verdictSemanticsVersion: 3,
|
|
11687
11829
|
mutantSetPolicy: input.options.mutator.mutantSetPolicy,
|
|
11688
11830
|
runInputsDigest,
|
|
11689
11831
|
...report,
|
|
11690
11832
|
files: stampFileIdentities(stampClosureDigests(report.files, input.closureDigestsByMutantId), identities),
|
|
11833
|
+
costs: costsOf(input, input.results),
|
|
11691
11834
|
...dryRunCoverageFieldOf(input.testCoverage)
|
|
11692
11835
|
}).pipe(Effect$1.orDie);
|
|
11693
|
-
yield* deps
|
|
11836
|
+
yield* writeFileAtomic(deps, input.options.incrementalFile, json);
|
|
11694
11837
|
});
|
|
11695
11838
|
const writeReproducers = (deps, input, report) => {
|
|
11696
11839
|
const decision = Result.getOrThrow(buildReproducers(BuildReproducersCommand.make({ report })));
|
|
@@ -11727,24 +11870,24 @@ const reportAll = Effect$1.fn(SpanTaxonomy_exports.Spans.mutationReportingReport
|
|
|
11727
11870
|
verdict: finalVerdict
|
|
11728
11871
|
};
|
|
11729
11872
|
});
|
|
11730
|
-
const writeAtomic = Effect$1.fn(SpanTaxonomy_exports.Spans.mutationReportingWriteAtomic.name)(function* (deps, file, content) {
|
|
11731
|
-
yield* deps.fs.makeDirectory(deps.path.dirname(file), { recursive: true });
|
|
11732
|
-
const tmp = `${file}.tmp`;
|
|
11733
|
-
yield* deps.fs.writeFileString(tmp, content);
|
|
11734
|
-
yield* deps.fs.rename(tmp, file).pipe(Effect$1.catch(() => deps.fs.copyFile(tmp, file).pipe(Effect$1.andThen(deps.fs.remove(tmp)))));
|
|
11735
|
-
});
|
|
11736
11873
|
const slimIncrementalReport = Effect$1.fn(SpanTaxonomy_exports.Spans.mutationReportingSlimIncrementalReport.name)(function* (deps, input, results) {
|
|
11737
11874
|
const { files, testFiles, identities } = yield* assembleReport(deps, input, results);
|
|
11738
11875
|
const runInputsDigest = yield* runInputsDigestOf(deps.fs, deps.path, input.basePath, input.options);
|
|
11739
11876
|
return {
|
|
11740
|
-
incrementalVersion: "
|
|
11741
|
-
verdictSemanticsVersion:
|
|
11877
|
+
incrementalVersion: "3",
|
|
11878
|
+
verdictSemanticsVersion: 3,
|
|
11742
11879
|
mutantSetPolicy: input.options.mutator.mutantSetPolicy,
|
|
11743
11880
|
runInputsDigest,
|
|
11744
11881
|
schemaVersion: Report_exports.WrittenSchemaVersion.literal,
|
|
11745
11882
|
thresholds: input.options.thresholds,
|
|
11746
11883
|
files: stampFileIdentities(stampClosureDigests(files, input.closureDigestsByMutantId), identities),
|
|
11884
|
+
costs: costsOf(input, results),
|
|
11747
11885
|
testFiles,
|
|
11886
|
+
budget: budgetOf$1({
|
|
11887
|
+
results,
|
|
11888
|
+
concurrency: input.concurrency,
|
|
11889
|
+
actualSeconds: ((yield* Clock.currentTimeMillis) - input.runStartedAt) / 1e3
|
|
11890
|
+
}),
|
|
11748
11891
|
...dryRunCoverageFieldOf(input.testCoverage)
|
|
11749
11892
|
};
|
|
11750
11893
|
});
|
|
@@ -11778,7 +11921,7 @@ const checkpointResultsOf = (input, plannedMutants) => Result.match(checkpointMu
|
|
|
11778
11921
|
const checkpointIncremental = Effect$1.fn(SpanTaxonomy_exports.Spans.mutationReportingCheckpoint.name)(function* (deps, input, plannedMutants) {
|
|
11779
11922
|
const report = yield* slimIncrementalReport(deps, input, checkpointResultsOf(input, plannedMutants));
|
|
11780
11923
|
const json = yield* S.encodeEffect(S.fromJsonString(S.Unknown))(report).pipe(Effect$1.orDie);
|
|
11781
|
-
yield*
|
|
11924
|
+
yield* writeFileAtomic(deps, input.options.incrementalFile, json);
|
|
11782
11925
|
});
|
|
11783
11926
|
const checkpoint = (deps, input, plannedMutants) => Boolean$1$1.match(input.options.incremental, {
|
|
11784
11927
|
onTrue: () => checkpointIncremental(deps, input, plannedMutants),
|
|
@@ -12395,8 +12538,8 @@ const renderJsonReport = Workflow.make({
|
|
|
12395
12538
|
});
|
|
12396
12539
|
//#endregion
|
|
12397
12540
|
//#region src/json-report.cell.ts
|
|
12398
|
-
const reportOf$
|
|
12399
|
-
const readJsonReport = (input) => Effect$1.map(Stream.fromAsyncIterable(input.events, failAsJsonReporter).pipe(Stream.filterMap(reportOf$
|
|
12541
|
+
const reportOf$1 = Filter.make((event) => Match$1.value(event).pipe(Match$1.tag("mutationTestReportReady", (ready) => Result.succeed(ready.report)), Match$1.orElse(() => Result.fail("not-ready"))));
|
|
12542
|
+
const readJsonReport = (input) => Effect$1.map(Stream.fromAsyncIterable(input.events, failAsJsonReporter).pipe(Stream.filterMap(reportOf$1), Stream.run(Sink.last())), (last) => ({
|
|
12400
12543
|
_tag: "JsonReportCommand",
|
|
12401
12544
|
reported: Option$1.getOrUndefined(last),
|
|
12402
12545
|
rendered: true,
|
|
@@ -12830,7 +12973,7 @@ const logOf = (command, results) => {
|
|
|
12830
12973
|
}]
|
|
12831
12974
|
};
|
|
12832
12975
|
};
|
|
12833
|
-
const decide$
|
|
12976
|
+
const decide$21 = (command) => {
|
|
12834
12977
|
const surfaced = surfacedOf(command);
|
|
12835
12978
|
const results = Arr.take(surfaced, command.maxResults);
|
|
12836
12979
|
const log = logOf(command, results);
|
|
@@ -12846,7 +12989,7 @@ const sarifReport = Workflow.make({
|
|
|
12846
12989
|
command: SarifReportCommand,
|
|
12847
12990
|
decision: SarifReportDecision,
|
|
12848
12991
|
error: S.Never,
|
|
12849
|
-
decide: (command) => Result.succeed(decide$
|
|
12992
|
+
decide: (command) => Result.succeed(decide$21(command))
|
|
12850
12993
|
});
|
|
12851
12994
|
//#endregion
|
|
12852
12995
|
//#region src/cap-survivors.workflow.ts
|
|
@@ -12963,7 +13106,7 @@ const linesOf = (command) => {
|
|
|
12963
13106
|
onFalse: () => Arr.flatMap(Option$1.toArray(HashMap.get(byId, ref.id)), (entry) => [lineOf(entry)])
|
|
12964
13107
|
}));
|
|
12965
13108
|
};
|
|
12966
|
-
const decide$
|
|
13109
|
+
const decide$20 = (command) => {
|
|
12967
13110
|
const lines = linesOf(command);
|
|
12968
13111
|
return Boolean$1$1.match(Arr.length(lines) === 0, {
|
|
12969
13112
|
onTrue: () => NothingToAnnotate.make({ survivorCount: Arr.length(command.survivors) }),
|
|
@@ -12974,7 +13117,7 @@ Workflow.make({
|
|
|
12974
13117
|
command: RenderAnnotationsCommand,
|
|
12975
13118
|
decision: RenderAnnotationsDecision,
|
|
12976
13119
|
error: S.Never,
|
|
12977
|
-
decide: (command) => Result.succeed(decide$
|
|
13120
|
+
decide: (command) => Result.succeed(decide$20(command))
|
|
12978
13121
|
});
|
|
12979
13122
|
//#endregion
|
|
12980
13123
|
//#region src/surfacing.ts
|
|
@@ -13050,8 +13193,8 @@ const failAsSarif = (cause) => Reporter_exports.ReporterFailed.make({
|
|
|
13050
13193
|
event: "mutationTestReportReady",
|
|
13051
13194
|
cause: Option$1.getOrElse(Option$1.map(ErrorText_exports.errorTextOf(cause), (rendered) => rendered.text), () => "")
|
|
13052
13195
|
});
|
|
13053
|
-
const reportOf
|
|
13054
|
-
const readSarifReport = (events) => Effect$1.map(Stream.fromAsyncIterable(events, failAsSarif).pipe(Stream.filterMap(reportOf
|
|
13196
|
+
const reportOf = Filter.make((event) => Match$1.value(event).pipe(Match$1.tag("mutationTestReportReady", (ready) => Result.succeed(ready.report)), Match$1.orElse(() => Result.fail("not-ready"))));
|
|
13197
|
+
const readSarifReport = (events) => Effect$1.map(Stream.fromAsyncIterable(events, failAsSarif).pipe(Stream.filterMap(reportOf), Stream.run(Sink.last())), (last) => Option$1.getOrUndefined(last));
|
|
13055
13198
|
const writeSarifReport = (options, report) => Effect$1.gen(function* () {
|
|
13056
13199
|
const fs = yield* FileSystem.FileSystem;
|
|
13057
13200
|
const path = yield* Path.Path;
|
|
@@ -13140,9 +13283,9 @@ var RunEnvironment = class extends Context.Service()("@systemfsoftware/stryker-j
|
|
|
13140
13283
|
};
|
|
13141
13284
|
const stageLayerOf = (env, events) => {
|
|
13142
13285
|
const eventsLayer = Match$1.value(events).pipe(Match$1.when(void 0, () => Layer.effect(RunEvents, Queue.bounded(RunEvent_exports.RunEvent.QUEUE_BOUND))), Match$1.orElse((queue) => Layer.succeed(RunEvents, queue)));
|
|
13143
|
-
const stageLayer = Layer.mergeAll(Layer.succeed(RunEnvironment, env), eventsLayer, PhaseClock.layer(env.runStartedAt), IdGenerator.layer, ProjectFiles.layer, Layer.effect(Scope.Scope, Effect$1.gen(function* () {
|
|
13286
|
+
const stageLayer = Layer.mergeAll(Layer.succeed(RunEnvironment, env), eventsLayer, WorkerReportsLive.pipe(Layer.provide(eventsLayer)), PhaseClock.layer(env.runStartedAt), IdGenerator.layer, ProjectFiles.layer, Layer.effect(Scope.Scope, Effect$1.gen(function* () {
|
|
13144
13287
|
const stageScope = yield* Scope.make();
|
|
13145
|
-
yield* Effect$1.addFinalizer(() => Scope.close(stageScope,
|
|
13288
|
+
yield* Effect$1.addFinalizer((exit) => Scope.close(stageScope, exit));
|
|
13146
13289
|
return stageScope;
|
|
13147
13290
|
})));
|
|
13148
13291
|
return Layer.mergeAll(stageLayer, MutationReporting.layer.pipe(Layer.provide(stageLayer)), Reporter.layer.pipe(Layer.provide(ReporterOutput.layer), Layer.provide(stageLayer)));
|
|
@@ -13508,7 +13651,7 @@ var WorkerCrashed = class extends S.TaggedClass()("WorkerCrashed", {
|
|
|
13508
13651
|
};
|
|
13509
13652
|
const ClassifyWorkerExitDecision = S.Union([WorkerOutOfMemory, WorkerCrashed]);
|
|
13510
13653
|
const OutOfMemoryExitCode = S.Literals([134, 137]);
|
|
13511
|
-
const decide$
|
|
13654
|
+
const decide$19 = (command) => Boolean$1$1.match(S.is(OutOfMemoryExitCode)(command.exitCode), {
|
|
13512
13655
|
onTrue: () => Result.succeed(WorkerOutOfMemory.make({
|
|
13513
13656
|
pid: command.pid,
|
|
13514
13657
|
exitCode: command.exitCode
|
|
@@ -13522,7 +13665,7 @@ const classifyWorkerExit = Workflow.make({
|
|
|
13522
13665
|
command: ClassifyWorkerExitCommand,
|
|
13523
13666
|
decision: ClassifyWorkerExitDecision,
|
|
13524
13667
|
error: S.Never,
|
|
13525
|
-
decide: decide$
|
|
13668
|
+
decide: decide$19
|
|
13526
13669
|
});
|
|
13527
13670
|
//#endregion
|
|
13528
13671
|
//#region src/git-diff.schema.ts
|
|
@@ -13728,11 +13871,13 @@ const failInFlightRequests = Effect$1.fn(SpanTaxonomy_exports.Spans.workerProtoc
|
|
|
13728
13871
|
const makeWorkerProtocol = Effect$1.fn(SpanTaxonomy_exports.Spans.workerProtocolMake.name)(function* (socket) {
|
|
13729
13872
|
const responseHandlers = yield* Ref.make(HashMap.empty());
|
|
13730
13873
|
const liveConnections = yield* FiberSet.make();
|
|
13874
|
+
const connected = yield* Deferred.make();
|
|
13731
13875
|
const hooks = Layer.succeed(RpcClient.ConnectionHooks, {
|
|
13732
|
-
onConnect: FiberSet.run(liveConnections, Effect$1.never.pipe(Effect$1.onInterrupt(() => failInFlightRequests(responseHandlers))))
|
|
13876
|
+
onConnect: Deferred.succeed(connected, void 0).pipe(Effect$1.andThen(FiberSet.run(liveConnections, Effect$1.never.pipe(Effect$1.onInterrupt(() => failInFlightRequests(responseHandlers))))), Effect$1.asVoid),
|
|
13733
13877
|
onDisconnect: FiberSet.clear(liveConnections)
|
|
13734
13878
|
});
|
|
13735
13879
|
const protocol = yield* RpcClient.layerProtocolSocket({ retryTransientErrors: true }).pipe(Layer.provide(Layer.mergeAll(socket, RpcSerialization.layerNdjson, hooks)), Layer.build, Effect$1.map(Context.get(RpcClient.Protocol)));
|
|
13880
|
+
yield* Deferred.await(connected);
|
|
13736
13881
|
return RpcClient.Protocol.of({
|
|
13737
13882
|
...protocol,
|
|
13738
13883
|
run: (clientId, handler) => Ref.update(responseHandlers, HashMap.set(clientId, handler)).pipe(Effect$1.andThen(protocol.run(clientId, handler)))
|
|
@@ -13745,6 +13890,7 @@ const WorkerProtocol = Blueprint.make()(TypeId$9).steps({
|
|
|
13745
13890
|
const layerWorkerProtocol = (socket) => WorkerProtocol.of({ socket }).layer;
|
|
13746
13891
|
//#endregion
|
|
13747
13892
|
//#region src/drivers/node.ts
|
|
13893
|
+
const WORKER_TERMINATION_GRACE = Duration.seconds(5);
|
|
13748
13894
|
const restrictToOwnerOrWarn = (fs, file) => fs.chmod(file, 384).pipe(Effect$1.tapError((cause) => Effect$1.logWarning(`Could not restrict "${file}" to its owner; the worker directory's own mode still protects it.`).pipe(Effect$1.annotateLogs("cause", cause))), Effect$1.catchTag("PlatformError", () => Effect$1.void));
|
|
13749
13895
|
const nodeWorkerLauncherLayer = (childEnv) => Layer.effect(WorkerLauncher, Effect$1.gen(function* () {
|
|
13750
13896
|
const crypto = yield* Crypto.Crypto;
|
|
@@ -13768,7 +13914,8 @@ const nodeWorkerLauncherLayer = (childEnv) => Layer.effect(WorkerLauncher, Effec
|
|
|
13768
13914
|
...childEnv,
|
|
13769
13915
|
...params.env
|
|
13770
13916
|
},
|
|
13771
|
-
stderr: "inherit"
|
|
13917
|
+
stderr: "inherit",
|
|
13918
|
+
forceKillAfter: WORKER_TERMINATION_GRACE
|
|
13772
13919
|
}).pipe(Effect$1.provideService(ChildProcessSpawner.ChildProcessSpawner, spawner));
|
|
13773
13920
|
const clientLayer = layerWorkerProtocol(NodeSocket.layerNet({ path: socketPath }));
|
|
13774
13921
|
const exited = handle.exitCode.pipe(Effect$1.orDie, Effect$1.flatMap((exitCode) => Result.match(classifyWorkerExit(ClassifyWorkerExitCommand.make({
|
|
@@ -13850,7 +13997,9 @@ const IncrementalReportSchema = S.StructWithRest(S.Struct({
|
|
|
13850
13997
|
runInputsDigest: S.String,
|
|
13851
13998
|
thresholds: ThresholdsLikeSchema,
|
|
13852
13999
|
files: S.Record(S.String, FileResultLikeSchema),
|
|
14000
|
+
costs: MutantCosts,
|
|
13853
14001
|
testFiles: S.optional(S.Record(S.String, TestFileLikeSchema)),
|
|
14002
|
+
budget: S.optional(RunEvent_exports.Budget),
|
|
13854
14003
|
dryRunCoverage: S.optionalKey(S.Unknown)
|
|
13855
14004
|
}), [S.Record(S.String, S.Unknown)]);
|
|
13856
14005
|
//#endregion
|
|
@@ -13928,12 +14077,12 @@ const splitOf = (details, checkerCount) => Boolean$1$1.match(checkerCount > 0, {
|
|
|
13928
14077
|
announcement: details.announcement
|
|
13929
14078
|
})
|
|
13930
14079
|
});
|
|
13931
|
-
const decide$
|
|
14080
|
+
const decide$18 = (command) => Result.succeed(splitOf(detailsOf(command.concurrency, command.availableParallelism), command.checkerCount));
|
|
13932
14081
|
const resolveConcurrency = Workflow.make({
|
|
13933
14082
|
command: ResolveConcurrency,
|
|
13934
14083
|
decision: ConcurrencySplit,
|
|
13935
14084
|
error: S.Never,
|
|
13936
|
-
decide: decide$
|
|
14085
|
+
decide: decide$18
|
|
13937
14086
|
});
|
|
13938
14087
|
//#endregion
|
|
13939
14088
|
//#region src/concurrency.cell.ts
|
|
@@ -14165,7 +14314,7 @@ const discardOf = (reason, actual, expected) => IncrementalReportDiscard.make({
|
|
|
14165
14314
|
actual,
|
|
14166
14315
|
expected
|
|
14167
14316
|
});
|
|
14168
|
-
const decide$
|
|
14317
|
+
const decide$17 = (command) => Option$1.match(Option$1.fromUndefinedOr(command.report), {
|
|
14169
14318
|
onNone: () => discardOf("noPriorRecord", void 0, command.expectedIncrementalVersion),
|
|
14170
14319
|
onSome: (report) => Option$1.match(Option$1.firstSomeOf(identityMismatchesOf(command, report).map(mismatchOptionOf)), {
|
|
14171
14320
|
onNone: () => IncrementalReportKeep.make({ report }),
|
|
@@ -14176,7 +14325,7 @@ const admitIncrementalReport = Workflow.make({
|
|
|
14176
14325
|
command: AdmitIncrementalReportCommand,
|
|
14177
14326
|
decision: S.Union([IncrementalReportKeep, IncrementalReportDiscard]),
|
|
14178
14327
|
error: S.Never,
|
|
14179
|
-
decide: (command) => Result.succeed(decide$
|
|
14328
|
+
decide: (command) => Result.succeed(decide$17(command))
|
|
14180
14329
|
});
|
|
14181
14330
|
//#endregion
|
|
14182
14331
|
//#region src/git-diff.workflow.ts
|
|
@@ -14531,11 +14680,15 @@ const ALWAYS_IGNORE = Object.freeze([
|
|
|
14531
14680
|
"/stryker.log",
|
|
14532
14681
|
".next",
|
|
14533
14682
|
".nuxt",
|
|
14534
|
-
".svelte-kit"
|
|
14683
|
+
".svelte-kit",
|
|
14684
|
+
".turbo"
|
|
14535
14685
|
]);
|
|
14536
14686
|
const CRAWL_CONCURRENCY = 256;
|
|
14537
14687
|
const DISCARD_TEXTS = {
|
|
14538
|
-
noPriorRecord: (command) => `Unable to parse incremental result file at ${command.incrementalFile}
|
|
14688
|
+
noPriorRecord: (command) => `Unable to parse incremental result file at ${command.incrementalFile}${Option$1.match(Option$1.fromUndefinedOr(command.decodeError), {
|
|
14689
|
+
onNone: () => "",
|
|
14690
|
+
onSome: (error) => `: ${error}`
|
|
14691
|
+
})}; a full mutation testing run will be performed.`,
|
|
14539
14692
|
cacheLayoutChanged: (command, discard) => `Incremental result file at ${command.incrementalFile} has cache layout version ${discard.actual ?? ""}, expected ${discard.expected}; a full mutation testing run will be performed.`,
|
|
14540
14693
|
semanticsChanged: (command, discard) => `Incremental result file at ${command.incrementalFile} has verdict semantics version ${discard.actual ?? ""}, expected ${discard.expected}; a full mutation testing run will be performed.`,
|
|
14541
14694
|
policyChanged: (command, discard) => `Incremental result file at ${command.incrementalFile} has mutant-set policy ${discard.actual ?? ""}, expected ${discard.expected}; a full mutation testing run will be performed.`,
|
|
@@ -14593,7 +14746,14 @@ const isEntryIncluded = (ignorePatterns, entry) => {
|
|
|
14593
14746
|
};
|
|
14594
14747
|
const resolveInputFileNames = (ignorePatterns, basePath) => crawlDirectory(ignorePatterns, basePath, basePath).pipe(Stream.runCollect, Effect$1.map((files) => [...files]));
|
|
14595
14748
|
const parseAndDecodeIncrementalReport = Schema.decodeUnknownResult(Schema.fromJsonString(IncrementalReportSchema));
|
|
14596
|
-
const
|
|
14749
|
+
const decodeFailureText = (failure) => failure.message.replace(/\s+/gu, " ").trim();
|
|
14750
|
+
const reportReadOf = (contents) => Option$1.match(Option$1.fromUndefinedOr(contents), {
|
|
14751
|
+
onNone: () => ({}),
|
|
14752
|
+
onSome: (text) => Result.match(parseAndDecodeIncrementalReport(text), {
|
|
14753
|
+
onFailure: (failure) => ({ decodeError: decodeFailureText(failure) }),
|
|
14754
|
+
onSuccess: (report) => ({ report })
|
|
14755
|
+
})
|
|
14756
|
+
});
|
|
14597
14757
|
const incrementalContentsOf = (fs, options) => Boolean$1.match(options.incremental, {
|
|
14598
14758
|
onFalse: () => Effect$1.succeedNone,
|
|
14599
14759
|
onTrue: () => fs.readFileString(options.incrementalFile).pipe(Effect$1.asSome, Effect$1.tapError((error) => Match$1.value(error.reason).pipe(Match$1.tag("NotFound", () => Effect$1.logInfo(`No incremental result file found at ${options.incrementalFile}, a full mutation testing run will be performed.`)), Match$1.orElse(() => Effect$1.void))), Effect$1.catchTag("PlatformError", (error) => Match$1.value(error.reason).pipe(Match$1.tag("NotFound", () => Effect$1.succeedNone), Match$1.orElse(() => Effect$1.fail(error)))))
|
|
@@ -14698,11 +14858,12 @@ const readProject = Effect$1.fn(SpanTaxonomy_exports.Spans.projectReadFromDisk.n
|
|
|
14698
14858
|
yield* Effect$1.forEach(testFilePatterns, (pattern) => warnUnmatchedTestPattern(inputFileNames, input.basePath, pattern), { discard: true });
|
|
14699
14859
|
const runInputsDigest = yield* runInputsDigestOf(fs, pathService, input.basePath, options);
|
|
14700
14860
|
const contents = Option$1.getOrUndefined(yield* incrementalContentsOf(fs, options));
|
|
14861
|
+
const reportRead = reportReadOf(contents);
|
|
14701
14862
|
return {
|
|
14702
14863
|
_tag: "AdmitIncrementalReportCommand",
|
|
14703
|
-
report:
|
|
14704
|
-
expectedIncrementalVersion: "
|
|
14705
|
-
verdictSemanticsVersion:
|
|
14864
|
+
report: reportRead.report,
|
|
14865
|
+
expectedIncrementalVersion: "3",
|
|
14866
|
+
verdictSemanticsVersion: 3,
|
|
14706
14867
|
mutantSetPolicy: options.mutator.mutantSetPolicy,
|
|
14707
14868
|
runInputsDigest,
|
|
14708
14869
|
options,
|
|
@@ -14711,6 +14872,7 @@ const readProject = Effect$1.fn(SpanTaxonomy_exports.Spans.projectReadFromDisk.n
|
|
|
14711
14872
|
incremental: options.incremental,
|
|
14712
14873
|
incrementalFile: options.incrementalFile,
|
|
14713
14874
|
contents,
|
|
14875
|
+
decodeError: reportRead.decodeError,
|
|
14714
14876
|
fileDescriptions: decision.fileDescriptions,
|
|
14715
14877
|
testFiles: [...decision.testFiles]
|
|
14716
14878
|
};
|
|
@@ -14763,6 +14925,58 @@ const readProjectCell = Sandwich.named(SpanTaxonomy_exports.Spans.projectRead.na
|
|
|
14763
14925
|
}))
|
|
14764
14926
|
});
|
|
14765
14927
|
//#endregion
|
|
14928
|
+
//#region src/refuse-local-mutation.workflow.ts
|
|
14929
|
+
const LocalMutationDecisionTypeId = Symbol.for("@systemfsoftware/stryker-js/LocalMutationDecision");
|
|
14930
|
+
var RefuseLocalMutationCommand = class extends S.TaggedClass()("RefuseLocalMutationCommand", {
|
|
14931
|
+
dryRunOnly: S.Boolean,
|
|
14932
|
+
githubActions: S.UndefinedOr(S.String),
|
|
14933
|
+
allowLocalMutation: S.UndefinedOr(S.String)
|
|
14934
|
+
}) {
|
|
14935
|
+
static [Workflow.InstrumentationBrand] = {};
|
|
14936
|
+
};
|
|
14937
|
+
var LocalMutationAllowed = class extends S.TaggedClass()("LocalMutationAllowed", {}) {
|
|
14938
|
+
[LocalMutationDecisionTypeId] = LocalMutationDecisionTypeId;
|
|
14939
|
+
};
|
|
14940
|
+
var LocalMutationRefused = class extends S.TaggedError()("LocalMutationRefused", {
|
|
14941
|
+
rule: RunEvent_exports.RefusalRule,
|
|
14942
|
+
message: S.String
|
|
14943
|
+
}) {};
|
|
14944
|
+
const decide$16 = (command) => Match$1.value({
|
|
14945
|
+
dryRunOnly: command.dryRunOnly,
|
|
14946
|
+
githubActions: command.githubActions,
|
|
14947
|
+
allowLocalMutation: command.allowLocalMutation
|
|
14948
|
+
}).pipe(Match$1.when({ dryRunOnly: true }, () => Result.succeed(LocalMutationAllowed.make({}))), Match$1.when({ githubActions: "true" }, () => Result.succeed(LocalMutationAllowed.make({}))), Match$1.when({ allowLocalMutation: "1" }, () => Result.succeed(LocalMutationAllowed.make({}))), Match$1.orElse(() => Result.fail(LocalMutationRefused.make({
|
|
14949
|
+
rule: "mutation-runs-on-main-ci",
|
|
14950
|
+
message: "mutation runs only on main CI"
|
|
14951
|
+
}))));
|
|
14952
|
+
const refuseLocalMutation = Workflow.make({
|
|
14953
|
+
command: RefuseLocalMutationCommand,
|
|
14954
|
+
decision: LocalMutationAllowed,
|
|
14955
|
+
error: LocalMutationRefused,
|
|
14956
|
+
decide: decide$16
|
|
14957
|
+
});
|
|
14958
|
+
//#endregion
|
|
14959
|
+
//#region src/refuse-local-mutation.cell.ts
|
|
14960
|
+
const envOf = (key) => Config.option(Config.String(key)).pipe(Effect$1.map(Option$1.getOrUndefined), Effect$1.orElseSucceed(() => void 0));
|
|
14961
|
+
const guardOf = (input) => Effect$1.gen(function* () {
|
|
14962
|
+
const githubActions = yield* envOf("GITHUB_ACTIONS");
|
|
14963
|
+
const allowLocalMutation = yield* envOf("ALLOW_LOCAL_MUTATION");
|
|
14964
|
+
const command = RefuseLocalMutationCommand.make({
|
|
14965
|
+
dryRunOnly: input.options.dryRunOnly,
|
|
14966
|
+
githubActions,
|
|
14967
|
+
allowLocalMutation
|
|
14968
|
+
});
|
|
14969
|
+
return yield* Result.match(refuseLocalMutation(command), {
|
|
14970
|
+
onFailure: (refused) => Effect$1.fail(StageError.make({
|
|
14971
|
+
stage: "prepare",
|
|
14972
|
+
reason: refused.message,
|
|
14973
|
+
cause: refused
|
|
14974
|
+
})),
|
|
14975
|
+
onSuccess: () => Effect$1.succeed(input)
|
|
14976
|
+
});
|
|
14977
|
+
});
|
|
14978
|
+
const refuseLocalMutationCell = (input) => Cell.fromEffect(guardOf(input));
|
|
14979
|
+
//#endregion
|
|
14766
14980
|
//#region src/dry-run-coverage.schema.ts
|
|
14767
14981
|
const DryRunCoverageSchema = S.Struct({
|
|
14768
14982
|
tests: S.Array(TestRunner_exports.TestResultSchema),
|
|
@@ -15946,6 +16160,35 @@ const buildTestRunner = dual(2, (context, childProcessRunner) => Option$1.match(
|
|
|
15946
16160
|
onNone: () => decorateChildRunner(context, childProcessRunner)
|
|
15947
16161
|
}));
|
|
15948
16162
|
//#endregion
|
|
16163
|
+
//#region src/run/dry-run-coverage.ts
|
|
16164
|
+
const testsByIdOf = (result) => MutableHashMap.fromIterable(result.tests.map((test) => [test.id, test]));
|
|
16165
|
+
const coveredMutantIdsOf = (coverage) => Object.entries(coverage).filter(([, count]) => count > 0).map(([mutantId]) => mutantId);
|
|
16166
|
+
const testsByMutantIdOf = (mutantCoverage, testsById) => Object.entries(mutantCoverage.perTest).reduce((testsByMutantId, [testId, coverage]) => Option$1.match(MutableHashMap.get(testsById, testId), {
|
|
16167
|
+
onNone: () => testsByMutantId,
|
|
16168
|
+
onSome: (test) => coveredMutantIdsOf(coverage).reduce((acc, mutantId) => MutableHashMap.set(acc, mutantId, MutableHashSet.add(Option$1.getOrElse(MutableHashMap.get(acc, mutantId), () => MutableHashSet.empty()), test)), testsByMutantId)
|
|
16169
|
+
}), MutableHashMap.empty());
|
|
16170
|
+
const hitsByMutantIdOf = (mutantCoverage) => [mutantCoverage.static, ...Object.values(mutantCoverage.perTest)].reduce((hitsByMutantId, coverage) => Object.entries(coverage).reduce((acc, [mutantId, count]) => MutableHashMap.set(acc, mutantId, Option$1.getOrElse(MutableHashMap.get(acc, mutantId), () => 0) + count), hitsByMutantId), MutableHashMap.empty());
|
|
16171
|
+
const testCoverageOf = ({ result, dryRunCoverage }) => {
|
|
16172
|
+
const testsById = testsByIdOf(result);
|
|
16173
|
+
const mutantCoverage = Option$1.fromNullishOr(result.mutantCoverage);
|
|
16174
|
+
return {
|
|
16175
|
+
testsByMutantId: Option$1.match(mutantCoverage, {
|
|
16176
|
+
onNone: () => MutableHashMap.empty(),
|
|
16177
|
+
onSome: (coverage) => testsByMutantIdOf(coverage, testsById)
|
|
16178
|
+
}),
|
|
16179
|
+
testsById,
|
|
16180
|
+
staticCoverage: Option$1.match(mutantCoverage, {
|
|
16181
|
+
onNone: () => void 0,
|
|
16182
|
+
onSome: (coverage) => coverage.static
|
|
16183
|
+
}),
|
|
16184
|
+
hitsByMutantId: Option$1.match(mutantCoverage, {
|
|
16185
|
+
onNone: () => MutableHashMap.empty(),
|
|
16186
|
+
onSome: (coverage) => hitsByMutantIdOf(coverage)
|
|
16187
|
+
}),
|
|
16188
|
+
dryRunCoverage
|
|
16189
|
+
};
|
|
16190
|
+
};
|
|
16191
|
+
//#endregion
|
|
15949
16192
|
//#region src/run/incremental-reuse.ts
|
|
15950
16193
|
const absoluteSourceOf = (path, basePath, file) => path.isAbsolute(file) ? file : path.join(basePath, file);
|
|
15951
16194
|
const matchedSourcesOf = Effect$1.fnUntraced(function* (input) {
|
|
@@ -16275,33 +16518,6 @@ const withOriginalFileName = (test, prev) => Match$1.value(test.fileName).pipe(M
|
|
|
16275
16518
|
fileName: originalFileFor(prev.sandbox, fileName)
|
|
16276
16519
|
})), Match$1.orElse(() => test));
|
|
16277
16520
|
const withOriginalFileNames = (tests, prev) => tests.map((test) => withOriginalFileName(test, prev));
|
|
16278
|
-
const testsByIdOf = (result) => MutableHashMap.fromIterable(result.tests.map((test) => [test.id, test]));
|
|
16279
|
-
const coveredMutantIdsOf = (coverage) => Object.entries(coverage).filter(([, count]) => count > 0).map(([mutantId]) => mutantId);
|
|
16280
|
-
const testsByMutantIdOf = (mutantCoverage, testsById) => Object.entries(mutantCoverage.perTest).reduce((testsByMutantId, [testId, coverage]) => Option$1.match(MutableHashMap.get(testsById, testId), {
|
|
16281
|
-
onNone: () => testsByMutantId,
|
|
16282
|
-
onSome: (test) => coveredMutantIdsOf(coverage).reduce((acc, mutantId) => MutableHashMap.set(acc, mutantId, MutableHashSet.add(Option$1.getOrElse(MutableHashMap.get(acc, mutantId), () => MutableHashSet.empty()), test)), testsByMutantId)
|
|
16283
|
-
}), MutableHashMap.empty());
|
|
16284
|
-
const hitsByMutantIdOf = (mutantCoverage) => [mutantCoverage.static, ...Object.values(mutantCoverage.perTest)].reduce((hitsByMutantId, coverage) => Object.entries(coverage).reduce((acc, [mutantId, count]) => MutableHashMap.set(acc, mutantId, Option$1.getOrElse(MutableHashMap.get(acc, mutantId), () => 0) + count), hitsByMutantId), MutableHashMap.empty());
|
|
16285
|
-
const testCoverageFrom = (result, dryRunCoverage) => {
|
|
16286
|
-
const testsById = testsByIdOf(result);
|
|
16287
|
-
const mutantCoverage = Option$1.fromNullishOr(result.mutantCoverage);
|
|
16288
|
-
return {
|
|
16289
|
-
testsByMutantId: Option$1.match(mutantCoverage, {
|
|
16290
|
-
onNone: () => MutableHashMap.empty(),
|
|
16291
|
-
onSome: (coverage) => testsByMutantIdOf(coverage, testsById)
|
|
16292
|
-
}),
|
|
16293
|
-
testsById,
|
|
16294
|
-
staticCoverage: Option$1.match(mutantCoverage, {
|
|
16295
|
-
onNone: () => void 0,
|
|
16296
|
-
onSome: (coverage) => coverage.static
|
|
16297
|
-
}),
|
|
16298
|
-
hitsByMutantId: Option$1.match(mutantCoverage, {
|
|
16299
|
-
onNone: () => MutableHashMap.empty(),
|
|
16300
|
-
onSome: (coverage) => hitsByMutantIdOf(coverage)
|
|
16301
|
-
}),
|
|
16302
|
-
dryRunCoverage
|
|
16303
|
-
};
|
|
16304
|
-
};
|
|
16305
16521
|
const announceDryRunOutcome = (tests, prev, gross, overheadMillis) => Match$1.value(tests.length).pipe(Match$1.when(0, () => Effect$1.logInfo("No tests were found")), Match$1.orElse(() => Effect$1.logInfo(`Initial test run succeeded. Ran ${tests.length} tests in ${Duration.format(gross)} (net ${totalTestTime(tests)} ms, overhead ${overheadMillis} ms).`).pipe(Effect$1.andThen(Effect$1.when(Effect$1.logInfo("Note: running the dry-run only. No mutations will be tested."), Effect$1.succeed(prev.options.dryRunOnly))))));
|
|
16306
16522
|
const reportDryRunCompleted = (raw, tests, overheadMillis) => offerReporterEvent(raw.prev.reporterStage, Reporter_exports.DryRunCompleted.make({
|
|
16307
16523
|
timing: {
|
|
@@ -16325,7 +16541,10 @@ const freshCoverageOf = (raw, dryRunResult, overheadMillis) => ({
|
|
|
16325
16541
|
const dryRunDoneOf = (raw, dryRunResult, coverage) => ({
|
|
16326
16542
|
...raw.prev,
|
|
16327
16543
|
dryRunResult,
|
|
16328
|
-
testCoverage:
|
|
16544
|
+
testCoverage: testCoverageOf({
|
|
16545
|
+
result: dryRunResult,
|
|
16546
|
+
dryRunCoverage: coverage
|
|
16547
|
+
}),
|
|
16329
16548
|
timeOverhead: Duration.millis(coverage.timeOverheadMs)
|
|
16330
16549
|
});
|
|
16331
16550
|
const completeFreshDryRun = Effect$1.fnUntraced(function* (raw, dryRunResult) {
|
|
@@ -16355,6 +16574,7 @@ const completeDryRunPassed = (raw) => Match$1.value(raw.rawResult).pipe(Match$1.
|
|
|
16355
16574
|
}))), Match$1.exhaustive);
|
|
16356
16575
|
const runFreshDryRun = Effect$1.fnUntraced(function* (command, idGenerator, currentTestClosureDigest, runInputsDigest) {
|
|
16357
16576
|
const env = yield* RunEnvironment;
|
|
16577
|
+
const reports = yield* WorkerReports;
|
|
16358
16578
|
const { files, testFiles } = yield* resolveDryRunFiles(command);
|
|
16359
16579
|
const dryRunTimeout = command.options.dryRunTimeoutMinutes * 60 * 1e3;
|
|
16360
16580
|
const options = dryRunOptionsOf(command, files, testFiles, dryRunTimeout);
|
|
@@ -16370,6 +16590,7 @@ const runFreshDryRun = Effect$1.fnUntraced(function* (command, idGenerator, curr
|
|
|
16370
16590
|
idGenerator
|
|
16371
16591
|
})));
|
|
16372
16592
|
});
|
|
16593
|
+
const startedAt = yield* Clock.currentTimeMillis;
|
|
16373
16594
|
const runner = yield* buildTestRunner({
|
|
16374
16595
|
options: command.options,
|
|
16375
16596
|
fileDescriptions: command.project.fileDescriptions,
|
|
@@ -16378,6 +16599,7 @@ const runFreshDryRun = Effect$1.fnUntraced(function* (command, idGenerator, curr
|
|
|
16378
16599
|
retire: Effect$1.void,
|
|
16379
16600
|
testFiles: testFiles ?? []
|
|
16380
16601
|
}, childRunnerEffect);
|
|
16602
|
+
yield* reports.report("testRunner", (yield* Clock.currentTimeMillis) - startedAt);
|
|
16381
16603
|
const capabilities = yield* runner.capabilities.pipe(Effect$1.mapError((cause) => StageError.make({
|
|
16382
16604
|
stage: "dryRun",
|
|
16383
16605
|
reason: "Failed to get test runner capabilities",
|
|
@@ -17329,6 +17551,10 @@ const FailedCheckResultSchema = S.Struct({
|
|
|
17329
17551
|
status: S.Literal("compileError"),
|
|
17330
17552
|
reason: S.String
|
|
17331
17553
|
});
|
|
17554
|
+
const IgnoredCheckResultSchema = S.Struct({
|
|
17555
|
+
status: S.Literal("ignored"),
|
|
17556
|
+
reason: S.String
|
|
17557
|
+
});
|
|
17332
17558
|
var CheckedPlanPassed = class extends S.TaggedClass()("CheckedPlanPassed", {
|
|
17333
17559
|
mutantId: Mutant_exports.MutantId,
|
|
17334
17560
|
entryIndex: S.Int
|
|
@@ -17343,27 +17569,48 @@ var CheckedPlanFailed = class extends S.TaggedClass()("CheckedPlanFailed", {
|
|
|
17343
17569
|
}) {
|
|
17344
17570
|
[CheckedPlanTypeId] = CheckedPlanTypeId;
|
|
17345
17571
|
};
|
|
17572
|
+
var CheckedPlanIgnored = class extends S.TaggedClass()("CheckedPlanIgnored", {
|
|
17573
|
+
mutantId: Mutant_exports.MutantId,
|
|
17574
|
+
entryIndex: S.Int,
|
|
17575
|
+
reason: S.String,
|
|
17576
|
+
result: IgnoredCheckResultSchema
|
|
17577
|
+
}) {
|
|
17578
|
+
[CheckedPlanTypeId] = CheckedPlanTypeId;
|
|
17579
|
+
};
|
|
17346
17580
|
var PartitionCheckedPlansCommand = class extends S.TaggedClass()("PartitionCheckedPlansCommand", { checked: S.Array(S.Tuple([Mutant_exports.MutantId, Checker_exports.CheckResultSchema])) }) {
|
|
17347
17581
|
static [Workflow.InstrumentationBrand] = {};
|
|
17348
17582
|
};
|
|
17349
|
-
const isFailed = (result) => result.status
|
|
17583
|
+
const isFailed = (result) => result.status === "compileError";
|
|
17584
|
+
const isIgnored = (result) => result.status === "ignored";
|
|
17350
17585
|
const failedReasonOf = (failed) => failed.reason;
|
|
17351
|
-
const decideCheckedPlan = (mutantId, result, entryIndex) => Option$1.match(Option$1.liftPredicate(result,
|
|
17352
|
-
|
|
17353
|
-
mutantId,
|
|
17354
|
-
entryIndex
|
|
17355
|
-
}),
|
|
17356
|
-
onSome: (failed) => CheckedPlanFailed.make({
|
|
17586
|
+
const decideCheckedPlan = (mutantId, result, entryIndex) => Option$1.match(Option$1.liftPredicate(result, isIgnored), {
|
|
17587
|
+
onSome: (ignored) => CheckedPlanIgnored.make({
|
|
17357
17588
|
mutantId,
|
|
17358
17589
|
entryIndex,
|
|
17359
|
-
reason:
|
|
17360
|
-
result:
|
|
17590
|
+
reason: ignored.reason,
|
|
17591
|
+
result: ignored
|
|
17592
|
+
}),
|
|
17593
|
+
onNone: () => Option$1.match(Option$1.liftPredicate(result, isFailed), {
|
|
17594
|
+
onNone: () => CheckedPlanPassed.make({
|
|
17595
|
+
mutantId,
|
|
17596
|
+
entryIndex
|
|
17597
|
+
}),
|
|
17598
|
+
onSome: (failed) => CheckedPlanFailed.make({
|
|
17599
|
+
mutantId,
|
|
17600
|
+
entryIndex,
|
|
17601
|
+
reason: failedReasonOf(failed),
|
|
17602
|
+
result: failed
|
|
17603
|
+
})
|
|
17361
17604
|
})
|
|
17362
17605
|
});
|
|
17363
17606
|
const decide$8 = (command) => Result.succeed(command.checked.map(([mutantId, result], entryIndex) => decideCheckedPlan(mutantId, result, entryIndex)));
|
|
17364
17607
|
const partitionCheckedPlans = Workflow.make({
|
|
17365
17608
|
command: PartitionCheckedPlansCommand,
|
|
17366
|
-
decision: S.Array(S.Union([
|
|
17609
|
+
decision: S.Array(S.Union([
|
|
17610
|
+
CheckedPlanPassed,
|
|
17611
|
+
CheckedPlanFailed,
|
|
17612
|
+
CheckedPlanIgnored
|
|
17613
|
+
])),
|
|
17367
17614
|
error: S.Never,
|
|
17368
17615
|
decide: decide$8
|
|
17369
17616
|
});
|
|
@@ -17400,6 +17647,7 @@ const onCheckerSlot = (pool, checkerIndex, run) => Pool.use(pool, (slot) => Opti
|
|
|
17400
17647
|
}));
|
|
17401
17648
|
const noPassedPlans = [];
|
|
17402
17649
|
const noFailedChecks = [];
|
|
17650
|
+
const noIgnoredChecks = [];
|
|
17403
17651
|
const splitCheckedPlans = Effect$1.fn(SpanTaxonomy_exports.Spans.checkerPoolSplitChecked.name)(function* (checked) {
|
|
17404
17652
|
const decisions = yield* Effect$1.fromResult(partitionCheckedPlans(PartitionCheckedPlansCommand.make({ checked: checked.map(([plan, result]) => [plan.mutant.id, result]) })));
|
|
17405
17653
|
return {
|
|
@@ -17410,6 +17658,10 @@ const splitCheckedPlans = Effect$1.fn(SpanTaxonomy_exports.Spans.checkerPoolSpli
|
|
|
17410
17658
|
failedChecks: decisions.flatMap((decision) => Option$1.match(Option$1.liftPredicate(decision, S.is(CheckedPlanFailed)), {
|
|
17411
17659
|
onNone: () => [],
|
|
17412
17660
|
onSome: (failed) => Option$1.toArray(Option$1.map(Arr.get(checked, failed.entryIndex), ([plan]) => [plan, failed.result]))
|
|
17661
|
+
})),
|
|
17662
|
+
ignoredChecks: decisions.flatMap((decision) => Option$1.match(Option$1.liftPredicate(decision, S.is(CheckedPlanIgnored)), {
|
|
17663
|
+
onNone: () => [],
|
|
17664
|
+
onSome: (ignored) => Option$1.toArray(Option$1.map(Arr.get(checked, ignored.entryIndex), ([plan]) => [plan, ignored.result]))
|
|
17413
17665
|
}))
|
|
17414
17666
|
};
|
|
17415
17667
|
});
|
|
@@ -17418,23 +17670,34 @@ const failedElement = (failedChecks) => Option$1.match(Arr.head(failedChecks), {
|
|
|
17418
17670
|
onNone: () => Stream.empty,
|
|
17419
17671
|
onSome: () => Stream.succeed({
|
|
17420
17672
|
passedPlans: noPassedPlans,
|
|
17421
|
-
failedChecks
|
|
17673
|
+
failedChecks,
|
|
17674
|
+
ignoredChecks: noIgnoredChecks
|
|
17675
|
+
})
|
|
17676
|
+
});
|
|
17677
|
+
const ignoredElement = (ignoredChecks) => Option$1.match(Arr.head(ignoredChecks), {
|
|
17678
|
+
onNone: () => Stream.empty,
|
|
17679
|
+
onSome: () => Stream.succeed({
|
|
17680
|
+
passedPlans: noPassedPlans,
|
|
17681
|
+
failedChecks: noFailedChecks,
|
|
17682
|
+
ignoredChecks
|
|
17422
17683
|
})
|
|
17423
17684
|
});
|
|
17424
17685
|
const checkedGroupsFor = (pool, checkerNames, checkerIndex, plans) => Option$1.match(Arr.get(checkerNames, checkerIndex), {
|
|
17425
17686
|
onNone: () => Stream.succeed({
|
|
17426
17687
|
passedPlans: plans,
|
|
17427
|
-
failedChecks: noFailedChecks
|
|
17688
|
+
failedChecks: noFailedChecks,
|
|
17689
|
+
ignoredChecks: noIgnoredChecks
|
|
17428
17690
|
}),
|
|
17429
17691
|
onSome: (checkerName) => Stream.unwrap(onCheckerSlot(pool, checkerIndex, (checker) => groupPlans(checker, checkerName, plans)).pipe(Effect$1.map((groups) => Stream.fromIterable(groups).pipe(Stream.mapEffect((group) => onCheckerSlot(pool, checkerIndex, (checker) => checkPlans$1(checker, checkerName, group)).pipe(Effect$1.flatMap((checked) => splitCheckedPlans(checked))), {
|
|
17430
17692
|
concurrency: "unbounded",
|
|
17431
17693
|
unordered: true
|
|
17432
|
-
}), Stream.flatMap((split) => Stream.concat(failedElement(split.failedChecks), checkedGroupsFor(pool, checkerNames, checkerIndex + 1, split.passedPlans)))))))
|
|
17694
|
+
}), Stream.flatMap((split) => Stream.concat(ignoredElement(split.ignoredChecks), Stream.concat(failedElement(split.failedChecks), checkedGroupsFor(pool, checkerNames, checkerIndex + 1, split.passedPlans))))))))
|
|
17433
17695
|
});
|
|
17434
17696
|
const checkPlansStream = dual(2, (checkerPool, plans) => Option$1.fromNullishOr(checkerPool).pipe(Option$1.match({
|
|
17435
17697
|
onNone: () => Stream.succeed({
|
|
17436
17698
|
passedPlans: plans,
|
|
17437
|
-
failedChecks: noFailedChecks
|
|
17699
|
+
failedChecks: noFailedChecks,
|
|
17700
|
+
ignoredChecks: noIgnoredChecks
|
|
17438
17701
|
}),
|
|
17439
17702
|
onSome: (handle) => checkerNamesOf(CheckerPoolHandle.slot(handle)).pipe(Effect$1.map((checkerNames) => checkedGroupsFor(CheckerPoolHandle.slot(handle), checkerNames, 0, plans)), Stream.unwrap)
|
|
17440
17703
|
}), Stream.withSpan(SpanTaxonomy_exports.Spans.checkerPoolCheckPlans.name)));
|
|
@@ -17442,16 +17705,23 @@ Effect$1.fnUntraced(function* (checkerPool, plans) {
|
|
|
17442
17705
|
const checkedGroups = yield* Stream.runCollect(checkPlansStream(checkerPool, plans));
|
|
17443
17706
|
const passedPlans = [];
|
|
17444
17707
|
const failedChecks = [];
|
|
17708
|
+
const ignoredChecks = [];
|
|
17445
17709
|
for (const group of checkedGroups) {
|
|
17446
17710
|
passedPlans.push(...group.passedPlans);
|
|
17447
17711
|
failedChecks.push(...group.failedChecks);
|
|
17712
|
+
ignoredChecks.push(...group.ignoredChecks);
|
|
17448
17713
|
}
|
|
17449
17714
|
return {
|
|
17450
17715
|
passedPlans,
|
|
17451
|
-
failedChecks
|
|
17716
|
+
failedChecks,
|
|
17717
|
+
ignoredChecks
|
|
17452
17718
|
};
|
|
17453
17719
|
});
|
|
17454
|
-
const runCheckedPlans = dual(2, (self, execution) => self.pipe(Stream.flatMap(({ passedPlans, failedChecks }) => Stream.fromIterable([
|
|
17720
|
+
const runCheckedPlans = dual(2, (self, execution) => self.pipe(Stream.flatMap(({ passedPlans, failedChecks, ignoredChecks }) => Stream.fromIterable([
|
|
17721
|
+
...failedChecks.map(([plan, result]) => () => execution.settleFailure(plan, result)),
|
|
17722
|
+
...ignoredChecks.map(([plan, result]) => () => execution.settleIgnored(plan, result)),
|
|
17723
|
+
...passedPlans.map((plan) => () => execution.runPlan(plan))
|
|
17724
|
+
])), Stream.mapEffect((work) => work(), {
|
|
17455
17725
|
concurrency: Math.max(1, execution.concurrency),
|
|
17456
17726
|
unordered: true
|
|
17457
17727
|
})));
|
|
@@ -17506,11 +17776,13 @@ const checkerWorkerSpawnOf = (loaded, configured) => Effect$1.mapError(Effect$1.
|
|
|
17506
17776
|
cause: PluginNotFoundError.make({ descriptor: missing.descriptor })
|
|
17507
17777
|
}));
|
|
17508
17778
|
const acquire$1 = Effect$1.fnUntraced(function* (spec) {
|
|
17779
|
+
const reports = yield* WorkerReports;
|
|
17509
17780
|
return yield* Boolean$1$1.match(spec.options.checkers.length === 0, {
|
|
17510
17781
|
onTrue: () => Effect$1.as(Effect$1.void, void 0),
|
|
17511
17782
|
onFalse: () => Pool.make({
|
|
17512
17783
|
acquire: Effect$1.forEach(spec.options.checkers, (checker) => Effect$1.gen(function* () {
|
|
17513
17784
|
const resolved = yield* checkerWorkerSpawnOf(spec.loadedPlugins, ConfiguredPluginModulePath.make({ modulePath: checker.plugin }));
|
|
17785
|
+
const startedAt = yield* Clock.currentTimeMillis;
|
|
17514
17786
|
const service = yield* scoped$2({
|
|
17515
17787
|
options: {
|
|
17516
17788
|
...spec.options,
|
|
@@ -17522,6 +17794,7 @@ const acquire$1 = Effect$1.fnUntraced(function* (spec) {
|
|
|
17522
17794
|
times: CHECKER_ACQUIRE_RETRIES,
|
|
17523
17795
|
while: isCheckerCrash
|
|
17524
17796
|
}));
|
|
17797
|
+
yield* reports.report("checker", (yield* Clock.currentTimeMillis) - startedAt);
|
|
17525
17798
|
return {
|
|
17526
17799
|
checkerName: resolved.name,
|
|
17527
17800
|
checker: service
|
|
@@ -17879,7 +18152,7 @@ const readIncrementalReuseCommand = Effect$1.fn(SpanTaxonomy_exports.Spans.incre
|
|
|
17879
18152
|
previousRecords: [...previousRecords],
|
|
17880
18153
|
closureDigestsByMutantId: closures.digests,
|
|
17881
18154
|
closureAnalysisFailed: closures.failed,
|
|
17882
|
-
verdictSemanticsVersion:
|
|
18155
|
+
verdictSemanticsVersion: 3,
|
|
17883
18156
|
mutantSetPolicy: input.options.mutator.mutantSetPolicy,
|
|
17884
18157
|
runInputsDigest,
|
|
17885
18158
|
force: input.force,
|
|
@@ -18062,6 +18335,7 @@ const toReportedMutant = (mutant) => Object.assign(mutant, {
|
|
|
18062
18335
|
coveredBy: mutant.coveredBy,
|
|
18063
18336
|
static: mutant.static
|
|
18064
18337
|
});
|
|
18338
|
+
const isNoCoveragePlan = (plan) => plan.runOptions.testFilter !== void 0 && plan.runOptions.testFilter.length === 0;
|
|
18065
18339
|
const inPlannedOrder = ({ planned, results }) => {
|
|
18066
18340
|
const rankById = Object.fromEntries(planned.map((mutant, index) => [mutant.id, index]));
|
|
18067
18341
|
return Arr.sortWith(results, (result) => rankById[result.id] ?? planned.length, Order.Number);
|
|
@@ -18099,11 +18373,14 @@ const reportingInputOf = (input) => ({
|
|
|
18099
18373
|
options: input.prev.options,
|
|
18100
18374
|
project: input.prev.project,
|
|
18101
18375
|
testCoverage: input.prev.testCoverage,
|
|
18376
|
+
timeOverheadMs: Duration.toMillis(input.prev.timeOverhead),
|
|
18102
18377
|
runId: input.env.runId,
|
|
18103
18378
|
resolvedMode: input.env.resolvedMode,
|
|
18104
18379
|
basePath: input.env.basePath,
|
|
18105
18380
|
reporterStage: input.prev.reporterStage,
|
|
18106
|
-
formatRegistry: input.prev.formatRegistry
|
|
18381
|
+
formatRegistry: input.prev.formatRegistry,
|
|
18382
|
+
concurrency: input.prev.concurrency.testRunners + input.prev.concurrency.checkers,
|
|
18383
|
+
runStartedAt: input.env.runStartedAt
|
|
18107
18384
|
});
|
|
18108
18385
|
const preparedStreamableOf = Effect$1.fnUntraced(function* (context, result) {
|
|
18109
18386
|
return yield* Option$1.match(Option$1.filter(Option$1.some(result.status), isMutantStatus), {
|
|
@@ -18357,10 +18634,11 @@ const coveredByField = (coveredBy) => Option$1.match(Option$1.fromUndefinedOr(co
|
|
|
18357
18634
|
onNone: () => ({}),
|
|
18358
18635
|
onSome: (present) => ({ coveredBy: [...present] })
|
|
18359
18636
|
});
|
|
18360
|
-
const testFilterField = (testFilter) => Option$1.match(Option$1.
|
|
18637
|
+
const testFilterField = (testFilter) => Option$1.match(Option$1.fromUndefinedOr(testFilter), {
|
|
18361
18638
|
onNone: () => ({}),
|
|
18362
18639
|
onSome: (present) => ({ testFilter: [...present] })
|
|
18363
18640
|
});
|
|
18641
|
+
const nonEmptyTestFilterOf = (tests) => Option$1.getOrUndefined(Option$1.filter(Option$1.fromUndefinedOr(tests), (present) => present.length > 0));
|
|
18364
18642
|
const staticCoverageCountOf = (staticCoverage, mutantId) => Option$1.getOrElse(Option$1.flatMap(Option$1.fromNullishOr(staticCoverage), (countsByMutantId) => Record$1.get(countsByMutantId, mutantId)), () => 0);
|
|
18365
18643
|
const hasCoverageForPlan = (staticCoverage) => Option$1.isSome(Option$1.fromUndefinedOr(staticCoverage));
|
|
18366
18644
|
const mutantIsStatic = (command, mutantId) => staticCoverageCountOf(command.staticCoverage, mutantId) > 0;
|
|
@@ -18446,10 +18724,13 @@ const orderedTestsOf = (command, mutantId, tests) => {
|
|
|
18446
18724
|
onSome: (present) => [present, ...rest]
|
|
18447
18725
|
});
|
|
18448
18726
|
};
|
|
18449
|
-
const runWithCoveredTests = (mutant, command, isStatic, tests, coveredBy) => toRunPlan(mutant, command, calculateTotalTimeForIds(tests, command.testTimeById), orderedTestsOf(command, mutant.id, tests), isStatic, coveredBy);
|
|
18727
|
+
const runWithCoveredTests = (mutant, command, isStatic, tests, coveredBy) => toRunPlan(mutant, command, calculateTotalTimeForIds(tests, command.testTimeById), nonEmptyTestFilterOf(orderedTestsOf(command, mutant.id, tests)), isStatic, coveredBy);
|
|
18728
|
+
const NO_COVERAGE_NET_TIME_MS = 0;
|
|
18729
|
+
const NO_COVERAGE_TEST_FILTER = [];
|
|
18730
|
+
const toNoCoverageRunPlan = (mutant, command, isStatic, coveredBy) => toRunPlan(mutant, command, NO_COVERAGE_NET_TIME_MS, NO_COVERAGE_TEST_FILTER, isStatic, coveredBy);
|
|
18450
18731
|
const planForUncoveredStatic = (mutant, command, isStatic, coveredBy) => Boolean$1$1.match(command.options.ignoreStatic, {
|
|
18451
18732
|
onTrue: () => Result.succeed(toEarlyResultPlan(mutant, isStatic, "Ignored", IGNORED_STATIC_MUTANT_REASON, coveredBy)),
|
|
18452
|
-
onFalse: () => toRunPlan(mutant, command, command.timeSpentAllTests, command.globalTestFilter, isStatic, coveredBy)
|
|
18733
|
+
onFalse: () => toRunPlan(mutant, command, command.timeSpentAllTests, nonEmptyTestFilterOf(command.globalTestFilter), isStatic, coveredBy)
|
|
18453
18734
|
});
|
|
18454
18735
|
const planForStaticallyCovered = (mutant, command, isStatic) => {
|
|
18455
18736
|
const tests = Option$1.getOrElse(Record$1.get(command.testsByMutantId, mutant.id), () => []);
|
|
@@ -18478,10 +18759,10 @@ const decidePlanForMutant = (mutant, command) => {
|
|
|
18478
18759
|
return Option$1.match(Option$1.fromUndefinedOr(mutant.status), {
|
|
18479
18760
|
onSome: (status) => Result.succeed(toEarlyResultPlan(mutant, isStatic, status, mutant.statusReason, coveredByOfMutant(mutant))),
|
|
18480
18761
|
onNone: () => Boolean$1$1.match(isPerTestUncoveredNonStatic(command, mutant, isStatic), {
|
|
18481
|
-
onTrue: () =>
|
|
18762
|
+
onTrue: () => toNoCoverageRunPlan(mutant, command, isStatic, coveringTestIdsOf(command, mutant.id)),
|
|
18482
18763
|
onFalse: () => Boolean$1$1.match(hasCoverageForPlan(command.staticCoverage), {
|
|
18483
18764
|
onTrue: () => planForStaticallyCovered(mutant, command, isStatic),
|
|
18484
|
-
onFalse: () => toRunPlan(mutant, command, command.timeSpentAllTests, command.globalTestFilter, void 0, void 0)
|
|
18765
|
+
onFalse: () => toRunPlan(mutant, command, command.timeSpentAllTests, nonEmptyTestFilterOf(command.globalTestFilter), void 0, void 0)
|
|
18485
18766
|
})
|
|
18486
18767
|
})
|
|
18487
18768
|
});
|
|
@@ -18773,7 +19054,10 @@ const planMutationTest = Effect$1.fn(SpanTaxonomy_exports.Spans.mutationTestPlan
|
|
|
18773
19054
|
}))
|
|
18774
19055
|
})).pipe(Effect$1.ignoreCause);
|
|
18775
19056
|
const progressQueue = yield* RunEvents;
|
|
18776
|
-
yield* Queue.offer(progressQueue, RunEvent_exports.PlanKnown.make({
|
|
19057
|
+
yield* Queue.offer(progressQueue, RunEvent_exports.PlanKnown.make({
|
|
19058
|
+
total: plansForReporter.length + earlyResults.length,
|
|
19059
|
+
shardPlan: null
|
|
19060
|
+
}));
|
|
18777
19061
|
return {
|
|
18778
19062
|
runPlans: sortedPlans,
|
|
18779
19063
|
earlyResults,
|
|
@@ -18796,8 +19080,10 @@ const testRunnerWorkerSpawnOf = (loaded, configured) => Effect$1.mapError(Effect
|
|
|
18796
19080
|
cause: PluginNotFoundError.make({ descriptor: missing.descriptor })
|
|
18797
19081
|
}));
|
|
18798
19082
|
const acquire = Effect$1.fnUntraced(function* (spec) {
|
|
18799
|
-
|
|
18800
|
-
|
|
19083
|
+
const reports = yield* WorkerReports;
|
|
19084
|
+
const acquireOne = Effect$1.gen(function* () {
|
|
19085
|
+
const startedAt = yield* Clock.currentTimeMillis;
|
|
19086
|
+
const runner = yield* buildTestRunner({
|
|
18801
19087
|
options: spec.options,
|
|
18802
19088
|
fileDescriptions: spec.fileDescriptions,
|
|
18803
19089
|
sandboxWorkingDirectory: spec.sandboxWorkingDirectory,
|
|
@@ -18810,7 +19096,12 @@ const acquire = Effect$1.fnUntraced(function* (spec) {
|
|
|
18810
19096
|
sandboxWorkingDirectory: spec.sandboxWorkingDirectory,
|
|
18811
19097
|
workerEntrypoint: resolved.entrypoint,
|
|
18812
19098
|
idGenerator: spec.idGenerator
|
|
18813
|
-
})))))
|
|
19099
|
+
})))));
|
|
19100
|
+
yield* reports.report("testRunner", (yield* Clock.currentTimeMillis) - startedAt);
|
|
19101
|
+
return runner;
|
|
19102
|
+
});
|
|
19103
|
+
return yield* Pool.makeWithTTL({
|
|
19104
|
+
acquire: acquireOne,
|
|
18814
19105
|
min: spec.min,
|
|
18815
19106
|
max: spec.max,
|
|
18816
19107
|
timeToLive: IDLE_TIME_TO_LIVE
|
|
@@ -18823,6 +19114,9 @@ const TestRunnerPools = Blueprint.make()(TypeId).steps({
|
|
|
18823
19114
|
const scoped = (spec) => TestRunnerPools.of(spec).scoped;
|
|
18824
19115
|
//#endregion
|
|
18825
19116
|
//#region src/run/mutation-test.cell.ts
|
|
19117
|
+
const TCE_EQUIVALENT_TO_ORIGINAL_REASON = "equivalent-to-original: tce";
|
|
19118
|
+
const TCE_DUPLICATE_AT_SITE_REASON = "duplicate-at-site: tce";
|
|
19119
|
+
const countIgnoredByReason = (results, reason) => results.filter((result) => result.status === "Ignored" && result.statusReason === reason).length;
|
|
18826
19120
|
const writeMutationTestNoTests = Effect$1.fn(SpanTaxonomy_exports.Spans.mutationTestNoTests.name)(function* () {
|
|
18827
19121
|
const env = yield* RunEnvironment;
|
|
18828
19122
|
const now = yield* Clock.currentTimeMillis;
|
|
@@ -18926,22 +19220,26 @@ const proceedPipeline = Effect$1.fnUntraced(function* (raw) {
|
|
|
18926
19220
|
});
|
|
18927
19221
|
const runResults = yield* Effect$1.scoped(Effect$1.gen(function* () {
|
|
18928
19222
|
const checkpoint = yield* makeCheckpointWriter(context, settledResults);
|
|
19223
|
+
const settleReported = (reported) => Effect$1.gen(function* () {
|
|
19224
|
+
yield* announceSettledMutant(context, reported);
|
|
19225
|
+
yield* checkpoint.record(reported);
|
|
19226
|
+
return reported;
|
|
19227
|
+
});
|
|
18929
19228
|
return yield* withPhaseSpan(SpanTaxonomy_exports.Spans.mutationTestBatch, {
|
|
18930
19229
|
total: plan.plannedTotal,
|
|
18931
19230
|
testRunners: prev.concurrency.testRunners
|
|
18932
19231
|
}, () => runCheckedPlans(checkedPlans, {
|
|
18933
|
-
settleFailure: (mutantPlan, result) => Effect$1.
|
|
18934
|
-
|
|
18935
|
-
|
|
18936
|
-
|
|
18937
|
-
|
|
19232
|
+
settleFailure: (mutantPlan, result) => reporting.reportCheckFailure(toReportedMutant(mutantPlan.mutant), result).pipe(Effect$1.flatMap(settleReported)),
|
|
19233
|
+
settleIgnored: (mutantPlan, result) => reporting.reportIgnored(toReportedMutant(mutantPlan.mutant), result).pipe(Effect$1.flatMap(settleReported)),
|
|
19234
|
+
runPlan: (runPlan) => Option$1.match(Option$1.liftPredicate(runPlan, isNoCoveragePlan), {
|
|
19235
|
+
onNone: () => Effect$1.scoped(mutantRunCell.run({
|
|
19236
|
+
context,
|
|
19237
|
+
testRunnerPool,
|
|
19238
|
+
checkpoint,
|
|
19239
|
+
plan: runPlan
|
|
19240
|
+
})),
|
|
19241
|
+
onSome: (noCoverageRunPlan) => reporting.reportNoCoverage(toReportedMutant(noCoverageRunPlan.mutant)).pipe(Effect$1.flatMap(settleReported))
|
|
18938
19242
|
}),
|
|
18939
|
-
runPlan: (runPlan) => Effect$1.scoped(mutantRunCell.run({
|
|
18940
|
-
context,
|
|
18941
|
-
testRunnerPool,
|
|
18942
|
-
checkpoint,
|
|
18943
|
-
plan: runPlan
|
|
18944
|
-
})),
|
|
18945
19243
|
concurrency: testRunnerCapacity
|
|
18946
19244
|
}).pipe(Stream.runFold(() => [], (acc, result) => {
|
|
18947
19245
|
acc.push(result);
|
|
@@ -18957,6 +19255,10 @@ const proceedPipeline = Effect$1.fnUntraced(function* (raw) {
|
|
|
18957
19255
|
requested: requestedIdsOf(prev.options),
|
|
18958
19256
|
results: allResults
|
|
18959
19257
|
}), (detail) => Queue.offer(progressQueue, detail), { discard: true });
|
|
19258
|
+
yield* Queue.offer(progressQueue, RunEvent_exports.TceReported.make({
|
|
19259
|
+
equivalentToOriginal: countIgnoredByReason(allResults, TCE_EQUIVALENT_TO_ORIGINAL_REASON),
|
|
19260
|
+
duplicateAtSite: countIgnoredByReason(allResults, TCE_DUPLICATE_AT_SITE_REASON)
|
|
19261
|
+
}));
|
|
18960
19262
|
const outcomeResult = yield* reporting.reportAll({
|
|
18961
19263
|
...reportingInputOf({
|
|
18962
19264
|
prev,
|
|
@@ -19707,13 +20009,11 @@ const reporterInputsOf = dual(5, (names, choicesByName, loaded, projectBasePath,
|
|
|
19707
20009
|
//#endregion
|
|
19708
20010
|
//#region src/keep-temp-dir.workflow.ts
|
|
19709
20011
|
const KeepTempDirTypeId = Symbol.for("@systemfsoftware/stryker-js/KeepTempDir");
|
|
19710
|
-
|
|
19711
|
-
|
|
19712
|
-
|
|
19713
|
-
|
|
19714
|
-
|
|
19715
|
-
};
|
|
19716
|
-
const KeepTempDirOption = S.Union([KeepTempDirAlways, KeepTempDirOnFailure]);
|
|
20012
|
+
const CleanTempDirOption = S.Literals([
|
|
20013
|
+
"always",
|
|
20014
|
+
false,
|
|
20015
|
+
true
|
|
20016
|
+
]);
|
|
19717
20017
|
var TempDirKept = class extends S.TaggedClass()("TempDirKept", {}) {
|
|
19718
20018
|
[KeepTempDirTypeId] = KeepTempDirTypeId;
|
|
19719
20019
|
};
|
|
@@ -19721,13 +20021,13 @@ var TempDirRemoved = class extends S.TaggedClass()("TempDirRemoved", {}) {
|
|
|
19721
20021
|
[KeepTempDirTypeId] = KeepTempDirTypeId;
|
|
19722
20022
|
};
|
|
19723
20023
|
var KeepTempDirCommand = class extends S.TaggedClass()("KeepTempDirCommand", {
|
|
19724
|
-
cleanTempDir:
|
|
20024
|
+
cleanTempDir: CleanTempDirOption,
|
|
19725
20025
|
failed: S.Boolean
|
|
19726
20026
|
}) {
|
|
19727
20027
|
static [Workflow.InstrumentationBrand] = {};
|
|
19728
20028
|
};
|
|
19729
|
-
const
|
|
19730
|
-
const decide = (command) => Match$1.value(command.cleanTempDir).pipe(Match$1.
|
|
20029
|
+
const keptIff = (kept) => Match$1.value(kept).pipe(Match$1.when(true, () => TempDirKept.make({})), Match$1.when(false, () => TempDirRemoved.make({})), Match$1.exhaustive);
|
|
20030
|
+
const decide = (command) => Match$1.value(command.cleanTempDir).pipe(Match$1.when(false, () => TempDirKept.make({})), Match$1.when(true, () => keptIff(command.failed)), Match$1.when("always", () => TempDirRemoved.make({})), Match$1.exhaustive, Result.succeed);
|
|
19731
20031
|
const keepTempDir = Workflow.make({
|
|
19732
20032
|
command: KeepTempDirCommand,
|
|
19733
20033
|
decision: S.Union([TempDirKept, TempDirRemoved]),
|
|
@@ -19736,11 +20036,10 @@ const keepTempDir = Workflow.make({
|
|
|
19736
20036
|
});
|
|
19737
20037
|
//#endregion
|
|
19738
20038
|
//#region src/Sandbox.service.ts
|
|
19739
|
-
const
|
|
19740
|
-
cleanTempDir
|
|
20039
|
+
const removesTempDir = (exit, cleanTempDir) => Result.match(keepTempDir(KeepTempDirCommand.make({
|
|
20040
|
+
cleanTempDir,
|
|
19741
20041
|
failed: Exit.isFailure(exit)
|
|
19742
|
-
})
|
|
19743
|
-
const removesTempDir = (exit, cleanTempDir) => Result.match(keepTempDir(keepTempDirCommand(exit, cleanTempDir)), {
|
|
20042
|
+
})), {
|
|
19744
20043
|
onFailure: () => false,
|
|
19745
20044
|
onSuccess: (decision) => Match$1.value(decision).pipe(Match$1.tag("TempDirRemoved", () => true), Match$1.tag("TempDirKept", () => false), Match$1.exhaustive)
|
|
19746
20045
|
});
|
|
@@ -19781,7 +20080,7 @@ const makeTemporaryDirectory = Effect$1.fn(SpanTaxonomy_exports.Spans.sandboxMak
|
|
|
19781
20080
|
yield* Effect$1.logDebug(`Using temp directory "${tmp}"`);
|
|
19782
20081
|
yield* Effect$1.addFinalizer((exit) => Boolean$1.match(removesTempDir(exit, options.cleanTempDir), {
|
|
19783
20082
|
onTrue: () => removeTempDirectory(tmp, parent, fs),
|
|
19784
|
-
onFalse: () => Effect$1.logDebug(
|
|
20083
|
+
onFalse: () => Effect$1.logDebug(`Keeping stryker temp directory ${tmp}`)
|
|
19785
20084
|
}).pipe(Effect$1.orDie));
|
|
19786
20085
|
return { path: tmp };
|
|
19787
20086
|
});
|
|
@@ -20051,11 +20350,11 @@ const prepareCell = Sandwich.named(SpanTaxonomy_exports.Spans.prepare.name)(read
|
|
|
20051
20350
|
//#endregion
|
|
20052
20351
|
//#region src/run/run-stages.cell.ts
|
|
20053
20352
|
const configReadReasonOf = (cause) => Match$1.value(cause).pipe(Match$1.tag("ConfigError", (refused) => refused.message), Match$1.orElse(() => "Failed to read config"));
|
|
20054
|
-
const mutationTestCell = Cell.andThen(Cell.andThen(Cell.andThen(Cell.mapError(loadConfigCell, (cause) => StageError.make({
|
|
20353
|
+
const mutationTestCell = Cell.andThen(Cell.andThen(Cell.andThen(Cell.andThen(Cell.mapError(loadConfigCell, (cause) => StageError.make({
|
|
20055
20354
|
stage: "prepare",
|
|
20056
20355
|
reason: configReadReasonOf(cause),
|
|
20057
20356
|
cause
|
|
20058
|
-
})), Cell.mapError(readProjectCell, (cause) => StageError.make({
|
|
20357
|
+
})), (loaded) => refuseLocalMutationCell(loaded)), Cell.mapError(readProjectCell, (cause) => StageError.make({
|
|
20059
20358
|
stage: "prepare",
|
|
20060
20359
|
reason: "Failed to read project",
|
|
20061
20360
|
cause
|
|
@@ -20198,7 +20497,7 @@ S.Struct({
|
|
|
20198
20497
|
mode: OutputMode_exports.OutputMode,
|
|
20199
20498
|
signal: OutputMode_exports.ModeSignal
|
|
20200
20499
|
});
|
|
20201
|
-
const nextFramingState = (state, event) => Match$1.value(event).pipe(Match$1.tag("verdict", "error", "help", () => FramingState.make({
|
|
20500
|
+
const nextFramingState = (state, event) => Match$1.value(event).pipe(Match$1.tag("verdict", "error", "help", "refused", () => FramingState.make({
|
|
20202
20501
|
mode: state.mode,
|
|
20203
20502
|
signal: state.signal,
|
|
20204
20503
|
headerWritten: state.headerWritten,
|
|
@@ -20219,7 +20518,7 @@ const nextFramingState = (state, event) => Match$1.value(event).pipe(Match$1.tag
|
|
|
20219
20518
|
terminalSeen: state.terminalSeen,
|
|
20220
20519
|
completed: e.completed,
|
|
20221
20520
|
total: e.total
|
|
20222
|
-
})), Match$1.tag("stream", () => state), Match$1.tag("phase", () => state), Match$1.tag("tick", () => state), Match$1.tag("plugins", () => state), Match$1.tag("formats", () => state), Match$1.tag("skipped", () => state), Match$1.tag("reuse", "mutant-detail", "feedback", () => state), Match$1.exhaustive);
|
|
20521
|
+
})), Match$1.tag("stream", () => state), Match$1.tag("phase", () => state), Match$1.tag("tick", () => state), Match$1.tag("worker", () => state), Match$1.tag("plugins", () => state), Match$1.tag("formats", () => state), Match$1.tag("skipped", () => state), Match$1.tag("reuse", "tce", "mutant-detail", "feedback", () => state), Match$1.exhaustive);
|
|
20223
20522
|
const noteState = (state, event) => nextFramingState(state, event);
|
|
20224
20523
|
const formatScore = (score) => Option$1.match(Option$1.fromNullishOr(score), {
|
|
20225
20524
|
onNone: () => "n/a",
|
|
@@ -20229,7 +20528,7 @@ const formatTotal = (total) => Option$1.match(Option$1.fromNullishOr(total), {
|
|
|
20229
20528
|
onNone: () => "?",
|
|
20230
20529
|
onSome: (val) => String(val)
|
|
20231
20530
|
});
|
|
20232
|
-
const formatStderrEvent = (event) => Match$1.value(event).pipe(Match$1.tag("plan", (e) => `plan ${e.total} mutants`), Match$1.tag("phase", (e) => `phase ${e.phase}`), Match$1.tag("tick", (e) => `${e.completed}/${formatTotal(e.total)} elapsed ${e.elapsedMs}ms`), Match$1.tag("verdict", (e) => `score ${formatScore(e.score)} killed ${e.counts.killed} survived ${e.counts.survived}`), Match$1.tag("error", (e) => `error ${e.error}`), Match$1.tag("stream", () => null), Match$1.tag("mutantTested", () => null), Match$1.tag("help", () => null), Match$1.tag("plugins", () => null), Match$1.tag("formats", () => null), Match$1.tag("skipped", () => null), Match$1.tag("reuse", "mutant-detail", "feedback", () => null), Match$1.exhaustive);
|
|
20531
|
+
const formatStderrEvent = (event) => Match$1.value(event).pipe(Match$1.tag("plan", (e) => `plan ${e.total} mutants`), Match$1.tag("phase", (e) => `phase ${e.phase}`), Match$1.tag("tick", (e) => `${e.completed}/${formatTotal(e.total)} elapsed ${e.elapsedMs}ms`), Match$1.tag("verdict", (e) => `score ${formatScore(e.score)} killed ${e.counts.killed} survived ${e.counts.survived}`), Match$1.tag("error", (e) => `error ${e.error}`), Match$1.tag("refused", (e) => `refused ${e.rule}`), Match$1.tag("stream", () => null), Match$1.tag("mutantTested", () => null), Match$1.tag("worker", () => null), Match$1.tag("help", () => null), Match$1.tag("plugins", () => null), Match$1.tag("formats", () => null), Match$1.tag("skipped", () => null), Match$1.tag("reuse", "tce", "mutant-detail", "feedback", () => null), Match$1.exhaustive);
|
|
20233
20532
|
const stderrLineFor = (state, event) => Boolean$1$1.match(Boolean$1$1.and(state.mode === "human", !state.terminalSeen), {
|
|
20234
20533
|
onTrue: () => formatStderrEvent(event),
|
|
20235
20534
|
onFalse: () => null
|
|
@@ -20393,16 +20692,17 @@ const CONFIG_CODE = 2;
|
|
|
20393
20692
|
const UNKNOWN_FAILURE = "Unknown failure";
|
|
20394
20693
|
const SIGNAL_REMEDIATION = "the run was interrupted by a signal; re-run it to continue";
|
|
20395
20694
|
const PARSE_REMEDIATION = "re-run with --help to see the full usage";
|
|
20695
|
+
const REFUSAL_REMEDIATION = "run mutation testing on main CI (GitHub Actions)";
|
|
20396
20696
|
const DEFAULT_REMEDIATION = "see --reportFile or the verdict envelope on stdout";
|
|
20397
|
-
const exitCodeOf = (outcome) => Match$1.value(outcome).pipe(Match$1.tag("RunOk", () => 0), Match$1.tag("RunInterrupted", (error) => error.code), Match$1.tag("RunParseFailed", () => CONFIG_CODE), Match$1.tag("RunSurvivorsRejected", () => CONFIG_CODE), Match$1.tag("RunConfigFailed", () => CONFIG_CODE), Match$1.tag("RunFailed", (failed) => failed.code), Match$1.exhaustive);
|
|
20697
|
+
const exitCodeOf = (outcome) => Match$1.value(outcome).pipe(Match$1.tag("RunOk", () => 0), Match$1.tag("RunInterrupted", (error) => error.code), Match$1.tag("RunParseFailed", () => CONFIG_CODE), Match$1.tag("RunSurvivorsRejected", () => CONFIG_CODE), Match$1.tag("RunConfigFailed", () => CONFIG_CODE), Match$1.tag("RunRefused", () => CONFIG_CODE), Match$1.tag("RunFailed", (failed) => failed.code), Match$1.exhaustive);
|
|
20398
20698
|
const nonEmptyText = Option$1.liftPredicate(S.is(S.NonEmptyString));
|
|
20399
20699
|
const capturedOrUnknown = (captured) => Option$1.getOrElse(nonEmptyText(captured), () => UNKNOWN_FAILURE);
|
|
20400
20700
|
const capturedThenRecorded = (captured, recorded) => Option$1.getOrElse(nonEmptyText(captured), () => Option$1.getOrElse(Option$1.fromNullishOr(recorded), () => UNKNOWN_FAILURE));
|
|
20401
|
-
const failureTextOf = (error, captured) => Match$1.value(error).pipe(Match$1.tag("RunParseFailed", (failed) => Option$1.getOrElse(Option$1.map(Option$1.fromNullishOr(failed.unrecognized), (value) => `Received unknown argument: '${value}'`), () => capturedOrUnknown(captured))), Match$1.tag("RunSurvivorsRejected", (failed) => Option$1.getOrElse(Option$1.fromNullishOr(failed.diagnostic), () => UNKNOWN_FAILURE)), Match$1.tag("RunInterrupted", () => capturedOrUnknown(captured)), Match$1.tag("RunConfigFailed", (failed) => capturedThenRecorded(captured, failed.detail)), Match$1.tag("RunFailed", (failed) => capturedThenRecorded(captured, failed.diagnostic)), Match$1.exhaustive);
|
|
20701
|
+
const failureTextOf = (error, captured) => Match$1.value(error).pipe(Match$1.tag("RunParseFailed", (failed) => Option$1.getOrElse(Option$1.map(Option$1.fromNullishOr(failed.unrecognized), (value) => `Received unknown argument: '${value}'`), () => capturedOrUnknown(captured))), Match$1.tag("RunSurvivorsRejected", (failed) => Option$1.getOrElse(Option$1.fromNullishOr(failed.diagnostic), () => UNKNOWN_FAILURE)), Match$1.tag("RunInterrupted", () => capturedOrUnknown(captured)), Match$1.tag("RunConfigFailed", (failed) => capturedThenRecorded(captured, failed.detail)), Match$1.tag("RunRefused", (failed) => failed.message), Match$1.tag("RunFailed", (failed) => capturedThenRecorded(captured, failed.diagnostic)), Match$1.exhaustive);
|
|
20402
20702
|
const remediationTextOf = (error) => Match$1.value(error).pipe(Match$1.tag("RunInterrupted", () => SIGNAL_REMEDIATION), Match$1.tag("RunParseFailed", () => PARSE_REMEDIATION), Match$1.tag("RunSurvivorsRejected", (failed) => Option$1.getOrElse(Option$1.fromNullishOr(failed.diagnostic), () => DEFAULT_REMEDIATION)), Match$1.tag("RunConfigFailed", (failed) => Option$1.match(Option$1.fromNullishOr(failed.detail), {
|
|
20403
20703
|
onSome: (detail) => `check the config file: ${detail}`,
|
|
20404
20704
|
onNone: () => "check the config file"
|
|
20405
|
-
})), Match$1.tag("RunFailed", () => DEFAULT_REMEDIATION), Match$1.exhaustive);
|
|
20705
|
+
})), Match$1.tag("RunRefused", () => REFUSAL_REMEDIATION), Match$1.tag("RunFailed", () => DEFAULT_REMEDIATION), Match$1.exhaustive);
|
|
20406
20706
|
const errorEnvelopeFromOutcome = (input) => ErrorEnvelope.make({
|
|
20407
20707
|
schemaVersion: RunEvent_exports.StreamSchemaVersion.literal,
|
|
20408
20708
|
code: exitCodeOf(input.error),
|
|
@@ -20499,22 +20799,33 @@ const emitNullScoreVerdict = (params) => {
|
|
|
20499
20799
|
version: StrykerPackage.version
|
|
20500
20800
|
}
|
|
20501
20801
|
};
|
|
20502
|
-
|
|
20503
|
-
|
|
20504
|
-
|
|
20505
|
-
|
|
20506
|
-
|
|
20507
|
-
|
|
20508
|
-
|
|
20509
|
-
|
|
20510
|
-
|
|
20511
|
-
|
|
20512
|
-
|
|
20513
|
-
|
|
20514
|
-
|
|
20515
|
-
|
|
20516
|
-
|
|
20517
|
-
|
|
20802
|
+
return Effect$1.gen(function* () {
|
|
20803
|
+
const now = yield* Clock.currentTimeMillis;
|
|
20804
|
+
const envelope = buildVerdictEnvelope({
|
|
20805
|
+
...report,
|
|
20806
|
+
budget: {
|
|
20807
|
+
predictedSeconds: 0,
|
|
20808
|
+
actualSeconds: (now - stream.startedAt) / 1e3
|
|
20809
|
+
}
|
|
20810
|
+
}, mode.mode, mode.signal, stream.runId, basePath, pathService, Option$1.none(), null);
|
|
20811
|
+
yield* Queue.offer(stream.queue, RunEvent_exports.VerdictReached.make({
|
|
20812
|
+
schemaVersion: envelope.schemaVersion,
|
|
20813
|
+
runId: envelope.runId,
|
|
20814
|
+
mode: envelope.mode,
|
|
20815
|
+
signal: envelope.signal,
|
|
20816
|
+
score: envelope.score,
|
|
20817
|
+
thresholds: envelope.thresholds,
|
|
20818
|
+
reportFile: envelope.reportFile,
|
|
20819
|
+
counts: envelope.counts,
|
|
20820
|
+
mutants: envelope.mutants,
|
|
20821
|
+
scope: envelope.scope,
|
|
20822
|
+
mutantSetPolicy: envelope.mutantSetPolicy,
|
|
20823
|
+
incrementalMode: envelope.incrementalMode,
|
|
20824
|
+
phaseDurations: envelope.phaseDurations,
|
|
20825
|
+
static: envelope.static,
|
|
20826
|
+
budget: envelope.budget
|
|
20827
|
+
}));
|
|
20828
|
+
});
|
|
20518
20829
|
};
|
|
20519
20830
|
const offerFailureEnvelope = (stream, failed, captured) => {
|
|
20520
20831
|
const envelope = errorEnvelopeFromOutcome({
|
|
@@ -20529,6 +20840,11 @@ const offerFailureEnvelope = (stream, failed, captured) => {
|
|
|
20529
20840
|
reason: null
|
|
20530
20841
|
}));
|
|
20531
20842
|
};
|
|
20843
|
+
const offerRefusedEnvelope = (stream, refused) => Queue.offer(stream.queue, RunEvent_exports.Refused.make({
|
|
20844
|
+
schemaVersion: RunEvent_exports.StreamSchemaVersion.literal,
|
|
20845
|
+
rule: refused.rule,
|
|
20846
|
+
message: refused.message
|
|
20847
|
+
}));
|
|
20532
20848
|
const emitHelpEnvelope = (stream, help) => Queue.offer(stream.queue, RunEvent_exports.HelpRendered.make({
|
|
20533
20849
|
schemaVersion: RunEvent_exports.StreamSchemaVersion.literal,
|
|
20534
20850
|
code: 0,
|
|
@@ -20560,7 +20876,7 @@ const emitMachineModeOutput = Effect$1.fn(SpanTaxonomy_exports.Spans.runEventStr
|
|
|
20560
20876
|
onSuccess: (decision) => Match$1.value(decision).pipe(Match$1.tag("RunOk", (ok) => Option$1.match(helpPayload(ok, captured), {
|
|
20561
20877
|
onSome: (help) => emitHelpEnvelope(stream, help),
|
|
20562
20878
|
onNone: () => emitNullScoreVerdictWhenOpen(stream, mode, basePath, pathService)
|
|
20563
|
-
})), Match$1.tag("RunParseFailed", (failed) => offerFailureEnvelope(stream, failed, captured)), Match$1.tag("RunSurvivorsRejected", (failed) => offerFailureEnvelope(stream, failed, captured)), Match$1.tag("RunConfigFailed", (failed) => offerFailureEnvelope(stream, failed, captured)), Match$1.tag("RunFailed", (failed) => offerFailureEnvelope(stream, failed, captured)), Match$1.exhaustive),
|
|
20879
|
+
})), Match$1.tag("RunParseFailed", (failed) => offerFailureEnvelope(stream, failed, captured)), Match$1.tag("RunSurvivorsRejected", (failed) => offerFailureEnvelope(stream, failed, captured)), Match$1.tag("RunConfigFailed", (failed) => offerFailureEnvelope(stream, failed, captured)), Match$1.tag("RunRefused", (refused) => offerRefusedEnvelope(stream, refused)), Match$1.tag("RunFailed", (failed) => offerFailureEnvelope(stream, failed, captured)), Match$1.exhaustive),
|
|
20564
20880
|
onFailure: (failure) => offerFailureEnvelope(stream, failure, captured)
|
|
20565
20881
|
});
|
|
20566
20882
|
});
|