mutant 0.9.3 → 0.9.8
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/.github/workflows/ci.yml +121 -0
- data/Changelog.md +24 -0
- data/Gemfile +0 -15
- data/Gemfile.lock +56 -59
- data/Gemfile.shared +7 -0
- data/LICENSE +1 -1
- data/README.md +10 -1
- data/config/rubocop.yml +10 -3
- data/docs/commercial-support.md +14 -0
- data/lib/mutant.rb +4 -2
- data/lib/mutant/cli.rb +5 -5
- data/lib/mutant/integration.rb +1 -1
- data/lib/mutant/license.rb +2 -2
- data/lib/mutant/license/subscription/opensource.rb +1 -1
- data/lib/mutant/meta.rb +1 -3
- data/lib/mutant/meta/example/verification.rb +1 -1
- data/lib/mutant/mutator/node/generic.rb +0 -48
- data/lib/mutant/mutator/node/send.rb +1 -1
- data/lib/mutant/parallel.rb +1 -1
- data/lib/mutant/registry.rb +2 -7
- data/lib/mutant/reporter/cli/format.rb +1 -1
- data/lib/mutant/transform.rb +6 -5
- data/lib/mutant/version.rb +1 -1
- data/lib/mutant/zombifier.rb +2 -0
- data/mutant.gemspec +15 -13
- data/spec/integrations.yml +3 -1
- data/spec/support/corpus.rb +3 -3
- data/spec/support/ruby_vm.rb +1 -2
- data/spec/support/shared_context.rb +3 -3
- data/spec/support/xspec.rb +2 -2
- data/spec/unit/mutant/license_spec.rb +2 -2
- data/spec/unit/mutant/parallel/driver_spec.rb +4 -4
- data/spec/unit/mutant/parallel/worker_spec.rb +5 -5
- data/spec/unit/mutant/parallel_spec.rb +7 -7
- data/spec/unit/mutant/registry_spec.rb +52 -25
- data/spec/unit/mutant/repository/diff/ranges_spec.rb +2 -2
- metadata +44 -23
- data/.circleci/config.yml +0 -53
- data/lib/mutant/base.rb +0 -192
- data/lib/mutant/variable.rb +0 -282
- data/spec/unit/mutant/either_spec.rb +0 -247
- data/spec/unit/mutant/maybe_spec.rb +0 -60
- data/spec/unit/mutant/variable_spec.rb +0 -618
@@ -0,0 +1,14 @@
|
|
1
|
+
# Commercial Support
|
2
|
+
|
3
|
+
Mutant offers only community support.
|
4
|
+
|
5
|
+
Commercial license customers are entited to priority support via email.
|
6
|
+
|
7
|
+
## Priority Support
|
8
|
+
|
9
|
+
Covers 1 incident per quarter, with a max response time of 7 days.
|
10
|
+
Scope is limited to mutant not the application or infrastructure.
|
11
|
+
|
12
|
+
For support email [Markus Schirp](mailto:mbj@schirp-dso.com?subject=Mutant%20Support).
|
13
|
+
Please email using the same domain as the roiginal license email or explain
|
14
|
+
your connection to the license.
|
data/lib/mutant.rb
CHANGED
@@ -10,6 +10,7 @@ require 'digest/sha1'
|
|
10
10
|
require 'equalizer'
|
11
11
|
require 'etc'
|
12
12
|
require 'ice_nine'
|
13
|
+
require 'mprelude'
|
13
14
|
require 'json'
|
14
15
|
require 'open3'
|
15
16
|
require 'optparse'
|
@@ -20,6 +21,7 @@ require 'set'
|
|
20
21
|
require 'singleton'
|
21
22
|
require 'stringio'
|
22
23
|
require 'unparser'
|
24
|
+
require 'variable'
|
23
25
|
require 'yaml'
|
24
26
|
|
25
27
|
# This setting is done to make errors within the parallel
|
@@ -30,13 +32,14 @@ Thread.abort_on_exception = true
|
|
30
32
|
#
|
31
33
|
# @api private
|
32
34
|
module Mutant
|
35
|
+
Either = MPrelude::Either
|
36
|
+
|
33
37
|
EMPTY_STRING = ''
|
34
38
|
EMPTY_ARRAY = [].freeze
|
35
39
|
EMPTY_HASH = {}.freeze
|
36
40
|
SCOPE_OPERATOR = '::'
|
37
41
|
end # Mutant
|
38
42
|
|
39
|
-
require 'mutant/base'
|
40
43
|
require 'mutant/bootstrap'
|
41
44
|
require 'mutant/version'
|
42
45
|
require 'mutant/env'
|
@@ -183,7 +186,6 @@ require 'mutant/reporter/cli/format'
|
|
183
186
|
require 'mutant/repository'
|
184
187
|
require 'mutant/repository/diff'
|
185
188
|
require 'mutant/repository/diff/ranges'
|
186
|
-
require 'mutant/variable'
|
187
189
|
require 'mutant/warnings'
|
188
190
|
require 'mutant/zombifier'
|
189
191
|
require 'mutant/range'
|
data/lib/mutant/cli.rb
CHANGED
@@ -36,10 +36,10 @@ module Mutant
|
|
36
36
|
def self.run(world, default_config, arguments)
|
37
37
|
License
|
38
38
|
.apply(world)
|
39
|
-
.
|
40
|
-
.
|
41
|
-
.
|
42
|
-
.
|
39
|
+
.bind { Config.load_config_file(world, default_config) }
|
40
|
+
.bind { |file_config| apply(world, file_config, arguments) }
|
41
|
+
.bind { |cli_config| Bootstrap.apply(world, cli_config) }
|
42
|
+
.bind(&Runner.method(:apply))
|
43
43
|
.from_right { |error| world.stderr.puts(error); return false }
|
44
44
|
.success?
|
45
45
|
end
|
@@ -105,7 +105,7 @@ module Mutant
|
|
105
105
|
#
|
106
106
|
# @return [undefined]
|
107
107
|
#
|
108
|
-
# rubocop:disable MethodLength
|
108
|
+
# rubocop:disable Metrics/MethodLength
|
109
109
|
def add_environment_options(opts)
|
110
110
|
opts.separator('Environment:')
|
111
111
|
opts.on('--zombie', 'Run mutant zombified') do
|
data/lib/mutant/integration.rb
CHANGED
data/lib/mutant/license.rb
CHANGED
@@ -4,7 +4,7 @@ module Mutant
|
|
4
4
|
module License
|
5
5
|
NAME = 'mutant-license'
|
6
6
|
VERSION = '~> 0.1.0'
|
7
|
-
SLEEP =
|
7
|
+
SLEEP = 40
|
8
8
|
|
9
9
|
UNLICENSED =
|
10
10
|
IceNine.deep_freeze(
|
@@ -23,7 +23,7 @@ module Mutant
|
|
23
23
|
load_mutant_license(world)
|
24
24
|
.fmap { license_path(world) }
|
25
25
|
.fmap { |path| Subscription.from_json(world.json.load(path)) }
|
26
|
-
.
|
26
|
+
.bind { |sub| sub.apply(world) }
|
27
27
|
end
|
28
28
|
private_class_method :license_result
|
29
29
|
|
data/lib/mutant/meta.rb
CHANGED
@@ -10,14 +10,12 @@ module Mutant
|
|
10
10
|
# Mutation example
|
11
11
|
class Example
|
12
12
|
|
13
|
-
# rubocop:disable MutableConstant
|
13
|
+
# rubocop:disable Style/MutableConstant
|
14
14
|
ALL = []
|
15
15
|
|
16
16
|
# Add example
|
17
17
|
#
|
18
18
|
# @return [undefined]
|
19
|
-
#
|
20
|
-
# rubocop:disable Performance/Caller
|
21
19
|
def self.add(*types, &block)
|
22
20
|
file = caller.first.split(':in', 2).first
|
23
21
|
ALL << DSL.call(file, Set.new(types), block)
|
@@ -61,7 +61,7 @@ module Mutant
|
|
61
61
|
def invalid_syntax
|
62
62
|
mutations.reject do |mutation|
|
63
63
|
::Parser::CurrentRuby.parse(mutation.source)
|
64
|
-
rescue ::Parser::SyntaxError # rubocop:disable Lint/
|
64
|
+
rescue ::Parser::SyntaxError # rubocop:disable Lint/SuppressedException
|
65
65
|
end
|
66
66
|
end
|
67
67
|
memoize :invalid_syntax
|
@@ -3,57 +3,9 @@
|
|
3
3
|
module Mutant
|
4
4
|
class Mutator
|
5
5
|
class Node
|
6
|
-
|
7
6
|
# Generic mutator
|
8
7
|
class Generic < self
|
9
8
|
|
10
|
-
unsupported_nodes = %i[
|
11
|
-
__FILE__
|
12
|
-
__LINE__
|
13
|
-
alias
|
14
|
-
arg_expr
|
15
|
-
back_ref
|
16
|
-
blockarg
|
17
|
-
blockarg_expr
|
18
|
-
complex
|
19
|
-
eflipflop
|
20
|
-
empty
|
21
|
-
ensure
|
22
|
-
for
|
23
|
-
ident
|
24
|
-
iflipflop
|
25
|
-
kwnilarg
|
26
|
-
kwrestarg
|
27
|
-
kwsplat
|
28
|
-
match_with_lvasgn
|
29
|
-
meth_ref
|
30
|
-
module
|
31
|
-
numargs
|
32
|
-
numblock
|
33
|
-
numparam
|
34
|
-
objc_kwarg
|
35
|
-
objc_restarg
|
36
|
-
objc_varargs
|
37
|
-
postexe
|
38
|
-
preexe
|
39
|
-
rational
|
40
|
-
redo
|
41
|
-
restarg
|
42
|
-
restarg_expr
|
43
|
-
retry
|
44
|
-
root
|
45
|
-
sclass
|
46
|
-
shadowarg
|
47
|
-
undef
|
48
|
-
until_post
|
49
|
-
while_post
|
50
|
-
xstr
|
51
|
-
]
|
52
|
-
|
53
|
-
# These nodes still need a dedicated mutator,
|
54
|
-
# your contribution is that close!
|
55
|
-
handle(*unsupported_nodes)
|
56
|
-
|
57
9
|
private
|
58
10
|
|
59
11
|
# Emit mutations
|
data/lib/mutant/parallel.rb
CHANGED
data/lib/mutant/registry.rb
CHANGED
@@ -32,14 +32,9 @@ module Mutant
|
|
32
32
|
#
|
33
33
|
# @param [Symbol] type
|
34
34
|
#
|
35
|
-
# @return [Class]
|
36
|
-
#
|
37
|
-
# @raise [ArgumentError]
|
38
|
-
# raises argument error when class cannot be found
|
35
|
+
# @return [Class<Mutator>]
|
39
36
|
def lookup(type)
|
40
|
-
contents.fetch(type)
|
41
|
-
fail RegistryError, "No entry for: #{type.inspect}"
|
42
|
-
end
|
37
|
+
contents.fetch(type, Mutator::Node::Generic)
|
43
38
|
end
|
44
39
|
|
45
40
|
end # Registry
|
data/lib/mutant/transform.rb
CHANGED
@@ -263,7 +263,7 @@ module Mutant
|
|
263
263
|
PRIMITIVE
|
264
264
|
.apply(input)
|
265
265
|
.lmap(&method(:lift_error))
|
266
|
-
.
|
266
|
+
.bind(&method(:run))
|
267
267
|
end
|
268
268
|
|
269
269
|
private
|
@@ -351,8 +351,8 @@ module Mutant
|
|
351
351
|
PRIMITIVE
|
352
352
|
.apply(input)
|
353
353
|
.lmap(&method(:lift_error))
|
354
|
-
.
|
355
|
-
.
|
354
|
+
.bind(&method(:reject_keys))
|
355
|
+
.bind(&method(:transform))
|
356
356
|
end
|
357
357
|
|
358
358
|
private
|
@@ -363,7 +363,7 @@ module Mutant
|
|
363
363
|
#
|
364
364
|
# @return [Either<Error, Hash>]
|
365
365
|
def transform(input)
|
366
|
-
transform_required(input).
|
366
|
+
transform_required(input).bind do |required|
|
367
367
|
transform_optional(input).fmap(&required.method(:merge))
|
368
368
|
end
|
369
369
|
end
|
@@ -503,7 +503,8 @@ module Mutant
|
|
503
503
|
#
|
504
504
|
# @return [Either<Error, Object>]
|
505
505
|
def apply(input)
|
506
|
-
Either
|
506
|
+
Either
|
507
|
+
.wrap_error(error_class) { block.call(input) }
|
507
508
|
.lmap { |exception| error(input: input, message: exception.to_s) }
|
508
509
|
end
|
509
510
|
end # Exception
|
data/lib/mutant/version.rb
CHANGED
data/lib/mutant/zombifier.rb
CHANGED
data/mutant.gemspec
CHANGED
@@ -21,19 +21,21 @@ Gem::Specification.new do |gem|
|
|
21
21
|
gem.extra_rdoc_files = %w[LICENSE]
|
22
22
|
gem.executables = %w[mutant]
|
23
23
|
|
24
|
-
gem.add_runtime_dependency('abstract_type',
|
25
|
-
gem.add_runtime_dependency('adamantium',
|
26
|
-
gem.add_runtime_dependency('anima',
|
27
|
-
gem.add_runtime_dependency('ast',
|
28
|
-
gem.add_runtime_dependency('concord',
|
29
|
-
gem.add_runtime_dependency('diff-lcs',
|
30
|
-
gem.add_runtime_dependency('equalizer',
|
31
|
-
gem.add_runtime_dependency('ice_nine',
|
32
|
-
gem.add_runtime_dependency('memoizable',
|
33
|
-
gem.add_runtime_dependency('
|
34
|
-
gem.add_runtime_dependency('
|
35
|
-
gem.add_runtime_dependency('
|
24
|
+
gem.add_runtime_dependency('abstract_type', '~> 0.0.7')
|
25
|
+
gem.add_runtime_dependency('adamantium', '~> 0.2.0')
|
26
|
+
gem.add_runtime_dependency('anima', '~> 0.3.1')
|
27
|
+
gem.add_runtime_dependency('ast', '~> 2.2')
|
28
|
+
gem.add_runtime_dependency('concord', '~> 0.1.5')
|
29
|
+
gem.add_runtime_dependency('diff-lcs', '= 1.3')
|
30
|
+
gem.add_runtime_dependency('equalizer', '~> 0.0.9')
|
31
|
+
gem.add_runtime_dependency('ice_nine', '~> 0.11.1')
|
32
|
+
gem.add_runtime_dependency('memoizable', '~> 0.4.2')
|
33
|
+
gem.add_runtime_dependency('mprelude', '~> 0.1.0')
|
34
|
+
gem.add_runtime_dependency('parser', '~> 2.7.1')
|
35
|
+
gem.add_runtime_dependency('procto', '~> 0.0.2')
|
36
|
+
gem.add_runtime_dependency('unparser', '~> 0.4.6')
|
37
|
+
gem.add_runtime_dependency('variable', '~> 0.0.1')
|
36
38
|
|
37
|
-
gem.add_development_dependency('devtools', '~> 0.1.
|
39
|
+
gem.add_development_dependency('devtools', '~> 0.1.25')
|
38
40
|
gem.add_development_dependency('parallel', '~> 1.3')
|
39
41
|
end
|
data/spec/integrations.yml
CHANGED
@@ -2,13 +2,14 @@
|
|
2
2
|
- name: rubyspec
|
3
3
|
namespace: Rubyspec
|
4
4
|
repo_uri: 'https://github.com/ruby/rubyspec.git'
|
5
|
-
repo_ref:
|
5
|
+
repo_ref: 249a36c2e9fcddbb208a0d618d05f6bd9a64fd17
|
6
6
|
integration: mspec
|
7
7
|
mutation_coverage: false
|
8
8
|
mutation_generation: true
|
9
9
|
exclude:
|
10
10
|
- command_line/fixtures/bad_syntax.rb
|
11
11
|
- command_line/fixtures/freeze_flag_required_diff_enc.rb
|
12
|
+
- core/file/stat_spec.rb
|
12
13
|
- core/kernel/shared/sprintf_encoding.rb
|
13
14
|
- core/module/fixtures/autoload_empty.rb
|
14
15
|
- core/module/fixtures/autoload_never_set.rb
|
@@ -26,6 +27,7 @@
|
|
26
27
|
- language/predefined/fixtures/data_only.rb
|
27
28
|
- language/source_encoding_spec.rb
|
28
29
|
- library/base64/decode64_spec.rb
|
30
|
+
- library/cgi/escapeHTML_spec.rb
|
29
31
|
- security/cve_2010_1330_spec.rb
|
30
32
|
- name: regexp_parser
|
31
33
|
namespace: Regexp
|
data/spec/support/corpus.rb
CHANGED
@@ -10,7 +10,7 @@ module MutantSpec
|
|
10
10
|
|
11
11
|
# Namespace module for corpus testing
|
12
12
|
#
|
13
|
-
# rubocop:disable MethodLength
|
13
|
+
# rubocop:disable Metrics/MethodLength
|
14
14
|
module Corpus
|
15
15
|
TMP = ROOT.join('tmp').freeze
|
16
16
|
EXCLUDE_GLOB_FORMAT = '{%s}'
|
@@ -22,7 +22,7 @@ module MutantSpec
|
|
22
22
|
private_constant(*constants(false))
|
23
23
|
|
24
24
|
# Project under corpus test
|
25
|
-
# rubocop:disable ClassLength
|
25
|
+
# rubocop:disable Metrics/ClassLength
|
26
26
|
class Project
|
27
27
|
MUTEX = Mutex.new
|
28
28
|
|
@@ -259,7 +259,7 @@ module MutantSpec
|
|
259
259
|
#
|
260
260
|
# @param [Array<String>] arguments
|
261
261
|
#
|
262
|
-
# rubocop:disable GuardClause - guard clause without else does not make sense
|
262
|
+
# rubocop:disable Style/GuardClause - guard clause without else does not make sense
|
263
263
|
def system(arguments)
|
264
264
|
return if Kernel.system(*arguments)
|
265
265
|
|
data/spec/support/ruby_vm.rb
CHANGED
@@ -26,8 +26,7 @@ module MutantSpec
|
|
26
26
|
super(DEFAULTS.merge(attributes))
|
27
27
|
end
|
28
28
|
|
29
|
-
# rubocop:disable Naming/
|
30
|
-
def handle(vm, observation)
|
29
|
+
def handle(vm, observation) # rubocop:disable Naming/MethodParameterName
|
31
30
|
unless match?(observation)
|
32
31
|
fail "Unexpected event observation: #{observation.inspect}, expected #{inspect}"
|
33
32
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
# rubocop:disable ModuleLength
|
3
|
+
# rubocop:disable Metrics/ModuleLength
|
4
4
|
module SharedContext
|
5
5
|
# Prepend an anonymous module with the new `with` method
|
6
6
|
#
|
@@ -25,8 +25,8 @@ module SharedContext
|
|
25
25
|
end
|
26
26
|
end
|
27
27
|
|
28
|
-
# rubocop:disable MethodLength
|
29
|
-
# rubocop:disable AbcSize
|
28
|
+
# rubocop:disable Metrics/MethodLength
|
29
|
+
# rubocop:disable Metrics/AbcSize
|
30
30
|
def setup_shared_context
|
31
31
|
let(:mutation_a) { Mutant::Mutation::Evil.new(subject_a, mutation_a_node) }
|
32
32
|
let(:mutation_a_node) { s(:false) }
|
data/spec/support/xspec.rb
CHANGED
@@ -93,7 +93,7 @@ module XSpec
|
|
93
93
|
class MessageExpectation
|
94
94
|
include Anima.new(:receiver, :selector, :arguments, :reaction)
|
95
95
|
|
96
|
-
# rubocop:disable ParameterLists
|
96
|
+
# rubocop:disable Metrics/ParameterLists
|
97
97
|
def self.parse(receiver:, selector:, arguments: [], reaction: nil)
|
98
98
|
new(
|
99
99
|
receiver: receiver,
|
@@ -152,7 +152,7 @@ module XSpec
|
|
152
152
|
expectations.empty? or fail "unconsumed expectations:\n#{expectations.map(&:inspect).join("\n")}"
|
153
153
|
end
|
154
154
|
|
155
|
-
# rubocop:disable MethodLength
|
155
|
+
# rubocop:disable Metrics/MethodLength
|
156
156
|
def self.verify(rspec_context, expectations)
|
157
157
|
verifier = new(expectations)
|
158
158
|
|
@@ -89,7 +89,7 @@ RSpec.describe Mutant::License do
|
|
89
89
|
|
90
90
|
expect(stderr)
|
91
91
|
.to have_received(:puts)
|
92
|
-
.with('[Mutant-License-Error]: Soft fail, continuing in
|
92
|
+
.with('[Mutant-License-Error]: Soft fail, continuing in 40 seconds')
|
93
93
|
.ordered
|
94
94
|
|
95
95
|
expect(stderr)
|
@@ -104,7 +104,7 @@ RSpec.describe Mutant::License do
|
|
104
104
|
|
105
105
|
expect(kernel)
|
106
106
|
.to have_received(:sleep)
|
107
|
-
.with(
|
107
|
+
.with(40)
|
108
108
|
.ordered
|
109
109
|
end
|
110
110
|
end
|