@systemfsoftware/stryker-js 12.0.0 → 12.1.1
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 +36 -0
- package/README.md +31 -9
- package/dist/{Run.schema-BxsyHwHr.mjs → Run.schema-BaK_pxuK.mjs} +16 -3
- package/dist/{Run.schema-D43Nx5kI.d.mts → Run.schema-D7N2ILY3.d.mts} +4 -2
- package/dist/{RunEnvironment.service-pCzdC0Sy.d.mts → RunEnvironment.service-6aDpmGcD.d.mts} +3 -3
- package/dist/config.d.mts +2 -2
- package/dist/events.d.mts +1 -1
- package/dist/events.mjs +1 -1
- package/dist/{index-f-U3oZaJ.d.mts → index-B8dqrKV1.d.mts} +10 -3
- package/dist/index.d.mts +19 -12
- package/dist/index.mjs +6 -3
- package/dist/main.mjs +11335 -40208
- package/dist/promises.d.mts +2 -2
- package/dist/promises.mjs +1 -1
- package/dist/{run-stages.cell-MyhsNxH2.mjs → run-stages.cell-CtFLJCm0.mjs} +200 -299
- package/dist/{stryker-config.schema-GS_4_5gX.d.mts → stryker-config.schema-DFWkz89S.d.mts} +1 -1
- package/package.json +8 -7
- package/dist/dist-DKhCurgc.mjs +0 -1524
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { A as Plugin_exports, D as VerdictReached, E as SkippedReported, F as ErrorText_exports, I as Format_exports, L as Instrument_exports, M as Reporter_exports, N as TestRunner_exports, O as Checker_exports, P as Trace_exports$1, R as Mutant_exports, _ as PluginsReported, b as RunFailed$1, c as Heartbeat, f as OutputMode, i as FormatRegistryResolved, j as Report_exports, k as Options_exports, l as HelpRendered, m as PlanKnown, n as StageError, p as PhaseEntered, t as PrepareError, u as ModeSignal, w as RunStarted, x as RunMutantTested, y as RunEvent } from "./Run.schema-
|
|
1
|
+
import { A as Plugin_exports, D as VerdictReached, E as SkippedReported, F as ErrorText_exports, I as Format_exports, L as Instrument_exports, M as Reporter_exports, N as TestRunner_exports, O as Checker_exports, P as Trace_exports$1, R as Mutant_exports, _ as PluginsReported, b as RunFailed$1, c as Heartbeat, f as OutputMode, i as FormatRegistryResolved, j as Report_exports, k as Options_exports, l as HelpRendered, m as PlanKnown, n as StageError, p as PhaseEntered, t as PrepareError, u as ModeSignal, w as RunStarted, x as RunMutantTested, y as RunEvent } from "./Run.schema-BaK_pxuK.mjs";
|
|
2
2
|
import { t as mergeConfig } from "./merge-config-ByZJPeQZ.mjs";
|
|
3
3
|
import { Blueprint, Cell, Handle, Sandwich, Workflow } from "@systemfsoftware/effect-cell-types";
|
|
4
4
|
import * as Boolean$1 from "effect/Boolean";
|
|
@@ -61,13 +61,13 @@ import * as NodeFileSystem$1 from "@effect/platform-node-shared/NodeFileSystem";
|
|
|
61
61
|
import * as NodePath$1 from "@effect/platform-node-shared/NodePath";
|
|
62
62
|
import { badArgument } from "effect/PlatformError";
|
|
63
63
|
import * as Equivalence from "effect/Equivalence";
|
|
64
|
-
import { Session } from "@systemfsoftware/stryker-vm-harness";
|
|
65
64
|
import * as Console from "effect/Console";
|
|
66
65
|
import * as Formatter from "effect/Formatter";
|
|
67
66
|
import * as Runtime from "effect/Runtime";
|
|
68
67
|
import * as Order from "effect/Order";
|
|
69
68
|
import * as CliError from "effect/unstable/cli/CliError";
|
|
70
69
|
import { sha256 } from "@noble/hashes/sha2.js";
|
|
70
|
+
import "effect/Deferred";
|
|
71
71
|
import * as Pool from "effect/Pool";
|
|
72
72
|
import * as Semaphore from "effect/Semaphore";
|
|
73
73
|
//#region src/admit-checker-answer.workflow.ts
|
|
@@ -178,14 +178,14 @@ var WorkerBootTimeoutError = class extends Schema.TaggedError()("WorkerBootTimeo
|
|
|
178
178
|
};
|
|
179
179
|
//#endregion
|
|
180
180
|
//#region src/Checker/Checker.handle.ts
|
|
181
|
-
const TypeId$
|
|
181
|
+
const TypeId$10 = Symbol.for("~systemfsoftware/stryker-js/Checker");
|
|
182
182
|
const checkerDuration = Metric.timer("stryker.checker.duration", { description: "Checker worker RPC duration in milliseconds" });
|
|
183
183
|
const checkerMutantsChecked = Metric.counter("stryker.checker.mutants.checked", { description: "Total number of mutants a checker worker answered for" });
|
|
184
184
|
const checkerRpcFailures = Metric.counter("stryker.checker.rpc_failures", {
|
|
185
185
|
description: "Checker worker RPC calls that did not complete, excluding interruptions",
|
|
186
186
|
incremental: true
|
|
187
187
|
});
|
|
188
|
-
const CheckerHandle = Handle.make()(TypeId$
|
|
188
|
+
const CheckerHandle = Handle.make()(TypeId$10);
|
|
189
189
|
const isCheckerHandle = CheckerHandle.is;
|
|
190
190
|
const connectionCrashed = (cause) => ChildProcessCrashedError.make({
|
|
191
191
|
pid: 0,
|
|
@@ -418,7 +418,7 @@ const checkCell = Sandwich.named("stryker.checker.check_plans")(readCheckCommand
|
|
|
418
418
|
CheckerSkippedRequested: (breach) => Effect$1.fail(CheckerSkippedRequested.make(breach)),
|
|
419
419
|
CommandRejected: ({ issue }, raw) => Effect$1.fail(commandFailed(issue, raw))
|
|
420
420
|
});
|
|
421
|
-
const
|
|
421
|
+
const groupCell = Sandwich.named("stryker.checker.group_plans")(readGroupCommand).decide(admitCheckerAnswer).write({
|
|
422
422
|
CheckGroupDecision: ({ groups }, raw) => writeDecidedGroups({
|
|
423
423
|
plans: raw.plans,
|
|
424
424
|
checkerName: raw.checkerName,
|
|
@@ -432,16 +432,20 @@ const checkGroupedCell = Sandwich.named("stryker.checker.group_plans")(readGroup
|
|
|
432
432
|
CheckerAnsweredUnrequested: (breach) => Effect$1.fail(CheckerAnsweredUnrequested.make(breach)),
|
|
433
433
|
CheckerSkippedRequested: (breach) => Effect$1.fail(CheckerSkippedRequested.make(breach)),
|
|
434
434
|
CommandRejected: ({ issue }, raw) => Effect$1.fail(commandFailed(issue, raw))
|
|
435
|
-
})
|
|
435
|
+
});
|
|
436
|
+
const checkGroupedCell = groupCell.pipe(Cell.flatMap((groups) => Cell.mapInput(Cell.collect(checkCell, (perGroup) => perGroup.flat()), (input) => groups.map((group) => ({
|
|
436
437
|
...input,
|
|
437
438
|
plans: group
|
|
438
439
|
})))));
|
|
439
|
-
const
|
|
440
|
+
const checkRequestOf = (checker, checkerName, plans) => ({
|
|
440
441
|
checker,
|
|
441
442
|
checkerName,
|
|
442
443
|
plans,
|
|
443
444
|
lookup: lookupOf(partitionMutantsForWire(plans))
|
|
444
|
-
})
|
|
445
|
+
});
|
|
446
|
+
const groupPlans = dual(3, (checker, checkerName, plans) => groupCell.run(checkRequestOf(checker, checkerName, plans)));
|
|
447
|
+
const checkPlans = dual(3, (checker, checkerName, plans) => checkCell.run(checkRequestOf(checker, checkerName, plans)));
|
|
448
|
+
const checkGroupedPlans = dual(3, (checker, checkerName, plans) => checkGroupedCell.run(checkRequestOf(checker, checkerName, plans)));
|
|
445
449
|
//#endregion
|
|
446
450
|
//#region src/Config.schema.ts
|
|
447
451
|
const ConfigDocumentSchema = S.Record(S.String, S.Unknown);
|
|
@@ -718,8 +722,8 @@ const interpretDryRunResult = Workflow.make({
|
|
|
718
722
|
});
|
|
719
723
|
//#endregion
|
|
720
724
|
//#region src/pooled-test-runner.handle.ts
|
|
721
|
-
const TypeId$
|
|
722
|
-
const PooledTestRunner = Handle.make()(TypeId$
|
|
725
|
+
const TypeId$9 = Symbol.for("~systemfsoftware/stryker-js/PooledTestRunner");
|
|
726
|
+
const PooledTestRunner = Handle.make()(TypeId$9);
|
|
723
727
|
PooledTestRunner.is;
|
|
724
728
|
const make$3 = (runner) => PooledTestRunner.make({
|
|
725
729
|
capabilities: runner.capabilities,
|
|
@@ -820,7 +824,7 @@ const withEnvironmentReload = dual(2, (inner, retire) => Effect$1.gen(function*
|
|
|
820
824
|
}));
|
|
821
825
|
//#endregion
|
|
822
826
|
//#region src/command-runner.blueprint.ts
|
|
823
|
-
const TypeId$
|
|
827
|
+
const TypeId$8 = Symbol.for("~systemfsoftware/stryker-js/CommandRunner");
|
|
824
828
|
const ALL_TESTS_NAME = "All tests";
|
|
825
829
|
const isCommandRunner = (name) => typeof name === "string" && name.toLowerCase() === "command";
|
|
826
830
|
const commandRunnerCapabilities = { reloadEnvironment: true };
|
|
@@ -881,7 +885,7 @@ const pooledRunnerOf = (config, spawner) => {
|
|
|
881
885
|
mutantRun: (options) => commandRunnerMutantRun(config, options).pipe(provided)
|
|
882
886
|
});
|
|
883
887
|
};
|
|
884
|
-
const CommandRunners = Blueprint.make()(TypeId$
|
|
888
|
+
const CommandRunners = Blueprint.make()(TypeId$8).steps({
|
|
885
889
|
steps: {},
|
|
886
890
|
targets: { runner: (spec) => (spawner) => pooledRunnerOf({
|
|
887
891
|
workingDir: spec.workingDir,
|
|
@@ -1036,7 +1040,7 @@ const resolveConfig = Workflow.make({
|
|
|
1036
1040
|
const ExitDecisionTypeId = Symbol.for("@systemfsoftware/stryker-js/ExitDecision");
|
|
1037
1041
|
var ClassifyExitCommand = class extends S.TaggedClass()("ClassifyExitCommand", {
|
|
1038
1042
|
pending: S.Array(Plugin_exports.ExitClass),
|
|
1039
|
-
score:
|
|
1043
|
+
score: Report_exports.MutationScore,
|
|
1040
1044
|
breakingThreshold: S.NullOr(S.Finite)
|
|
1041
1045
|
}) {
|
|
1042
1046
|
static [Workflow.InstrumentationBrand] = {};
|
|
@@ -1071,9 +1075,12 @@ const PRECEDENCE = [
|
|
|
1071
1075
|
];
|
|
1072
1076
|
const precedenceOf = (pending) => Arr.findFirst(PRECEDENCE, (candidate) => pending.includes(candidate));
|
|
1073
1077
|
const decisionOf$1 = (exitClass) => Match.value(exitClass).pipe(Match.when("VerdictFail", () => ExitVerdictFailed.make({})), Match.when("ConfigError", () => ExitConfigErrored.make({})), Match.when("RuntimeError", () => ExitRuntimeErrored.make({})), Match.when("InternalError", () => ExitInternalErrored.make({})), Match.exhaustive);
|
|
1074
|
-
const verdictExitClass = (score, breakingThreshold) =>
|
|
1075
|
-
|
|
1076
|
-
|
|
1078
|
+
const verdictExitClass = (score, breakingThreshold) => Match.valueTags(score, {
|
|
1079
|
+
Unscored: () => null,
|
|
1080
|
+
Scored: ({ percentage }) => Option$1.match(Option$1.fromNullishOr(breakingThreshold), {
|
|
1081
|
+
onNone: () => null,
|
|
1082
|
+
onSome: (threshold) => Match.value(percentage < threshold).pipe(Match.when(true, () => "VerdictFail"), Match.when(false, () => null), Match.exhaustive)
|
|
1083
|
+
})
|
|
1077
1084
|
});
|
|
1078
1085
|
const decide$9 = (command) => Option$1.match(Option$1.fromNullishOr(verdictExitClass(command.score, command.breakingThreshold)), {
|
|
1079
1086
|
onNone: () => Option$1.match(precedenceOf(command.pending), {
|
|
@@ -1266,13 +1273,13 @@ const restrictSocket = (address) => Match.value(address).pipe(Match.tag("UnixPat
|
|
|
1266
1273
|
onTrue: () => Effect$1.void,
|
|
1267
1274
|
onFalse: () => Effect$1.flatMap(FileSystem.FileSystem, (fs) => fs.chmod(path, 384))
|
|
1268
1275
|
})), Match.orElse(() => Effect$1.void));
|
|
1269
|
-
const TypeId$
|
|
1276
|
+
const TypeId$7 = Symbol.for("~systemfsoftware/stryker-js-plugin-runtime/WorkerServer");
|
|
1270
1277
|
const workerServerLayerOf = (params) => Layer.unwrap(Effect$1.gen(function* () {
|
|
1271
1278
|
const socket = yield* SocketServer.SocketServer;
|
|
1272
1279
|
yield* restrictSocket(socket.address);
|
|
1273
1280
|
return RpcServer.layer(params.rpcs).pipe(Layer.provide(params.handlers), Layer.provide(params.schemaServices), Layer.provide(RpcServer.layerProtocolSocketServer), Layer.provide(RpcSerialization.layerNdjson), Layer.provide(traceContextServer));
|
|
1274
1281
|
}));
|
|
1275
|
-
Blueprint.make()(TypeId$
|
|
1282
|
+
Blueprint.make()(TypeId$7).steps({
|
|
1276
1283
|
steps: {},
|
|
1277
1284
|
targets: { layer: workerServerLayerOf }
|
|
1278
1285
|
}).is;
|
|
@@ -1320,8 +1327,8 @@ var Worker_exports = /* @__PURE__ */ __exportAll$1({
|
|
|
1320
1327
|
});
|
|
1321
1328
|
//#endregion
|
|
1322
1329
|
//#region src/spawned-socket-worker.handle.ts
|
|
1323
|
-
const TypeId$
|
|
1324
|
-
const SpawnedSocketWorker = Handle.make()(TypeId$
|
|
1330
|
+
const TypeId$6 = Symbol.for("~systemfsoftware/stryker-js/SpawnedSocketWorker");
|
|
1331
|
+
const SpawnedSocketWorker = Handle.make()(TypeId$6);
|
|
1325
1332
|
SpawnedSocketWorker.is;
|
|
1326
1333
|
const make$2 = (worker) => SpawnedSocketWorker.make({
|
|
1327
1334
|
pid: worker.pid,
|
|
@@ -1333,9 +1340,9 @@ const clientLayer = (self) => SpawnedSocketWorker.slot(self).clientLayer;
|
|
|
1333
1340
|
var WorkerLauncher = class extends Context.Service()("@systemfsoftware/stryker-js/WorkerLauncher.service/WorkerLauncher") {};
|
|
1334
1341
|
//#endregion
|
|
1335
1342
|
//#region src/worker-client.blueprint.ts
|
|
1336
|
-
const TypeId$
|
|
1343
|
+
const TypeId$5 = Symbol.for("~systemfsoftware/stryker-js/WorkerClient");
|
|
1337
1344
|
const connectRetry = Schedule.max([Schedule.spaced(50), Schedule.recurs(100)]);
|
|
1338
|
-
const scopedOf$
|
|
1345
|
+
const scopedOf$1 = (params) => Effect$1.gen(function* () {
|
|
1339
1346
|
const launcher = yield* WorkerLauncher;
|
|
1340
1347
|
const optionsJson = yield* S.encodeEffect(Worker_exports.WorkerOptionsWire)(params.options).pipe(Effect$1.orDie);
|
|
1341
1348
|
const worker = yield* launcher.spawn({
|
|
@@ -1350,9 +1357,9 @@ const scopedOf$2 = (params) => Effect$1.gen(function* () {
|
|
|
1350
1357
|
const traceContext = yield* Layer.build(Trace_exports.layerTraceContextClient);
|
|
1351
1358
|
return yield* RpcClient.make(params.rpcs).pipe(Effect$1.provideContext(Context.merge(protocol, traceContext)));
|
|
1352
1359
|
});
|
|
1353
|
-
const WorkerClients = () => Blueprint.make()(TypeId$
|
|
1360
|
+
const WorkerClients = () => Blueprint.make()(TypeId$5).steps({
|
|
1354
1361
|
steps: {},
|
|
1355
|
-
targets: { scoped: scopedOf$
|
|
1362
|
+
targets: { scoped: scopedOf$1 }
|
|
1356
1363
|
});
|
|
1357
1364
|
const makeWorkerClient = (params) => WorkerClients().of(params).scoped;
|
|
1358
1365
|
const ReporterStageTypeId = Symbol.for("@systemfsoftware/stryker-js/ReporterStage");
|
|
@@ -1702,7 +1709,10 @@ var VerdictEnvelope = class VerdictEnvelope extends S.Class("VerdictEnvelope")({
|
|
|
1702
1709
|
runId,
|
|
1703
1710
|
mode,
|
|
1704
1711
|
signal,
|
|
1705
|
-
score:
|
|
1712
|
+
score: Report_exports.MutationScore.match(metrics.mutationScore, {
|
|
1713
|
+
Scored: ({ percentage }) => percentage,
|
|
1714
|
+
Unscored: () => null
|
|
1715
|
+
}),
|
|
1706
1716
|
thresholds: {
|
|
1707
1717
|
high: report.thresholds.high,
|
|
1708
1718
|
low: report.thresholds.low,
|
|
@@ -1740,7 +1750,7 @@ var RunEvents = class extends Context.Service()("@systemfsoftware/stryker-js/run
|
|
|
1740
1750
|
var RunIdentity = class extends Context.Service()("@systemfsoftware/stryker-js/run-events.service/RunIdentity") {};
|
|
1741
1751
|
//#endregion
|
|
1742
1752
|
//#region package.json
|
|
1743
|
-
var version = "12.
|
|
1753
|
+
var version = "12.1.1";
|
|
1744
1754
|
//#endregion
|
|
1745
1755
|
//#region src/stryker-package.schema.ts
|
|
1746
1756
|
var StrykerPackage = class extends S.Class("StrykerPackage")({
|
|
@@ -2032,22 +2042,28 @@ const mutationTestReport = (deps, input) => (results) => Effect$1.gen(function*
|
|
|
2032
2042
|
identities
|
|
2033
2043
|
};
|
|
2034
2044
|
});
|
|
2035
|
-
const determineExitCode = (input) => (metrics) =>
|
|
2036
|
-
const { mutationScore } = metrics.metrics;
|
|
2045
|
+
const determineExitCode = (input) => (metrics) => {
|
|
2037
2046
|
const breaking = input.options.thresholds.break;
|
|
2038
|
-
const
|
|
2039
|
-
|
|
2047
|
+
const score = metrics.metrics.mutationScore;
|
|
2048
|
+
const failure = Option$1.fromNullishOr(Result.match(classifyExit(ClassifyExitCommand.make({
|
|
2040
2049
|
pending: [],
|
|
2041
|
-
score
|
|
2050
|
+
score,
|
|
2042
2051
|
breakingThreshold: breaking
|
|
2043
2052
|
})), {
|
|
2044
2053
|
onFailure: (refused) => refused,
|
|
2045
2054
|
onSuccess: (decision) => Match.value(decision).pipe(Match.tag("ExitVerdictFailed", () => "VerdictFail"), Match.orElse(() => null))
|
|
2046
|
-
}))
|
|
2047
|
-
|
|
2048
|
-
|
|
2055
|
+
}));
|
|
2056
|
+
return Report_exports.MutationScore.match(score, {
|
|
2057
|
+
Scored: ({ percentage }) => Option$1.match(failure, {
|
|
2058
|
+
onNone: () => Effect$1.as(logScoredPass(breaking, percentage), null),
|
|
2059
|
+
onSome: (exitClass) => Effect$1.as(logBroken(breaking, percentage), exitClass)
|
|
2060
|
+
}),
|
|
2061
|
+
Unscored: () => Effect$1.as(logUnscored(breaking), Option$1.getOrNull(failure))
|
|
2049
2062
|
});
|
|
2050
|
-
}
|
|
2063
|
+
};
|
|
2064
|
+
const logScoredPass = (breaking, percentage) => Match.value(breaking).pipe(Match.when(null, () => Effect$1.logDebug("No breaking threshold configured. Won't fail the build no matter how low your mutation score is. Set `thresholds.break` to change this behavior.")), Match.orElse((threshold) => Effect$1.logInfo(`Final mutation score of ${percentage.toFixed(2)} is greater than or equal to break threshold ${String(threshold)}`)));
|
|
2065
|
+
const logUnscored = (breaking) => Match.value(breaking).pipe(Match.when(null, () => Effect$1.void), Match.orElse((threshold) => Effect$1.logInfo(`No valid mutant was tested, so there is no mutation score to hold against break threshold ${String(threshold)}`)));
|
|
2066
|
+
const logBroken = (breaking, percentage) => Effect$1.andThen(Effect$1.logError(`Final mutation score ${percentage.toFixed(2)} under breaking threshold ${String(breaking)}, setting exit code to 1 (failure).`), Effect$1.logInfo("(improve mutation score or set `thresholds.break = null` to prevent this error in the future)"));
|
|
2051
2067
|
const emitVerdict = (deps, input) => (report) => Effect$1.gen(function* () {
|
|
2052
2068
|
const envelope = VerdictEnvelope.build(report, input.resolvedMode.mode, input.resolvedMode.signal, input.runId, input.basePath, deps.path);
|
|
2053
2069
|
yield* Queue.offer(deps.events, VerdictReached.make({
|
|
@@ -2079,7 +2095,7 @@ const reportAll = (deps, input) => Effect$1.gen(function* () {
|
|
|
2079
2095
|
const verdict = yield* determineExitCode(input)(metrics);
|
|
2080
2096
|
const finalVerdict = Result.match(classifyExit(ClassifyExitCommand.make({
|
|
2081
2097
|
pending: [verdict, terminalDrain].filter((candidate) => candidate !== null),
|
|
2082
|
-
score:
|
|
2098
|
+
score: Report_exports.MutationScore.cases.Unscored.make({}),
|
|
2083
2099
|
breakingThreshold: null
|
|
2084
2100
|
})), {
|
|
2085
2101
|
onFailure: (refused) => refused,
|
|
@@ -2431,8 +2447,12 @@ const mutantReportSection = (report, metrics, render) => Boolean$1.match(render.
|
|
|
2431
2447
|
},
|
|
2432
2448
|
onFalse: () => EMPTY_SECTIONS
|
|
2433
2449
|
});
|
|
2450
|
+
const hasFullScore = (metrics) => Match.valueTags(metrics.mutationScore, {
|
|
2451
|
+
Scored: ({ percentage }) => percentage === 100,
|
|
2452
|
+
Unscored: () => false
|
|
2453
|
+
});
|
|
2434
2454
|
const partialScoresVisible = (metrics, render) => Boolean$1.match(render.skipFull, {
|
|
2435
|
-
onTrue: () => metrics.childResults.some((child) => child.metrics
|
|
2455
|
+
onTrue: () => metrics.childResults.some((child) => !hasFullScore(child.metrics)),
|
|
2436
2456
|
onFalse: () => true
|
|
2437
2457
|
});
|
|
2438
2458
|
const drawsScoreTable = (metrics, render) => Boolean$1.match(render.reportScoreTable, {
|
|
@@ -2440,14 +2460,14 @@ const drawsScoreTable = (metrics, render) => Boolean$1.match(render.reportScoreT
|
|
|
2440
2460
|
onFalse: () => false
|
|
2441
2461
|
});
|
|
2442
2462
|
const mutationScoreOf = (scoreType, metrics) => Match.value(scoreType).pipe(Match.when("total", () => metrics.mutationScore), Match.when("covered", () => metrics.mutationScoreBasedOnCoveredCode), Match.exhaustive);
|
|
2443
|
-
const scoreText = (scoreType, row) => {
|
|
2444
|
-
|
|
2445
|
-
|
|
2446
|
-
|
|
2447
|
-
|
|
2448
|
-
})
|
|
2449
|
-
|
|
2450
|
-
|
|
2463
|
+
const scoreText = (scoreType, row) => Match.valueTags(mutationScoreOf(scoreType, row.metrics), {
|
|
2464
|
+
Scored: ({ percentage }) => percentage.toFixed(2),
|
|
2465
|
+
Unscored: () => "n/a"
|
|
2466
|
+
});
|
|
2467
|
+
const thresholdTone = (thresholds, score) => Match.valueTags(score, {
|
|
2468
|
+
Scored: ({ percentage }) => Match.value(percentage).pipe(Match.when((value) => value >= thresholds.high, () => "positive"), Match.when((value) => value >= thresholds.low, () => "warning"), Match.orElse(() => "negative")),
|
|
2469
|
+
Unscored: () => "muted"
|
|
2470
|
+
});
|
|
2451
2471
|
const scoreTone = (thresholds, scoreType, allowColor) => Boolean$1.match(allowColor, {
|
|
2452
2472
|
onTrue: () => (row) => thresholdTone(thresholds, mutationScoreOf(scoreType, row.metrics)),
|
|
2453
2473
|
onFalse: () => () => "plain"
|
|
@@ -2544,7 +2564,7 @@ const createColumns = (metricsResult, render) => [
|
|
|
2544
2564
|
const leafRules = (columns) => columns.flatMap((column) => column.leaves.map((leaf) => [rule("-", slotWidthOf(leaf))]));
|
|
2545
2565
|
const leafHeaders = (columns) => columns.flatMap((column) => column.leaves.map((leaf) => placedLine(leaf.header, leaf.style, leaf.netWidth)));
|
|
2546
2566
|
const fullRowVisible = (render, row) => Boolean$1.match(render.skipFull, {
|
|
2547
|
-
onTrue: () => row.metrics
|
|
2567
|
+
onTrue: () => !hasFullScore(row.metrics),
|
|
2548
2568
|
onFalse: () => true
|
|
2549
2569
|
});
|
|
2550
2570
|
const bodyRow = (columns, row, ancestorCount) => rowOfLines(columns.flatMap((column) => column.leaves.map((leaf) => [placedCell(leaf.cell(row, ancestorCount), leaf.style, leaf.netWidth, leaf.tone(row))])));
|
|
@@ -2650,41 +2670,33 @@ const readClearTextReport = (input) => Effect$1.map(Stream.fromAsyncIterable(inp
|
|
|
2650
2670
|
}));
|
|
2651
2671
|
const tint = (color, text) => `${AnsiCode.fields[color].literal}${text}${AnsiCode.fields.reset.literal}`;
|
|
2652
2672
|
const TINT_BY_TONE = {
|
|
2653
|
-
|
|
2654
|
-
|
|
2655
|
-
|
|
2656
|
-
|
|
2657
|
-
|
|
2658
|
-
|
|
2659
|
-
|
|
2660
|
-
};
|
|
2661
|
-
const
|
|
2662
|
-
|
|
2663
|
-
|
|
2664
|
-
|
|
2665
|
-
|
|
2666
|
-
|
|
2667
|
-
|
|
2668
|
-
|
|
2669
|
-
|
|
2670
|
-
|
|
2671
|
-
onTrue: () => [...runs.slice(0, -1), {
|
|
2672
|
-
...last,
|
|
2673
|
-
text: `${last.text}${span.text}`
|
|
2674
|
-
}],
|
|
2675
|
-
onFalse: () => [...runs, span]
|
|
2676
|
-
})
|
|
2673
|
+
plain: (text) => text,
|
|
2674
|
+
identifier: (text) => tint("cyan", text),
|
|
2675
|
+
emphasis: (text) => tint("yellow", text),
|
|
2676
|
+
positive: (text) => tint("green", text),
|
|
2677
|
+
warning: (text) => tint("yellow", text),
|
|
2678
|
+
negative: (text) => tint("red", text),
|
|
2679
|
+
muted: (text) => tint("grey", text)
|
|
2680
|
+
};
|
|
2681
|
+
const bytesOf = (span) => `${" ".repeat(span.leftPad)}${span.text.repeat(span.repeat)}${" ".repeat(span.rightPad)}`;
|
|
2682
|
+
const appendSpan = (runs, span) => Option$1.match(Option$1.filter(Arr.last(runs), (last) => last.tone === span.tone), {
|
|
2683
|
+
onNone: () => [...runs, {
|
|
2684
|
+
tone: span.tone,
|
|
2685
|
+
bytes: bytesOf(span)
|
|
2686
|
+
}],
|
|
2687
|
+
onSome: (last) => [...runs.slice(0, -1), {
|
|
2688
|
+
tone: last.tone,
|
|
2689
|
+
bytes: `${last.bytes}${bytesOf(span)}`
|
|
2690
|
+
}]
|
|
2677
2691
|
});
|
|
2678
|
-
const
|
|
2679
|
-
const
|
|
2680
|
-
const
|
|
2681
|
-
const renderChunk = (chunk) => chunk.map(renderLine).join("\n");
|
|
2682
|
-
const writeChunks = (output, channel, chunks) => output.write(channel, chunks.map((chunk) => `${renderChunk(chunk)}\n`)).pipe(Effect$1.mapError(failAsClearText), Effect$1.asVoid);
|
|
2692
|
+
const renderLine = (line) => Arr.reduce(line, Arr.empty(), appendSpan).map((run) => TINT_BY_TONE[run.tone](run.bytes)).join("");
|
|
2693
|
+
const renderChunk = (chunk) => `${chunk.map(renderLine).join("\n")}\n`;
|
|
2694
|
+
const writeChunks = (output, channel, chunks) => Effect$1.mapError(output.write(channel, chunks.map(renderChunk)), failAsClearText);
|
|
2683
2695
|
const clearTextReportCell = Sandwich.named("stryker.report.clearText")(readClearTextReport).decide(renderClearTextReport).write({
|
|
2684
|
-
ClearTextReportRendered: (rendered
|
|
2696
|
+
ClearTextReportRendered: (rendered) => Effect$1.gen(function* () {
|
|
2685
2697
|
const output = yield* ReporterOutput;
|
|
2686
2698
|
yield* writeChunks(output, "stdout", rendered.stdout);
|
|
2687
|
-
yield*
|
|
2699
|
+
yield* writeChunks(output, "stderr", rendered.stderr);
|
|
2688
2700
|
}),
|
|
2689
2701
|
ClearTextReportSuppressed: () => Effect$1.void,
|
|
2690
2702
|
CommandRejected: ({ issue }) => Effect$1.fail(failAsClearText(issue))
|
|
@@ -3697,7 +3709,7 @@ const classifyWorkerExit = Workflow.make({
|
|
|
3697
3709
|
});
|
|
3698
3710
|
//#endregion
|
|
3699
3711
|
//#region src/worker-protocol.blueprint.ts
|
|
3700
|
-
const TypeId$
|
|
3712
|
+
const TypeId$4 = Symbol.for("~systemfsoftware/stryker-js/WorkerProtocol");
|
|
3701
3713
|
const droppedConnection = RpcClientError.make({ reason: Socket.SocketReadError.make({ cause: /* @__PURE__ */ new Error("worker connection dropped with the request in flight") }) });
|
|
3702
3714
|
const layerOf = (socket) => Layer.effect(RpcClient.Protocol, Effect$1.gen(function* () {
|
|
3703
3715
|
const handlers = MutableHashMap.empty();
|
|
@@ -3738,7 +3750,7 @@ const layerOf = (socket) => Layer.effect(RpcClient.Protocol, Effect$1.gen(functi
|
|
|
3738
3750
|
send: (clientId, request, transferables) => track(clientId, request).pipe(Effect$1.andThen(inner.send(clientId, request, transferables)))
|
|
3739
3751
|
});
|
|
3740
3752
|
}));
|
|
3741
|
-
const WorkerProtocol = Blueprint.make()(TypeId$
|
|
3753
|
+
const WorkerProtocol = Blueprint.make()(TypeId$4).steps({
|
|
3742
3754
|
steps: {},
|
|
3743
3755
|
targets: { layer: (spec) => layerOf(spec.socket) }
|
|
3744
3756
|
});
|
|
@@ -3746,7 +3758,7 @@ const layerWorkerProtocol = (socket) => WorkerProtocol.of({ socket }).layer;
|
|
|
3746
3758
|
//#endregion
|
|
3747
3759
|
//#region src/drivers/node.ts
|
|
3748
3760
|
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));
|
|
3749
|
-
const nodeWorkerLauncherLayer = Layer.effect(WorkerLauncher, Effect$1.gen(function* () {
|
|
3761
|
+
const nodeWorkerLauncherLayer = (childEnv) => Layer.effect(WorkerLauncher, Effect$1.gen(function* () {
|
|
3750
3762
|
const crypto = yield* Crypto.Crypto;
|
|
3751
3763
|
const fs = yield* FileSystem.FileSystem;
|
|
3752
3764
|
const path = yield* Path.Path;
|
|
@@ -3765,6 +3777,7 @@ const nodeWorkerLauncherLayer = Layer.effect(WorkerLauncher, Effect$1.gen(functi
|
|
|
3765
3777
|
env: {
|
|
3766
3778
|
STRYKER_WORKER_DIR: workerDir,
|
|
3767
3779
|
STRYKER_SOCKET: socketPath,
|
|
3780
|
+
...childEnv,
|
|
3768
3781
|
...params.env
|
|
3769
3782
|
},
|
|
3770
3783
|
stderr: "inherit"
|
|
@@ -3804,7 +3817,8 @@ const nodeWorkerLauncherLayer = Layer.effect(WorkerLauncher, Effect$1.gen(functi
|
|
|
3804
3817
|
const nodeFsPathLayer$1 = Layer.mergeAll(NodeFileSystem.layer, NodePath.layer);
|
|
3805
3818
|
const nodeSpawnerLayer = NodeChildProcessSpawner.layer.pipe(Layer.provide(nodeFsPathLayer$1));
|
|
3806
3819
|
const nodeBase = Layer.mergeAll(nodeFsPathLayer$1, nodeSpawnerLayer, NodeStdio.layer);
|
|
3807
|
-
const
|
|
3820
|
+
const makeNodePlatformLayer = (options) => Layer.mergeAll(nodeWorkerLauncherLayer(options.childEnv).pipe(Layer.provide(Layer.merge(nodeBase, NodeCrypto.layer))), nodeBase);
|
|
3821
|
+
const nodePlatformLayer = makeNodePlatformLayer({ childEnv: {} });
|
|
3808
3822
|
//#endregion
|
|
3809
3823
|
//#region src/IncrementalDiff.schema.ts
|
|
3810
3824
|
const PositionSchema$1 = S.Struct({
|
|
@@ -4146,138 +4160,6 @@ const admitIncrementalReport = Workflow.make({
|
|
|
4146
4160
|
decide: (command) => Result.succeed(decide$6(command))
|
|
4147
4161
|
});
|
|
4148
4162
|
//#endregion
|
|
4149
|
-
//#region src/VmRunner.blueprint.ts
|
|
4150
|
-
const TypeId$4 = Symbol.for("~systemfsoftware/stryker-js/VmTestRunner");
|
|
4151
|
-
const isVmRunner = (name) => typeof name === "string" && name.toLowerCase() === "vm";
|
|
4152
|
-
const vmRunnerCapabilities = { reloadEnvironment: true };
|
|
4153
|
-
const HOST_TIMEOUT_SLACK_MS = 1e3;
|
|
4154
|
-
const messageOf$1 = (cause) => cause instanceof Error ? cause.message : new Error("the vm test runner failed", { cause }).message;
|
|
4155
|
-
const testResultOf = (test) => {
|
|
4156
|
-
const base = {
|
|
4157
|
-
id: test.id,
|
|
4158
|
-
name: test.name,
|
|
4159
|
-
timeSpentMs: test.timeSpentMs
|
|
4160
|
-
};
|
|
4161
|
-
return Match.value(test.status).pipe(Match.when("failed", () => ({
|
|
4162
|
-
...base,
|
|
4163
|
-
status: "failed",
|
|
4164
|
-
failureMessage: test.failureMessage ?? ""
|
|
4165
|
-
})), Match.when("skipped", () => ({
|
|
4166
|
-
...base,
|
|
4167
|
-
status: "skipped"
|
|
4168
|
-
})), Match.orElse(() => ({
|
|
4169
|
-
...base,
|
|
4170
|
-
status: "success"
|
|
4171
|
-
})));
|
|
4172
|
-
};
|
|
4173
|
-
const dryRunResultOf = (response) => {
|
|
4174
|
-
const tests = response.tests.map(testResultOf);
|
|
4175
|
-
return Option$1.match(Option$1.fromUndefinedOr(response.mutantCoverage), {
|
|
4176
|
-
onNone: () => ({
|
|
4177
|
-
status: "complete",
|
|
4178
|
-
tests
|
|
4179
|
-
}),
|
|
4180
|
-
onSome: (mutantCoverage) => ({
|
|
4181
|
-
status: "complete",
|
|
4182
|
-
tests,
|
|
4183
|
-
mutantCoverage
|
|
4184
|
-
})
|
|
4185
|
-
});
|
|
4186
|
-
};
|
|
4187
|
-
const respond = (response) => Match.value(response).pipe(Match.discriminator("status")("init-failed", (failed) => Effect$1.fail(TestRunner_exports.TestRunnerFailed.make({
|
|
4188
|
-
runnerName: "vm",
|
|
4189
|
-
phase: "init",
|
|
4190
|
-
cause: failed.message
|
|
4191
|
-
}))), Match.discriminator("status")("timeout", () => Effect$1.succeed({ status: "timeout" })), Match.discriminator("status")("error", (errored) => Effect$1.succeed({
|
|
4192
|
-
status: "error",
|
|
4193
|
-
errorMessage: errored.errorMessage
|
|
4194
|
-
})), Match.discriminator("status")("complete", (complete) => Effect$1.succeed(dryRunResultOf(complete))), Match.exhaustive);
|
|
4195
|
-
const pooledVmRunner = (config, scope) => {
|
|
4196
|
-
let client;
|
|
4197
|
-
let sessionTestFiles = config.testFiles;
|
|
4198
|
-
const sessionOptions = () => ({
|
|
4199
|
-
sandboxWorkingDirectory: config.sandboxWorkingDirectory,
|
|
4200
|
-
testFiles: sessionTestFiles
|
|
4201
|
-
});
|
|
4202
|
-
const spawnClient = Effect$1.try({
|
|
4203
|
-
try: () => {
|
|
4204
|
-
const spawned = Session.createVmWorkerClient(sessionOptions(), { onExit: () => {
|
|
4205
|
-
if (client === spawned) client = void 0;
|
|
4206
|
-
} });
|
|
4207
|
-
return spawned;
|
|
4208
|
-
},
|
|
4209
|
-
catch: (cause) => TestRunner_exports.TestRunnerFailed.make({
|
|
4210
|
-
runnerName: "vm",
|
|
4211
|
-
phase: "init",
|
|
4212
|
-
cause: `the vm test runner could not start its worker: ${messageOf$1(cause)}`
|
|
4213
|
-
})
|
|
4214
|
-
});
|
|
4215
|
-
const dropClient = Effect$1.suspend(() => {
|
|
4216
|
-
const current = client;
|
|
4217
|
-
client = void 0;
|
|
4218
|
-
return current === void 0 ? Effect$1.void : Effect$1.promise(() => current.terminate());
|
|
4219
|
-
});
|
|
4220
|
-
const run = (request) => Effect$1.gen(function* () {
|
|
4221
|
-
if (client === void 0) {
|
|
4222
|
-
const spawned = yield* spawnClient;
|
|
4223
|
-
yield* Scope.addFinalizer(scope, Effect$1.promise(() => spawned.terminate()));
|
|
4224
|
-
client = spawned;
|
|
4225
|
-
}
|
|
4226
|
-
const current = client;
|
|
4227
|
-
const answer = yield* Effect$1.tryPromise({
|
|
4228
|
-
try: () => current.run(request),
|
|
4229
|
-
catch: (cause) => ({
|
|
4230
|
-
status: "error",
|
|
4231
|
-
errorMessage: messageOf$1(cause)
|
|
4232
|
-
})
|
|
4233
|
-
}).pipe(Effect$1.catch((failed) => Effect$1.succeed(failed)), Effect$1.timeoutOrElse({
|
|
4234
|
-
duration: request.timeoutMs + HOST_TIMEOUT_SLACK_MS,
|
|
4235
|
-
orElse: () => dropClient.pipe(Effect$1.as({ status: "timeout" }))
|
|
4236
|
-
}));
|
|
4237
|
-
return yield* respond(answer);
|
|
4238
|
-
}).pipe(Effect$1.onInterrupt(() => dropClient));
|
|
4239
|
-
const shouldAdoptTestFiles = () => config.testFiles.length === 0 && client === void 0;
|
|
4240
|
-
const adoptedTestFiles = (testFiles) => testFiles ?? [];
|
|
4241
|
-
const testFilterFieldOf = (testFilter) => testFilter === void 0 ? {} : { testFilter: [...testFilter] };
|
|
4242
|
-
const hitLimitFieldOf = (hitLimit) => hitLimit === void 0 ? {} : { hitLimit };
|
|
4243
|
-
const mutantRequestOf = (options) => ({
|
|
4244
|
-
kind: "mutant",
|
|
4245
|
-
timeoutMs: options.timeout,
|
|
4246
|
-
activeMutantId: String(options.activeMutant.id),
|
|
4247
|
-
...testFilterFieldOf(options.testFilter),
|
|
4248
|
-
...hitLimitFieldOf(options.hitLimit),
|
|
4249
|
-
reloadEnvironment: options.reloadEnvironment
|
|
4250
|
-
});
|
|
4251
|
-
return make$3({
|
|
4252
|
-
capabilities: Effect$1.succeed(vmRunnerCapabilities),
|
|
4253
|
-
init: Effect$1.void,
|
|
4254
|
-
dryRun: (options) => {
|
|
4255
|
-
if (shouldAdoptTestFiles()) sessionTestFiles = adoptedTestFiles(options.testFiles);
|
|
4256
|
-
return run({
|
|
4257
|
-
kind: "dry",
|
|
4258
|
-
timeoutMs: options.timeout,
|
|
4259
|
-
reloadEnvironment: true
|
|
4260
|
-
});
|
|
4261
|
-
},
|
|
4262
|
-
mutantRun: (options) => run(mutantRequestOf(options)).pipe(Effect$1.map((dryRunResult) => interpretDryRunResult(InterpretDryRunResultCommand.make({ dryRunResult }))), Effect$1.flatMap((decided) => Result.match(decided, {
|
|
4263
|
-
onFailure: (failure) => Effect$1.fail(failure),
|
|
4264
|
-
onSuccess: (decision) => Effect$1.succeed(decision.asResult)
|
|
4265
|
-
})), Effect$1.catchTag("TestRunnerFailed", (failure) => Effect$1.succeed({
|
|
4266
|
-
status: "error",
|
|
4267
|
-
errorMessage: failure.cause
|
|
4268
|
-
})))
|
|
4269
|
-
});
|
|
4270
|
-
};
|
|
4271
|
-
const scopedOf$1 = (config) => Effect$1.gen(function* () {
|
|
4272
|
-
const scope = yield* Effect$1.scope;
|
|
4273
|
-
return pooledVmRunner(config, scope);
|
|
4274
|
-
});
|
|
4275
|
-
const VmRunners = Blueprint.make()(TypeId$4).steps({
|
|
4276
|
-
steps: {},
|
|
4277
|
-
targets: { scoped: scopedOf$1 }
|
|
4278
|
-
});
|
|
4279
|
-
const vmTestRunner = (config) => VmRunners.of(config).scoped;
|
|
4280
|
-
//#endregion
|
|
4281
4163
|
//#region src/read-project.parts.ts
|
|
4282
4164
|
const ALWAYS_IGNORE = Object.freeze([
|
|
4283
4165
|
"node_modules",
|
|
@@ -4290,23 +4172,9 @@ const ALWAYS_IGNORE = Object.freeze([
|
|
|
4290
4172
|
]);
|
|
4291
4173
|
const IGNORE_PATTERN_CHARACTER = "!";
|
|
4292
4174
|
const DEFAULT_GLOB = "**/*.{js,ts,jsx,tsx,html,vue,mjs,mts,cts,cjs}";
|
|
4293
|
-
const
|
|
4294
|
-
|
|
4295
|
-
|
|
4296
|
-
"**/dist/**",
|
|
4297
|
-
"**/.{idea,git,cache,output,temp}/**",
|
|
4298
|
-
`**/${tempDirName}/**`
|
|
4299
|
-
];
|
|
4300
|
-
const shouldDiscoverTestFiles = (options) => options.testFiles.length === 0 && isVmRunner(options.testRunner);
|
|
4301
|
-
const testFileSelectionOf = (options) => Boolean.match(shouldDiscoverTestFiles(options), {
|
|
4302
|
-
onTrue: () => ({
|
|
4303
|
-
testFilePatterns: VITEST_DEFAULT_TEST_FILE_PATTERNS,
|
|
4304
|
-
testFileIgnores: defaultTestFileIgnores(options.tempDirName)
|
|
4305
|
-
}),
|
|
4306
|
-
onFalse: () => ({
|
|
4307
|
-
testFilePatterns: options.testFiles,
|
|
4308
|
-
testFileIgnores: []
|
|
4309
|
-
})
|
|
4175
|
+
const testFileSelectionOf = (options) => ({
|
|
4176
|
+
testFilePatterns: options.testFiles,
|
|
4177
|
+
testFileIgnores: []
|
|
4310
4178
|
});
|
|
4311
4179
|
const normalizeFileName = (value) => value.replace(/\\/g, "/");
|
|
4312
4180
|
const escapeRegExp = (value) => value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
@@ -4818,8 +4686,11 @@ const formatTotal = (total) => Option$1.match(Option$1.fromNullishOr(total), {
|
|
|
4818
4686
|
onSome: (val) => String(val)
|
|
4819
4687
|
});
|
|
4820
4688
|
const formatStderrEvent = (event) => Match.value(event).pipe(Match.tag("plan", (e) => `plan ${e.total} mutants`), Match.tag("phase", (e) => `phase ${e.phase}`), Match.tag("tick", (e) => `${e.completed}/${formatTotal(e.total)} elapsed ${e.elapsedMs}ms`), Match.tag("verdict", (e) => `score ${formatScore(e.score)} killed ${e.counts.killed} survived ${e.counts.survived}`), Match.tag("error", (e) => `error ${e.error}`), Match.tag("stream", () => null), Match.tag("mutant", () => null), Match.tag("help", () => null), Match.tag("plugins", () => null), Match.tag("formats", () => null), Match.tag("skipped", () => null), Match.exhaustive);
|
|
4821
|
-
const stderrLineFor = (state, event) =>
|
|
4822
|
-
|
|
4689
|
+
const stderrLineFor = (state, event) => Boolean$1.match(Boolean$1.and(state.mode === "human", !state.terminalSeen), {
|
|
4690
|
+
onTrue: () => formatStderrEvent(event),
|
|
4691
|
+
onFalse: () => null
|
|
4692
|
+
});
|
|
4693
|
+
const shouldFrame = (state) => !state.terminalSeen;
|
|
4823
4694
|
const decideFrame = (command) => {
|
|
4824
4695
|
const nextState = noteState(command.state, command.event);
|
|
4825
4696
|
const stderrLine = stderrLineFor(command.state, command.event);
|
|
@@ -4878,7 +4749,10 @@ const formatTemplate = (template, args) => {
|
|
|
4878
4749
|
};
|
|
4879
4750
|
const headOf = (args) => Option$1.fromNullishOr(args[0]);
|
|
4880
4751
|
const formatArgs = (args) => Option$1.match(Option$1.filter(headOf(args), Predicate$1.isString), {
|
|
4881
|
-
onSome: (first) =>
|
|
4752
|
+
onSome: (first) => Boolean$1.match(args.length === 1, {
|
|
4753
|
+
onTrue: () => first,
|
|
4754
|
+
onFalse: () => formatTemplate(first, args.slice(1))
|
|
4755
|
+
}),
|
|
4882
4756
|
onNone: () => args.map(inspectValue).join(" ")
|
|
4883
4757
|
});
|
|
4884
4758
|
const DEFAULT_CONSOLE_LABEL = "default";
|
|
@@ -5530,7 +5404,7 @@ var RunEventDrain = class RunEventDrain extends Context.Service()("@systemfsoftw
|
|
|
5530
5404
|
static layer = Layer.effect(RunEventDrain, Effect$1.gen(function* () {
|
|
5531
5405
|
const stdio = yield* Stdio.Stdio;
|
|
5532
5406
|
return RunEventDrain.of({
|
|
5533
|
-
drainFramed: (framed) => drainOf(stdio, framed),
|
|
5407
|
+
drainFramed: (framed, toStdout) => drainOf(stdio, framed, toStdout),
|
|
5534
5408
|
setProgressStreamFile: () => Effect$1.void
|
|
5535
5409
|
});
|
|
5536
5410
|
}));
|
|
@@ -5543,25 +5417,29 @@ var RunEventDrain = class RunEventDrain extends Context.Service()("@systemfsoftw
|
|
|
5543
5417
|
};
|
|
5544
5418
|
const RunEventDrainLive = RunEventDrain.layer;
|
|
5545
5419
|
const encodeUtf8 = (line) => new TextEncoder().encode(line);
|
|
5546
|
-
const
|
|
5420
|
+
const runToSink = (stdio, lines, toStdout) => Boolean$1.match(toStdout, {
|
|
5421
|
+
onTrue: () => Stream.run(lines, stdio.stdout({ endOnDone: true })),
|
|
5422
|
+
onFalse: () => Stream.runDrain(lines)
|
|
5423
|
+
});
|
|
5424
|
+
const drainToSinks = (fs, path, stdio, fileName, toStdout, framed) => Effect$1.gen(function* () {
|
|
5547
5425
|
yield* fs.makeDirectory(path.dirname(fileName), { recursive: true });
|
|
5548
5426
|
yield* Effect$1.scoped(Effect$1.gen(function* () {
|
|
5549
5427
|
const handle = yield* fs.open(fileName, { flag: "w" });
|
|
5550
5428
|
const withFile = framed.pipe(Stream.tap((line) => handle.writeAll(encodeUtf8(line)).pipe(Effect$1.flatMap(() => handle.sync))));
|
|
5551
|
-
yield*
|
|
5429
|
+
yield* runToSink(stdio, withFile, toStdout).pipe(Effect$1.ignore);
|
|
5552
5430
|
}));
|
|
5553
5431
|
}).pipe(Effect$1.orDie);
|
|
5554
5432
|
const drainFileOf = (stdio, fs, path) => Effect$1.gen(function* () {
|
|
5555
5433
|
const fileNameRef = yield* Ref.make(DEFAULT_PROGRESS_STREAM_FILE);
|
|
5556
5434
|
return RunEventDrain.of({
|
|
5557
|
-
drainFramed: (framed) => Effect$1.gen(function* () {
|
|
5435
|
+
drainFramed: (framed, toStdout) => Effect$1.gen(function* () {
|
|
5558
5436
|
const fileName = yield* Ref.get(fileNameRef);
|
|
5559
|
-
yield*
|
|
5437
|
+
yield* drainToSinks(fs, path, stdio, fileName, toStdout, framed);
|
|
5560
5438
|
}).pipe(Effect$1.tapCause((cause) => Effect$1.logError("stryker.output.drain_file_failed", cause)), Effect$1.ignoreCause),
|
|
5561
5439
|
setProgressStreamFile: (fileName) => Ref.set(fileNameRef, fileName)
|
|
5562
5440
|
});
|
|
5563
5441
|
});
|
|
5564
|
-
const drainOf = (stdio, framed) =>
|
|
5442
|
+
const drainOf = (stdio, framed, toStdout) => runToSink(stdio, framed, toStdout).pipe(Effect$1.withSpan("stryker.output.drain"), Effect$1.tapCause((cause) => Effect$1.logError("stryker.output.drain_failed", cause)), Effect$1.ignoreCause);
|
|
5565
5443
|
const writeStderr = (stdio, line) => Stream.run(Stream.succeed(`${line}\n`), stdio.stderr({ endOnDone: false })).pipe(Effect$1.ignore);
|
|
5566
5444
|
const emitNullScoreVerdict = (params) => {
|
|
5567
5445
|
const { stream, mode, thresholds, basePath, pathService } = params;
|
|
@@ -5708,7 +5586,8 @@ const makeRunEventStream = (resolved) => Effect$1.gen(function* () {
|
|
|
5708
5586
|
open: Effect$1.gen(function* () {
|
|
5709
5587
|
yield* Option$1.match(yield* Ref.get(drainFiberRef), {
|
|
5710
5588
|
onNone: () => Effect$1.gen(function* () {
|
|
5711
|
-
const
|
|
5589
|
+
const mode = (yield* Ref.get(stateRef)).mode;
|
|
5590
|
+
const drainFiber = yield* drain.drainFramed(framed, mode === "machine").pipe(Effect$1.forkDetach);
|
|
5712
5591
|
yield* Ref.set(drainFiberRef, Option$1.some(drainFiber));
|
|
5713
5592
|
}),
|
|
5714
5593
|
onSome: () => Effect$1.void
|
|
@@ -5730,7 +5609,11 @@ const makeRunEventStream = (resolved) => Effect$1.gen(function* () {
|
|
|
5730
5609
|
var DryRunError = class extends S.TaggedError()("DryRunError", {
|
|
5731
5610
|
stage: S.Literals(["dryRun", "dryRunNoTests"]),
|
|
5732
5611
|
reason: S.String
|
|
5733
|
-
}) {
|
|
5612
|
+
}) {
|
|
5613
|
+
get message() {
|
|
5614
|
+
return this.reason;
|
|
5615
|
+
}
|
|
5616
|
+
};
|
|
5734
5617
|
var FailedTestSummary = class extends S.Class("FailedTestSummary")({
|
|
5735
5618
|
name: S.String,
|
|
5736
5619
|
failureMessage: S.String
|
|
@@ -5865,6 +5748,15 @@ const originalFileFor = dual(2, (self, sandboxFileName) => {
|
|
|
5865
5748
|
const slot = SandboxHandle.slot(self);
|
|
5866
5749
|
return originalFileNameOf(sandboxFileName, self.workingDirectory, slot.basePath, slot.pathService);
|
|
5867
5750
|
});
|
|
5751
|
+
const VM_RUNNER_SPECIFIER = "@systemfsoftware/stryker-js-vm-runner";
|
|
5752
|
+
const vmRunnerOptions = { pool: "threads" };
|
|
5753
|
+
const vmRunnerPluginUrl = () => import.meta.resolve(VM_RUNNER_SPECIFIER);
|
|
5754
|
+
const isVmRunner = (name) => typeof name === "string" && name.toLowerCase() === "vm";
|
|
5755
|
+
const vmTestRunnerConfig = () => ({
|
|
5756
|
+
plugin: vmRunnerPluginUrl(),
|
|
5757
|
+
options: { ...vmRunnerOptions }
|
|
5758
|
+
});
|
|
5759
|
+
const testRunnerConfigOf = (configured) => Match.value(configured).pipe(Match.when(isVmRunner, vmTestRunnerConfig), Match.orElse((unchanged) => unchanged));
|
|
5868
5760
|
//#endregion
|
|
5869
5761
|
//#region src/TestRunner.blueprint.ts
|
|
5870
5762
|
const TypeId$2 = Symbol.for("~systemfsoftware/stryker-js/TestRunner");
|
|
@@ -5891,11 +5783,15 @@ const toRunnerFailure = (runnerName, phase) => (error) => Match.value(error).pip
|
|
|
5891
5783
|
* can see.
|
|
5892
5784
|
*/
|
|
5893
5785
|
const scopedOf = (params) => Effect$1.gen(function* () {
|
|
5894
|
-
const
|
|
5895
|
-
|
|
5786
|
+
const options = {
|
|
5787
|
+
...params.options,
|
|
5788
|
+
testRunner: testRunnerConfigOf(params.options.testRunner)
|
|
5789
|
+
};
|
|
5790
|
+
const runnerName = Match.value(options.testRunner).pipe(Match.when(Options_exports.isCustomTestRunner, (runner) => runner.plugin), Match.orElse((name) => name));
|
|
5791
|
+
const execArgv = Match.value(options.testRunner).pipe(Match.when(Options_exports.isCustomTestRunner, (runner) => Match.value(runner.nodeArgs).pipe(Match.when(Match.undefined, () => options.testRunnerNodeArgs), Match.orElse((args) => args))), Match.orElse(() => options.testRunnerNodeArgs));
|
|
5896
5792
|
const client = yield* makeWorkerClient({
|
|
5897
5793
|
rpcs: Plugin_exports.TestRunnerRpcs,
|
|
5898
|
-
options
|
|
5794
|
+
options,
|
|
5899
5795
|
entrypoint: params.workerEntrypoint,
|
|
5900
5796
|
workingDirectory: params.sandboxWorkingDirectory,
|
|
5901
5797
|
execArgv: [...execArgv],
|
|
@@ -5919,10 +5815,7 @@ const TestRunners = Blueprint.make()(TypeId$2).steps({
|
|
|
5919
5815
|
});
|
|
5920
5816
|
const makeChildProcessTestRunner = (params) => TestRunners.of(params).scoped;
|
|
5921
5817
|
const commandRunnerEffect = (context) => ChildProcessSpawner.ChildProcessSpawner.pipe(Effect$1.map((spawner) => commandRunner(context, spawner).pipe(withTimeout, withRetry)));
|
|
5922
|
-
const inProcessRunner = (context) => Match.value(context.options.testRunner).pipe(Match.when(isCommandRunner, () => Option$1.some(commandRunnerEffect(context))), Match.
|
|
5923
|
-
testFiles: context.testFiles,
|
|
5924
|
-
sandboxWorkingDirectory: context.sandboxWorkingDirectory
|
|
5925
|
-
}))), Match.orElse(() => Option$1.none()));
|
|
5818
|
+
const inProcessRunner = (context) => Match.value(context.options.testRunner).pipe(Match.when(isCommandRunner, () => Option$1.some(commandRunnerEffect(context))), Match.orElse(() => Option$1.none()));
|
|
5926
5819
|
const buildTestRunner = dual(2, (context, childProcessRunner) => Option$1.match(inProcessRunner(context), {
|
|
5927
5820
|
onSome: (inProcess) => inProcess,
|
|
5928
5821
|
onNone: () => Effect$1.gen(function* () {
|
|
@@ -6081,7 +5974,7 @@ const resolveConfiguredPlugin = Workflow.make({
|
|
|
6081
5974
|
//#endregion
|
|
6082
5975
|
//#region src/run/dry-run.parts.ts
|
|
6083
5976
|
const sandboxPathsOf = (sandbox, fileNames) => Result.all(fileNames.map((fileName) => sandboxFileFor(sandbox, fileName)));
|
|
6084
|
-
const configuredPluginOf$1 = (configured) => Match.value(configured).pipe(Match.when(Options_exports.isCustomTestRunner, (custom) => ConfiguredPluginModulePath.make({ modulePath: custom.plugin })), Match.orElse((name) => ConfiguredPluginName.make({ name })));
|
|
5977
|
+
const configuredPluginOf$1 = (configured) => Match.value(testRunnerConfigOf(configured)).pipe(Match.when(Options_exports.isCustomTestRunner, (custom) => ConfiguredPluginModulePath.make({ modulePath: custom.plugin })), Match.orElse((name) => ConfiguredPluginName.make({ name })));
|
|
6085
5978
|
const workerSpawnOf$1 = (stage, loaded, kind, configured) => Effect$1.mapError(Effect$1.fromResult(resolveConfiguredPlugin(WorkerSpawnCommand.make({
|
|
6086
5979
|
sources: loaded.pluginSources,
|
|
6087
5980
|
kind,
|
|
@@ -6095,7 +5988,11 @@ const optionalSandboxPathsOf = (command) => Boolean$1.match(command.options.test
|
|
|
6095
5988
|
onTrue: () => Result.succeed(void 0),
|
|
6096
5989
|
onFalse: () => sandboxPathsOf(command.sandbox, command.project.testFiles)
|
|
6097
5990
|
});
|
|
6098
|
-
const
|
|
5991
|
+
const mutatedFileNamesOf = (command) => {
|
|
5992
|
+
const mutated = MutableHashSet.fromIterable(command.mutants.map((mutant) => mutant.fileName));
|
|
5993
|
+
return [...MutableHashMap.keys(command.project.filesToMutate)].filter((name) => MutableHashSet.has(mutated, name));
|
|
5994
|
+
};
|
|
5995
|
+
const buildDryRunFiles = (command) => Result.flatMap(sandboxPathsOf(command.sandbox, mutatedFileNamesOf(command)), (files) => Result.map(optionalSandboxPathsOf(command), (testFiles) => ({
|
|
6099
5996
|
files,
|
|
6100
5997
|
testFiles
|
|
6101
5998
|
})));
|
|
@@ -6326,14 +6223,11 @@ const dryRunCell = Sandwich.named("stryker.dry_run")(readDryRun).decide(dryRun).
|
|
|
6326
6223
|
});
|
|
6327
6224
|
//#endregion
|
|
6328
6225
|
//#region src/plan-instrumentation.workflow.ts
|
|
6329
|
-
|
|
6330
|
-
stage: S.Literal("instrument"),
|
|
6331
|
-
reason: S.String
|
|
6332
|
-
}) {};
|
|
6226
|
+
const Count = S.Int.check(S.isGreaterThanOrEqualTo(0));
|
|
6333
6227
|
var InstrumentCommand = class extends S.TaggedClass()("InstrumentCommand", {
|
|
6334
|
-
fileCount:
|
|
6228
|
+
fileCount: Count,
|
|
6335
6229
|
inPlace: S.Boolean,
|
|
6336
|
-
pluginCount:
|
|
6230
|
+
pluginCount: Count
|
|
6337
6231
|
}) {
|
|
6338
6232
|
static [Workflow.InstrumentationBrand] = {
|
|
6339
6233
|
fileCount: "stryker.instrument.file_count",
|
|
@@ -6344,32 +6238,28 @@ const InstrumentDecisionTypeId = Symbol.for("@systemfsoftware/stryker-js/Instrum
|
|
|
6344
6238
|
var InPlaceInstrument = class extends S.TaggedClass()("InPlaceInstrument", {
|
|
6345
6239
|
workingDirectoryHint: S.String,
|
|
6346
6240
|
backupDirectoryHint: S.String,
|
|
6347
|
-
fileCount:
|
|
6241
|
+
fileCount: Count
|
|
6348
6242
|
}) {
|
|
6349
6243
|
[InstrumentDecisionTypeId] = InstrumentDecisionTypeId;
|
|
6350
6244
|
};
|
|
6351
6245
|
var EphemeralInstrument = class extends S.TaggedClass()("EphemeralInstrument", {
|
|
6352
6246
|
workingDirectoryHint: S.String,
|
|
6353
|
-
fileCount:
|
|
6247
|
+
fileCount: Count
|
|
6354
6248
|
}) {
|
|
6355
6249
|
[InstrumentDecisionTypeId] = InstrumentDecisionTypeId;
|
|
6356
6250
|
};
|
|
6357
|
-
const
|
|
6358
|
-
const decide$3 = (command) => Match.value(commandShape(command)).pipe(Match.when("empty", () => Result.fail(InstrumentError.make({
|
|
6359
|
-
stage: "instrument",
|
|
6360
|
-
reason: "No files to instrument."
|
|
6361
|
-
}))), Match.when("inPlace", () => Result.succeed(InPlaceInstrument.make({
|
|
6251
|
+
const decide$3 = (command) => Match.value(command.inPlace).pipe(Match.when(true, () => Result.succeed(InPlaceInstrument.make({
|
|
6362
6252
|
workingDirectoryHint: "inPlace",
|
|
6363
6253
|
backupDirectoryHint: "backup",
|
|
6364
6254
|
fileCount: command.fileCount
|
|
6365
|
-
}))), Match.when(
|
|
6255
|
+
}))), Match.when(false, () => Result.succeed(EphemeralInstrument.make({
|
|
6366
6256
|
workingDirectoryHint: "temp",
|
|
6367
6257
|
fileCount: command.fileCount
|
|
6368
6258
|
}))), Match.exhaustive);
|
|
6369
6259
|
const planInstrumentation = Workflow.make({
|
|
6370
6260
|
command: InstrumentCommand,
|
|
6371
6261
|
decision: S.Union([InPlaceInstrument, EphemeralInstrument]),
|
|
6372
|
-
error:
|
|
6262
|
+
error: S.Never,
|
|
6373
6263
|
decide: decide$3
|
|
6374
6264
|
});
|
|
6375
6265
|
//#endregion
|
|
@@ -7117,14 +7007,6 @@ const instrumentCell = Sandwich.named("stryker.instrument")((command) => Effect$
|
|
|
7117
7007
|
})).decide(planInstrumentation).write({
|
|
7118
7008
|
InPlaceInstrument: (_decision, raw) => writeInstrument(raw),
|
|
7119
7009
|
EphemeralInstrument: (_decision, raw) => writeInstrument(raw),
|
|
7120
|
-
InstrumentError: ({ stage, reason }, raw) => enteringInstrumentPhase(raw, Effect$1.fail(StageError.make({
|
|
7121
|
-
stage,
|
|
7122
|
-
reason,
|
|
7123
|
-
cause: InstrumentError.make({
|
|
7124
|
-
stage,
|
|
7125
|
-
reason
|
|
7126
|
-
})
|
|
7127
|
-
}))),
|
|
7128
7010
|
CommandRejected: ({ issue }) => Effect$1.fail(StageError.make({
|
|
7129
7011
|
stage: "instrument",
|
|
7130
7012
|
reason: issue
|
|
@@ -7149,7 +7031,11 @@ var MutationTestCommand = class extends S.TaggedClass()("MutationTestCommand", {
|
|
|
7149
7031
|
var MutationTestError = class extends S.TaggedError()("MutationTestError", {
|
|
7150
7032
|
stage: S.Literal("mutationTest"),
|
|
7151
7033
|
reason: S.String
|
|
7152
|
-
}) {
|
|
7034
|
+
}) {
|
|
7035
|
+
get message() {
|
|
7036
|
+
return this.reason;
|
|
7037
|
+
}
|
|
7038
|
+
};
|
|
7153
7039
|
const MutationTestDecisionTypeId = Symbol.for("@systemfsoftware/stryker-js/MutationTestDecision");
|
|
7154
7040
|
var MutationTestProceed = class extends S.TaggedClass()("MutationTestProceed", {}) {
|
|
7155
7041
|
[MutationTestDecisionTypeId] = MutationTestDecisionTypeId;
|
|
@@ -7586,8 +7472,9 @@ const toReportedMutant = (mutant) => Object.assign(mutant, {
|
|
|
7586
7472
|
static: mutant.static
|
|
7587
7473
|
});
|
|
7588
7474
|
const CHECKER_ACQUIRE_RETRIES = 2;
|
|
7475
|
+
const TEST_RUNNER_POOL_IDLE_TIME_TO_LIVE = Duration.minutes(1);
|
|
7589
7476
|
const isCheckerCrash = (error) => Match.value(error).pipe(Match.tag("ChildProcessCrashedError", "OutOfMemoryError", () => true), Match.orElse(() => false));
|
|
7590
|
-
const configuredPluginOf = (configured) => Match.value(configured).pipe(Match.when(Options_exports.isCustomTestRunner, (custom) => ConfiguredPluginModulePath.make({ modulePath: custom.plugin })), Match.orElse((name) => ConfiguredPluginName.make({ name })));
|
|
7477
|
+
const configuredPluginOf = (configured) => Match.value(testRunnerConfigOf(configured)).pipe(Match.when(Options_exports.isCustomTestRunner, (custom) => ConfiguredPluginModulePath.make({ modulePath: custom.plugin })), Match.orElse((name) => ConfiguredPluginName.make({ name })));
|
|
7591
7478
|
const workerSpawnOf = (stage, loaded, kind, configured) => Effect$1.mapError(Effect$1.fromResult(resolveConfiguredPlugin(WorkerSpawnCommand.make({
|
|
7592
7479
|
sources: loaded.pluginSources,
|
|
7593
7480
|
kind,
|
|
@@ -7781,13 +7668,17 @@ const checkerBreachToStageError = (error) => Match.value(error).pipe(Match.tag("
|
|
|
7781
7668
|
cause: breach
|
|
7782
7669
|
})), Match.exhaustive);
|
|
7783
7670
|
const invalidateSlot = (pool, slot, error) => Effect$1.flatMap(Pool.invalidate(pool, slot), () => Effect$1.fail(error));
|
|
7784
|
-
const
|
|
7785
|
-
|
|
7786
|
-
|
|
7787
|
-
|
|
7788
|
-
|
|
7789
|
-
|
|
7671
|
+
const onCheckerSlot = (pool, checkerIndex, run) => Pool.use(pool, (slot) => Option$1.match(Option$1.fromUndefinedOr(slot[checkerIndex]), {
|
|
7672
|
+
onNone: () => Effect$1.die(/* @__PURE__ */ new Error(`checker slot has no entry at index ${checkerIndex}`)),
|
|
7673
|
+
onSome: ({ checker }) => run(checker).pipe(Effect$1.catchTags({
|
|
7674
|
+
OutOfMemoryError: (error) => invalidateSlot(pool, slot, error),
|
|
7675
|
+
ChildProcessCrashedError: (error) => invalidateSlot(pool, slot, error),
|
|
7676
|
+
CheckerFailed: (error) => error.pipe(checkerBreachToStageError, Effect$1.fail),
|
|
7677
|
+
CheckerAnsweredUnrequested: (error) => error.pipe(checkerBreachToStageError, Effect$1.fail),
|
|
7678
|
+
CheckerSkippedRequested: (error) => error.pipe(checkerBreachToStageError, Effect$1.fail)
|
|
7679
|
+
}))
|
|
7790
7680
|
}));
|
|
7681
|
+
const checkGroupsConcurrently = (pool, checkerIndex, checkerName, currentPlans) => Effect$1.flatMap(onCheckerSlot(pool, checkerIndex, (checker) => groupPlans(checker, checkerName, currentPlans)), (groups) => Effect$1.map(Effect$1.forEach(groups, (group) => onCheckerSlot(pool, checkerIndex, (checker) => checkPlans(checker, checkerName, group)), { concurrency: "unbounded" }), (perGroup) => perGroup.flat()));
|
|
7791
7682
|
const isFailedCheck = (check) => check[1].status !== "passed";
|
|
7792
7683
|
const splitCheckedPlans = (checked, reporting) => {
|
|
7793
7684
|
const failures = checked.filter(isFailedCheck);
|
|
@@ -7797,18 +7688,15 @@ const splitCheckedPlans = (checked, reporting) => {
|
|
|
7797
7688
|
results
|
|
7798
7689
|
}));
|
|
7799
7690
|
};
|
|
7800
|
-
const stepOneChecker = (pool,
|
|
7691
|
+
const stepOneChecker = (pool, checkerIndex, checkerName, currentPlans, reporting) => checkGroupsConcurrently(pool, checkerIndex, checkerName, currentPlans).pipe(Effect$1.flatMap((checked) => splitCheckedPlans(checked, reporting)));
|
|
7801
7692
|
const emptyRunResults = [];
|
|
7802
|
-
const runConfiguredCheckers = (pool, plans, reporting) => Effect$1.
|
|
7803
|
-
|
|
7804
|
-
|
|
7805
|
-
|
|
7806
|
-
|
|
7807
|
-
|
|
7808
|
-
|
|
7809
|
-
checkerResults: [...acc.checkerResults, ...split.results]
|
|
7810
|
-
})));
|
|
7811
|
-
}));
|
|
7693
|
+
const runConfiguredCheckers = (pool, plans, reporting) => Effect$1.flatMap(Pool.use(pool, (slot) => Effect$1.succeed(slot.map(({ checkerName }) => checkerName))), (checkerNames) => Effect$1.reduce(checkerNames, () => ({
|
|
7694
|
+
passedPlans: plans,
|
|
7695
|
+
checkerResults: emptyRunResults
|
|
7696
|
+
}), (acc, checkerName, checkerIndex) => Effect$1.map(stepOneChecker(pool, checkerIndex, checkerName, acc.passedPlans, reporting), (split) => ({
|
|
7697
|
+
passedPlans: split.passed,
|
|
7698
|
+
checkerResults: [...acc.checkerResults, ...split.results]
|
|
7699
|
+
}))));
|
|
7812
7700
|
const checkPlansWithConfiguredCheckers = (checkerPool, plans, reporting) => Option$1.match(Option$1.fromNullishOr(checkerPool), {
|
|
7813
7701
|
onNone: () => Effect$1.succeed({
|
|
7814
7702
|
passedPlans: plans,
|
|
@@ -7816,6 +7704,14 @@ const checkPlansWithConfiguredCheckers = (checkerPool, plans, reporting) => Opti
|
|
|
7816
7704
|
}),
|
|
7817
7705
|
onSome: (pool) => runConfiguredCheckers(pool, plans, reporting)
|
|
7818
7706
|
});
|
|
7707
|
+
const checkerResourcesInOwnScope = (acquire) => Effect$1.gen(function* () {
|
|
7708
|
+
const checkerScope = yield* Scope.make();
|
|
7709
|
+
yield* Effect$1.addFinalizer(() => Scope.close(checkerScope, Exit.void));
|
|
7710
|
+
return {
|
|
7711
|
+
resources: yield* acquire.pipe(Scope.provide(checkerScope)),
|
|
7712
|
+
releaseInBackground: Scope.close(checkerScope, Exit.void).pipe(Effect$1.forkScoped({ uninterruptible: true }))
|
|
7713
|
+
};
|
|
7714
|
+
});
|
|
7819
7715
|
const isPlannable = (mutant) => Result.isSuccess(S.decodeResult(CheckerMutantFromMutant)(mutant));
|
|
7820
7716
|
const DROPPED_IDS_IN_WARNING = 5;
|
|
7821
7717
|
const configuredTestFilesOf = (run) => run.options.testFiles.length === 0 ? [] : run.project.testFiles;
|
|
@@ -7861,14 +7757,15 @@ const writeMutationTestDryRunOnly = Effect$1.gen(function* () {
|
|
|
7861
7757
|
});
|
|
7862
7758
|
const writeMutationTestProceed = (raw) => Effect$1.gen(function* () {
|
|
7863
7759
|
const prev = raw.prev;
|
|
7760
|
+
const testRunnerCapacity = prev.concurrency.testRunners + prev.concurrency.checkers;
|
|
7864
7761
|
const { dropped, plannable: plannableMutants } = partitionPlannable(prev.mutants);
|
|
7865
7762
|
yield* reportDroppedMutants(dropped);
|
|
7866
7763
|
yield* phaseEntered("mutation-test");
|
|
7867
7764
|
const idGenerator = yield* IdGenerator;
|
|
7868
7765
|
const env = yield* RunEnvironment;
|
|
7869
|
-
const
|
|
7766
|
+
const scopedCheckers = yield* checkerResourcesInOwnScope(makeCheckerPool(prev, env.basePath));
|
|
7870
7767
|
const testFiles = yield* Effect$1.map(sandboxFilesOf(prev.sandbox, configuredTestFilesOf(prev)), (pairs) => pairs.map(([, sandboxFileName]) => sandboxFileName));
|
|
7871
|
-
const testRunnerPool = yield* Pool.
|
|
7768
|
+
const testRunnerPool = yield* Pool.makeWithTTL({
|
|
7872
7769
|
acquire: buildTestRunner({
|
|
7873
7770
|
options: prev.options,
|
|
7874
7771
|
fileDescriptions: prev.project.fileDescriptions,
|
|
@@ -7886,7 +7783,9 @@ const writeMutationTestProceed = (raw) => Effect$1.gen(function* () {
|
|
|
7886
7783
|
idGenerator
|
|
7887
7784
|
})));
|
|
7888
7785
|
})),
|
|
7889
|
-
|
|
7786
|
+
min: prev.concurrency.testRunners,
|
|
7787
|
+
max: testRunnerCapacity,
|
|
7788
|
+
timeToLive: TEST_RUNNER_POOL_IDLE_TIME_TO_LIVE
|
|
7890
7789
|
});
|
|
7891
7790
|
const reporting = yield* MutationReporting;
|
|
7892
7791
|
const sandboxFileByName = Object.fromEntries(yield* sandboxFilesOf(prev.sandbox, [...MutableHashMap.keys(prev.project.filesToMutate)]));
|
|
@@ -7929,7 +7828,8 @@ const writeMutationTestProceed = (raw) => Effect$1.gen(function* () {
|
|
|
7929
7828
|
})).pipe(Effect$1.ignoreCause);
|
|
7930
7829
|
const progressQueue = yield* RunEvents;
|
|
7931
7830
|
yield* Queue.offer(progressQueue, PlanKnown.make({ total: allPlansForReporter.length + noCoverageResults.length }));
|
|
7932
|
-
const { passedPlans, checkerResults } = yield* checkPlansWithConfiguredCheckers(
|
|
7831
|
+
const { passedPlans, checkerResults } = yield* checkPlansWithConfiguredCheckers(scopedCheckers.resources, sortedPlans, reporting);
|
|
7832
|
+
const checkerRelease = yield* scopedCheckers.releaseInBackground;
|
|
7933
7833
|
const testRunnerStream = Stream.fromIterable(passedPlans);
|
|
7934
7834
|
const plannedTotal = sortedPlans.length + noCoverageResults.length + rememberedResults.length;
|
|
7935
7835
|
const completedRef = yield* Ref.make(0);
|
|
@@ -8030,7 +7930,7 @@ const writeMutationTestProceed = (raw) => Effect$1.gen(function* () {
|
|
|
8030
7930
|
yield* offerStreamTested(reported, finished, prepared);
|
|
8031
7931
|
yield* persist(reported);
|
|
8032
7932
|
return reported;
|
|
8033
|
-
})), { concurrency: Math.max(1,
|
|
7933
|
+
})), { concurrency: Math.max(1, testRunnerCapacity) }).pipe(Stream.runCollect, Effect$1.map((chunk) => [...chunk])));
|
|
8034
7934
|
const allResults = [
|
|
8035
7935
|
...rememberedResults,
|
|
8036
7936
|
...noCoverageResults,
|
|
@@ -8038,6 +7938,7 @@ const writeMutationTestProceed = (raw) => Effect$1.gen(function* () {
|
|
|
8038
7938
|
...runResults
|
|
8039
7939
|
];
|
|
8040
7940
|
const outcomeResult = yield* reporting.reportAll(reportingInputOf(prev, env, allResults));
|
|
7941
|
+
yield* Fiber.await(checkerRelease);
|
|
8041
7942
|
const doneNow = yield* Clock.currentTimeMillis;
|
|
8042
7943
|
const elapsed = Duration.millis(doneNow - env.runStartedAt);
|
|
8043
7944
|
yield* Effect$1.logInfo(`Done in ${Duration.format(elapsed)}.`);
|
|
@@ -8517,7 +8418,7 @@ const pluginUrlsFromOptions = (options) => [
|
|
|
8517
8418
|
...options.plugins,
|
|
8518
8419
|
...options.appendPlugins,
|
|
8519
8420
|
...options.ignorers,
|
|
8520
|
-
...Match.value(options.testRunner).pipe(Match.when(Options_exports.isCustomTestRunner, (runner) => [runner.plugin]), Match.orElse(() => [])),
|
|
8421
|
+
...Match.value(options.testRunner).pipe(Match.when(Options_exports.isCustomTestRunner, (runner) => [runner.plugin]), Match.when(isVmRunner, () => [vmRunnerPluginUrl()]), Match.orElse(() => [])),
|
|
8521
8422
|
...options.checkers.map((checker) => checker.plugin)
|
|
8522
8423
|
];
|
|
8523
8424
|
//#endregion
|
|
@@ -8817,4 +8718,4 @@ const strykerCell = dual((args) => Predicate$1.isObject(args[0]), (options, targ
|
|
|
8817
8718
|
})
|
|
8818
8719
|
})), Effect$1.scoped));
|
|
8819
8720
|
//#endregion
|
|
8820
|
-
export {
|
|
8721
|
+
export { ExtendsStepDone as $, RunEvents as A, make$2 as B, forkCoreSchema as C, validateOptions as D, mergeConfigs as E, MetricsResultFromReport as F, ConfigFileInvalidError as G, isCommandRunner as H, reporterWorkerFactory as I, ConfigFileUnsupportedError as J, ConfigFileNotFoundError as K, spawnReporterWorker as L, VerdictEnvelope as M, VerdictMutant as N, RunEnvironment as O, VerdictThresholds as P, ExtendsStepDocumentSchema as Q, makeWorkerClient as R, describeErrors as S, initialExtendsStepState as T, FileMatcher as U, StrykerError as V, ConfigError as W, defaultOptions as X, createDefaultOptions as Y, ConfigDocumentSchema as Z, ClassifyWorkerExitDecision as _, isVmRunner as a, MergeCommand as at, readConfig as b, vmTestRunnerConfig as c, extendsPropertySchema as ct, makeRunEventStream as d, checkGroupedPlans as dt, ExtendsStepRead as et, RunEventWireLine as f, ChildProcessCrashedError as ft, ClassifyWorkerExitCommand as g, CheckerSkippedRequested as gt, layerWorkerProtocol as h, CheckerAnsweredUnrequested as ht, makeChildProcessTestRunner as i, ImportedModuleSchema as it, RunIdentity as j, IdGenerator as k, RunEventDrain as l, forkOptionsSchema as lt, nodePlatformLayer as m, WorkerBootTimeoutError as mt, strykerCell as n, ExtendsStepResolve as nt, testRunnerConfigOf as o, MergeResult as ot, IncrementalReportSchema as p, OutOfMemoryError as pt, ConfigFileUnreadableError as q, buildTestRunner as r, ExtendsStepStateSchema as rt, vmRunnerPluginUrl as s, ReadConfigCommand as st, mutationTestCell as t, ExtendsStepRefused as tt, RunEventDrainLive as u, survivorsPriorReport as ut, classifyWorkerExit as v, importModule as w, decideExtendsStep as x, loadConfigCell as y, WorkerLauncher as z };
|