mutest 0.0.3 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -3
- data/Rakefile +1 -1
- data/config/flay.yml +1 -1
- data/lib/mutest/ast/regexp/transformer/quantifier.rb +30 -8
- data/lib/mutest/env/bootstrap.rb +1 -1
- data/lib/mutest/mutator/node.rb +0 -7
- data/lib/mutest/mutator/node/define.rb +7 -3
- data/lib/mutest/mutator/node/regexp/one_or_more.rb +6 -1
- data/lib/mutest/mutator/node/send.rb +8 -5
- data/lib/mutest/version.rb +1 -1
- data/meta/def.rb +10 -0
- data/meta/kwoptarg.rb +4 -4
- data/meta/kwrestarg.rb +8 -0
- data/meta/restarg.rb +8 -0
- data/meta/send.rb +31 -2
- data/mutest.gemspec +0 -1
- data/spec/unit/mutest/ast/regexp_spec.rb +29 -0
- data/spec/unit/mutest/context_spec.rb +10 -0
- metadata +2 -17
- data/spec/support/rb_bug.rb +0 -15
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 882e92ac10cfa19bf05b12f38997801b2fced697
|
4
|
+
data.tar.gz: e73ae60634c05d15a3ecc32e3162f2d6d4d1f8ed
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 489fefd9e304924294d8f2176e875939960d78a39ac01f3f795294719cfe4284919358cebc9c20a6095f6aaff500fe417524a755d117185acc5b622aa018a66b
|
7
|
+
data.tar.gz: 6729e041f46105175f37d425f2fad5c774d7f05151557258260e5f9030cb86c374c9f4609e2bd82694dfd408ab9d10fc20199f34d1047787292af3d71d9a3ea9
|
data/Gemfile.lock
CHANGED
@@ -35,7 +35,7 @@ GIT
|
|
35
35
|
PATH
|
36
36
|
remote: .
|
37
37
|
specs:
|
38
|
-
mutest (0.0.
|
38
|
+
mutest (0.0.3)
|
39
39
|
abstract_type (~> 0.0.7)
|
40
40
|
adamantium (~> 0.2.0)
|
41
41
|
anima (~> 0.3.0)
|
@@ -101,7 +101,6 @@ GEM
|
|
101
101
|
docile (1.1.5)
|
102
102
|
equalizer (0.0.11)
|
103
103
|
erubis (2.7.0)
|
104
|
-
ffi (1.9.17)
|
105
104
|
flay (2.8.1)
|
106
105
|
erubis (~> 2.7.0)
|
107
106
|
path_expander (~> 1.0)
|
@@ -204,7 +203,6 @@ PLATFORMS
|
|
204
203
|
DEPENDENCIES
|
205
204
|
bundler (~> 1.10)
|
206
205
|
devtools (~> 0.1.16)
|
207
|
-
ffi (~> 1.9.6)
|
208
206
|
mutant!
|
209
207
|
mutest!
|
210
208
|
pry (~> 0.10)
|
data/Rakefile
CHANGED
data/config/flay.yml
CHANGED
@@ -61,7 +61,7 @@ module Mutest
|
|
61
61
|
# @return [String]
|
62
62
|
def text
|
63
63
|
if type.equal?(:interval)
|
64
|
-
|
64
|
+
Interval.new(min, max).to_s + suffix
|
65
65
|
else
|
66
66
|
suffix
|
67
67
|
end
|
@@ -95,13 +95,35 @@ module Mutest
|
|
95
95
|
QUANTIFIER_MAP.fetch(node.type)
|
96
96
|
end
|
97
97
|
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
98
|
+
class Interval
|
99
|
+
include Concord.new(:min, :max)
|
100
|
+
|
101
|
+
def initialize(*)
|
102
|
+
super
|
103
|
+
|
104
|
+
unless valid_min? && valid_max?
|
105
|
+
fail ArgumentError, 'Unexpected quantifier interval bound.'
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def to_s
|
110
|
+
"{#{compacted_interval.join(',')}}"
|
111
|
+
end
|
112
|
+
|
113
|
+
private
|
114
|
+
|
115
|
+
def compacted_interval
|
116
|
+
[min, max].map { |bound| bound if bound > 0 }.uniq
|
117
|
+
end
|
118
|
+
|
119
|
+
def valid_min?
|
120
|
+
min >= 0
|
121
|
+
end
|
122
|
+
|
123
|
+
def valid_max?
|
124
|
+
max > 0 || max.equal?(-1)
|
125
|
+
end
|
126
|
+
end # Interval
|
105
127
|
end # ASTToExpression
|
106
128
|
|
107
129
|
ASTToExpression::QUANTIFIER_MAP.keys.each(&method(:register))
|
data/lib/mutest/env/bootstrap.rb
CHANGED
@@ -150,7 +150,7 @@ module Mutest
|
|
150
150
|
# Write a semantics warning
|
151
151
|
#
|
152
152
|
# @return [undefined]
|
153
|
-
def semantics_warning(format, options)
|
153
|
+
def semantics_warning(format, **options)
|
154
154
|
message = format % options
|
155
155
|
warn(format(SEMANTICS_MESSAGE_FORMAT, message: message))
|
156
156
|
end
|
data/lib/mutest/mutator/node.rb
CHANGED
@@ -40,13 +40,6 @@ module Mutest
|
|
40
40
|
# @return [Parser::AST::Node]
|
41
41
|
alias_method :dup_node, :dup_input
|
42
42
|
|
43
|
-
# Original nodes children
|
44
|
-
#
|
45
|
-
# @return [Array<Parser::AST::Node>]
|
46
|
-
def children
|
47
|
-
node.children
|
48
|
-
end
|
49
|
-
|
50
43
|
# Dispatch on child index
|
51
44
|
#
|
52
45
|
# @param [Fixnum] index
|
@@ -22,8 +22,8 @@ module Mutest
|
|
22
22
|
#
|
23
23
|
# @return [undefined]
|
24
24
|
def emit_optarg_body_assignments
|
25
|
-
|
26
|
-
next unless n_optarg?(argument)
|
25
|
+
used_arguments.each do |argument|
|
26
|
+
next unless n_optarg?(argument)
|
27
27
|
|
28
28
|
emit_body_prepend(s(:lvasgn, *argument))
|
29
29
|
end
|
@@ -33,7 +33,7 @@ module Mutest
|
|
33
33
|
#
|
34
34
|
# @return [undefined]
|
35
35
|
def emit_restarg_body_mutation
|
36
|
-
|
36
|
+
used_arguments.each do |argument|
|
37
37
|
replacement =
|
38
38
|
if n_restarg?(argument)
|
39
39
|
s(:array)
|
@@ -47,6 +47,10 @@ module Mutest
|
|
47
47
|
end
|
48
48
|
end
|
49
49
|
|
50
|
+
def used_arguments
|
51
|
+
arguments.children.select { |arg| AST::Meta::Optarg.new(arg).used? }
|
52
|
+
end
|
53
|
+
|
50
54
|
# Emit valid body ASTs depending on instance body
|
51
55
|
#
|
52
56
|
# @param node [Parser::AST::Node]
|
@@ -10,6 +10,9 @@ module Mutest
|
|
10
10
|
regexp_possessive_one_or_more: :regexp_possessive_interval
|
11
11
|
)
|
12
12
|
|
13
|
+
# -1 marks an infinite upper bound
|
14
|
+
UNBOUNDED = -1
|
15
|
+
|
13
16
|
handle(*MAP.keys)
|
14
17
|
|
15
18
|
children :min, :max, :subject
|
@@ -18,10 +21,12 @@ module Mutest
|
|
18
21
|
#
|
19
22
|
# @return [undefined]
|
20
23
|
def dispatch
|
21
|
-
emit(s(MAP.fetch(node.type), 2,
|
24
|
+
emit(s(MAP.fetch(node.type), 2, UNBOUNDED, subject))
|
22
25
|
emit_subject_mutations
|
23
26
|
emit(subject)
|
24
27
|
end
|
28
|
+
|
29
|
+
private_constant(*constants(false))
|
25
30
|
end # OneOrMore
|
26
31
|
end # Regexp
|
27
32
|
end # Node
|
@@ -13,11 +13,11 @@ module Mutest
|
|
13
13
|
SELECTOR_REPLACEMENTS = IceNine.deep_freeze(
|
14
14
|
__send__: %i[public_send],
|
15
15
|
:[] => %i[at fetch key?],
|
16
|
-
:< => %i[==
|
16
|
+
:< => %i[== eql? equal?],
|
17
17
|
:<= => %i[< == eql? equal?],
|
18
18
|
:== => %i[eql? equal?],
|
19
19
|
:=== => %i[kind_of?],
|
20
|
-
:> => %i[==
|
20
|
+
:> => %i[== eql? equal?],
|
21
21
|
:>= => %i[> == eql? equal?],
|
22
22
|
'=~': %i[match?],
|
23
23
|
at: %i[fetch key?],
|
@@ -174,7 +174,7 @@ module Mutest
|
|
174
174
|
#
|
175
175
|
# @return [undefined]
|
176
176
|
def emit_drop_mutation
|
177
|
-
return if !selector.equal?(:[]) || !arguments.one? || !n_irange?(arguments
|
177
|
+
return if !selector.equal?(:[]) || !arguments.one? || !n_irange?(Mutest::Util.one(arguments))
|
178
178
|
|
179
179
|
start, ending = *arguments.first
|
180
180
|
|
@@ -239,8 +239,11 @@ module Mutest
|
|
239
239
|
#
|
240
240
|
# @return [undefined]
|
241
241
|
def emit_argument_propagation
|
242
|
-
|
243
|
-
|
242
|
+
return unless arguments.one?
|
243
|
+
|
244
|
+
node = Mutest::Util.one(arguments)
|
245
|
+
|
246
|
+
emit(node) unless NOT_STANDALONE.include?(node.type)
|
244
247
|
end
|
245
248
|
|
246
249
|
# Emit receiver mutations
|
data/lib/mutest/version.rb
CHANGED
data/meta/def.rb
CHANGED
@@ -15,6 +15,16 @@ Mutest::Meta::Example.add :def do
|
|
15
15
|
mutation 'def foo(a); super; end'
|
16
16
|
end
|
17
17
|
|
18
|
+
Mutest::Meta::Example.add :def do
|
19
|
+
source 'def foo(**bar); end'
|
20
|
+
|
21
|
+
mutation 'def foo; end'
|
22
|
+
mutation 'def foo(**_bar); end'
|
23
|
+
mutation 'def foo(**bar); bar = {}; end'
|
24
|
+
mutation 'def foo(**bar); raise; end'
|
25
|
+
mutation 'def foo(**bar); super; end'
|
26
|
+
end
|
27
|
+
|
18
28
|
Mutest::Meta::Example.add :def do
|
19
29
|
source 'def foo(a = {}); end'
|
20
30
|
|
data/meta/kwoptarg.rb
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
Mutest::Meta::Example.add :kwarg do
|
2
|
-
source 'def foo(bar:
|
2
|
+
source 'def foo(bar: {}); end'
|
3
3
|
|
4
4
|
mutation 'def foo; end'
|
5
|
-
mutation 'def foo(bar:
|
6
|
-
mutation 'def foo(bar:
|
5
|
+
mutation 'def foo(bar: {}); raise; end'
|
6
|
+
mutation 'def foo(bar: {}); super; end'
|
7
7
|
mutation 'def foo(bar: nil); end'
|
8
8
|
mutation 'def foo(bar: self); end'
|
9
9
|
mutation 'def foo(bar:); end'
|
10
|
-
mutation 'def foo(_bar:
|
10
|
+
mutation 'def foo(_bar: {}); end'
|
11
11
|
end
|
data/meta/kwrestarg.rb
CHANGED
@@ -8,6 +8,14 @@ Mutest::Meta::Example.add :kwrestarg do
|
|
8
8
|
mutation 'def foo(**bar); super; end'
|
9
9
|
end
|
10
10
|
|
11
|
+
Mutest::Meta::Example.add :kwrestarg do
|
12
|
+
source 'def foo(**_bar); end'
|
13
|
+
|
14
|
+
mutation 'def foo; end'
|
15
|
+
mutation 'def foo(**_bar); raise; end'
|
16
|
+
mutation 'def foo(**_bar); super; end'
|
17
|
+
end
|
18
|
+
|
11
19
|
Mutest::Meta::Example.add :kwrestarg do
|
12
20
|
source 'def foo(**); end'
|
13
21
|
|
data/meta/restarg.rb
CHANGED
@@ -7,3 +7,11 @@ Mutest::Meta::Example.add :restarg do
|
|
7
7
|
mutation 'def foo(*bar); raise; end'
|
8
8
|
mutation 'def foo(*bar); super; end'
|
9
9
|
end
|
10
|
+
|
11
|
+
Mutest::Meta::Example.add :restarg do
|
12
|
+
source 'def foo(*_bar); end'
|
13
|
+
|
14
|
+
mutation 'def foo; end'
|
15
|
+
mutation 'def foo(*_bar); raise; end'
|
16
|
+
mutation 'def foo(*_bar); super; end'
|
17
|
+
end
|
data/meta/send.rb
CHANGED
@@ -3,7 +3,6 @@ Mutest::Meta::Example.add :send do
|
|
3
3
|
|
4
4
|
singleton_mutations
|
5
5
|
mutation 'a == b'
|
6
|
-
mutation 'a >= b'
|
7
6
|
mutation 'a.eql?(b)'
|
8
7
|
mutation 'a.equal?(b)'
|
9
8
|
mutation 'nil > b'
|
@@ -28,6 +27,37 @@ Mutest::Meta::Example.add :send do
|
|
28
27
|
mutation 'self.const_get(:B)'
|
29
28
|
end
|
30
29
|
|
30
|
+
Mutest::Meta::Example.add :send do
|
31
|
+
source 'A.const_get(:B, true)'
|
32
|
+
|
33
|
+
singleton_mutations
|
34
|
+
mutation 'A'
|
35
|
+
mutation 'A::B'
|
36
|
+
mutation 'self.const_get(:B, true)'
|
37
|
+
mutation 'A.const_get'
|
38
|
+
mutation 'A.const_get(nil, true)'
|
39
|
+
mutation 'A.const_get(self, true)'
|
40
|
+
mutation 'A.const_get(:B__mutest__, true)'
|
41
|
+
mutation 'A.const_get(true)'
|
42
|
+
mutation 'A.const_get(:B, nil)'
|
43
|
+
mutation 'A.const_get(:B, false)'
|
44
|
+
mutation 'A.const_get(:B)'
|
45
|
+
end
|
46
|
+
|
47
|
+
Mutest::Meta::Example.add :send do
|
48
|
+
source 'A.const_get(:B)'
|
49
|
+
|
50
|
+
singleton_mutations
|
51
|
+
mutation 'A::B'
|
52
|
+
mutation 'A.const_get'
|
53
|
+
mutation 'A'
|
54
|
+
mutation ':B'
|
55
|
+
mutation 'A.const_get(nil)'
|
56
|
+
mutation 'A.const_get(self)'
|
57
|
+
mutation 'A.const_get(:B__mutest__)'
|
58
|
+
mutation 'self.const_get(:B)'
|
59
|
+
end
|
60
|
+
|
31
61
|
Mutest::Meta::Example.add :send do
|
32
62
|
source 'A.const_get(bar)'
|
33
63
|
|
@@ -88,7 +118,6 @@ Mutest::Meta::Example.add :send do
|
|
88
118
|
|
89
119
|
singleton_mutations
|
90
120
|
mutation 'a == b'
|
91
|
-
mutation 'a <= b'
|
92
121
|
mutation 'a.eql?(b)'
|
93
122
|
mutation 'a.equal?(b)'
|
94
123
|
mutation 'nil < b'
|
data/mutest.gemspec
CHANGED
@@ -41,5 +41,4 @@ Gem::Specification.new do |gem|
|
|
41
41
|
gem.add_development_dependency('rubocop-rspec', '~> 1.10.0')
|
42
42
|
gem.add_development_dependency('devtools', '~> 0.1.16')
|
43
43
|
gem.add_development_dependency('bundler', '~> 1.10')
|
44
|
-
gem.add_development_dependency('ffi', '~> 1.9.6')
|
45
44
|
end
|
@@ -623,3 +623,32 @@ RegexpSpec.expect_mapping(/\*/, :regexp_zero_or_more_escape) do
|
|
623
623
|
s(:regexp_root_expression,
|
624
624
|
s(:regexp_zero_or_more_escape))
|
625
625
|
end
|
626
|
+
|
627
|
+
RSpec.describe Mutest::AST::Regexp::Transformer::Quantifier do # rubocop:disable RSpec/FilePath
|
628
|
+
def regexp(lower_bound, upper_bound)
|
629
|
+
sexp =
|
630
|
+
s(:regexp_root_expression,
|
631
|
+
s(:regexp_greedy_interval, lower_bound, upper_bound,
|
632
|
+
s(:regexp_literal_literal, 'a')))
|
633
|
+
|
634
|
+
Mutest::AST::Regexp.to_expression(sexp).to_re
|
635
|
+
end
|
636
|
+
|
637
|
+
shared_examples 'an invalid quantifier range' do |lower_bound, upper_bound|
|
638
|
+
it 'raises an error' do
|
639
|
+
expect { regexp(lower_bound, upper_bound) }
|
640
|
+
.to raise_error(ArgumentError, 'Unexpected quantifier interval bound.')
|
641
|
+
end
|
642
|
+
end
|
643
|
+
|
644
|
+
include_examples 'an invalid quantifier range', -1, 1
|
645
|
+
include_examples 'an invalid quantifier range', 1, 0
|
646
|
+
|
647
|
+
it 'treats 0 as a sentinel value' do
|
648
|
+
expect(regexp(0, 1)).to eql(/a{,1}/)
|
649
|
+
end
|
650
|
+
|
651
|
+
it 'treats -1 as a sentinel value' do
|
652
|
+
expect(regexp(1, -1)).to eql(/a{1,}/)
|
653
|
+
end
|
654
|
+
end
|
@@ -110,6 +110,16 @@ RSpec.describe Mutest::Context do
|
|
110
110
|
end
|
111
111
|
end
|
112
112
|
|
113
|
+
describe '#source_path' do
|
114
|
+
let(:source_file) do
|
115
|
+
instance_double(Mutest::SourceFile, path: instance_double(Pathname))
|
116
|
+
end
|
117
|
+
|
118
|
+
it 'exposes source file path' do
|
119
|
+
expect(described_class.new(scope, source_file).source_path).to be(source_file.path)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
113
123
|
describe '#ignore?' do
|
114
124
|
let(:object) do
|
115
125
|
described_class.new(scope, source_file)
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mutest
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Daniel Gollahon
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2017-
|
12
|
+
date: 2017-02-16 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: parser
|
@@ -269,20 +269,6 @@ dependencies:
|
|
269
269
|
- - "~>"
|
270
270
|
- !ruby/object:Gem::Version
|
271
271
|
version: '1.10'
|
272
|
-
- !ruby/object:Gem::Dependency
|
273
|
-
name: ffi
|
274
|
-
requirement: !ruby/object:Gem::Requirement
|
275
|
-
requirements:
|
276
|
-
- - "~>"
|
277
|
-
- !ruby/object:Gem::Version
|
278
|
-
version: 1.9.6
|
279
|
-
type: :development
|
280
|
-
prerelease: false
|
281
|
-
version_requirements: !ruby/object:Gem::Requirement
|
282
|
-
requirements:
|
283
|
-
- - "~>"
|
284
|
-
- !ruby/object:Gem::Version
|
285
|
-
version: 1.9.6
|
286
272
|
description: Mutation testing for ruby
|
287
273
|
email:
|
288
274
|
- johncbackus@gmail.com
|
@@ -581,7 +567,6 @@ files:
|
|
581
567
|
- spec/support/fake_actor.rb
|
582
568
|
- spec/support/file_system.rb
|
583
569
|
- spec/support/ice_nine_config.rb
|
584
|
-
- spec/support/rb_bug.rb
|
585
570
|
- spec/support/ruby_vm.rb
|
586
571
|
- spec/support/shared_context.rb
|
587
572
|
- spec/support/test_app.rb
|
data/spec/support/rb_bug.rb
DELETED
@@ -1,15 +0,0 @@
|
|
1
|
-
require 'ffi'
|
2
|
-
|
3
|
-
# @api private
|
4
|
-
module RbBug
|
5
|
-
extend FFI::Library
|
6
|
-
ffi_lib 'ruby'
|
7
|
-
attach_function :rb_bug, %i[string varargs], :void
|
8
|
-
|
9
|
-
# Call the test bug
|
10
|
-
#
|
11
|
-
# @return [undefined]
|
12
|
-
def self.call
|
13
|
-
rb_bug('%s', :string, 'test bug')
|
14
|
-
end
|
15
|
-
end # RbBug
|