Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package rubygem-parallel_tests for openSUSE:Factory checked in at 2022-08-07 18:33:55 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/rubygem-parallel_tests (Old) and /work/SRC/openSUSE:Factory/.rubygem-parallel_tests.new.1521 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "rubygem-parallel_tests" Sun Aug 7 18:33:55 2022 rev:14 rq:993507 version:3.11.1 Changes: -------- --- /work/SRC/openSUSE:Factory/rubygem-parallel_tests/rubygem-parallel_tests.changes 2022-05-02 16:24:49.692788746 +0200 +++ /work/SRC/openSUSE:Factory/.rubygem-parallel_tests.new.1521/rubygem-parallel_tests.changes 2022-08-07 18:34:03.389174951 +0200 @@ -1,0 +2,6 @@ +Thu Aug 4 13:22:05 UTC 2022 - Stephan Kulow <co...@suse.com> + +updated to version 3.11.1 + no changelog found + +------------------------------------------------------------------- Old: ---- parallel_tests-3.8.1.gem New: ---- parallel_tests-3.11.1.gem ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ rubygem-parallel_tests.spec ++++++ --- /var/tmp/diff_new_pack.3Y7fPS/_old 2022-08-07 18:34:03.821176207 +0200 +++ /var/tmp/diff_new_pack.3Y7fPS/_new 2022-08-07 18:34:03.833176242 +0200 @@ -24,7 +24,7 @@ # Name: rubygem-parallel_tests -Version: 3.8.1 +Version: 3.11.1 Release: 0 %define mod_name parallel_tests %define mod_full_name %{mod_name}-%{version} ++++++ parallel_tests-3.8.1.gem -> parallel_tests-3.11.1.gem ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Readme.md new/Readme.md --- old/Readme.md 2022-03-28 18:29:01.000000000 +0200 +++ new/Readme.md 2022-06-26 00:51:53.000000000 +0200 @@ -42,7 +42,7 @@ ### Setup environment from scratch (create db and loads schema, useful for CI) rake parallel:setup - + ### Drop all test databases rake parallel:drop @@ -193,15 +193,15 @@ - use `ENV['TEST_ENV_NUMBER']` inside your tests to select separate db/memcache/etc. (docker compose: expose it) - Only run a subset of files / folders: - + `parallel_test test/bar test/baz/foo_text.rb` - Pass test-options and files via `--`: - + `parallel_rspec -- -t acceptance -f progress -- spec/foo_spec.rb spec/acceptance` - + - Pass in test options, by using the -o flag (wrap everything in quotes): - + `parallel_cucumber -n 2 -o '-p foo_profile --tags @only_this_tag or @only_that_tag --format summary'` Options are: @@ -402,6 +402,7 @@ - [Vikram B Kumar](https://github.com/v-kumar) - [Joshua Pinter](https://github.com/joshuapinter) - [Zach Dennis](https://github.com/zdennis) + - [Jon Dufresne](https://github.com/jdufresne) [Michael Grosser](http://grosser.it)<br/> mich...@grosser.it<br/> Binary files old/checksums.yaml.gz and new/checksums.yaml.gz differ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/parallel_tests/cli.rb new/lib/parallel_tests/cli.rb --- old/lib/parallel_tests/cli.rb 2022-03-28 18:29:01.000000000 +0200 +++ new/lib/parallel_tests/cli.rb 2022-06-26 00:51:53.000000000 +0200 @@ -20,7 +20,7 @@ options[:first_is_1] ||= first_is_1? if options[:execute] - execute_shell_command_in_parallel(options[:execute], num_processes, options) + execute_command_in_parallel(options[:execute], num_processes, options) else run_tests_in_parallel(num_processes, options) end @@ -61,20 +61,15 @@ groups = @runner.tests_in_groups(options[:files], num_processes, options) groups.reject!(&:empty?) - test_results = if options[:only_group] - groups_to_run = options[:only_group].map { |i| groups[i - 1] }.compact - report_number_of_tests(groups_to_run) unless options[:quiet] - execute_in_parallel(groups_to_run, groups_to_run.size, options) do |group| - run_tests(group, groups_to_run.index(group), 1, options) - end - else - report_number_of_tests(groups) unless options[:quiet] - - execute_in_parallel(groups, groups.size, options) do |group| - run_tests(group, groups.index(group), num_processes, options) - end + if options[:only_group] + groups = options[:only_group].map { |i| groups[i - 1] }.compact + num_processes = 1 end + report_number_of_tests(groups) unless options[:quiet] + test_results = execute_in_parallel(groups, groups.size, options) do |group| + run_tests(group, groups.index(group), num_processes, options) + end report_results(test_results, options) unless options[:quiet] end @@ -100,7 +95,7 @@ def run_tests(group, process_number, num_processes, options) if group.empty? - { stdout: '', exit_status: 0, command: '', seed: nil } + { stdout: '', exit_status: 0, command: nil, seed: nil } else @runner.run_tests(group, process_number, num_processes, options) end @@ -140,9 +135,8 @@ puts "\n\nTests have failed for a parallel_test group. Use the following command to run the group again:\n\n" failing_sets.each do |failing_set| command = failing_set[:command] - command = command.gsub(/;export [A-Z_]+;/, ' ') # remove ugly export statements command = @runner.command_with_seed(command, failing_set[:seed]) if failing_set[:seed] - puts command + puts Shellwords.shelljoin(command) end end end @@ -229,7 +223,7 @@ processes in a specific formation. Commas indicate specs in the same process, pipes indicate specs in a new process. Cannot use with --single, --isolate, or --isolate-n. Ex. - $ parallel_tests -n 3 . --specify-groups '1_spec.rb,2_spec.rb|3_spec.rb' + $ parallel_test -n 3 . --specify-groups '1_spec.rb,2_spec.rb|3_spec.rb' Process 1 will contain 1_spec.rb and 2_spec.rb Process 2 will contain 3_spec.rb Process 3 will contain all other specs @@ -238,8 +232,8 @@ opts.on("--only-group INT[,INT]", Array) { |groups| options[:only_group] = groups.map(&:to_i) } - opts.on("-e", "--exec [COMMAND]", "execute this code parallel and with ENV['TEST_ENV_NUMBER']") { |path| options[:execute] = path } - opts.on("-o", "--test-options '[OPTIONS]'", "execute test commands with those options") { |arg| options[:test_options] = arg.lstrip } + opts.on("-e", "--exec [COMMAND]", "execute this code parallel and with ENV['TEST_ENV_NUMBER']") { |arg| options[:execute] = Shellwords.shellsplit(arg) } + opts.on("-o", "--test-options '[OPTIONS]'", "execute test commands with those options") { |arg| options[:test_options] = Shellwords.shellsplit(arg) } opts.on("-t", "--type [TYPE]", "test(default) / rspec / cucumber / spinach") do |type| @runner = load_runner(type) rescue NameError, LoadError => e @@ -334,8 +328,8 @@ new_opts = extract_test_options(argv) return if new_opts.empty? - prev_and_new = [options[:test_options], new_opts.shelljoin] - options[:test_options] = prev_and_new.compact.join(' ') + options[:test_options] ||= [] + options[:test_options] += new_opts end def load_runner(type) @@ -345,7 +339,7 @@ klass_name.split('::').inject(Object) { |x, y| x.const_get(y) } end - def execute_shell_command_in_parallel(command, num_processes, options) + def execute_command_in_parallel(command, num_processes, options) runs = if options[:only_group] options[:only_group].map { |g| g - 1 } else diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/parallel_tests/cucumber/runner.rb new/lib/parallel_tests/cucumber/runner.rb --- old/lib/parallel_tests/cucumber/runner.rb 2022-03-28 18:29:01.000000000 +0200 +++ new/lib/parallel_tests/cucumber/runner.rb 2022-06-26 00:51:53.000000000 +0200 @@ -35,8 +35,8 @@ end def command_with_seed(cmd, seed) - clean = cmd.sub(/\s--order\s+random(:\d+)?\b/, '') - "#{clean} --order random:#{seed}" + clean = remove_command_arguments(cmd, '--order') + [*clean, '--order', "random:#{seed}"] end end end diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/parallel_tests/cucumber/scenarios.rb new/lib/parallel_tests/cucumber/scenarios.rb --- old/lib/parallel_tests/cucumber/scenarios.rb 2022-03-28 18:29:01.000000000 +0200 +++ new/lib/parallel_tests/cucumber/scenarios.rb 2022-06-26 00:51:53.000000000 +0200 @@ -4,7 +4,6 @@ require 'cucumber' require 'parallel_tests/cucumber/scenario_line_logger' require 'parallel_tests/gherkin/listener' -require 'shellwords' begin gem "cuke_modeler", "~> 3.0" @@ -20,7 +19,7 @@ def all(files, options = {}) # Parse tag expression from given test options and ignore tag pattern. Refer here to understand how new tag expression syntax works - https://github.com/cucumber/cucumber/tree/master/tag-expressions tags = [] - words = options[:test_options].to_s.shellsplit + words = options[:test_options] || [] words.each_with_index { |w, i| tags << words[i + 1] if ["-t", "--tags"].include?(w) } if ignore = options[:ignore_tag_pattern] tags << "not (#{ignore})" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/parallel_tests/gherkin/runner.rb new/lib/parallel_tests/gherkin/runner.rb --- old/lib/parallel_tests/gherkin/runner.rb 2022-03-28 18:29:01.000000000 +0200 +++ new/lib/parallel_tests/gherkin/runner.rb 2022-06-26 00:51:53.000000000 +0200 @@ -1,6 +1,5 @@ # frozen_string_literal: true require "parallel_tests/test/runner" -require 'shellwords' module ParallelTests module Gherkin @@ -16,17 +15,13 @@ end end - sanitized_test_files = combined_scenarios.map { |val| WINDOWS ? "\"#{val}\"" : Shellwords.escape(val) } - options[:env] ||= {} options[:env] = options[:env].merge({ 'AUTOTEST' => '1' }) if $stdout.tty? - cmd = [ - executable, - (runtime_logging if File.directory?(File.dirname(runtime_log))), - *sanitized_test_files, - cucumber_opts(options[:test_options]) - ].compact.reject(&:empty?).join(' ') + cmd = executable + cmd += runtime_logging if File.directory?(File.dirname(runtime_log)) + cmd += combined_scenarios + cmd += cucumber_opts(options[:test_options]) execute_command(cmd, process_number, num_processes, options) end @@ -67,17 +62,17 @@ end def cucumber_opts(given) - if given =~ (/--profile/) || given =~ (/(^|\s)-p /) + if given&.include?('--profile') || given&.include?('-p') given else - [given, profile_from_config].compact.join(" ") + [*given, *profile_from_config] end end def profile_from_config # copied from https://github.com/cucumber/cucumber/blob/master/lib/cucumber/cli/profile_loader.rb#L85 config = Dir.glob("{,.config/,config/}#{name}{.yml,.yaml}").first - "--profile parallel" if config && File.read(config) =~ /^parallel:/ + ['--profile', 'parallel'] if config && File.read(config) =~ /^parallel:/ end def tests_in_groups(tests, num_groups, options = {}) @@ -91,7 +86,7 @@ end def runtime_logging - "--format ParallelTests::Gherkin::RuntimeLogger --out #{runtime_log}" + ['--format', 'ParallelTests::Gherkin::RuntimeLogger', '--out', runtime_log] end def runtime_log @@ -102,11 +97,11 @@ if File.exist?("bin/#{name}") ParallelTests.with_ruby_binary("bin/#{name}") elsif ParallelTests.bundler_enabled? - "bundle exec #{name}" + ["bundle", "exec", name] elsif File.file?("script/#{name}") ParallelTests.with_ruby_binary("script/#{name}") else - name.to_s + [name.to_s] end end end diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/parallel_tests/rspec/runner.rb new/lib/parallel_tests/rspec/runner.rb --- old/lib/parallel_tests/rspec/runner.rb 2022-03-28 18:29:01.000000000 +0200 +++ new/lib/parallel_tests/rspec/runner.rb 2022-06-26 00:51:53.000000000 +0200 @@ -7,8 +7,7 @@ DEV_NULL = (WINDOWS ? "NUL" : "/dev/null") class << self def run_tests(test_files, process_number, num_processes, options) - exe = executable # expensive, so we cache - cmd = [exe, options[:test_options], color, spec_opts, *test_files].compact.join(" ") + cmd = [*executable, *options[:test_options], *color, *spec_opts, *test_files] execute_command(cmd, process_number, num_processes, options) end @@ -16,9 +15,9 @@ if File.exist?("bin/rspec") ParallelTests.with_ruby_binary("bin/rspec") elsif ParallelTests.bundler_enabled? - "bundle exec rspec" + ["bundle", "exec", "rspec"] else - "rspec" + ["rspec"] end end @@ -48,8 +47,8 @@ # --order rand:1234 # --order random:1234 def command_with_seed(cmd, seed) - clean = cmd.sub(/\s--(seed\s+\d+|order\s+rand(om)?(:\d+)?)\b/, '') - "#{clean} --seed #{seed}" + clean = remove_command_arguments(cmd, '--seed', '--order') + [*clean, '--seed', seed] end # Summarize results from threads and colorize results based on failure and pending counts. @@ -71,19 +70,13 @@ private - # so it can be stubbed.... - def run(cmd) - `#{cmd}` - end - def color - '--color --tty' if $stdout.tty? + ['--color', '--tty'] if $stdout.tty? end def spec_opts options_file = ['.rspec_parallel', 'spec/parallel_spec.opts', 'spec/spec.opts'].detect { |f| File.file?(f) } - return unless options_file - "-O #{options_file}" + ["-O", options_file] if options_file end end end diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/parallel_tests/tasks.rb new/lib/parallel_tests/tasks.rb --- old/lib/parallel_tests/tasks.rb 2022-03-28 18:29:01.000000000 +0200 +++ new/lib/parallel_tests/tasks.rb 2022-06-26 00:51:53.000000000 +0200 @@ -9,16 +9,8 @@ 'test' end - def rake_bin - # Prevent 'Exec format error' Errno::ENOEXEC on Windows - return "rake" if RUBY_PLATFORM =~ /mswin|mingw|cygwin/ - binstub_path = File.join('bin', 'rake') - return binstub_path if File.exist?(binstub_path) - "rake" - end - def load_lib - $LOAD_PATH << File.expand_path(File.join(File.dirname(__FILE__), '..')) + $LOAD_PATH << File.expand_path('..', __dir__) require "parallel_tests" end @@ -30,12 +22,15 @@ def run_in_parallel(cmd, options = {}) load_lib - count = " -n #{options[:count]}" unless options[:count].to_s.empty? + # Using the relative path to find the binary allow to run a specific version of it executable = File.expand_path('../../bin/parallel_test', __dir__) - non_parallel = (options[:non_parallel] ? ' --non-parallel' : '') - command = "#{ParallelTests.with_ruby_binary(Shellwords.escape(executable))} --exec '#{cmd}'#{count}#{non_parallel}" - abort unless system(command) + command = ParallelTests.with_ruby_binary(executable) + command += ['--exec', Shellwords.join(cmd)] + command += ['-n', options[:count]] unless options[:count].to_s.empty? + command << '--non-parallel' if options[:non_parallel] + + abort unless system(*command) end # this is a crazy-complex solution for a very simple problem: @@ -48,16 +43,14 @@ # - pipefail makes pipe fail with exitstatus of first failed command # - pipefail is not supported in (zsh) # - defining a new rake task like silence_schema would force users to load parallel_tests in test env - # - do not use ' since run_in_parallel uses them to quote stuff # - simple system "set -o pipefail" returns nil even though set -o pipefail exists with 0 def suppress_output(command, ignore_regex) activate_pipefail = "set -o pipefail" - remove_ignored_lines = %{(grep -v "#{ignore_regex}" || test 1)} + remove_ignored_lines = %{(grep -v #{Shellwords.escape(ignore_regex)} || true)} - if File.executable?('/bin/bash') && system('/bin/bash', '-c', "#{activate_pipefail} 2>/dev/null && test 1") - # We need to shell escape single quotes (' becomes '"'"') because - # run_in_parallel wraps command in single quotes - %{/bin/bash -c '"'"'#{activate_pipefail} && (#{command}) | #{remove_ignored_lines}'"'"'} + if system('/bin/bash', '-c', "#{activate_pipefail} 2>/dev/null") + shell_command = "#{activate_pipefail} && (#{Shellwords.shelljoin(command)}) | #{remove_ignored_lines}" + ['/bin/bash', '-c', shell_command] else command end @@ -90,7 +83,7 @@ options = args.shift pass_through = args.shift - [num_processes, pattern.to_s, options.to_s, pass_through.to_s] + [num_processes, pattern, options, pass_through] end def schema_format_based_on_rails_version @@ -109,6 +102,29 @@ end end + def build_run_command(type, args) + count, pattern, options, pass_through = ParallelTests::Tasks.parse_args(args) + test_framework = { + 'spec' => 'rspec', + 'test' => 'test', + 'features' => 'cucumber', + 'features-spinach' => 'spinach' + }.fetch(type) + + type = 'features' if test_framework == 'spinach' + + # Using the relative path to find the binary allow to run a specific version of it + executable = File.expand_path('../../bin/parallel_test', __dir__) + executable = ParallelTests.with_ruby_binary(executable) + + command = [*executable, type, '--type', test_framework] + command += ['-n', count.to_s] if count + command += ['--pattern', pattern] if pattern + command += ['--test-options', options] if options + command += Shellwords.shellsplit pass_through if pass_through + command + end + private def rails_7_or_greater? @@ -125,22 +141,28 @@ namespace :parallel do desc "Setup test databases via db:setup --> parallel:setup[num_cpus]" task :setup, :count do |_, args| - command = "#{ParallelTests::Tasks.rake_bin} db:setup RAILS_ENV=#{ParallelTests::Tasks.rails_env}" + command = [$0, "db:setup", "RAILS_ENV=#{ParallelTests::Tasks.rails_env}"] ParallelTests::Tasks.run_in_parallel(ParallelTests::Tasks.suppress_schema_load_output(command), args) end desc "Create test databases via db:create --> parallel:create[num_cpus]" task :create, :count do |_, args| ParallelTests::Tasks.run_in_parallel( - "#{ParallelTests::Tasks.rake_bin} db:create RAILS_ENV=#{ParallelTests::Tasks.rails_env}", args + [$0, "db:create", "RAILS_ENV=#{ParallelTests::Tasks.rails_env}"], + args ) end desc "Drop test databases via db:drop --> parallel:drop[num_cpus]" task :drop, :count do |_, args| ParallelTests::Tasks.run_in_parallel( - "#{ParallelTests::Tasks.rake_bin} db:drop RAILS_ENV=#{ParallelTests::Tasks.rails_env} " \ - "DISABLE_DATABASE_ENVIRONMENT_CHECK=1", args + [ + $0, + "db:drop", + "RAILS_ENV=#{ParallelTests::Tasks.rails_env}", + "DISABLE_DATABASE_ENVIRONMENT_CHECK=1" + ], + args ) end @@ -162,7 +184,7 @@ # slow: dump and load in in serial args = args.to_hash.merge(non_parallel: true) # normal merge returns nil task_name = Rake::Task.task_defined?('db:test:prepare') ? 'db:test:prepare' : 'app:db:test:prepare' - ParallelTests::Tasks.run_in_parallel("#{ParallelTests::Tasks.rake_bin} #{task_name}", args) + ParallelTests::Tasks.run_in_parallel([$0, task_name], args) next end end @@ -171,23 +193,29 @@ desc "Update test databases via db:migrate --> parallel:migrate[num_cpus]" task :migrate, :count do |_, args| ParallelTests::Tasks.run_in_parallel( - "#{ParallelTests::Tasks.rake_bin} db:migrate RAILS_ENV=#{ParallelTests::Tasks.rails_env}", args + [$0, "db:migrate", "RAILS_ENV=#{ParallelTests::Tasks.rails_env}"], + args ) end desc "Rollback test databases via db:rollback --> parallel:rollback[num_cpus]" task :rollback, :count do |_, args| ParallelTests::Tasks.run_in_parallel( - "#{ParallelTests::Tasks.rake_bin} db:rollback RAILS_ENV=#{ParallelTests::Tasks.rails_env}", args + [$0, "db:rollback", "RAILS_ENV=#{ParallelTests::Tasks.rails_env}"], + args ) end # just load the schema (good for integration server <-> no development db) desc "Load dumped schema for test databases via db:schema:load --> parallel:load_schema[num_cpus]" task :load_schema, :count do |_, args| - command = - "#{ParallelTests::Tasks.rake_bin} #{ParallelTests::Tasks.purge_before_load} " \ - "db:schema:load RAILS_ENV=#{ParallelTests::Tasks.rails_env} DISABLE_DATABASE_ENVIRONMENT_CHECK=1" + command = [ + $0, + ParallelTests::Tasks.purge_before_load, + "db:schema:load", + "RAILS_ENV=#{ParallelTests::Tasks.rails_env}", + "DISABLE_DATABASE_ENVIRONMENT_CHECK=1" + ] ParallelTests::Tasks.run_in_parallel(ParallelTests::Tasks.suppress_schema_load_output(command), args) end @@ -196,23 +224,34 @@ desc "Load structure for test databases via db:schema:load --> parallel:load_structure[num_cpus]" task :load_structure, :count do |_, args| ParallelTests::Tasks.run_in_parallel( - "#{ParallelTests::Tasks.rake_bin} #{ParallelTests::Tasks.purge_before_load} " \ - "db:structure:load RAILS_ENV=#{ParallelTests::Tasks.rails_env} DISABLE_DATABASE_ENVIRONMENT_CHECK=1", args + [ + $0, + ParallelTests::Tasks.purge_before_load, + "db:structure:load", + "RAILS_ENV=#{ParallelTests::Tasks.rails_env}", + "DISABLE_DATABASE_ENVIRONMENT_CHECK=1" + ], + args ) end desc "Load the seed data from db/seeds.rb via db:seed --> parallel:seed[num_cpus]" task :seed, :count do |_, args| ParallelTests::Tasks.run_in_parallel( - "#{ParallelTests::Tasks.rake_bin} db:seed RAILS_ENV=#{ParallelTests::Tasks.rails_env}", args + [ + $0, + "db:seed", + "RAILS_ENV=#{ParallelTests::Tasks.rails_env}" + ], + args ) end desc "Launch given rake command in parallel" task :rake, :command, :count do |_, args| ParallelTests::Tasks.run_in_parallel( - "RAILS_ENV=#{ParallelTests::Tasks.rails_env} #{ParallelTests::Tasks.rake_bin} " \ - "#{args.command}", args + [$0, args.command, "RAILS_ENV=#{ParallelTests::Tasks.rails_env}"], + args ) end @@ -221,27 +260,9 @@ task type, [:count, :pattern, :options, :pass_through] do |_t, args| ParallelTests::Tasks.check_for_pending_migrations ParallelTests::Tasks.load_lib + command = ParallelTests::Tasks.build_run_command(type, args) - count, pattern, options, pass_through = ParallelTests::Tasks.parse_args(args) - test_framework = { - 'spec' => 'rspec', - 'test' => 'test', - 'features' => 'cucumber', - 'features-spinach' => 'spinach' - }[type] - - type = 'features' if test_framework == 'spinach' - # Using the relative path to find the binary allow to run a specific version of it - executable = File.join(File.dirname(__FILE__), '..', '..', 'bin', 'parallel_test') - - command = - "#{ParallelTests.with_ruby_binary(Shellwords.escape(executable))} #{type} " \ - "--type #{test_framework} " \ - "-n #{count} " \ - "--pattern '#{pattern}' " \ - "--test-options '#{options}' " \ - "#{pass_through}" - abort unless system(command) # allow to chain tasks e.g. rake parallel:spec parallel:features + abort unless system(*command) # allow to chain tasks e.g. rake parallel:spec parallel:features end end end diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/parallel_tests/test/runner.rb new/lib/parallel_tests/test/runner.rb --- old/lib/parallel_tests/test/runner.rb 2022-03-28 18:29:01.000000000 +0200 +++ new/lib/parallel_tests/test/runner.rb 2022-06-26 00:51:53.000000000 +0200 @@ -1,9 +1,12 @@ # frozen_string_literal: true +require 'shellwords' require 'parallel_tests' module ParallelTests module Test class Runner + RuntimeLogTooSmallError = Class.new(StandardError) + class << self # --- usually overwritten by other runners @@ -25,7 +28,14 @@ def run_tests(test_files, process_number, num_processes, options) require_list = test_files.map { |file| file.gsub(" ", "\\ ") }.join(" ") - cmd = "#{executable} -Itest -e '%w[#{require_list}].each { |f| require %{./\#{f}} }' -- #{options[:test_options]}" + cmd = [ + *executable, + '-Itest', + '-e', + "%w[#{require_list}].each { |f| require %{./\#{f}} }", + '--', + *options[:test_options] + ] execute_command(cmd, process_number, num_processes, options) end @@ -76,22 +86,29 @@ end def execute_command(cmd, process_number, num_processes, options) + number = test_env_number(process_number, options).to_s env = (options[:env] || {}).merge( - "TEST_ENV_NUMBER" => test_env_number(process_number, options).to_s, + "TEST_ENV_NUMBER" => number, "PARALLEL_TEST_GROUPS" => num_processes.to_s, "PARALLEL_PID_FILE" => ParallelTests.pid_file_path ) - cmd = "nice #{cmd}" if options[:nice] - cmd = "#{cmd} 2>&1" if options[:combine_stderr] + cmd = ["nice", *cmd] if options[:nice] + + # being able to run with for example `-output foo-$TEST_ENV_NUMBER` worked originally and is convenient + cmd.map! { |c| c.gsub("$TEST_ENV_NUMBER", number).gsub("${TEST_ENV_NUMBER}", number) } - puts cmd if report_process_command?(options) && !options[:serialize_stdout] + puts Shellwords.shelljoin(cmd) if report_process_command?(options) && !options[:serialize_stdout] execute_command_and_capture_output(env, cmd, options) end def execute_command_and_capture_output(env, cmd, options) pid = nil - output = IO.popen(env, cmd) do |io| + + popen_options = {} + popen_options[:err] = [:child, :out] if options[:combine_stderr] + + output = IO.popen(env, cmd, popen_options) do |io| pid = io.pid ParallelTests.pids.add(pid) capture_output(io, env, options) @@ -100,7 +117,7 @@ exitstatus = $?.exitstatus seed = output[/seed (\d+)/, 1] - output = [cmd, output].join("\n") if report_process_command?(options) && options[:serialize_stdout] + output = "#{Shellwords.shelljoin(cmd)}\n#{output}" if report_process_command?(options) && options[:serialize_stdout] { stdout: output, exit_status: exitstatus, command: cmd, seed: seed } end @@ -129,18 +146,22 @@ # remove old seed and add new seed def command_with_seed(cmd, seed) - clean = cmd.sub(/\s--seed\s+\d+\b/, '') - "#{clean} --seed #{seed}" + clean = remove_command_arguments(cmd, '--seed') + [*clean, '--seed', seed] end protected def executable - ENV['PARALLEL_TESTS_EXECUTABLE'] || determine_executable + if ENV.include?('PARALLEL_TESTS_EXECUTABLE') + [ENV['PARALLEL_TESTS_EXECUTABLE']] + else + determine_executable + end end def determine_executable - "ruby" + ["ruby"] end def sum_up_results(results) @@ -184,7 +205,7 @@ allowed_missing -= 1 unless time = runtimes[test] if allowed_missing < 0 log = options[:runtime_log] || runtime_log - raise "Runtime log file '#{log}' does not contain sufficient data to sort #{tests.size} test files, please update or remove it." + raise RuntimeLogTooSmallError, "Runtime log file '#{log}' does not contain sufficient data to sort #{tests.size} test files, please update or remove it." end [test, time] end @@ -237,6 +258,21 @@ Dir[File.join(folder, pattern)].uniq.sort end + def remove_command_arguments(command, *args) + remove_next = false + command.select do |arg| + if remove_next + remove_next = false + false + elsif args.include?(arg) + remove_next = true + false + else + true + end + end + end + private # fill gaps with unknown-runtime if given, average otherwise diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/parallel_tests/version.rb new/lib/parallel_tests/version.rb --- old/lib/parallel_tests/version.rb 2022-03-28 18:29:01.000000000 +0200 +++ new/lib/parallel_tests/version.rb 2022-06-26 00:51:53.000000000 +0200 @@ -1,4 +1,4 @@ # frozen_string_literal: true module ParallelTests - VERSION = '3.8.1' + VERSION = '3.11.1' end diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/parallel_tests.rb new/lib/parallel_tests.rb --- old/lib/parallel_tests.rb 2022-03-28 18:29:01.000000000 +0200 +++ new/lib/parallel_tests.rb 2022-06-26 00:51:53.000000000 +0200 @@ -76,7 +76,7 @@ end def with_ruby_binary(command) - WINDOWS ? "#{RUBY_BINARY} -- #{command}" : command + WINDOWS ? [RUBY_BINARY, '--', command] : [command] end def wait_for_other_processes_to_finish diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/metadata new/metadata --- old/metadata 2022-03-28 18:29:01.000000000 +0200 +++ new/metadata 2022-06-26 00:51:53.000000000 +0200 @@ -1,14 +1,14 @@ --- !ruby/object:Gem::Specification name: parallel_tests version: !ruby/object:Gem::Version - version: 3.8.1 + version: 3.11.1 platform: ruby authors: - Michael Grosser -autorequire: +autorequire: bindir: bin cert_chain: [] -date: 2022-03-28 00:00:00.000000000 Z +date: 2022-06-25 00:00:00.000000000 Z dependencies: - !ruby/object:Gem::Dependency name: parallel @@ -24,7 +24,7 @@ - - ">=" - !ruby/object:Gem::Version version: '0' -description: +description: email: mich...@grosser.it executables: - parallel_spinach @@ -68,10 +68,10 @@ - MIT metadata: bug_tracker_uri: https://github.com/grosser/parallel_tests/issues - documentation_uri: https://github.com/grosser/parallel_tests/blob/v3.8.1/Readme.md - source_code_uri: https://github.com/grosser/parallel_tests/tree/v3.8.1 + documentation_uri: https://github.com/grosser/parallel_tests/blob/v3.11.1/Readme.md + source_code_uri: https://github.com/grosser/parallel_tests/tree/v3.11.1 wiki_uri: https://github.com/grosser/parallel_tests/wiki -post_install_message: +post_install_message: rdoc_options: [] require_paths: - lib @@ -86,8 +86,8 @@ - !ruby/object:Gem::Version version: '0' requirements: [] -rubygems_version: 3.3.10 -signing_key: +rubygems_version: 3.3.3 +signing_key: specification_version: 4 summary: Run Test::Unit / RSpec / Cucumber / Spinach in parallel test_files: []