mutant 0.11.16 → 0.11.17

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ebfdb4dba80abb7c2b06b6b057cebf6db686b598219979ed3d0730b6e5a9ed82
4
- data.tar.gz: ee03173b094cf29a9d21ad30b383a0b01b8cac7b7ba1132f24f36c25e9e4fee3
3
+ metadata.gz: 32bc27a55a33df968de61bde922b6318d158bf5f3ab0d3676720e2ba8e9ac2db
4
+ data.tar.gz: 20a7a9db2b3a034d9579bca78bfcca98d3e25117937407696bad239263c3b402
5
5
  SHA512:
6
- metadata.gz: 90d9c06d5a2900441b49b3bc0fa039b11bb296e389af41927f711431855a28369a8e31faf0b1cc5ba74ab09c6300c21002ac30c0d6eae6b3d63eac3129a692e8
7
- data.tar.gz: 725ecfb369b3c28133d898f3405bb5cec8f780027c8e7c05de59c225719924fde51e192186d2f7a2199a57352b056401fa562a67d75409a637d182bbb50d9390
6
+ metadata.gz: 4297d6e5172b74dc1e776739c68a5980cbda44581e38b06f76ed2ee395b816b2d664e146b98ac8c9a5f25e31e2b6078016398db862d0b96675299fbc3bc2cc49
7
+ data.tar.gz: f899277fb892b69bfac0b988e84fb9955036ea415cf2c55fecb90976bc3cdd9dd249d5bac1c154039df3c8af37db04b2d2d0c97003eac01c539371a7c9804d41
data/bin/mutant CHANGED
@@ -1,55 +1,64 @@
1
1
  #!/usr/bin/env ruby
2
2
  # frozen_string_literal: true
3
3
 
4
- trap('INT') do |status|
5
- effective_status = status ? status + 128 : 128
6
- exit! effective_status
7
- end
4
+ module Mutant
5
+ # Record executable timestamp
6
+ @executable_timestamp = Process.clock_gettime(Process::CLOCK_MONOTONIC)
7
+
8
+ trap('INT') do |status|
9
+ effective_status = status ? status + 128 : 128
10
+ exit! effective_status
11
+ end
8
12
 
9
- require 'mutant'
13
+ require 'mutant'
10
14
 
11
- Mutant::CLI.parse(
12
- arguments: ARGV,
13
- world: Mutant::WORLD
14
- ).either(
15
- ->(message) { Mutant::WORLD.stderr.puts(message); Kernel.exit(false) },
16
- # rubocop:disable Metrics/BlockLength
17
- lambda do |command|
18
- status =
15
+ WORLD.record(:cli_parse) do
16
+ CLI.parse(
17
+ arguments: ARGV,
18
+ world: Mutant::WORLD
19
+ )
20
+ end.either(
21
+ ->(message) { Mutant::WORLD.stderr.puts(message); Kernel.exit(false) },
22
+ # rubocop:disable Metrics/BlockLength
23
+ lambda do |command|
19
24
  if command.zombie?
20
- $stderr.puts('Running mutant zombified!')
21
- Mutant::Zombifier.call(
22
- namespace: :Zombie,
23
- load_path: $LOAD_PATH,
24
- kernel: Kernel,
25
- pathname: Pathname,
26
- require_highjack: Mutant::RequireHighjack
27
- .public_method(:call)
28
- .to_proc
29
- .curry
30
- .call(Kernel),
31
- root_require: 'mutant',
32
- includes: %w[
33
- adamantium
34
- anima
35
- concord
36
- equalizer
37
- mprelude
38
- mutant
39
- unparser
40
- variable
41
- ]
42
- )
25
+ command = WORLD.record(:zombify) do
26
+ $stderr.puts('Running mutant zombified!')
27
+ Zombifier.call(
28
+ namespace: :Zombie,
29
+ load_path: $LOAD_PATH,
30
+ kernel: Kernel,
31
+ pathname: Pathname,
32
+ require_highjack: RequireHighjack
33
+ .public_method(:call)
34
+ .to_proc
35
+ .curry
36
+ .call(Kernel),
37
+ root_require: 'mutant',
38
+ includes: %w[
39
+ adamantium
40
+ anima
41
+ concord
42
+ equalizer
43
+ mprelude
44
+ mutant
45
+ unparser
46
+ variable
47
+ ]
48
+ )
43
49
 
44
- Zombie::Mutant::CLI.parse(
45
- arguments: ARGV,
46
- world: Zombie::Mutant::WORLD
47
- ).from_right.call
48
- else
49
- command.call
50
+ Zombie::Mutant::CLI.parse(
51
+ arguments: ARGV,
52
+ world: Mutant::WORLD
53
+ ).from_right
54
+ end
50
55
  end
51
56
 
52
- Kernel.exit(status)
53
- end
54
- # rubocop:enable Metrics/BlockLength
55
- )
57
+ WORLD.record(:execute) { command.call }.tap do |status|
58
+ WORLD.recorder.print_profile(WORLD.stderr) if command.print_profile?
59
+ WORLD.kernel.exit(status)
60
+ end
61
+ end
62
+ # rubocop:enable Metrics/BlockLength
63
+ )
64
+ end
@@ -7,6 +7,8 @@ module Mutant
7
7
  # the impure world to produce an environment.
8
8
  #
9
9
  # env = config interpreted against the world
10
+ #
11
+ # rubocop:disable Metrics/ModuleLength
10
12
  module Bootstrap
11
13
  include Adamantium, Anima.new(:config, :parser, :world)
12
14
 
@@ -30,66 +32,94 @@ module Mutant
30
32
  #
31
33
  # rubocop:disable Metrics/MethodLength
32
34
  def self.call(env)
