mutest 0.0.3 → 0.0.4
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/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
|