mutation_tester 1.5.0 → 1.5.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +4 -0
- data/Gemfile.lock +1 -1
- data/examples/github_actions/ai_mutation_gate.yml +1 -1
- data/examples/github_actions/mutation_test.yml +1 -1
- data/lib/mutation_tester/fork_runner/worker.rb +1 -0
- data/lib/mutation_tester/fork_runner.rb +3 -2
- data/lib/mutation_tester/test_command.rb +2 -1
- data/lib/mutation_tester/version.rb +1 -1
- data/readme.md +335 -538
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e32ba3afbad23fb7f2d04c12f197c8e7d7af50d0eb537266f76e3bd957165110
|
|
4
|
+
data.tar.gz: b27a1b44965b42cb4498daaba8d221dcf820b71fd3e61f3b94c47a71c7cad41d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 4a05a309477ff66005be2371bedd4b5ce4b3622a064f2013b3b62336dbe5d43af7c0e27526eee2ab186c07d9faef5fc8e3a568fe1bdda5e428c3142af19b0165
|
|
7
|
+
data.tar.gz: 3fd04d05930cf47e0a4fb15680531586dfd9183ecd77ec3040aae3e5397ca1cd0cef2ac68ea087acf87c0acdd43dd8f3a18a40a46f05d8c5fac9a545511988f0
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [1.5.1] - 2026-08-13
|
|
4
|
+
|
|
5
|
+
- Fixed load-time mutants losing per-worker database isolation in a parallel in-memory run with `--worker-env` and `--after-fork`. Mutants on load-time code (constants, class macros, `included do`) are decided file-based on purpose, but that file-based run acquires a fork-runner worker, and a worker booted inside a `Parallel` worker process inherited the parent process's value of the worker-env variable instead of the per-worker assignment: with 8 workers, every load-time mutant's test run hit the parent's database concurrently, races on shared rows failed tests unrelated to the mutant, and those failures were scored as kills. The same file could report 75% and 100% on consecutive runs with no error and no timeout in the output, while the spawn path and the pooled fork runner (which already carried the per-worker value) stayed stable. The fork execution path now passes the same per-worker env override the spawn path always used, and the worker applies it inside the forked test child before the spec loads, so every execution path resolves the same per-worker database. Reported in the field with exactly this signature: only class-macro mutants unstable, serial and fork-runner scores identical and stable.
|
|
6
|
+
|
|
3
7
|
## [1.5.0] - 2026-08-08
|
|
4
8
|
|
|
5
9
|
- Added `--after-fork FILE` (and `config.after_fork_file` / the `MUTATION_TESTER_AFTER_FORK` environment variable): a Ruby file loaded inside each preloaded in-memory clone right after it forks and receives its per-worker environment, so the app can re-establish per-worker state such as its ActiveRecord connection. With `--worker-env` set, this keeps the `in_memory` runner available in parallel runs instead of falling back to `fork`: each clone now receives its own per-worker value of the variable through the existing per-clone environment plumbing and runs the after-fork file once, giving in-memory execution and per-worker database isolation at the same time. Failure modes stay loud: a clone whose after-fork file raises reports the error on stderr and is dropped, its worker deciding its share of mutants file-based, and a missing after-fork file makes the whole run fall back to file-based execution with a warning. A serial in-memory run (`-p 1`) has only one worker and now stays in memory with `--worker-env` even without the hook.
|
data/Gemfile.lock
CHANGED
|
@@ -70,6 +70,7 @@ supervise_child = lambda do |job, out, child_body|
|
|
|
70
70
|
rescue Errno::EACCES, Errno::EPERM
|
|
71
71
|
end
|
|
72
72
|
Dir.chdir(job['chdir']) if job['chdir']
|
|
73
|
+
job['env']&.each { |name, value| ENV[name] = value }
|
|
73
74
|
mirror_load_path.call(job['mirror_of'], job['chdir'])
|
|
74
75
|
sink = File.open(job['log'] || File::NULL, 'w')
|
|
75
76
|
sink.sync = true
|
|
@@ -154,7 +154,7 @@ module MutationTester
|
|
|
154
154
|
end
|
|
155
155
|
|
|
156
156
|
def execute(spec_file, timeout: nil, chdir: nil, capture: false, args: [], stop_on_first_failure: false,
|
|
157
|
-
mirror_of: nil)
|
|
157
|
+
mirror_of: nil, env: nil)
|
|
158
158
|
log = capture ? Tempfile.new(['mutation_tester_fork', '.log']) : nil
|
|
159
159
|
job = {
|
|
160
160
|
spec: spec_file,
|
|
@@ -163,7 +163,8 @@ module MutationTester
|
|
|
163
163
|
log: log&.path,
|
|
164
164
|
args: args,
|
|
165
165
|
stop_on_first_failure: stop_on_first_failure,
|
|
166
|
-
mirror_of: mirror_of
|
|
166
|
+
mirror_of: mirror_of,
|
|
167
|
+
env: env
|
|
167
168
|
}
|
|
168
169
|
@job_writer.puts(JSON.generate(job))
|
|
169
170
|
status = await_result(timeout)['status']
|