33
- env = load_hooks(env)
34
- .tap(&method(:infect))
35
- .with(matchable_scopes: matchable_scopes(env))
36
-
37
- subjects = start_subject(env, Matcher.from_config(env.config.matcher).call(env))
38
-
39
- Integration.setup(env).fmap do |integration|
40
- env.with(
41
- integration: integration,
42
- mutations: subjects.flat_map(&:mutations),
43
- selector: Selector::Expression.new(integration),
44
- subjects: subjects
45
- )
35
+ env.record(:bootstrap) do
36
+ env = load_hooks(env)
37
+ .tap(&method(:infect))
38
+ .with(matchable_scopes: matchable_scopes(env))
39
+
40
+ matched_subjects = env.record(:subject_match) do
41
+ Matcher.from_config(env.config.matcher).call(env)
42
+ end
43
+
44
+ selected_subjects = subject_select(env, matched_subjects)
45
+
46
+ mutations = env.record(:mutation_generate) do
47
+ selected_subjects.flat_map(&:mutations)
48
+ end
49
+
50
+ Integration.setup(env).fmap do |integration|
51
+ env.with(
52
+ integration: integration,
53
+ mutations: mutations,
54
+ selector: Selector::Expression.new(integration),
55
+ subjects: selected_subjects
56
+ )
57
+ end
46
58
  end
47
59
  end
48
60
  # rubocop:enable Metrics/MethodLength
49
61
 
50
62
  def self.load_hooks(env)
51
- env.with(hooks: Hooks.load_config(env.config))
63
+ env.record(__method__) do
64
+ env.with(hooks: Hooks.load_config(env.config))
65
+ end
52
66
  end
53
67
  private_class_method :load_hooks
54
68
 
55
- def self.start_subject(env, subjects)
56
- start_expressions = env.config.matcher.start_expressions
69
+ def self.subject_select(env, subjects)
70
+ env.record(__method__) do
71
+ start_expressions = env.config.matcher.start_expressions
57
72
 
58
- return subjects if start_expressions.empty?
73
+ return subjects if start_expressions.empty?
59
74
 
60
- subjects.drop_while do |subject|
61
- start_expressions.none? do |expression|
62
- expression.prefix?(subject.expression)
75
+ subjects.drop_while do |subject|
76
+ start_expressions.none? do |expression|
77
+ expression.prefix?(subject.expression)
78
+ end
63
79
  end
64
80
  end
65
81
  end
66
- private_class_method :start_subject
82
+ private_class_method :subject_select
67
83
 
84
+ # rubocop:disable Metrics/AbcSize
85
+ # rubocop:disable Metrics/MethodLength
68
86
  def self.infect(env)
69
- config, hooks, world = env.config, env.hooks, env.world
87
+ env.record(__method__) do
88
+ config, hooks, world = env.config, env.hooks, env.world
70
89
 
71
- hooks.run(:env_infection_pre, env)
90
+ env.record(:hooks_env_infection_pre) do
91
+ hooks.run(:env_infection_pre, env)
92
+ end
72
93
 
73
- config.environment_variables.each do |key, value|
74
- world.environment_variables[key] = value
75
- end
94
+ env.record(:require_target) do
95
+ config.environment_variables.each do |key, value|
96
+ world.environment_variables[key] = value
97
+ end
76
98
 
77
- config.includes.each(&world.load_path.public_method(:<<))
78
- config.requires.each(&world.kernel.public_method(:require))
99
+ config.includes.each(&world.load_path.public_method(:<<))
100
+ config.requires.each(&world.kernel.public_method(:require))
101
+ end
79
102
 
80
- hooks.run(:env_infection_post, env)
103
+ env.record(:hooks_env_infection_post) do
104
+ hooks.run(:env_infection_post, env)
105
+ end
106
+ end
81
107
  end
82
108
  private_class_method :infect
109
+ # rubocop:enable Metrics/AbcSize
110
+ # rubocop:enable Metrics/MethodLength
83
111
 
84
112
  def self.matchable_scopes(env)
85
- config = env.config
113
+ env.record(__method__) do
114
+ config = env.config
86
115
 
87
- scopes = env.world.object_space.each_object(Module).each_with_object([]) do |scope, aggregate|
88
- expression = expression(config.reporter, config.expression_parser, scope) || next
89
- aggregate << Scope.new(scope, expression)
90
- end
116
+ scopes = env.world.object_space.each_object(Module).each_with_object([]) do |scope, aggregate|
117
+ expression = expression(config.reporter, config.expression_parser, scope) || next
118
+ aggregate << Scope.new(scope, expression)
119
+ end
91
120
 
92
- scopes.sort_by { |scope| scope.expression.syntax }
121
+ scopes.sort_by { |scope| scope.expression.syntax }
122
+ end
93
123
  end
94
124
  private_class_method :matchable_scopes
95
125
 
@@ -132,4 +162,5 @@ module Mutant
132
162
  end
133
163
  private_class_method :semantics_warning
134
164
  end # Bootstrap
165
+ # rubocop:enable Metrics/ModuleLength
135
166
  end # Mutant
@@ -27,8 +27,8 @@ module Mutant
27
27
  def bootstrap
28
28
  env = Env.empty(world, @config)
29
29
 
30
- Config.load_config_file(env)
31
- .fmap(&method(:expand))
30
+ env
31
+ .record(:config) { Config.load_config_file(env).fmap(&method(:expand)) }
32
32
  .bind { Bootstrap.call(env.with(config: @config)) }
33
33
  end
34
34
 
@@ -4,7 +4,13 @@ module Mutant
4
4
  module CLI
5
5
  # rubocop:disable Metrics/ClassLength
6
6
  class Command
7
- include AbstractType, Anima.new(:world, :main, :parent, :zombie)
7
+ include AbstractType, Anima.new(
8
+ :main,
9
+ :parent,
10
+ :print_profile,
11
+ :world,
12
+ :zombie
13
+ )
8
14
 
9
15
  OPTIONS = [].freeze
10
16
  SUBCOMMANDS = [].freeze
@@ -21,12 +27,13 @@ module Mutant
21
27
  # @return [Command]
22
28
  #
