summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--LEGAL27
-rw-r--r--common.mk2
-rw-r--r--spec/lib/turbo_tests.rb85
-rw-r--r--spec/lib/turbo_tests/cli.rb116
-rw-r--r--spec/lib/turbo_tests/json_rows_formatter.rb171
-rw-r--r--spec/lib/turbo_tests/reporter.rb166
-rw-r--r--spec/lib/turbo_tests/runner.rb282
-rw-r--r--spec/lib/turbo_tests/version.rb3
-rw-r--r--spec/lib/utils/hash_extension.rb7
-rw-r--r--tool/bundler/dev_gems.rb.lock4
10 files changed, 3 insertions, 860 deletions
diff --git a/LEGAL b/LEGAL
index ee01de962b..55c7ffc291 100644
--- a/LEGAL
+++ b/LEGAL
@@ -371,33 +371,6 @@ mentioned below.
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-[spec/lib/turbo_tests/*]
-[spec/lib/turbo_tests.rb]
-[spec/lib/utils/*]
-
- These files are under the MIT License.
-
- >>>
- Copyright (c) 2020 Ilya Zub
-
- Permission is hereby granted, free of charge, to any person obtaining a copy
- of this software and associated documentation files (the "Software"), to deal
- in the Software without restriction, including without limitation the rights
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- copies of the Software, and to permit persons to whom the Software is
- furnished to do so, subject to the following conditions:
-
- The above copyright notice and this permission notice shall be included in
- all copies or substantial portions of the Software.
-
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- THE SOFTWARE.
-
[parse.c]
[parse.h]
diff --git a/common.mk b/common.mk
index 3323a60d2a..f96250d998 100644
--- a/common.mk
+++ b/common.mk
@@ -1682,7 +1682,7 @@ yes-test-bundler-parallel: $(PREPARE_BUNDLER)
-I$(srcdir)/spec/bundler \
-e "ruby = ENV['RUBY']" \
-e "ARGV[-1] = File.expand_path(ARGV[-1])" \
- -e "ENV['PARALLEL_TESTS_EXECUTABLE'] = ruby + ARGV.shift" \
+ -e "ENV['RSPEC_EXECUTABLE'] = ruby + ARGV.shift" \
-e "load ARGV.shift" \
" -C $(srcdir) -Ispec/bundler -Ispec/lib .bundle/bin/rspec -r spec_helper" \
$(srcdir)/spec/bin/parallel_rspec $(RSPECOPTS) \
diff --git a/spec/lib/turbo_tests.rb b/spec/lib/turbo_tests.rb
deleted file mode 100644
index afb362bd16..0000000000
--- a/spec/lib/turbo_tests.rb
+++ /dev/null
@@ -1,85 +0,0 @@
-# frozen_string_literal: true
-
-require "securerandom"
-require "open3"
-require "fileutils"
-require "json"
-
-require "rspec"
-
-require "parallel_tests"
-require "parallel_tests/rspec/runner"
-
-require "turbo_tests/reporter"
-require "turbo_tests/runner"
-require "turbo_tests/json_rows_formatter"
-
-module TurboTests
- autoload :CLI, "turbo_tests/cli"
- autoload :VERSION, "turbo_tests/version"
-
- FakeException = Struct.new(:backtrace, :message, :cause)
- class FakeException
- def self.from_obj(obj)
- if obj
- klass =
- Class.new(FakeException) {
- define_singleton_method(:name) do
- obj[:class_name]
- end
- }
-
- klass.new(
- obj[:backtrace],
- obj[:message],
- FakeException.from_obj(obj[:cause])
- )
- end
- end
- end
-
- FakeExecutionResult = Struct.new(:example_skipped?, :pending_message, :status, :pending_fixed?, :exception, :pending_exception)
- class FakeExecutionResult
- def self.from_obj(obj)
- new(
- obj[:example_skipped?],
- obj[:pending_message],
- obj[:status].to_sym,
- obj[:pending_fixed?],
- FakeException.from_obj(obj[:exception]),
- FakeException.from_obj(obj[:exception])
- )
- end
- end
-
- FakeExample = Struct.new(:execution_result, :location, :description, :full_description, :metadata, :location_rerun_argument)
- class FakeExample
- def self.from_obj(obj)
- metadata = obj[:metadata]
-
- metadata[:shared_group_inclusion_backtrace].map! do |frame|
- RSpec::Core::SharedExampleGroupInclusionStackFrame.new(
- frame[:shared_group_name],
- frame[:inclusion_location]
- )
- end
-
- metadata[:shared_group_inclusion_backtrace] = metadata.delete(:shared_group_inclusion_backtrace)
-
- new(
- FakeExecutionResult.from_obj(obj[:execution_result]),
- obj[:location],
- obj[:description],
- obj[:full_description],
- metadata,
- obj[:location_rerun_argument]
- )
- end
-
- def notification
- RSpec::Core::Notifications::ExampleNotification.for(
- self
- )
- end
- end
-end
diff --git a/spec/lib/turbo_tests/cli.rb b/spec/lib/turbo_tests/cli.rb
deleted file mode 100644
index 6f033cc6d3..0000000000
--- a/spec/lib/turbo_tests/cli.rb
+++ /dev/null
@@ -1,116 +0,0 @@
-# frozen_string_literal: true
-
-require "optparse"
-
-module TurboTests
- class CLI
- def initialize(argv)
- @argv = argv
- end
-
- def run
- requires = []
- formatters = []
- tags = []
- count = nil
- runtime_log = nil
- verbose = false
- fail_fast = nil
- seed = nil
-
- OptionParser.new { |opts|
- opts.banner = <<~BANNER
- Run all tests in parallel, giving each process ENV['TEST_ENV_NUMBER'] ('1', '2', '3', ...).
-
- Reports test results incrementally. Uses methods from `parallel_tests` gem to split files to groups.
-
- Source code of `turbo_tests` gem is based on Discourse and RubyGems work in this area (see README file of the source repository).
-
- Usage: turbo_tests [options]
-
- [optional] Only selected files & folders:
- turbo_tests spec/bar spec/baz/xxx_spec.rb
-
- Options:
- BANNER
-
- opts.on("-n [PROCESSES]", Integer, "How many processes to use, default: available CPUs") { |n| count = n }
-
- opts.on("-r", "--require PATH", "Require a file.") do |filename|
- requires << filename
- end
-
- opts.on("-f", "--format FORMATTER", "Choose a formatter. Available formatters: progress (p), documentation (d). Default: progress") do |name|
- formatters << {
- name: name,
- outputs: []
- }
- end
-
- opts.on("-t", "--tag TAG", "Run examples with the specified tag.") do |tag|
- tags << tag
- end
-
- opts.on("-o", "--out FILE", "Write output to a file instead of $stdout") do |filename|
- if formatters.empty?
- formatters << {
- name: "progress",
- outputs: []
- }
- end
- formatters.last[:outputs] << filename
- end
-
- opts.on("--runtime-log FILE", "Location of previously recorded test runtimes") do |filename|
- runtime_log = filename
- end
-
- opts.on("-v", "--verbose", "More output") do
- verbose = true
- end
-
- opts.on("--fail-fast=[N]") do |n|
- n = begin
- Integer(n)
- rescue
- nil
- end
- fail_fast = n.nil? || n < 1 ? 1 : n
- end
-
- opts.on("--seed SEED", "Seed for rspec") do |s|
- seed = s
- end
- }.parse!(@argv)
-
- requires.each { |f| require(f) }
-
- if formatters.empty?
- formatters << {
- name: "progress",
- outputs: []
- }
- end
-
- formatters.each do |formatter|
- if formatter[:outputs].empty?
- formatter[:outputs] << "-"
- end
- end
-
- exitstatus = TurboTests::Runner.run(
- formatters: formatters,
- tags: tags,
- files: @argv.empty? ? ["spec"] : @argv,
- runtime_log: runtime_log,
- verbose: verbose,
- fail_fast: fail_fast,
- count: count,
- seed: seed
- )
-
- # From https://github.com/serpapi/turbo_tests/pull/20/
- exit exitstatus
- end
- end
-end
diff --git a/spec/lib/turbo_tests/json_rows_formatter.rb b/spec/lib/turbo_tests/json_rows_formatter.rb
deleted file mode 100644
index d0244caba8..0000000000
--- a/spec/lib/turbo_tests/json_rows_formatter.rb
+++ /dev/null
@@ -1,171 +0,0 @@
-# frozen_string_literal: true
-
-require "json"
-require "rspec/core"
-require "rspec/core/formatters"
-require "rspec/core/notifications"
-
-module RSpecExt
- def handle_interrupt
- if RSpec.world.wants_to_quit
- exit!(1)
- else
- RSpec.world.wants_to_quit = true
- end
- end
-end
-
-RSpec::Core::Runner.singleton_class.prepend(RSpecExt)
-
-module TurboTests
- # An RSpec formatter used for each subprocess during parallel test execution
- class JsonRowsFormatter
- RSpec::Core::Formatters.register(
- self,
- :start,
- :close,
- :example_failed,
- :example_passed,
- :example_pending,
- :example_group_started,
- :example_group_finished,
- :message,
- :seed
- )
-
- attr_reader :output
-
- def initialize(output)
- @output = output
- end
-
- def start(notification)
- output_row(
- type: :load_summary,
- summary: load_summary_to_json(notification)
- )
- end
-
- def example_group_started(notification)
- output_row(
- type: :group_started,
- group: group_to_json(notification)
- )
- end
-
- def example_group_finished(notification)
- output_row(
- type: :group_finished,
- group: group_to_json(notification)
- )
- end
-
- def example_passed(notification)
- output_row(
- type: :example_passed,
- example: example_to_json(notification.example)
- )
- end
-
- def example_pending(notification)
- output_row(
- type: :example_pending,
- example: example_to_json(notification.example)
- )
- end
-
- def example_failed(notification)
- output_row(
- type: :example_failed,
- example: example_to_json(notification.example)
- )
- end
-
- def seed(notification)
- output_row(
- type: :seed,
- seed: notification.seed
- )
- end
-
- def close(notification)
- output_row(
- type: :close
- )
- end
-
- def message(notification)
- output_row(
- type: :message,
- message: notification.message
- )
- end
-
- private
-
- def exception_to_json(exception)
- if exception
- {
- class_name: exception.class.name.to_s,
- backtrace: exception.backtrace,
- message: exception.message,
- cause: exception_to_json(exception.cause)
- }
- end
- end
-
- def execution_result_to_json(result)
- {
- example_skipped?: result.example_skipped?,
- pending_message: result.pending_message,
- status: result.status,
- pending_fixed?: result.pending_fixed?,
- exception: exception_to_json(result.exception || result.pending_exception)
- }
- end
-
- def stack_frame_to_json(frame)
- {
- shared_group_name: frame.shared_group_name,
- inclusion_location: frame.inclusion_location
- }
- end
-
- def example_to_json(example)
- {
- execution_result: execution_result_to_json(example.execution_result),
- location: example.location,
- description: example.description,
- full_description: example.full_description,
- metadata: {
- shared_group_inclusion_backtrace:
- example
- .metadata[:shared_group_inclusion_backtrace]
- .map { |frame| stack_frame_to_json(frame) },
- extra_failure_lines: example.metadata[:extra_failure_lines],
- },
- location_rerun_argument: example.location_rerun_argument,
- }
- end
-
- def load_summary_to_json(notification)
- {
- count: notification.count,
- load_time: notification.load_time,
- }
- end
-
- def group_to_json(notification)
- {
- group: {
- description: notification.group.description
- }
- }
- end
-
- def output_row(obj)
- output.puts ENV["RSPEC_FORMATTER_OUTPUT_ID"] + obj.to_json
- output.flush
- end
- end
-end
diff --git a/spec/lib/turbo_tests/reporter.rb b/spec/lib/turbo_tests/reporter.rb
deleted file mode 100644
index 417f06a063..0000000000
--- a/spec/lib/turbo_tests/reporter.rb
+++ /dev/null
@@ -1,166 +0,0 @@
-# frozen_string_literal: true
-
-module TurboTests
- class Reporter
- attr_writer :load_time
-
- def self.from_config(formatter_config, start_time, seed, seed_used)
- reporter = new(start_time, seed, seed_used)
-
- formatter_config.each do |config|
- name, outputs = config.values_at(:name, :outputs)
-
- outputs.map! do |filename|
- filename == "-" ? $stdout : File.open(filename, "w")
- end
-
- reporter.add(name, outputs)
- end
-
- reporter
- end
-
- attr_reader :pending_examples
- attr_reader :failed_examples
-
- def initialize(start_time, seed, seed_used)
- @formatters = []
- @pending_examples = []
- @failed_examples = []
- @all_examples = []
- @messages = []
- @start_time = start_time
- @seed = seed
- @seed_used = seed_used
- @load_time = 0
- @errors_outside_of_examples_count = 0
- end
-
- def add(name, outputs)
- outputs.each do |output|
- formatter_class =
- case name
- when "p", "progress"
- RSpec::Core::Formatters::ProgressFormatter
- when "d", "documentation"
- RSpec::Core::Formatters::DocumentationFormatter
- else
- Kernel.const_get(name)
- end
-
- @formatters << formatter_class.new(output)
- end
- end
-
- # Borrowed from RSpec::Core::Reporter
- # https://github.com/rspec/rspec-core/blob/5699fcdc4723087ff6139af55bd155ad9ad61a7b/lib/rspec/core/reporter.rb#L71
- def report(example_groups)
- start(example_groups)
- begin
- yield self
- ensure
- finish
- end
- end
-
- def start(example_groups, time=RSpec::Core::Time.now)
- @start = time
- @load_time = (@start - @start_time).to_f
-
- report_number_of_tests(example_groups)
- expected_example_count = example_groups.flatten(1).count
-
- delegate_to_formatters(:seed, RSpec::Core::Notifications::SeedNotification.new(@seed, @seed_used))
- delegate_to_formatters(:start, RSpec::Core::Notifications::StartNotification.new(expected_example_count, @load_time))
- end
-
- def report_number_of_tests(groups)
- name = ParallelTests::RSpec::Runner.test_file_name
-
- num_processes = groups.size
- num_tests = groups.map(&:size).sum
- tests_per_process = (num_processes == 0 ? 0 : num_tests.to_f / num_processes).round
-
- puts "#{num_processes} processes for #{num_tests} #{name}s, ~ #{tests_per_process} #{name}s per process"
- end
-
- def group_started(notification)
- delegate_to_formatters(:example_group_started, notification)
- end
-
- def group_finished
- delegate_to_formatters(:example_group_finished, nil)
- end
-
- def example_passed(example)
- delegate_to_formatters(:example_passed, example.notification)
-
- @all_examples << example
- end
-
- def example_pending(example)
- delegate_to_formatters(:example_pending, example.notification)
-
- @all_examples << example
- @pending_examples << example
- end
-
- def example_failed(example)
- delegate_to_formatters(:example_failed, example.notification)
-
- @all_examples << example
- @failed_examples << example
- end
-
- def message(message)
- delegate_to_formatters(:message, RSpec::Core::Notifications::MessageNotification.new(message))
- @messages << message
- end
-
- def error_outside_of_examples(error_message)
- @errors_outside_of_examples_count += 1
- message error_message
- end
-
- def finish
- end_time = RSpec::Core::Time.now
-
- @duration = end_time - @start_time
- delegate_to_formatters :stop, RSpec::Core::Notifications::ExamplesNotification.new(self)
-
- delegate_to_formatters :start_dump, RSpec::Core::Notifications::NullNotification
- delegate_to_formatters(:dump_pending,
- RSpec::Core::Notifications::ExamplesNotification.new(
- self
- ))
- delegate_to_formatters(:dump_failures,
- RSpec::Core::Notifications::ExamplesNotification.new(
- self
- ))
- delegate_to_formatters(:dump_summary,
- RSpec::Core::Notifications::SummaryNotification.new(
- end_time - @start_time,
- @all_examples,
- @failed_examples,
- @pending_examples,
- @load_time,
- @errors_outside_of_examples_count
- ))
- delegate_to_formatters(:seed,
- RSpec::Core::Notifications::SeedNotification.new(
- @seed,
- @seed_used,
- ))
- ensure
- delegate_to_formatters :close, RSpec::Core::Notifications::NullNotification
- end
-
- protected
-
- def delegate_to_formatters(method, *args)
- @formatters.each do |formatter|
- formatter.send(method, *args) if formatter.respond_to?(method)
- end
- end
- end
-end
diff --git a/spec/lib/turbo_tests/runner.rb b/spec/lib/turbo_tests/runner.rb
deleted file mode 100644
index 775e8d3ce1..0000000000
--- a/spec/lib/turbo_tests/runner.rb
+++ /dev/null
@@ -1,282 +0,0 @@
-# frozen_string_literal: true
-
-require "json"
-require "parallel_tests/rspec/runner"
-
-require_relative "../utils/hash_extension"
-
-module TurboTests
- class Runner
- using CoreExtensions
-
- def self.run(opts = {})
- files = opts[:files]
- formatters = opts[:formatters]
- tags = opts[:tags]
-
- start_time = opts.fetch(:start_time) { RSpec::Core::Time.now }
- runtime_log = opts.fetch(:runtime_log, nil)
- verbose = opts.fetch(:verbose, false)
- fail_fast = opts.fetch(:fail_fast, nil)
- count = opts.fetch(:count, nil)
- seed = opts.fetch(:seed)
- seed_used = !seed.nil?
-
- if verbose
- warn "VERBOSE"
- end
-
- reporter = Reporter.from_config(formatters, start_time, seed, seed_used)
-
- new(
- reporter: reporter,
- files: files,
- tags: tags,
- runtime_log: runtime_log,
- verbose: verbose,
- fail_fast: fail_fast,
- count: count,
- seed: seed,
- seed_used: seed_used,
- ).run
- end
-
- def initialize(opts)
- @reporter = opts[:reporter]
- @files = opts[:files]
- @tags = opts[:tags]
- @runtime_log = opts[:runtime_log] || "tmp/turbo_rspec_runtime.log"
- @verbose = opts[:verbose]
- @fail_fast = opts[:fail_fast]
- @count = opts[:count]
- @seed = opts[:seed]
- @seed_used = opts[:seed_used]
-
- @load_time = 0
- @load_count = 0
- @failure_count = 0
-
- @messages = Thread::Queue.new
- @threads = []
- @error = false
- end
-
- def run
- @num_processes = [
- ParallelTests.determine_number_of_processes(@count),
- ParallelTests::RSpec::Runner.tests_with_size(@files, {}).size
- ].min
-
- use_runtime_info = @files == ["spec"]
-
- group_opts = {}
-
- if use_runtime_info
- group_opts[:runtime_log] = @runtime_log
- else
- group_opts[:group_by] = :filesize
- end
-
- tests_in_groups =
- ParallelTests::RSpec::Runner.tests_in_groups(
- @files,
- @num_processes,
- **group_opts
- )
-
- subprocess_opts = {
- record_runtime: use_runtime_info,
- }
-
- @reporter.report(tests_in_groups) do |reporter|
- wait_threads = tests_in_groups.map.with_index do |tests, process_id|
- start_regular_subprocess(tests, process_id + 1, **subprocess_opts)
- end
-
- handle_messages
-
- @threads.each(&:join)
-
- if @reporter.failed_examples.empty? && wait_threads.map(&:value).all?(&:success?)
- 0
- else
- # From https://github.com/serpapi/turbo_tests/pull/20/
- wait_threads.map { |thread| thread.value.exitstatus }.max
- end
- end
- end
-
- private
-
- def start_regular_subprocess(tests, process_id, **opts)
- start_subprocess(
- {"TEST_ENV_NUMBER" => process_id.to_s},
- @tags.map { |tag| "--tag=#{tag}" },
- tests,
- process_id,
- **opts
- )
- end
-
- def start_subprocess(env, extra_args, tests, process_id, record_runtime:)
- if tests.empty?
- @messages << {
- type: "exit",
- process_id: process_id,
- }
- else
- env["RSPEC_FORMATTER_OUTPUT_ID"] = SecureRandom.uuid
- env["RUBYOPT"] = ["-I#{File.expand_path("..", __dir__)}", ENV["RUBYOPT"]].compact.join(" ")
- env["RSPEC_SILENCE_FILTER_ANNOUNCEMENTS"] = "1"
-
- if ENV["PARALLEL_TESTS_EXECUTABLE"]
- command_name = ENV["PARALLEL_TESTS_EXECUTABLE"].split
- elsif ENV["BUNDLE_BIN_PATH"]
- command_name = [ENV["BUNDLE_BIN_PATH"], "exec", "rspec"]
- else
- command_name = "rspec"
- end
-
- record_runtime_options =
- if record_runtime
- [
- "--format", "ParallelTests::RSpec::RuntimeLogger",
- "--out", @runtime_log,
- ]
- else
- []
- end
-
- seed_option = if @seed_used
- [
- "--seed", @seed,
- ]
- else
- []
- end
-
- command = [
- *command_name,
- *extra_args,
- *seed_option,
- "--format", "TurboTests::JsonRowsFormatter",
- *record_runtime_options,
- *tests,
- ]
-
- if @verbose
- command_str = [
- env.map { |k, v| "#{k}=#{v}" }.join(" "),
- command.join(" "),
- ].select { |x| x.size > 0 }.join(" ")
-
- warn "Process #{process_id}: #{command_str}"
- end
-
- stdin, stdout, stderr, wait_thr = Open3.popen3(env, *command)
- stdin.close
-
- @threads <<
- Thread.new do
- stdout.each_line do |line|
- result = line.split(env["RSPEC_FORMATTER_OUTPUT_ID"])
-
- output = result.shift
- print(output) unless output.empty?
-
- message = result.shift
- next unless message
-
- message = JSON.parse(message, symbolize_names: true)
- message[:process_id] = process_id
- @messages << message
- end
-
- @messages << { type: "exit", process_id: process_id }
- end
-
- @threads << start_copy_thread(stderr, STDERR)
-
- @threads << Thread.new do
- unless wait_thr.value.success?
- @messages << { type: "error" }
- end
- end
-
- wait_thr
- end
- end
-
- def start_copy_thread(src, dst)
- Thread.new do
- loop do
- msg = src.readpartial(4096)
- rescue EOFError
- src.close
- break
- else
- dst.write(msg)
- end
- end
- end
-
- def handle_messages
- exited = 0
-
- loop do
- message = @messages.pop
- case message[:type]
- when "example_passed"
- example = FakeExample.from_obj(message[:example])
- @reporter.example_passed(example)
- when "group_started"
- @reporter.group_started(message[:group].to_struct)
- when "group_finished"
- @reporter.group_finished
- when "example_pending"
- example = FakeExample.from_obj(message[:example])
- @reporter.example_pending(example)
- when "load_summary"
- message = message[:summary]
- # NOTE: notifications order and content is not guaranteed hence the fetch
- # and count increment tracking to get the latest accumulated load time
- @reporter.load_time = message[:load_time] if message.fetch(:count, 0) > @load_count
- when "example_failed"
- example = FakeExample.from_obj(message[:example])
- @reporter.example_failed(example)
- @failure_count += 1
- if fail_fast_met
- @threads.each(&:kill)
- break
- end
- when "message"
- if message[:message].include?("An error occurred") || message[:message].include?("occurred outside of examples")
- @reporter.error_outside_of_examples(message[:message])
- @error = true
- else
- @reporter.message(message[:message])
- end
- when "seed"
- when "close"
- when "error"
- # Do nothing
- nil
- when "exit"
- exited += 1
- if exited == @num_processes
- break
- end
- else
- STDERR.puts("Unhandled message in main process: #{message}")
- end
-
- STDOUT.flush
- end
- rescue Interrupt
- end
-
- def fail_fast_met
- !@fail_fast.nil? && @failure_count >= @fail_fast
- end
- end
-end
diff --git a/spec/lib/turbo_tests/version.rb b/spec/lib/turbo_tests/version.rb
deleted file mode 100644
index 4fa53b6dbf..0000000000
--- a/spec/lib/turbo_tests/version.rb
+++ /dev/null
@@ -1,3 +0,0 @@
-module TurboTests
- VERSION = "2.2.4"
-end
diff --git a/spec/lib/utils/hash_extension.rb b/spec/lib/utils/hash_extension.rb
deleted file mode 100644
index ba7cee6871..0000000000
--- a/spec/lib/utils/hash_extension.rb
+++ /dev/null
@@ -1,7 +0,0 @@
-module CoreExtensions
- refine Hash do
- def to_struct
- Struct.new(*self.keys).new(*self.values.map { |value| value.is_a?(Hash) ? value.to_struct : value })
- end
- end
-end
diff --git a/tool/bundler/dev_gems.rb.lock b/tool/bundler/dev_gems.rb.lock
index 07dce697c4..bfbc32de83 100644
--- a/tool/bundler/dev_gems.rb.lock
+++ b/tool/bundler/dev_gems.rb.lock
@@ -54,7 +54,7 @@ GEM
rspec-support (3.13.1)
test-unit (3.6.2)
power_assert
- turbo_tests (2.2.3)
+ turbo_tests (2.2.5)
parallel_tests (>= 3.3.0, < 5)
rspec (>= 3.10)
@@ -112,7 +112,7 @@ CHECKSUMS
rspec-mocks (3.13.0) sha256=735a891215758d77cdb5f4721fffc21078793959d1f0ee4a961874311d9b7f66
rspec-support (3.13.1) sha256=48877d4f15b772b7538f3693c22225f2eda490ba65a0515c4e7cf6f2f17de70f
test-unit (3.6.2) sha256=3ce480c23990ca504a3f0d6619be2a560e21326cefd1b86d0f9433c387f26039
- turbo_tests (2.2.3) sha256=c1a8763361a019c3ff68e8a47c5e1acb32c1e7668f9d4a4e08416ca4786ea8a0
+ turbo_tests (2.2.5) sha256=3fa31497d12976d11ccc298add29107b92bda94a90d8a0a5783f06f05102509f
BUNDLED WITH
2.7.0.dev