mutant 0.8.10 → 0.8.11
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/.rubocop.yml +1 -4
- data/Changelog.md +8 -0
- data/README.md +112 -43
- data/Rakefile +2 -16
- data/circle.yml +1 -1
- data/config/flay.yml +2 -2
- data/config/flog.yml +1 -1
- data/config/reek.yml +3 -4
- data/config/rubocop.yml +53 -16
- data/lib/mutant.rb +27 -6
- data/lib/mutant/ast/meta/const.rb +2 -0
- data/lib/mutant/ast/meta/optarg.rb +2 -0
- data/lib/mutant/ast/meta/resbody.rb +2 -0
- data/lib/mutant/ast/meta/restarg.rb +2 -0
- data/lib/mutant/ast/meta/send.rb +4 -0
- data/lib/mutant/ast/meta/symbol.rb +2 -0
- data/lib/mutant/ast/named_children.rb +14 -4
- data/lib/mutant/ast/nodes.rb +3 -1
- data/lib/mutant/ast/regexp.rb +53 -0
- data/lib/mutant/ast/regexp/transformer.rb +185 -0
- data/lib/mutant/ast/regexp/transformer/alternative.rb +39 -0
- data/lib/mutant/ast/regexp/transformer/character_set.rb +46 -0
- data/lib/mutant/ast/regexp/transformer/direct.rb +99 -0
- data/lib/mutant/ast/regexp/transformer/options_group.rb +66 -0
- data/lib/mutant/ast/regexp/transformer/quantifier.rb +112 -0
- data/lib/mutant/ast/regexp/transformer/recursive.rb +50 -0
- data/lib/mutant/ast/regexp/transformer/root.rb +29 -0
- data/lib/mutant/ast/regexp/transformer/text.rb +55 -0
- data/lib/mutant/ast/types.rb +92 -5
- data/lib/mutant/cli.rb +2 -14
- data/lib/mutant/color.rb +1 -1
- data/lib/mutant/config.rb +1 -3
- data/lib/mutant/expression/methods.rb +1 -1
- data/lib/mutant/expression/namespace.rb +2 -2
- data/lib/mutant/expression/parser.rb +1 -1
- data/lib/mutant/integration.rb +10 -28
- data/lib/mutant/isolation.rb +9 -60
- data/lib/mutant/isolation/fork.rb +72 -0
- data/lib/mutant/isolation/none.rb +25 -0
- data/lib/mutant/matcher/config.rb +2 -0
- data/lib/mutant/matcher/method/singleton.rb +5 -4
- data/lib/mutant/meta.rb +11 -4
- data/lib/mutant/meta/example.rb +2 -116
- data/lib/mutant/meta/example/dsl.rb +22 -19
- data/lib/mutant/meta/example/verification.rb +86 -0
- data/lib/mutant/mutator.rb +22 -49
- data/lib/mutant/mutator/node.rb +15 -19
- data/lib/mutant/mutator/node/and_asgn.rb +1 -1
- data/lib/mutant/mutator/node/argument.rb +10 -5
- data/lib/mutant/mutator/node/arguments.rb +5 -9
- data/lib/mutant/mutator/node/begin.rb +4 -17
- data/lib/mutant/mutator/node/block.rb +1 -1
- data/lib/mutant/mutator/node/break.rb +1 -1
- data/lib/mutant/mutator/node/class.rb +21 -0
- data/lib/mutant/mutator/node/conditional_loop.rb +1 -1
- data/lib/mutant/mutator/node/define.rb +1 -1
- data/lib/mutant/mutator/node/defined.rb +1 -1
- data/lib/mutant/mutator/node/dstr.rb +1 -1
- data/lib/mutant/mutator/node/dsym.rb +1 -1
- data/lib/mutant/mutator/node/generic.rb +3 -3
- data/lib/mutant/mutator/node/kwbegin.rb +1 -1
- data/lib/mutant/mutator/node/literal.rb +9 -0
- data/lib/mutant/mutator/node/literal/boolean.rb +1 -1
- data/lib/mutant/mutator/node/literal/fixnum.rb +2 -2
- data/lib/mutant/mutator/node/literal/float.rb +4 -6
- data/lib/mutant/mutator/node/literal/hash.rb +1 -1
- data/lib/mutant/mutator/node/literal/nil.rb +1 -1
- data/lib/mutant/mutator/node/literal/range.rb +2 -19
- data/lib/mutant/mutator/node/literal/regex.rb +43 -3
- data/lib/mutant/mutator/node/literal/string.rb +1 -1
- data/lib/mutant/mutator/node/literal/symbol.rb +2 -4
- data/lib/mutant/mutator/node/masgn.rb +1 -1
- data/lib/mutant/mutator/node/match_current_line.rb +1 -1
- data/lib/mutant/mutator/node/mlhs.rb +2 -3
- data/lib/mutant/mutator/node/named_value/access.rb +2 -2
- data/lib/mutant/mutator/node/named_value/constant_assignment.rb +4 -3
- data/lib/mutant/mutator/node/named_value/variable_assignment.rb +4 -4
- data/lib/mutant/mutator/node/next.rb +1 -1
- data/lib/mutant/mutator/node/nthref.rb +1 -1
- data/lib/mutant/mutator/node/or_asgn.rb +1 -1
- data/lib/mutant/mutator/node/regexp.rb +44 -0
- data/lib/mutant/mutator/node/regopt.rb +31 -0
- data/lib/mutant/mutator/node/resbody.rb +1 -1
- data/lib/mutant/mutator/node/rescue.rb +1 -3
- data/lib/mutant/mutator/node/return.rb +1 -1
- data/lib/mutant/mutator/node/send.rb +43 -3
- data/lib/mutant/mutator/node/send/attribute_assignment.rb +4 -1
- data/lib/mutant/mutator/node/send/conditional.rb +23 -0
- data/lib/mutant/mutator/node/send/index.rb +1 -1
- data/lib/mutant/mutator/node/splat.rb +1 -1
- data/lib/mutant/mutator/node/when.rb +1 -1
- data/lib/mutant/mutator/node/yield.rb +1 -1
- data/lib/mutant/mutator/util.rb +0 -30
- data/lib/mutant/mutator/util/array.rb +4 -16
- data/lib/mutant/parallel.rb +1 -1
- data/lib/mutant/parallel/worker.rb +1 -1
- data/lib/mutant/registry.rb +44 -0
- data/lib/mutant/reporter/cli/format.rb +2 -0
- data/lib/mutant/reporter/cli/printer.rb +2 -2
- data/lib/mutant/reporter/cli/printer/config.rb +0 -1
- data/lib/mutant/reporter/cli/printer/env_progress.rb +1 -11
- data/lib/mutant/reporter/cli/printer/mutation_progress_result.rb +1 -1
- data/lib/mutant/reporter/cli/printer/mutation_result.rb +2 -0
- data/lib/mutant/reporter/cli/tput.rb +1 -1
- data/lib/mutant/reporter/sequence.rb +3 -0
- data/lib/mutant/require_highjack.rb +6 -2
- data/lib/mutant/result.rb +1 -1
- data/lib/mutant/subject.rb +5 -5
- data/lib/mutant/subject/method/instance.rb +1 -2
- data/lib/mutant/util.rb +18 -0
- data/lib/mutant/version.rb +1 -1
- data/lib/mutant/zombifier.rb +5 -3
- data/meta/and.rb +1 -1
- data/meta/and_asgn.rb +1 -1
- data/meta/array.rb +2 -2
- data/meta/begin.rb +2 -2
- data/meta/block.rb +7 -7
- data/meta/block_pass.rb +1 -1
- data/meta/blockarg.rb +1 -1
- data/meta/break.rb +1 -1
- data/meta/case.rb +2 -2
- data/meta/casgn.rb +11 -2
- data/meta/cbase.rb +1 -1
- data/meta/class.rb +10 -0
- data/meta/const.rb +9 -1
- data/meta/csend.rb +8 -0
- data/meta/cvar.rb +1 -1
- data/meta/cvasgn.rb +1 -1
- data/meta/date.rb +4 -4
- data/meta/def.rb +14 -14
- data/meta/defined.rb +1 -1
- data/meta/dstr.rb +1 -1
- data/meta/dsym.rb +1 -1
- data/meta/ensure.rb +1 -1
- data/meta/false.rb +1 -1
- data/meta/float.rb +3 -3
- data/meta/gvar.rb +1 -1
- data/meta/gvasgn.rb +1 -1
- data/meta/hash.rb +1 -1
- data/meta/if.rb +17 -3
- data/meta/int.rb +1 -1
- data/meta/ivar.rb +1 -1
- data/meta/ivasgn.rb +14 -1
- data/meta/kwarg.rb +8 -0
- data/meta/kwbegin.rb +1 -1
- data/meta/kwoptarg.rb +11 -0
- data/meta/lvar.rb +1 -1
- data/meta/lvasgn.rb +1 -1
- data/meta/masgn.rb +1 -1
- data/meta/match_current_line.rb +2 -2
- data/meta/next.rb +1 -1
- data/meta/nil.rb +1 -1
- data/meta/nthref.rb +5 -5
- data/meta/op_assgn.rb +1 -1
- data/meta/or.rb +1 -1
- data/meta/or_asgn.rb +5 -5
- data/meta/range.rb +2 -8
- data/meta/redo.rb +1 -1
- data/meta/regexp.rb +106 -0
- data/meta/regexp/regexp_bol_anchor.rb +13 -0
- data/meta/regexp/regexp_bos_anchor.rb +26 -0
- data/meta/regexp/regexp_root_expression.rb +13 -0
- data/meta/regopt.rb +8 -0
- data/meta/rescue.rb +49 -4
- data/meta/restarg.rb +6 -9
- data/meta/return.rb +2 -2
- data/meta/self.rb +1 -1
- data/meta/send.rb +228 -55
- data/meta/str.rb +1 -1
- data/meta/super.rb +3 -3
- data/meta/{symbol.rb → sym.rb} +1 -1
- data/meta/true.rb +1 -1
- data/meta/until.rb +1 -1
- data/meta/while.rb +2 -2
- data/meta/yield.rb +1 -1
- data/mutant-rspec.gemspec +2 -2
- data/mutant.gemspec +6 -5
- data/spec/integration/mutant/isolation/fork_spec.rb +8 -0
- data/spec/integration/mutant/rspec_spec.rb +1 -1
- data/spec/integration/mutant/test_mutator_handles_types_spec.rb +1 -2
- data/spec/integrations.yml +93 -24
- data/spec/spec_helper.rb +12 -7
- data/spec/support/compress_helper.rb +1 -1
- data/spec/support/corpus.rb +115 -50
- data/spec/support/fake_actor.rb +5 -5
- data/spec/support/file_system.rb +1 -1
- data/spec/support/ice_nine_config.rb +3 -3
- data/spec/support/ruby_vm.rb +11 -12
- data/spec/support/shared_context.rb +22 -13
- data/spec/support/test_app.rb +1 -1
- data/spec/support/warning.rb +64 -0
- data/spec/support/warnings.yml +4 -0
- data/spec/support/xspec.rb +177 -0
- data/spec/unit/mutant/actor/env_spec.rb +2 -2
- data/spec/unit/mutant/actor/sender_spec.rb +1 -1
- data/spec/unit/mutant/ast/meta/send_spec.rb +1 -1
- data/spec/unit/mutant/ast/named_children_spec.rb +26 -0
- data/spec/unit/mutant/ast/regexp/parse_spec.rb +7 -0
- data/spec/unit/mutant/ast/regexp/supported_predicate_spec.rb +14 -0
- data/spec/unit/mutant/ast/regexp/transformer/lookup_table/table_spec.rb +19 -0
- data/spec/unit/mutant/ast/regexp/transformer/lookup_table_spec.rb +33 -0
- data/spec/unit/mutant/ast/regexp/transformer_spec.rb +19 -0
- data/spec/unit/mutant/ast/regexp_spec.rb +617 -0
- data/spec/unit/mutant/cli_spec.rb +7 -45
- data/spec/unit/mutant/context_spec.rb +4 -7
- data/spec/unit/mutant/env/{boostrap_spec.rb → bootstrap_spec.rb} +2 -2
- data/spec/unit/mutant/env_spec.rb +13 -16
- data/spec/unit/mutant/expression/namespace/{flat_spec.rb → exact_spec.rb} +0 -0
- data/spec/unit/mutant/integration/rspec_spec.rb +2 -2
- data/spec/unit/mutant/integration_spec.rb +14 -0
- data/spec/unit/mutant/isolation/fork_spec.rb +155 -0
- data/spec/unit/mutant/isolation/none_spec.rb +16 -0
- data/spec/unit/mutant/loader_spec.rb +1 -1
- data/spec/unit/mutant/matcher/methods/instance_spec.rb +2 -4
- data/spec/unit/mutant/meta/example/dsl_spec.rb +106 -0
- data/spec/unit/mutant/meta/example/verification_spec.rb +120 -0
- data/spec/unit/mutant/meta/example_spec.rb +32 -0
- data/spec/unit/mutant/mutator/node_spec.rb +37 -4
- data/spec/unit/mutant/mutator_spec.rb +21 -0
- data/spec/unit/mutant/{runner → parallel}/driver_spec.rb +0 -0
- data/spec/unit/mutant/parallel/master_spec.rb +13 -13
- data/spec/unit/mutant/registry_spec.rb +47 -0
- data/spec/unit/mutant/reporter/cli/printer/config_spec.rb +0 -4
- data/spec/unit/mutant/reporter/cli/printer/env_progress_spec.rb +0 -8
- data/spec/unit/mutant/reporter/cli/printer/env_result_spec.rb +0 -2
- data/spec/unit/mutant/reporter/cli/printer/status_progressive_spec.rb +0 -8
- data/spec/unit/mutant/reporter/cli/printer/status_spec.rb +0 -34
- data/spec/unit/mutant/reporter/cli_spec.rb +0 -22
- data/spec/unit/mutant/repository/diff_spec.rb +6 -6
- data/spec/unit/mutant/require_highjack_spec.rb +38 -14
- data/spec/unit/mutant/result/env_spec.rb +1 -4
- data/spec/unit/mutant/runner_spec.rb +1 -1
- data/spec/unit/mutant/subject/method/instance_spec.rb +1 -1
- data/spec/unit/mutant/subject_spec.rb +3 -3
- data/spec/unit/mutant/util/one_spec.rb +20 -0
- data/spec/unit/mutant/zombifier_spec.rb +18 -18
- data/test_app/{Gemfile.rspec3.3 → Gemfile.rspec3.5} +2 -2
- metadata +94 -24
- data/TODO +0 -21
- data/lib/mutant/mutator/node/blockarg.rb +0 -13
- data/lib/mutant/mutator/node/restarg.rb +0 -13
- data/lib/mutant/mutator/registry.rb +0 -49
- data/meta/boolean.rb +0 -13
- data/meta/regex.rb +0 -19
- data/spec/unit/mutant/isolation_spec.rb +0 -104
- data/spec/unit/mutant/mutator/registry_spec.rb +0 -57
@@ -125,13 +125,11 @@ Environment:
|
|
125
125
|
-j, --jobs NUMBER Number of kill jobs. Defaults to number of processors.
|
126
126
|
|
127
127
|
Options:
|
128
|
-
--expected-coverage COVERAGE Fail unless COVERAGE is not reached exactly, parsed via Rational()
|
129
128
|
--use INTEGRATION Use INTEGRATION to kill mutations
|
130
129
|
--ignore-subject EXPRESSION Ignore subjects that match EXPRESSION as prefix
|
131
130
|
--since REVISION Only select subjects touched since REVISION
|
132
131
|
--fail-fast Fail fast
|
133
132
|
--version Print mutants version
|
134
|
-
-d, --debug Enable debugging output
|
135
133
|
-h, --help Show this message
|
136
134
|
MESSAGE
|
137
135
|
end
|
@@ -151,6 +149,12 @@ Options:
|
|
151
149
|
context 'when integration exists' do
|
152
150
|
let(:flags) { %w[--use rspec] }
|
153
151
|
|
152
|
+
before do
|
153
|
+
expect(Kernel).to receive(:require)
|
154
|
+
.with('mutant/integration/rspec')
|
155
|
+
.and_call_original
|
156
|
+
end
|
157
|
+
|
154
158
|
it_should_behave_like 'a cli parser'
|
155
159
|
|
156
160
|
let(:expected_integration) { Mutant::Integration::Rspec }
|
@@ -189,38 +193,6 @@ Options:
|
|
189
193
|
end
|
190
194
|
end
|
191
195
|
|
192
|
-
context 'with expected-coverage flag' do
|
193
|
-
context 'given as decimal' do
|
194
|
-
let(:flags) { %w[--expected-coverage 0.1] }
|
195
|
-
|
196
|
-
it_should_behave_like 'a cli parser'
|
197
|
-
|
198
|
-
it 'configures expected coverage' do
|
199
|
-
expect(subject.config.expected_coverage).to eql(Rational(1, 10))
|
200
|
-
end
|
201
|
-
end
|
202
|
-
|
203
|
-
context 'given as scientific' do
|
204
|
-
let(:flags) { %w[--expected-coverage 1e-1] }
|
205
|
-
|
206
|
-
it_should_behave_like 'a cli parser'
|
207
|
-
|
208
|
-
it 'configures expected coverage' do
|
209
|
-
expect(subject.config.expected_coverage).to eql(Rational(1, 10))
|
210
|
-
end
|
211
|
-
end
|
212
|
-
|
213
|
-
context 'given as rational' do
|
214
|
-
let(:flags) { %w[--expected-coverage 1/10] }
|
215
|
-
|
216
|
-
it_should_behave_like 'a cli parser'
|
217
|
-
|
218
|
-
it 'configures expected coverage' do
|
219
|
-
expect(subject.config.expected_coverage).to eql(Rational(1, 10))
|
220
|
-
end
|
221
|
-
end
|
222
|
-
end
|
223
|
-
|
224
196
|
context 'with require flags' do
|
225
197
|
let(:flags) { %w[--require foo --require bar] }
|
226
198
|
|
@@ -271,18 +243,8 @@ Options:
|
|
271
243
|
end
|
272
244
|
end
|
273
245
|
|
274
|
-
context 'with debug flag' do
|
275
|
-
let(:flags) { %w[--debug] }
|
276
|
-
|
277
|
-
it_should_behave_like 'a cli parser'
|
278
|
-
|
279
|
-
it 'sets the debug option' do
|
280
|
-
expect(subject.config.debug).to be(true)
|
281
|
-
end
|
282
|
-
end
|
283
|
-
|
284
246
|
context 'with zombie flag' do
|
285
|
-
let(:flags)
|
247
|
+
let(:flags) { %w[--zombie] }
|
286
248
|
|
287
249
|
it_should_behave_like 'a cli parser'
|
288
250
|
|
@@ -1,18 +1,16 @@
|
|
1
|
-
# rubocop:disable ClosingParenthesisIndentation
|
2
1
|
RSpec.describe Mutant::Context do
|
3
2
|
describe '.wrap' do
|
4
3
|
subject { described_class.wrap(scope, node) }
|
5
4
|
|
6
|
-
let(:node)
|
5
|
+
let(:node) { s(:str, 'test') }
|
7
6
|
|
8
7
|
context 'with Module as scope' do
|
9
|
-
let(:scope) { Mutant
|
8
|
+
let(:scope) { Mutant }
|
10
9
|
|
11
10
|
let(:expected) do
|
12
11
|
s(:module,
|
13
12
|
s(:const, nil, :Mutant),
|
14
|
-
s(:str, 'test')
|
15
|
-
)
|
13
|
+
s(:str, 'test'))
|
16
14
|
end
|
17
15
|
|
18
16
|
it { should eql(expected) }
|
@@ -25,8 +23,7 @@ RSpec.describe Mutant::Context do
|
|
25
23
|
s(:class,
|
26
24
|
s(:const, nil, :Context),
|
27
25
|
nil,
|
28
|
-
s(:str, 'test')
|
29
|
-
)
|
26
|
+
s(:str, 'test'))
|
30
27
|
end
|
31
28
|
|
32
29
|
it { should eql(expected) }
|
@@ -177,8 +177,8 @@ RSpec.describe Mutant::Env::Bootstrap do
|
|
177
177
|
Mutant::Scope.new(TestApp::Empty, match_expressions.last),
|
178
178
|
Mutant::Scope.new(TestApp::Literal, match_expressions.first)
|
179
179
|
],
|
180
|
-
mutations:
|
181
|
-
subjects:
|
180
|
+
mutations: subjects.flat_map(&:mutations),
|
181
|
+
subjects: subjects
|
182
182
|
)
|
183
183
|
end
|
184
184
|
|
@@ -13,18 +13,15 @@ RSpec.describe Mutant::Env do
|
|
13
13
|
)
|
14
14
|
end
|
15
15
|
|
16
|
-
let(:integration) { instance_double(Mutant::Integration)
|
17
|
-
let(:wrapped_node) { instance_double(Parser::AST::Node)
|
18
|
-
let(:context) { instance_double(Mutant::Context)
|
19
|
-
let(:test_a) { instance_double(Mutant::Test)
|
20
|
-
let(:test_b) { instance_double(Mutant::Test)
|
21
|
-
let(:tests) { [test_a, test_b]
|
22
|
-
let(:selector) { instance_double(Mutant::Selector)
|
23
|
-
let(:integration_class) { Mutant::Integration::Null
|
24
|
-
|
25
|
-
let(:isolation) do
|
26
|
-
instance_double(Mutant::Isolation::Fork.singleton_class)
|
27
|
-
end
|
16
|
+
let(:integration) { instance_double(Mutant::Integration) }
|
17
|
+
let(:wrapped_node) { instance_double(Parser::AST::Node) }
|
18
|
+
let(:context) { instance_double(Mutant::Context) }
|
19
|
+
let(:test_a) { instance_double(Mutant::Test) }
|
20
|
+
let(:test_b) { instance_double(Mutant::Test) }
|
21
|
+
let(:tests) { [test_a, test_b] }
|
22
|
+
let(:selector) { instance_double(Mutant::Selector) }
|
23
|
+
let(:integration_class) { Mutant::Integration::Null }
|
24
|
+
let(:isolation) { instance_double(Mutant::Isolation::Fork) }
|
28
25
|
|
29
26
|
let(:mutation) do
|
30
27
|
instance_double(
|
@@ -37,16 +34,16 @@ RSpec.describe Mutant::Env do
|
|
37
34
|
Mutant::Config::DEFAULT.with(
|
38
35
|
isolation: isolation,
|
39
36
|
integration: integration_class,
|
40
|
-
kernel:
|
37
|
+
kernel: class_double(Kernel)
|
41
38
|
)
|
42
39
|
end
|
43
40
|
|
44
41
|
let(:mutation_subject) do
|
45
42
|
instance_double(
|
46
43
|
Mutant::Subject,
|
47
|
-
context:
|
44
|
+
context: context,
|
48
45
|
identification: 'subject',
|
49
|
-
source:
|
46
|
+
source: 'original'
|
50
47
|
)
|
51
48
|
end
|
52
49
|
|
@@ -56,7 +53,7 @@ RSpec.describe Mutant::Env do
|
|
56
53
|
specify do
|
57
54
|
should eql(
|
58
55
|
Mutant::Result::Mutation.new(
|
59
|
-
mutation:
|
56
|
+
mutation: mutation,
|
60
57
|
test_result: test_result
|
61
58
|
)
|
62
59
|
)
|
File without changes
|
@@ -10,6 +10,20 @@ RSpec.describe Mutant::Integration do
|
|
10
10
|
subject { object.setup }
|
11
11
|
it_should_behave_like 'a command method'
|
12
12
|
end
|
13
|
+
|
14
|
+
describe '.setup' do
|
15
|
+
subject { described_class.setup(kernel, name) }
|
16
|
+
|
17
|
+
let(:name) { 'null' }
|
18
|
+
let(:kernel) { class_double(Kernel) }
|
19
|
+
|
20
|
+
before do
|
21
|
+
expect(kernel).to receive(:require)
|
22
|
+
.with('mutant/integration/null')
|
23
|
+
end
|
24
|
+
|
25
|
+
it { should be(Mutant::Integration::Null) }
|
26
|
+
end
|
13
27
|
end
|
14
28
|
|
15
29
|
RSpec.describe Mutant::Integration::Null do
|
@@ -0,0 +1,155 @@
|
|
1
|
+
# The fork isolation is all about managing a series of systemcalls with proper error handling
|
2
|
+
#
|
3
|
+
# So creating a unit spec for this is challenging. Especially under mutation testing.
|
4
|
+
# Hence we even have to implement our own message expectation mechanism, as rspec build in
|
5
|
+
# expectations are not able to correctly specify a sequence of expectations where a specific
|
6
|
+
# message is send twice.
|
7
|
+
#
|
8
|
+
# Also our replacement for rspec-expectations used here allows easier deduplication.
|
9
|
+
RSpec.describe Mutant::Isolation::Fork do
|
10
|
+
let(:block_return) { instance_double(Object, :block_return) }
|
11
|
+
let(:block_return_blob) { instance_double(String, :block_return_blob) }
|
12
|
+
let(:devnull) { instance_double(Proc, :devnull) }
|
13
|
+
let(:io) { class_double(IO) }
|
14
|
+
let(:isolated_block) { -> { block_return } }
|
15
|
+
let(:marshal) { class_double(Marshal) }
|
16
|
+
let(:process) { class_double(Process) }
|
17
|
+
let(:pid) { class_double(Fixnum) }
|
18
|
+
let(:reader) { instance_double(IO, :reader) }
|
19
|
+
let(:stderr) { instance_double(IO, :stderr) }
|
20
|
+
let(:stdout) { instance_double(IO, :stdout) }
|
21
|
+
let(:writer) { instance_double(IO, :writer) }
|
22
|
+
let(:nullio) { instance_double(IO, :nullio) }
|
23
|
+
|
24
|
+
describe '#call' do
|
25
|
+
let(:object) do
|
26
|
+
described_class.new(
|
27
|
+
devnull: devnull,
|
28
|
+
io: io,
|
29
|
+
marshal: marshal,
|
30
|
+
process: process,
|
31
|
+
stderr: stderr,
|
32
|
+
stdout: stdout
|
33
|
+
)
|
34
|
+
end
|
35
|
+
|
36
|
+
subject { object.call(&isolated_block) }
|
37
|
+
|
38
|
+
let(:prefork_expectations) do
|
39
|
+
[
|
40
|
+
{
|
41
|
+
receiver: io,
|
42
|
+
selector: :pipe,
|
43
|
+
arguments: [binmode: true],
|
44
|
+
reaction: {
|
45
|
+
yields: [[reader, writer]]
|
46
|
+
}
|
47
|
+
}
|
48
|
+
]
|
49
|
+
end
|
50
|
+
|
51
|
+
context 'when no IO operation fails' do
|
52
|
+
let(:expectations) do
|
53
|
+
[
|
54
|
+
*prefork_expectations,
|
55
|
+
{
|
56
|
+
receiver: process,
|
57
|
+
selector: :fork,
|
58
|
+
reaction: {
|
59
|
+
yields: [],
|
60
|
+
return: pid
|
61
|
+
}
|
62
|
+
},
|
63
|
+
# Inside the killfork
|
64
|
+
{
|
65
|
+
receiver: reader,
|
66
|
+
selector: :close
|
67
|
+
},
|
68
|
+
{
|
69
|
+
receiver: writer,
|
70
|
+
selector: :binmode
|
71
|
+
},
|
72
|
+
{
|
73
|
+
receiver: devnull,
|
74
|
+
selector: :call,
|
75
|
+
reaction: {
|
76
|
+
yields: [nullio]
|
77
|
+
}
|
78
|
+
},
|
79
|
+
{
|
80
|
+
receiver: stderr,
|
81
|
+
selector: :reopen,
|
82
|
+
arguments: [nullio]
|
83
|
+
},
|
84
|
+
{
|
85
|
+
receiver: stdout,
|
86
|
+
selector: :reopen,
|
87
|
+
arguments: [nullio]
|
88
|
+
},
|
89
|
+
{
|
90
|
+
receiver: marshal,
|
91
|
+
selector: :dump,
|
92
|
+
arguments: [block_return],
|
93
|
+
reaction: {
|
94
|
+
return: block_return_blob
|
95
|
+
}
|
96
|
+
},
|
97
|
+
{
|
98
|
+
receiver: writer,
|
99
|
+
selector: :syswrite,
|
100
|
+
arguments: [block_return_blob]
|
101
|
+
},
|
102
|
+
{
|
103
|
+
receiver: writer,
|
104
|
+
selector: :close
|
105
|
+
},
|
106
|
+
# Outside the killfork
|
107
|
+
{
|
108
|
+
receiver: writer,
|
109
|
+
selector: :close
|
110
|
+
},
|
111
|
+
{
|
112
|
+
receiver: marshal,
|
113
|
+
selector: :load,
|
114
|
+
arguments: [reader],
|
115
|
+
reaction: {
|
116
|
+
return: block_return
|
117
|
+
}
|
118
|
+
},
|
119
|
+
{
|
120
|
+
receiver: process,
|
121
|
+
selector: :waitpid,
|
122
|
+
arguments: [pid]
|
123
|
+
}
|
124
|
+
].map(&XSpec::MessageExpectation.method(:parse))
|
125
|
+
end
|
126
|
+
|
127
|
+
specify do
|
128
|
+
XSpec::ExpectationVerifier.verify(self, expectations) do
|
129
|
+
expect(subject).to be(block_return)
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
context 'when fork fails' do
|
135
|
+
let(:expectations) do
|
136
|
+
[
|
137
|
+
*prefork_expectations,
|
138
|
+
{
|
139
|
+
receiver: process,
|
140
|
+
selector: :fork,
|
141
|
+
reaction: {
|
142
|
+
exception: RuntimeError.new('fork(2)')
|
143
|
+
}
|
144
|
+
}
|
145
|
+
].map(&XSpec::MessageExpectation.method(:parse))
|
146
|
+
end
|
147
|
+
|
148
|
+
specify do
|
149
|
+
XSpec::ExpectationVerifier.verify(self, expectations) do
|
150
|
+
expect { expect(subject) }.to raise_error(described_class::Error, 'fork(2)')
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
RSpec.describe Mutant::Isolation::None do
|
2
|
+
describe '.call' do
|
3
|
+
let(:object) { described_class.new }
|
4
|
+
|
5
|
+
it 'return block value' do
|
6
|
+
expect(object.call { :foo }).to be(:foo)
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'wraps *all* exceptions' do
|
10
|
+
expect { object.call { fail 'foo' } }.to raise_error(
|
11
|
+
Mutant::Isolation::Error,
|
12
|
+
'foo'
|
13
|
+
)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -11,7 +11,7 @@ RSpec.describe Mutant::Loader, '.call' do
|
|
11
11
|
let(:path) { instance_double(Pathname, to_s: path_str) }
|
12
12
|
let(:path_str) { instance_double(String) }
|
13
13
|
let(:line) { instance_double(Fixnum) }
|
14
|
-
let(:kernel) {
|
14
|
+
let(:kernel) { class_double(Kernel) }
|
15
15
|
let(:binding) { instance_double(Binding) }
|
16
16
|
let(:source) { instance_double(String) }
|
17
17
|
let(:node) { instance_double(Parser::AST::Node) }
|
@@ -16,17 +16,15 @@ RSpec.describe Mutant::Matcher::Methods::Instance, '#call' do
|
|
16
16
|
|
17
17
|
private :method_d
|
18
18
|
|
19
|
-
public
|
20
|
-
|
21
19
|
def method_a
|
22
20
|
end
|
23
21
|
|
24
|
-
|
22
|
+
protected
|
25
23
|
|
26
24
|
def method_b
|
27
25
|
end
|
28
26
|
|
29
|
-
|
27
|
+
private
|
30
28
|
|
31
29
|
def method_c
|
32
30
|
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
RSpec.describe Mutant::Meta::Example::DSL do
|
2
|
+
describe '.call' do
|
3
|
+
subject { described_class.call(file, type, block) }
|
4
|
+
|
5
|
+
let(:file) { 'foo.rb' }
|
6
|
+
let(:node) { s(:false) }
|
7
|
+
let(:type) { node.type }
|
8
|
+
let(:expected) { [] }
|
9
|
+
|
10
|
+
let(:expected_example) do
|
11
|
+
Mutant::Meta::Example.new(
|
12
|
+
file: file,
|
13
|
+
node: node,
|
14
|
+
node_type: type,
|
15
|
+
expected: expected
|
16
|
+
)
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.expect_example(&block)
|
20
|
+
let(:block) { block }
|
21
|
+
|
22
|
+
specify do
|
23
|
+
# Kill mutations to warnings
|
24
|
+
warnings = Mutant::WarningFilter.use do
|
25
|
+
should eql(expected_example)
|
26
|
+
end
|
27
|
+
expect(warnings).to eql([])
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.expect_error(message, &block)
|
32
|
+
let(:block) { block }
|
33
|
+
|
34
|
+
specify do
|
35
|
+
expect { subject }.to raise_error(RuntimeError, message)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
context 'source as node' do
|
40
|
+
expect_example do
|
41
|
+
source s(:false)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
context 'source as string' do
|
46
|
+
expect_example do
|
47
|
+
source 'false'
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
context 'on node that needs unparser preprocessing to be normalized' do
|
52
|
+
let(:node) { s(:send, s(:float, -1.0), :/, s(:float, 0.0)) }
|
53
|
+
|
54
|
+
expect_example do
|
55
|
+
source '(-1.0) / 0.0'
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
context 'using #mutation' do
|
60
|
+
let(:expected) { [s(:nil)] }
|
61
|
+
|
62
|
+
expect_example do
|
63
|
+
source 'false'
|
64
|
+
|
65
|
+
mutation 'nil'
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
context 'using #singleton_mutations' do
|
70
|
+
let(:expected) { [s(:nil), s(:self)] }
|
71
|
+
|
72
|
+
expect_example do
|
73
|
+
source 'false'
|
74
|
+
|
75
|
+
singleton_mutations
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
context 'no definition of source' do
|
80
|
+
expect_error('source not defined') do
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
context 'duplicate definition of source' do
|
85
|
+
expect_error('source already defined') do
|
86
|
+
source 'true'
|
87
|
+
source 'false'
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
context 'uncoercable source' do
|
92
|
+
expect_error('Cannot coerce to node: nil') do
|
93
|
+
source nil
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
context 'duplicate mutation expectation' do
|
98
|
+
expect_error('Mutation for input: "true" is already expected') do
|
99
|
+
source 'false'
|
100
|
+
|
101
|
+
mutation 'true'
|
102
|
+
mutation 'true'
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|