23
29
  # rubocop:disable Metrics/ParameterLists
24
- def self.parse(arguments:, parent: nil, world:, zombie: false)
30
+ def self.parse(arguments:, parent: nil, print_profile: false, world:, zombie: false)
25
31
  new(
26
- main: nil,
27
- parent: parent,
28
- world: world,
29
- zombie: zombie
32
+ main: nil,
33
+ parent: parent,
34
+ print_profile: print_profile,
35
+ world: world,
36
+ zombie: zombie
30
37
  ).__send__(:parse, arguments)
31
38
  end
32
39
  # rubocop:enable Metrics/ParameterLists
@@ -59,7 +66,8 @@ module Mutant
59
66
  [*parent&.full_name, self.class.command_name].join(' ')
60
67
  end
61
68
 
62
- alias_method :zombie?, :zombie
69
+ alias_method :print_profile?, :print_profile
70
+ alias_method :zombie?, :zombie
63
71
 
64
72
  abstract_method :action
65
73
 
@@ -136,6 +144,10 @@ module Mutant
136
144
  capture_main { world.stdout.puts("mutant-#{VERSION}"); true }
137
145
  end
138
146
 
147
+ parser.on('--profile', 'Profile mutant execution') do
148
+ @print_profile = true
149
+ end
150
+
139
151
  parser.on('--zombie', 'Run mutant zombified') do
140
152
  @zombie = true
141
153
  end
@@ -176,10 +188,11 @@ module Mutant
176
188
  else
177
189
  find_command(command_name).bind do |command|
178
190
  command.parse(
179
- arguments: arguments,
180
- parent: self,
181
- world: world,
182
- zombie: zombie
191
+ arguments: arguments,
192
+ parent: self,
193
+ print_profile: print_profile,
194
+ world: world,
195
+ zombie: zombie
183
196
  )
184
197
  end
185
198
  end
data/lib/mutant/env.rb CHANGED
@@ -134,6 +134,15 @@ module Mutant
134
134
  end
135
135
  memoize :test_subject_ratio
136
136
 
137
+ # Record segment
138
+ #
139
+ # @param [Symbol] name
140
+ #
141
+ # @return [self]
142
+ def record(name, &block)
143
+ world.record(name, &block)
144
+ end
145
+
137
146
  private
138
147
 
139
148
  def run_mutation_tests(mutation, tests)
@@ -49,6 +49,7 @@ module Mutant
49
49
  def finalize(status)
50
50
  status.tap do
51
51
  if status.done?
52
+ workers.each(&:signal)
52
53
  workers.each(&:join)
53
54
  threads.each(&:join)
54
55
  end
@@ -77,8 +77,12 @@ module Mutant
77
77
  self
78
78
  end
79
79
 
80
- def join
80
+ def signal
81
81
  process.kill('TERM', pid)
82
+ self
83
+ end
84
+
85
+ def join
82
86
  process.wait(pid)
83
87
  self
84
88
  end
data/lib/mutant/runner.rb CHANGED
@@ -15,15 +15,17 @@ module Mutant
15
15
  def self.run_mutation_analysis(env)
16
16
  reporter = reporter(env)
17
17
 
18
- run_driver(
19
- reporter,
20
- Parallel.async(env.world, mutation_test_config(env))
21
- ).tap do |result|
22
- reporter.report(result)
23
- end
18
+ env
19
+ .record(:analysis) { run_driver(reporter, async_driver(env)) }
20
+ .tap { |result| env.record(:report) { reporter.report(result) } }
24
21
  end
25
22
  private_class_method :run_mutation_analysis
26
23
 
24
+ def self.async_driver(env)
25
+ Parallel.async(env.world, mutation_test_config(env))
26
+ end
27
+ private_class_method :async_driver
28
+
27
29
  def self.run_driver(reporter, driver)
28
30
  Signal.trap('INT') do
29
31
  driver.stop
@@ -0,0 +1,124 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mutant
4
+ class Segment
5
+ class Recorder
6
+ include Anima.new(
7
+ :gen_id,
8
+ :parent_id,
9
+ :recording_start,
10
+ :root_id,
11
+ :segments,
12
+ :timer
13
+ )
14
+
15
+ private(*anima.attribute_names)
16
+
17
+ # rubocop:disable Metrics/MethodLength
18
+ def record(name)
19
+ start = timer.now
20
+ parent_id = parent_id()
21
+
22
+ @parent_id = id = gen_id.call
23
+
24
+ yield.tap do
25
+ segments << Segment.new(
26
+ id: id,
27
+ name: name,
28
+ parent_id: parent_id,
29
+ timestamp_end: timer.now,
30
+ timestamp_start: start
31
+ )
32
+ end
33
+ ensure
34
+ @parent_id = parent_id
35
+ end
36
+ # rubocop:enable Metrics/MethodLength
37
+
38
+ def print_profile(io)
39
+ print_node(io, tree, 0)
40
+ end
41
+
42
+ private
43
+
44
+ class Node
45
+ include Adamantium, Anima.new(:value, :children)
46
+ end
47
+ private_constant :Node
48
+
49
+ def tree
50
+ id_index = {}
51
+ parent_index = {}
52
+
53
+ final_segments.each do |segment|
54
+ id_index[segment.id] = segment
55
+
56
+ (parent_index[segment.parent_id] ||= []) << segment
57
+ end
58
+
59
+ build_node(
60
+ value: id_index.fetch(root_id),
61
+ parent_index: parent_index
62
+ )
63
+ end
64
+
65
+ def final_segments
66
+ timestamp_end = timer.now
67
+
68
+ segments.map do |segment|
69
+ if segment.timestamp_end
70
+ segment
71
+ else
72
+ segment.with(timestamp_end: timestamp_end)
73
+ end
74
+ end
75
+ end
76
+
77
+ def build_node(value:, parent_index:)
78
+ Node.new(
79
+ value: value,
80
+ children: build_children(
81
+ parent_id: value.id,
82
+ parent_index: parent_index
83
+ )
84
+ )
85
+ end
86
+
87
+ def build_children(parent_id:, parent_index:)
88
+ parent_index
89
+ .fetch(parent_id, EMPTY_ARRAY)
90
+ .map { |value| build_node(value: value, parent_index: parent_index) }
91
+ end
92
+
93
+ def print_node(io, node, indent)
94
+ segment = node.value
95
+
96
+ indent_str = ' ' * indent
97
+
98
+ print_line(io, :offset_start, segment, indent_str)
99
+
100
+ return unless node.children.any?
101
+
102
+ node.children.each do |child|
103
+ print_node(io, child, indent.succ)
104
+ end
105
+ print_line(io, :offset_end, segment, indent_str)
106
+ end
107
+
108
+ # rubocop:disable Metrics/ParameterLists
109
+ # rubocop:disable Style/FormatStringToken
110
+ def print_line(io, offset, segment, indent_str)
111
+ io.puts(
112
+ '%4.4f: (%4.4fs) %s %s' % [
113
+ segment.public_send(offset, recording_start),
114
+ segment.elapsed,
115
+ indent_str,
116
+ segment.name
117
+ ]
118
+ )
119
+ end
120
+ # rubocop:enable Metrics/ParameterLists
121
+ # rubocop:enable Style/FormatStringToken
122
+ end # Recorder
123
+ end # Segment
124
+ end # Mutant
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mutant
4
+ class Segment
5
+ include Adamantium, Anima.new(
6
+ :id,
7
+ :name,
8
+ :parent_id,
9
+ :timestamp_end,
10
+ :timestamp_start
11
+ )
12
+
13
+ def elapsed
14
+ timestamp_end - timestamp_start
15
+ end
16
+
17
+ def offset_start(recording_start)
18
+ timestamp_start - recording_start
19
+ end
20
+
21
+ def offset_end(recording_start)
22
+ timestamp_end - recording_start
23
+ end
24
+ end # Segment
25
+ end # Mutant
@@ -2,5 +2,5 @@
2
2
 
3
3
  module Mutant
4
4
  # Current mutant version
5
- VERSION = '0.11.16'
5
+ VERSION = '0.11.17'
6
6
  end # Mutant
data/lib/mutant/world.rb CHANGED
@@ -19,6 +19,7 @@ module Mutant
19
19
  :pathname,
20
20
  :process,
21
21
  :random,
22
+ :recorder,
22
23
  :stderr,
23
24
  :stdout,
24
25
  :thread,
@@ -77,5 +78,9 @@ module Mutant
77
78
  Timer::Deadline::None.new
78
79
  end
79
80
  end
81
+
82
+ def record(name, &block)
83
+ recorder.record(name, &block)
84
+ end
80
85
  end # World
81
86
  end # Mutant
data/lib/mutant.rb CHANGED
@@ -1,32 +1,54 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'diff/lcs'
4
- require 'diff/lcs/hunk'
5
- require 'digest/sha1'
6
- require 'etc'
7
- require 'irb'
8
- require 'json'
9
- require 'open3'
10
- require 'optparse'
11
- require 'parser'
12
- require 'parser/current'
13
- require 'pathname'
14
- require 'regexp_parser'
15
- require 'set'
16
- require 'singleton'
17
- require 'sorbet-runtime'
18
- require 'stringio'
19
- require 'unparser'
20
- require 'yaml'
21
-
22
- # This setting is done to make errors within the parallel
23
- # reporter / execution visible in the main thread.
24
- Thread.abort_on_exception = true
25
-
26
3
  # Library namespace
27
4
  #
28
5
  # @api private
6
+ # rubocop:disable Metrics/ModuleLength
29
7
  module Mutant
8
+ # Boot timing infrastructure
9
+ get_timestamp = lambda do
10
+ Process.clock_gettime(Process::CLOCK_MONOTONIC)
11
+ end
12
+
13
+ library_timestamp = get_timestamp.call
14
+ boot_events = []
15
+
16
+ record = lambda do |name, &block|
17
+ start = get_timestamp.call
18
+
19
+ block.call.tap do
20
+ boot_events << [name, start, get_timestamp.call]
21
+ end
22
+ end
23
+
24
+ record.call(:require_dependencies) do
25
+ %w[
26
+ diff/lcs
27
+ diff/lcs/hunk
28
+ digest/sha1
29
+ etc
30
+ irb
31
+ json
32
+ open3
33
+ optparse
34
+ parser
35
+ parser/current
36
+ pathname
37
+ regexp_parser
38
+ securerandom
39
+ set
40
+ singleton
41
+ sorbet-runtime
42
+ stringio
43
+ unparser
44
+ yaml
45
+ ].each { |name| require(name) }
46
+ end
47
+
48
+ # This setting is done to make errors within the parallel
49
+ # reporter / execution visible in the main thread.
50
+ Thread.abort_on_exception = true
51
+
30
52
  AbstractType = Unparser::AbstractType
31
53
  Adamantium = Unparser::Adamantium
32
54
  Anima = Unparser::Anima
@@ -43,211 +65,264 @@ module Mutant
43
65
 
44
66
  ENV_VARIABLE_KEY_VALUE_REGEXP = /\A(?<key>#{env_key}+)=(?<value>.*)\z/.freeze
45
67
  ENV_VARIABLE_KEY_REGEXP = /\A#{env_key}\z/.freeze
46
- end # Mutant
47
68
 
48
- require 'mutant/procto'
49
- require 'mutant/transform'
50
- require 'mutant/variable'
51
- require 'mutant/bootstrap'
52
- require 'mutant/version'
53
- require 'mutant/env'
54
- require 'mutant/pipe'
55
- require 'mutant/util'
56
- require 'mutant/registry'
57
- require 'mutant/ast'
58
- require 'mutant/ast/sexp'
59
- require 'mutant/ast/types'
60
- require 'mutant/ast/nodes'
61
- require 'mutant/ast/named_children'
62
- require 'mutant/ast/node_predicates'
63
- require 'mutant/ast/find_metaclass_containing'
64
- require 'mutant/ast/regexp'
65
- require 'mutant/ast/regexp/transformer'
66
- require 'mutant/ast/regexp/transformer/direct'
67
- require 'mutant/ast/regexp/transformer/named_group'
68
- require 'mutant/ast/regexp/transformer/options_group'
69
- require 'mutant/ast/regexp/transformer/quantifier'
70
- require 'mutant/ast/regexp/transformer/recursive'
71
- require 'mutant/ast/regexp/transformer/root'
72
- require 'mutant/ast/regexp/transformer/text'
73
- require 'mutant/ast/meta'
74
- require 'mutant/ast/meta/send'
75
- require 'mutant/ast/meta/const'
76
- require 'mutant/ast/meta/symbol'
77
- require 'mutant/ast/meta/optarg'
78
- require 'mutant/ast/meta/resbody'
79
- require 'mutant/ast/pattern'
80
- require 'mutant/ast/pattern/lexer'
81
- require 'mutant/ast/pattern/parser'
82
- require 'mutant/ast/pattern/source'
83
- require 'mutant/ast/pattern/token'
84
- require 'mutant/ast/structure'
85
- require 'mutant/parser'
86
- require 'mutant/isolation'
87
- require 'mutant/isolation/exception'
88
- require 'mutant/isolation/fork'
89
- require 'mutant/isolation/none'
90
- require 'mutant/parallel'
91
- require 'mutant/parallel/driver'
92
- require 'mutant/parallel/source'
93
- require 'mutant/parallel/worker'
94
- require 'mutant/require_highjack'
95
- require 'mutant/mutation'
96
- require 'mutant/mutation/config'
97
- require 'mutant/mutator'
98
- require 'mutant/mutator/util'
99
- require 'mutant/mutator/util/array'
100
- require 'mutant/mutator/util/symbol'
101
- require 'mutant/mutator/node'
102
- require 'mutant/mutator/node/generic'
103
- require 'mutant/mutator/node/regexp'
104
- require 'mutant/mutator/node/regexp/alternation_meta'
105
- require 'mutant/mutator/node/regexp/beginning_of_line_anchor'
106
- require 'mutant/mutator/node/regexp/capture_group'
107
- require 'mutant/mutator/node/regexp/named_group'
108
- require 'mutant/mutator/node/regexp/character_type'
109
- require 'mutant/mutator/node/regexp/end_of_line_anchor'
110
- require 'mutant/mutator/node/regexp/end_of_string_or_before_end_of_line_anchor'
111
- require 'mutant/mutator/node/regexp/zero_or_more'
112
- require 'mutant/mutator/node/literal'
113
- require 'mutant/mutator/node/literal/boolean'
114
- require 'mutant/mutator/node/literal/range'
115
- require 'mutant/mutator/node/literal/symbol'
116
- require 'mutant/mutator/node/literal/string'
117
- require 'mutant/mutator/node/literal/integer'
118
- require 'mutant/mutator/node/literal/float'
119
- require 'mutant/mutator/node/literal/array'
120
- require 'mutant/mutator/node/literal/hash'
121
- require 'mutant/mutator/node/literal/regex'
122
- require 'mutant/mutator/node/literal/nil'
123
- require 'mutant/mutator/node/argument'
124
- require 'mutant/mutator/node/arguments'
125
- require 'mutant/mutator/node/begin'
126
- require 'mutant/mutator/node/binary'
127
- require 'mutant/mutator/node/const'
128
- require 'mutant/mutator/node/dynamic_literal'
129
- require 'mutant/mutator/node/kwbegin'
130
- require 'mutant/mutator/node/named_value/access'
131
- require 'mutant/mutator/node/named_value/constant_assignment'
132
- require 'mutant/mutator/node/named_value/variable_assignment'
133
- require 'mutant/mutator/node/next'
134
- require 'mutant/mutator/node/break'
135
- require 'mutant/mutator/node/noop'
136
- require 'mutant/mutator/node/or_asgn'
137
- require 'mutant/mutator/node/and_asgn'
138
- require 'mutant/mutator/node/defined'
139
- require 'mutant/mutator/node/op_asgn'
140
- require 'mutant/mutator/node/conditional_loop'
141
- require 'mutant/mutator/node/yield'
142
- require 'mutant/mutator/node/super'
143
- require 'mutant/mutator/node/zsuper'
144
- require 'mutant/mutator/node/send'
145
- require 'mutant/mutator/node/send/binary'
146
- require 'mutant/mutator/node/send/conditional'
147
- require 'mutant/mutator/node/send/attribute_assignment'
148
- require 'mutant/mutator/node/when'
149
- require 'mutant/mutator/node/class'
150
- require 'mutant/mutator/node/sclass'
151
- require 'mutant/mutator/node/define'
152
- require 'mutant/mutator/node/mlhs'
153
- require 'mutant/mutator/node/nthref'
154
- require 'mutant/mutator/node/masgn'
155
- require 'mutant/mutator/node/module'
156
- require 'mutant/mutator/node/return'
157
- require 'mutant/mutator/node/block'
158
- require 'mutant/mutator/node/block_pass'
159
- require 'mutant/mutator/node/if'
160
- require 'mutant/mutator/node/case'
161
- require 'mutant/mutator/node/splat'
162
- require 'mutant/mutator/node/regopt'
163
- require 'mutant/mutator/node/resbody'
164
- require 'mutant/mutator/node/rescue'
165
- require 'mutant/mutator/node/match_current_line'
166
- require 'mutant/mutator/node/index'
167
- require 'mutant/mutator/node/procarg_zero'
168
- require 'mutant/mutator/node/kwargs'
169
- require 'mutant/mutator/node/numblock'
170
- require 'mutant/loader'
171
- require 'mutant/context'
172
- require 'mutant/scope'
173
- require 'mutant/subject'
174
- require 'mutant/subject/config'
175
- require 'mutant/subject/method'
176
- require 'mutant/subject/method/instance'
177
- require 'mutant/subject/method/singleton'
178
- require 'mutant/subject/method/metaclass'
179
- require 'mutant/matcher'
180
- require 'mutant/matcher/chain'
181
- require 'mutant/matcher/config'
182
- require 'mutant/matcher/descendants'
183
- require 'mutant/matcher/filter'
184
- require 'mutant/matcher/method'
185
- require 'mutant/matcher/method/instance'
186
- require 'mutant/matcher/method/metaclass'
187
- require 'mutant/matcher/method/singleton'
188
- require 'mutant/matcher/methods'
189
- require 'mutant/matcher/namespace'
190
- require 'mutant/matcher/null'
191
- require 'mutant/matcher/scope'
192
- require 'mutant/matcher/static'
193
- require 'mutant/expression'
194
- require 'mutant/expression/descendants'
195
- require 'mutant/expression/method'
196
- require 'mutant/expression/methods'
197
- require 'mutant/expression/namespace'
198
- require 'mutant/expression/parser'
199
- require 'mutant/test'
200
- require 'mutant/timer'
201
- require 'mutant/integration'
202
- require 'mutant/integration/null'
203
- require 'mutant/selector'
204
- require 'mutant/selector/expression'
205
- require 'mutant/selector/null'
206
- require 'mutant/world'
207
- require 'mutant/hooks'
208
- require 'mutant/config'
209
- require 'mutant/config/coverage_criteria'
210
- require 'mutant/cli'
211
- require 'mutant/cli/command'
212
- require 'mutant/cli/command/subscription'
213
- require 'mutant/cli/command/environment'
214
- require 'mutant/cli/command/environment/irb'
215
- require 'mutant/cli/command/environment/run'
216
- require 'mutant/cli/command/environment/show'
217
- require 'mutant/cli/command/environment/subject'
218
- require 'mutant/cli/command/environment/test'
219
- require 'mutant/cli/command/util'
220
- require 'mutant/cli/command/root'
221
- require 'mutant/runner'
222
- require 'mutant/runner/sink'
223
- require 'mutant/result'
224
- require 'mutant/reporter'
225
- require 'mutant/reporter/null'
226
- require 'mutant/reporter/sequence'
227
- require 'mutant/reporter/cli'
228
- require 'mutant/reporter/cli/printer'
229
- require 'mutant/reporter/cli/printer/config'
230
- require 'mutant/reporter/cli/printer/coverage_result'
231
- require 'mutant/reporter/cli/printer/env'
232
- require 'mutant/reporter/cli/printer/env_progress'
233
- require 'mutant/reporter/cli/printer/env_result'
234
- require 'mutant/reporter/cli/printer/isolation_result'
235
- require 'mutant/reporter/cli/printer/mutation'
236
- require 'mutant/reporter/cli/printer/mutation_result'
237
- require 'mutant/reporter/cli/printer/status_progressive'
238
- require 'mutant/reporter/cli/printer/subject_result'
239
- require 'mutant/reporter/cli/format'
240
- require 'mutant/repository'
241
- require 'mutant/repository/diff'
242
- require 'mutant/repository/diff/ranges'
243
- require 'mutant/zombifier'
244
- require 'mutant/range'
245
- require 'mutant/license'
246
- require 'mutant/license/subscription'
247
- require 'mutant/license/subscription/opensource'
248
- require 'mutant/license/subscription/commercial'
69
+ # rubocop:disable Metrics/BlockLength
70
+ record.call(:require_mutant_lib) do
71
+ require 'mutant/procto'
72
+ require 'mutant/transform'
73
+ require 'mutant/variable'
74
+ require 'mutant/bootstrap'
75
+ require 'mutant/version'
76
+ require 'mutant/env'
77
+ require 'mutant/pipe'
78
+ require 'mutant/util'
79
+ require 'mutant/registry'
80
+ require 'mutant/ast'
81
+ require 'mutant/ast/sexp'
82
+ require 'mutant/ast/types'
83
+ require 'mutant/ast/nodes'
84
+ require 'mutant/ast/named_children'
85
+ require 'mutant/ast/node_predicates'
86
+ require 'mutant/ast/find_metaclass_containing'
87
+ require 'mutant/ast/regexp'
88
+ require 'mutant/ast/regexp/transformer'
89
+ require 'mutant/ast/regexp/transformer/direct'
90
+ require 'mutant/ast/regexp/transformer/named_group'
91
+ require 'mutant/ast/regexp/transformer/options_group'
92
+ require 'mutant/ast/regexp/transformer/quantifier'
93
+ require 'mutant/ast/regexp/transformer/recursive'
94
+ require 'mutant/ast/regexp/transformer/root'
95
+ require 'mutant/ast/regexp/transformer/text'
96
+ require 'mutant/ast/meta'
97
+ require 'mutant/ast/meta/send'
98
+ require 'mutant/ast/meta/const'
99
+ require 'mutant/ast/meta/symbol'
100
+ require 'mutant/ast/meta/optarg'
101
+ require 'mutant/ast/meta/resbody'
102
+ require 'mutant/ast/pattern'
103
+ require 'mutant/ast/pattern/lexer'
104
+ require 'mutant/ast/pattern/parser'
105
+ require 'mutant/ast/pattern/source'
106
+ require 'mutant/ast/pattern/token'
107
+ require 'mutant/ast/structure'
108
+ require 'mutant/parser'
109
+ require 'mutant/isolation'
110
+ require 'mutant/isolation/exception'
111
+ require 'mutant/isolation/fork'
112
+ require 'mutant/isolation/none'
113
+ require 'mutant/parallel'
114
+ require 'mutant/parallel/driver'
115
+ require 'mutant/parallel/source'
116
+ require 'mutant/parallel/worker'
117
+ require 'mutant/require_highjack'
118
+ require 'mutant/mutation'
119
+ require 'mutant/mutation/config'
120
+ require 'mutant/mutator'
121
+ require 'mutant/mutator/util'
122
+ require 'mutant/mutator/util/array'
123
+ require 'mutant/mutator/util/symbol'
124
+ require 'mutant/mutator/node'
125
+ require 'mutant/mutator/node/generic'
126
+ require 'mutant/mutator/node/regexp'
127
+ require 'mutant/mutator/node/regexp/alternation_meta'
128
+ require 'mutant/mutator/node/regexp/beginning_of_line_anchor'
129
+ require 'mutant/mutator/node/regexp/capture_group'
130
+ require 'mutant/mutator/node/regexp/named_group'
131
+ require 'mutant/mutator/node/regexp/character_type'
132
+ require 'mutant/mutator/node/regexp/end_of_line_anchor'
133
+ require 'mutant/mutator/node/regexp/end_of_string_or_before_end_of_line_anchor'
134
+ require 'mutant/mutator/node/regexp/zero_or_more'
135
+ require 'mutant/mutator/node/literal'
136
+ require 'mutant/mutator/node/literal/boolean'
137
+ require 'mutant/mutator/node/literal/range'
138
+ require 'mutant/mutator/node/literal/symbol'
139
+ require 'mutant/mutator/node/literal/string'
140
+ require 'mutant/mutator/node/literal/integer'
141
+ require 'mutant/mutator/node/literal/float'
142
+ require 'mutant/mutator/node/literal/array'
143
+ require 'mutant/mutator/node/literal/hash'
144
+ require 'mutant/mutator/node/literal/regex'
145
+ require 'mutant/mutator/node/literal/nil'
146
+ require 'mutant/mutator/node/argument'
147
+ require 'mutant/mutator/node/arguments'
148
+ require 'mutant/mutator/node/begin'
149
+ require 'mutant/mutator/node/binary'
150
+ require 'mutant/mutator/node/const'
151
+ require 'mutant/mutator/node/dynamic_literal'
152
+ require 'mutant/mutator/node/kwbegin'
153
+ require 'mutant/mutator/node/named_value/access'
154
+ require 'mutant/mutator/node/named_value/constant_assignment'
155
+ require 'mutant/mutator/node/named_value/variable_assignment'
156
+ require 'mutant/mutator/node/next'
157
+ require 'mutant/mutator/node/break'
158
+ require 'mutant/mutator/node/noop'
159
+ require 'mutant/mutator/node/or_asgn'
160
+ require 'mutant/mutator/node/and_asgn'
161
+ require 'mutant/mutator/node/defined'
162
+ require 'mutant/mutator/node/op_asgn'
163
+ require 'mutant/mutator/node/conditional_loop'
164
+ require 'mutant/mutator/node/yield'
165
+ require 'mutant/mutator/node/super'
166
+ require 'mutant/mutator/node/zsuper'
167
+ require 'mutant/mutator/node/send'
168
+ require 'mutant/mutator/node/send/binary'
169
+ require 'mutant/mutator/node/send/conditional'
170
+ require 'mutant/mutator/node/send/attribute_assignment'
171
+ require 'mutant/mutator/node/when'
172
+ require 'mutant/mutator/node/class'
173
+ require 'mutant/mutator/node/sclass'
174
+ require 'mutant/mutator/node/define'
175
+ require 'mutant/mutator/node/mlhs'
176
+ require 'mutant/mutator/node/nthref'
177
+ require 'mutant/mutator/node/masgn'
178
+ require 'mutant/mutator/node/module'
179
+ require 'mutant/mutator/node/return'
180
+ require 'mutant/mutator/node/block'
181
+ require 'mutant/mutator/node/block_pass'
182
+ require 'mutant/mutator/node/if'
183
+ require 'mutant/mutator/node/case'
184
+ require 'mutant/mutator/node/splat'
185
+ require 'mutant/mutator/node/regopt'
186
+ require 'mutant/mutator/node/resbody'
187
+ require 'mutant/mutator/node/rescue'
188
+ require 'mutant/mutator/node/match_current_line'
189
+ require 'mutant/mutator/node/index'
190
+ require 'mutant/mutator/node/procarg_zero'
191
+ require 'mutant/mutator/node/kwargs'
192
+ require 'mutant/mutator/node/numblock'
193
+ require 'mutant/loader'
194
+ require 'mutant/context'
195
+ require 'mutant/scope'
196
+ require 'mutant/subject'
197
+ require 'mutant/subject/config'
198
+ require 'mutant/subject/method'
199
+ require 'mutant/subject/method/instance'
200
+ require 'mutant/subject/method/singleton'
201
+ require 'mutant/subject/method/metaclass'
202
+ require 'mutant/matcher'
203
+ require 'mutant/matcher/chain'
204
+ require 'mutant/matcher/config'
205
+ require 'mutant/matcher/descendants'
206
+ require 'mutant/matcher/filter'
207
+ require 'mutant/matcher/method'
208
+ require 'mutant/matcher/method/instance'
209
+ require 'mutant/matcher/method/metaclass'
210
+ require 'mutant/matcher/method/singleton'
211
+ require 'mutant/matcher/methods'
212
+ require 'mutant/matcher/namespace'
213
+ require 'mutant/matcher/null'
214
+ require 'mutant/matcher/scope'
215
+ require 'mutant/matcher/static'
216
+ require 'mutant/expression'
217
+ require 'mutant/expression/descendants'
218
+ require 'mutant/expression/method'
219
+ require 'mutant/expression/methods'
220
+ require 'mutant/expression/namespace'
221
+ require 'mutant/expression/parser'
222
+ require 'mutant/test'
223
+ require 'mutant/timer'
224
+ require 'mutant/integration'
225
+ require 'mutant/integration/null'
226
+ require 'mutant/selector'
227
+ require 'mutant/selector/expression'
228
+ require 'mutant/selector/null'
229
+ require 'mutant/world'
230
+ require 'mutant/hooks'
231
+ require 'mutant/config'
232
+ require 'mutant/config/coverage_criteria'
233
+ require 'mutant/cli'
234
+ require 'mutant/cli/command'
235
+ require 'mutant/cli/command/subscription'
236
+ require 'mutant/cli/command/environment'
237
+ require 'mutant/cli/command/environment/irb'
238
+ require 'mutant/cli/command/environment/run'
239
+ require 'mutant/cli/command/environment/show'
240
+ require 'mutant/cli/command/environment/subject'
241
+ require 'mutant/cli/command/environment/test'
242
+ require 'mutant/cli/command/util'
243
+ require 'mutant/cli/command/root'
244
+ require 'mutant/runner'
245
+ require 'mutant/runner/sink'
246
+ require 'mutant/result'
247
+ require 'mutant/reporter'
248
+ require 'mutant/reporter/null'
249
+ require 'mutant/reporter/sequence'
250
+ require 'mutant/reporter/cli'
251
+ require 'mutant/reporter/cli/printer'
252
+ require 'mutant/reporter/cli/printer/config'
253
+ require 'mutant/reporter/cli/printer/coverage_result'
254
+ require 'mutant/reporter/cli/printer/env'
255
+ require 'mutant/reporter/cli/printer/env_progress'
256
+ require 'mutant/reporter/cli/printer/env_result'
257
+ require 'mutant/reporter/cli/printer/isolation_result'
258
+ require 'mutant/reporter/cli/printer/mutation'
259
+ require 'mutant/reporter/cli/printer/mutation_result'
260
+ require 'mutant/reporter/cli/printer/status_progressive'
261
+ require 'mutant/reporter/cli/printer/subject_result'
262
+ require 'mutant/reporter/cli/format'
263
+ require 'mutant/repository'
264
+ require 'mutant/repository/diff'
265
+ require 'mutant/repository/diff/ranges'
266
+ require 'mutant/zombifier'
267
+ require 'mutant/range'
268
+ require 'mutant/license'
269
+ require 'mutant/license/subscription'
270
+ require 'mutant/license/subscription/opensource'
271
+ require 'mutant/license/subscription/commercial'
272
+ require 'mutant/segment'
273
+ require 'mutant/segment/recorder'
274
+ end
275
+ # rubocop:enable Metrics/BlockLength
276
+
277
+ gen_id = SecureRandom.method(:uuid)
278
+
279
+ # Transform boot events into segments
280
+ if instance_variable_defined?(:@executable_timestamp)
281
+ recording_start = @executable_timestamp
282
+
283
+ executable_segment =
284
+ Segment.new(
285
+ id: gen_id.call,
286
+ name: :executable,
287
+ parent_id: nil,
288
+ timestamp_end: nil,
289
+ timestamp_start: @executable_timestamp
290
+ )
291
+
292
+ remove_instance_variable(:@executable_timestamp)
293
+ else
294
+ recording_start = library_timestamp
295
+ end
296
+
297
+ library_segment = Segment.new(
298
+ id: gen_id.call,
299
+ name: :library,
300
+ parent_id: executable_segment&.id,
301
+ timestamp_end: nil,
302
+ timestamp_start: library_timestamp
303
+ )
304
+
305
+ boot_segments = boot_events.map do |name, timestamp_start, timestamp_end|
306
+ Segment.new(
307
+ id: gen_id.call,
308
+ name: name,
309
+ parent_id: library_segment.id,
310
+ timestamp_end: timestamp_end,
311
+ timestamp_start: timestamp_start
312
+ )
313
+ end
314
+
315
+ timer = Timer.new(Process)
316
+
317
+ recorder = Segment::Recorder.new(
318
+ gen_id: gen_id,
319
+ root_id: (executable_segment || library_segment).id,
320
+ parent_id: library_segment.id,
321
+ recording_start: recording_start,
322
+ segments: [*executable_segment, library_segment, *boot_segments],
323
+ timer: timer
324
+ )
249
325
 
250
- module Mutant
251
326
  WORLD = World.new(
252
327
  condition_variable: ConditionVariable,
253
328
  environment_variables: ENV,
@@ -264,10 +339,11 @@ module Mutant
264
339
  pathname: Pathname,
265
340
  process: Process,
266
341
  random: Random,
342
+ recorder: recorder,
267
343
  stderr: $stderr,
268
344
  stdout: $stdout,
269
345
  thread: Thread,
270
- timer: Timer.new(Process)
346
+ timer: timer
271
347
  )
272
348
 
273
349
  # Reopen class to initialize constant to avoid dep circle
@@ -281,8 +357,8 @@ module Mutant
281
357
  Expression::Namespace::Exact,
282
358
  Expression::Namespace::Recursive
283
359
  ]),
284
- fail_fast: false,
285
360
  environment_variables: EMPTY_HASH,
361
+ fail_fast: false,
286
362
  hooks: EMPTY_ARRAY,
287
363
  includes: EMPTY_ARRAY,
288
364
  integration: nil,
@@ -308,3 +384,4 @@ module Mutant
308
384
  )
309
385
  end
310
386
  end # Mutant
387
+ # rubocop:enable Metrics/ModuleLength
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mutant
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.11.16
4
+ version: 0.11.17
5
5
  platform: ruby
6
6
  authors:
7
7
  - Markus Schirp
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-09-11 00:00:00.000000000 Z
11
+ date: 2022-11-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: diff-lcs
@@ -356,6 +356,8 @@ files:
356
356
  - lib/mutant/runner.rb
357
357
  - lib/mutant/runner/sink.rb
358
358
  - lib/mutant/scope.rb
359
+ - lib/mutant/segment.rb
360
+ - lib/mutant/segment/recorder.rb
359
361
  - lib/mutant/selector.rb
360
362
  - lib/mutant/selector/expression.rb
361
363
  - lib/mutant/selector/null.rb