test-queue 0.5.0 → 0.7.0
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/test.yml +94 -0
- data/.gitignore +6 -0
- data/Appraisals +43 -0
- data/Gemfile +4 -2
- data/README.md +13 -13
- data/Rakefile +14 -0
- data/{bin → exe}/cucumber-queue +4 -0
- data/{bin → exe}/minitest-queue +4 -0
- data/{bin → exe}/rspec-queue +4 -0
- data/{bin → exe}/testunit-queue +4 -0
- data/gemfiles/cucumber1_3.gemfile +9 -0
- data/gemfiles/cucumber2_4.gemfile +9 -0
- data/gemfiles/minitest4.gemfile +7 -0
- data/gemfiles/minitest5.gemfile +7 -0
- data/gemfiles/rspec2.gemfile +8 -0
- data/gemfiles/rspec3.gemfile +7 -0
- data/gemfiles/rspec4.gemfile +11 -0
- data/gemfiles/testunit.gemfile +7 -0
- data/lib/test-queue.rb +1 -1
- data/lib/test_queue/iterator.rb +1 -1
- data/lib/test_queue/runner/minitest.rb +2 -2
- data/lib/test_queue/runner/minitest4.rb +1 -1
- data/lib/test_queue/runner/minitest5.rb +8 -1
- data/lib/test_queue/runner/puppet_lint.rb +1 -1
- data/lib/test_queue/runner/rspec.rb +8 -3
- data/lib/test_queue/runner/sample.rb +2 -2
- data/lib/test_queue/runner/testunit.rb +1 -1
- data/lib/test_queue/runner.rb +22 -22
- data/lib/test_queue.rb +2 -2
- data/script/bootstrap +1 -0
- data/spec/stats_spec.rb +3 -0
- data/test/minitest4.bats +1 -1
- data/test/minitest5.bats +5 -5
- data/test/{rspec.bats → rspec2.bats} +4 -4
- data/test/rspec3.bats +56 -0
- data/test/rspec4.bats +56 -0
- data/test/samples/sample_shared_examples_for_spec.rb +2 -4
- data/test/samples/sample_spec.rb +3 -3
- data/test/samples/sample_split_spec.rb +1 -1
- data/test/samples/sample_use_shared_example1_spec.rb +1 -2
- data/test/samples/sample_use_shared_example2_spec.rb +1 -2
- data/test/sleepy_runner.rb +3 -1
- data/test-queue.gemspec +4 -3
- metadata +23 -32
- data/.travis.yml +0 -18
- data/Gemfile-cucumber1-3 +0 -4
- data/Gemfile-cucumber1-3.lock +0 -33
- data/Gemfile-cucumber2-4 +0 -4
- data/Gemfile-cucumber2-4.lock +0 -37
- data/Gemfile-minitest4 +0 -3
- data/Gemfile-minitest4.lock +0 -19
- data/Gemfile-minitest5 +0 -3
- data/Gemfile-minitest5.lock +0 -19
- data/Gemfile-rspec2-1 +0 -3
- data/Gemfile-rspec2-1.lock +0 -27
- data/Gemfile-rspec3-0 +0 -3
- data/Gemfile-rspec3-0.lock +0 -31
- data/Gemfile-rspec3-1 +0 -3
- data/Gemfile-rspec3-1.lock +0 -31
- data/Gemfile-rspec3-2 +0 -3
- data/Gemfile-rspec3-2.lock +0 -32
- data/Gemfile-testunit +0 -3
- data/Gemfile-testunit.lock +0 -21
- data/Gemfile.lock +0 -41
- data/script/cibuild +0 -19
- data/script/spec +0 -7
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: a84d8eb24f2cdebe31f18be510d2ba28c8633e963beb62e498ef32674df3f761
|
|
4
|
+
data.tar.gz: 9869e95d639d312876faa0264b238ee8702ec21f5e5bc0bfe0d149ea1d83df31
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 7a33f1567709b2fda5670cac096733d0ab1e029fe4db18aec6e1a449b00dd919e979167febe5a249b875d28e536224f0680dfb9810f2b585ea6064fcdb500dcf
|
|
7
|
+
data.tar.gz: 2486c1c8a85b4fe9fbe87eb98b7aa76ea97e01951f7e66d6db64e91dae57f8692f8354d036a7d57c342a46ab2833c6aac9fb7263b138fdb802d6993765a2e9b4
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches:
|
|
6
|
+
- master
|
|
7
|
+
pull_request:
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
main:
|
|
11
|
+
name: >-
|
|
12
|
+
${{ matrix.ruby }} ${{ matrix.entry.name }}
|
|
13
|
+
runs-on: ${{ matrix.os }}-latest
|
|
14
|
+
env:
|
|
15
|
+
TEST_QUEUE_WORKERS: 2
|
|
16
|
+
TEST_QUEUE_VERBOSE: 1
|
|
17
|
+
strategy:
|
|
18
|
+
fail-fast: false
|
|
19
|
+
matrix:
|
|
20
|
+
os: [ubuntu]
|
|
21
|
+
# Lowest and Latest version.
|
|
22
|
+
ruby: ['2.7', '3.2']
|
|
23
|
+
entry:
|
|
24
|
+
- { name: cucumber1_3, bats: test/cucumber.bats }
|
|
25
|
+
- { name: cucumber2_4, bats: test/cucumber.bats }
|
|
26
|
+
- { name: minitest4, bats: test/minitest4.bats }
|
|
27
|
+
- { name: minitest5, bats: test/minitest5.bats }
|
|
28
|
+
- { name: rspec3, bats: test/rspec3.bats }
|
|
29
|
+
- { name: rspec4, bats: test/rspec4.bats }
|
|
30
|
+
- { name: testunit, bats: test/testunit.bats }
|
|
31
|
+
|
|
32
|
+
steps:
|
|
33
|
+
- name: checkout
|
|
34
|
+
uses: actions/checkout@v3
|
|
35
|
+
- name: set up Ruby
|
|
36
|
+
uses: ruby/setup-ruby@v1
|
|
37
|
+
with:
|
|
38
|
+
ruby-version: ${{ matrix.ruby }}
|
|
39
|
+
|
|
40
|
+
- name: install dependencies
|
|
41
|
+
run: bundle install --jobs 3 --retry 3
|
|
42
|
+
- name: setup for Bats
|
|
43
|
+
run: bundle exec rake setup
|
|
44
|
+
- name: spec
|
|
45
|
+
run: bundle exec rake spec
|
|
46
|
+
- name: install dependencies for ${{ matrix.entry.name }}
|
|
47
|
+
run: BUNDLE_GEMFILE=gemfiles/${{ matrix.entry.name }}.gemfile bundle install --jobs 3 --retry 3
|
|
48
|
+
- name: test
|
|
49
|
+
run: BUNDLE_GEMFILE=gemfiles/${{ matrix.entry.name }}.gemfile vendor/bats/bin/bats ${{ matrix.entry.bats }}
|
|
50
|
+
|
|
51
|
+
# RSpec 2 doesn't work with Ruby 3.2:
|
|
52
|
+
#
|
|
53
|
+
# /opt/hostedtoolcache/Ruby/3.2.1/x64/lib/ruby/gems/3.2.0/gems/rspec-core-2.99.2/lib/rspec/core/ruby_project.rb:27:
|
|
54
|
+
# in `block in find_first_parent_containing': undefined method `exists?' for File:Class (NoMethodError)
|
|
55
|
+
#
|
|
56
|
+
# ascend_until {|path| File.exists?(File.join(path, dir))}
|
|
57
|
+
# ^^^^^^^^
|
|
58
|
+
# Did you mean? exist?
|
|
59
|
+
#
|
|
60
|
+
# Up to Ruby 3.1 is the supported version for RSpec 2.
|
|
61
|
+
rspec2:
|
|
62
|
+
name: >-
|
|
63
|
+
${{ matrix.ruby }} ${{ matrix.entry.name }}
|
|
64
|
+
runs-on: ${{ matrix.os }}-latest
|
|
65
|
+
env:
|
|
66
|
+
TEST_QUEUE_WORKERS: 2
|
|
67
|
+
TEST_QUEUE_VERBOSE: 1
|
|
68
|
+
strategy:
|
|
69
|
+
fail-fast: false
|
|
70
|
+
matrix:
|
|
71
|
+
os: [ubuntu]
|
|
72
|
+
# Lowest and Latest version.
|
|
73
|
+
ruby: ['2.7', '3.1']
|
|
74
|
+
entry:
|
|
75
|
+
- { name: rspec2, bats: test/rspec2.bats }
|
|
76
|
+
|
|
77
|
+
steps:
|
|
78
|
+
- name: checkout
|
|
79
|
+
uses: actions/checkout@v3
|
|
80
|
+
- name: set up Ruby
|
|
81
|
+
uses: ruby/setup-ruby@v1
|
|
82
|
+
with:
|
|
83
|
+
ruby-version: ${{ matrix.ruby }}
|
|
84
|
+
|
|
85
|
+
- name: install dependencies
|
|
86
|
+
run: bundle install --jobs 3 --retry 3
|
|
87
|
+
- name: setup for Bats
|
|
88
|
+
run: bundle exec rake setup
|
|
89
|
+
- name: spec
|
|
90
|
+
run: bundle exec rake spec
|
|
91
|
+
- name: install dependencies for ${{ matrix.entry.name }}
|
|
92
|
+
run: BUNDLE_GEMFILE=gemfiles/${{ matrix.entry.name }}.gemfile bundle install --jobs 3 --retry 3
|
|
93
|
+
- name: test
|
|
94
|
+
run: BUNDLE_GEMFILE=gemfiles/${{ matrix.entry.name }}.gemfile vendor/bats/bin/bats ${{ matrix.entry.bats }}
|
data/.gitignore
CHANGED
data/Appraisals
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
appraise "cucumber1-3" do
|
|
2
|
+
gem 'cucumber', '~> 1.3.10'
|
|
3
|
+
# Pin Rake version to Prevent `NoMethodError: undefined method `last_comment'`.
|
|
4
|
+
gem 'rake', '< 11.0'
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
appraise "cucumber2-4" do
|
|
8
|
+
gem 'cucumber', '~> 2.4.0'
|
|
9
|
+
# Pin Rake version to Prevent `NoMethodError: undefined method `last_comment'`.
|
|
10
|
+
gem 'rake', '< 11.0'
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
appraise "minitest4" do
|
|
14
|
+
gem 'rake'
|
|
15
|
+
gem 'minitest', '~> 4.7'
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
appraise "minitest5" do
|
|
19
|
+
gem 'rake'
|
|
20
|
+
gem 'minitest', '5.10.0'
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
appraise "rspec2" do
|
|
24
|
+
# Pin Rake version to Prevent `NoMethodError: undefined method `last_comment'`.
|
|
25
|
+
gem 'rake', '< 11.0'
|
|
26
|
+
gem 'rspec', '~> 2.99'
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
appraise "rspec3" do
|
|
30
|
+
gem 'rspec', '~> 3.12'
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
appraise "rspec4" do
|
|
34
|
+
gem 'rspec', github: 'rspec/rspec-metagem', branch: '4-0-dev'
|
|
35
|
+
gem 'rspec-core', github: 'rspec/rspec-core', branch: '4-0-dev'
|
|
36
|
+
gem 'rspec-expectations', github: 'rspec/rspec-expectations', branch: '4-0-dev'
|
|
37
|
+
gem 'rspec-mocks', github: 'rspec/rspec-mocks', branch: '4-0-dev'
|
|
38
|
+
gem 'rspec-support', github: 'rspec/rspec-support', branch: '4-0-dev'
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
appraise "testunit" do
|
|
42
|
+
gem 'test-unit'
|
|
43
|
+
end
|
data/Gemfile
CHANGED
data/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
|
|
1
|
+
# test-queue
|
|
2
2
|
|
|
3
3
|
[](https://rubygems.org/gems/test-queue)
|
|
4
|
-
[](https://github.com/tmm1/test-queue/actions/workflows/test.yml)
|
|
5
5
|
|
|
6
6
|
Yet another parallel test runner, built using a centralized queue to ensure
|
|
7
7
|
optimal distribution of tests between workers.
|
|
@@ -10,13 +10,13 @@ Specifically optimized for CI environments: build statistics from each run
|
|
|
10
10
|
are stored locally and used to sort the queue at the beginning of the
|
|
11
11
|
next run.
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
## Design
|
|
14
14
|
|
|
15
15
|
test-queue uses a simple master + pre-fork worker model. The master
|
|
16
16
|
exposes a unix domain socket server which workers use to grab tests off
|
|
17
17
|
the queue.
|
|
18
18
|
|
|
19
|
-
```
|
|
19
|
+
```console
|
|
20
20
|
─┬─ 21232 minitest-queue master
|
|
21
21
|
├─── 21571 minitest-queue worker [3] - AuthenticationTest
|
|
22
22
|
├─── 21568 minitest-queue worker [2] - ApiTest
|
|
@@ -27,7 +27,7 @@ the queue.
|
|
|
27
27
|
test-queue also has a distributed mode, where additional masters can share
|
|
28
28
|
the workload and relay results back to a central master.
|
|
29
29
|
|
|
30
|
-
|
|
30
|
+
## Environment variables
|
|
31
31
|
|
|
32
32
|
- `TEST_QUEUE_WORKERS`: number of workers to use per master (default: all available cores)
|
|
33
33
|
- `TEST_QUEUE_VERBOSE`: show results as they are available (default: `0`)
|
|
@@ -40,11 +40,11 @@ the workload and relay results back to a central master.
|
|
|
40
40
|
- `TEST_QUEUE_REMOTE_MASTER_MESSAGE`: when using distributed builds, set this on a remote master and it will appear in that master's connection message on the central master.
|
|
41
41
|
- `TEST_QUEUE_SPLIT_GROUPS`: split tests up by example rather than example group. Faster for tests with short setup time such as selenium. RSpec only. Add the :no_split tag to ExampleGroups you don't want split.
|
|
42
42
|
|
|
43
|
-
|
|
43
|
+
## Usage
|
|
44
44
|
|
|
45
45
|
test-queue bundles `testunit-queue`, `minitest-queue` and `rspec-queue` binaries which can be used directly:
|
|
46
46
|
|
|
47
|
-
```
|
|
47
|
+
```console
|
|
48
48
|
$ minitest-queue $(find test/ -name \*_test.rb)
|
|
49
49
|
$ rspec-queue --format progress spec
|
|
50
50
|
```
|
|
@@ -53,7 +53,7 @@ But the underlying `TestQueue::Runner::TestUnit`, `TestQueue::Runner::MiniTest`
|
|
|
53
53
|
built to be subclassed by your application. I recommend checking a new
|
|
54
54
|
executable into your project using one of these superclasses.
|
|
55
55
|
|
|
56
|
-
```
|
|
56
|
+
```console
|
|
57
57
|
$ vim script/test-queue
|
|
58
58
|
$ chmod +x script/test-queue
|
|
59
59
|
$ git add script/test-queue
|
|
@@ -69,7 +69,7 @@ runner to reset any global state.
|
|
|
69
69
|
class MyAppTestRunner < TestQueue::Runner::MiniTest
|
|
70
70
|
def after_fork(num)
|
|
71
71
|
# use separate mysql database (we assume it exists and has the right schema already)
|
|
72
|
-
ActiveRecord::Base.configurations
|
|
72
|
+
ActiveRecord::Base.configurations.configs_for(env_name: 'test', name: 'primary').database << num.to_s
|
|
73
73
|
ActiveRecord::Base.establish_connection(:test)
|
|
74
74
|
|
|
75
75
|
# use separate redis database
|
|
@@ -97,13 +97,13 @@ end
|
|
|
97
97
|
MyAppTestRunner.new.execute
|
|
98
98
|
```
|
|
99
99
|
|
|
100
|
-
|
|
100
|
+
## Distributed mode
|
|
101
101
|
|
|
102
102
|
To use distributed mode, the central master must listen on a tcp port. Additional masters can be booted
|
|
103
|
-
in relay mode to connect to the central master. Remote masters must provide a TEST_QUEUE_RELAY_TOKEN
|
|
103
|
+
in relay mode to connect to the central master. Remote masters must provide a `TEST_QUEUE_RELAY_TOKEN`
|
|
104
104
|
to match the central master's.
|
|
105
105
|
|
|
106
|
-
```
|
|
106
|
+
```console
|
|
107
107
|
$ TEST_QUEUE_RELAY_TOKEN=123 TEST_QUEUE_SOCKET=0.0.0.0:12345 bundle exec minitest-queue ./test/sample_test.rb
|
|
108
108
|
$ TEST_QUEUE_RELAY_TOKEN=123 TEST_QUEUE_RELAY=0.0.0.0:12345 bundle exec minitest-queue ./test/sample_test.rb
|
|
109
109
|
$ TEST_QUEUE_RELAY_TOKEN=123 ./test-multi.sh
|
|
@@ -112,7 +112,7 @@ $ TEST_QUEUE_RELAY_TOKEN=123 ./test-multi.sh
|
|
|
112
112
|
See the [Parameterized Trigger Plugin](https://wiki.jenkins-ci.org/display/JENKINS/Parameterized+Trigger+Plugin)
|
|
113
113
|
for a simple way to do this with jenkins.
|
|
114
114
|
|
|
115
|
-
|
|
115
|
+
## See also
|
|
116
116
|
|
|
117
117
|
* https://github.com/Shopify/rails_parallel
|
|
118
118
|
* https://github.com/grosser/parallel_tests
|
data/Rakefile
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
require "bundler/gem_tasks"
|
|
2
|
+
require "rspec/core/rake_task"
|
|
3
|
+
|
|
4
|
+
RSpec::Core::RakeTask.new(:spec)
|
|
5
|
+
|
|
6
|
+
task :default => [:setup, :spec, :feature]
|
|
7
|
+
|
|
8
|
+
task :setup do
|
|
9
|
+
sh 'script/bootstrap' unless File.exist?("#{Dir.pwd}/vendor/bats/bin/bats")
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
task :feature do
|
|
13
|
+
sh 'TEST_QUEUE_WORKERS=2 TEST_QUEUE_VERBOSE=1 vendor/bats/bin/bats test'
|
|
14
|
+
end
|
data/{bin → exe}/cucumber-queue
RENAMED
data/{bin → exe}/minitest-queue
RENAMED
data/{bin → exe}/rspec-queue
RENAMED
data/{bin → exe}/testunit-queue
RENAMED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# This file was generated by Appraisal
|
|
2
|
+
|
|
3
|
+
source "https://rubygems.org"
|
|
4
|
+
|
|
5
|
+
gem 'rspec', github: 'rspec/rspec-metagem', branch: '4-0-dev'
|
|
6
|
+
gem 'rspec-core', github: 'rspec/rspec-core', branch: '4-0-dev'
|
|
7
|
+
gem 'rspec-expectations', github: 'rspec/rspec-expectations', branch: '4-0-dev'
|
|
8
|
+
gem 'rspec-mocks', github: 'rspec/rspec-mocks', branch: '4-0-dev'
|
|
9
|
+
gem 'rspec-support', github: 'rspec/rspec-support', branch: '4-0-dev'
|
|
10
|
+
|
|
11
|
+
gemspec path: "../"
|
data/lib/test-queue.rb
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
require_relative 'test_queue'
|
data/lib/test_queue/iterator.rb
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
begin
|
|
2
2
|
require 'minitest'
|
|
3
|
-
|
|
3
|
+
require_relative '../runner/minitest5'
|
|
4
4
|
rescue LoadError => e
|
|
5
5
|
require 'minitest/unit'
|
|
6
|
-
|
|
6
|
+
require_relative '../runner/minitest4'
|
|
7
7
|
end
|
|
8
8
|
|
|
9
9
|
module TestQueue
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
require_relative '../runner'
|
|
2
2
|
|
|
3
3
|
module MiniTest
|
|
4
4
|
def self.__run reporter, options
|
|
@@ -56,6 +56,13 @@ module TestQueue
|
|
|
56
56
|
class Runner
|
|
57
57
|
class MiniTest < Runner
|
|
58
58
|
def initialize
|
|
59
|
+
options = Minitest.process_args ARGV
|
|
60
|
+
|
|
61
|
+
if Minitest.respond_to?(:seed)
|
|
62
|
+
Minitest.seed = options[:seed]
|
|
63
|
+
srand Minitest.seed
|
|
64
|
+
end
|
|
65
|
+
|
|
59
66
|
if ::MiniTest::Test.runnables.any? { |r| r.runnable_methods.any? }
|
|
60
67
|
fail "Do not `require` test files. Pass them via ARGV instead and they will be required as needed."
|
|
61
68
|
end
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
|
|
1
|
+
require_relative '../runner'
|
|
2
2
|
require 'rspec/core'
|
|
3
3
|
|
|
4
4
|
case ::RSpec::Core::Version::STRING.to_i
|
|
5
5
|
when 2
|
|
6
6
|
require_relative 'rspec2'
|
|
7
|
-
when 3
|
|
7
|
+
when 3, 4
|
|
8
8
|
require_relative 'rspec3'
|
|
9
9
|
else
|
|
10
|
-
fail 'requires rspec version 2 or
|
|
10
|
+
fail 'requires rspec version 2, 3, or 4'
|
|
11
11
|
end
|
|
12
12
|
|
|
13
13
|
module TestQueue
|
|
@@ -36,6 +36,11 @@ module TestQueue
|
|
|
36
36
|
options.parse_options if options.respond_to?(:parse_options)
|
|
37
37
|
options.configure(::RSpec.configuration)
|
|
38
38
|
|
|
39
|
+
if ::RSpec.configuration.instance_variable_defined?(:@files_or_directories_to_run) &&
|
|
40
|
+
::RSpec.configuration.instance_variable_get(:@files_or_directories_to_run).empty?
|
|
41
|
+
::RSpec.configuration.instance_variable_set(:@files_or_directories_to_run, [::RSpec.configuration.default_path])
|
|
42
|
+
end
|
|
43
|
+
|
|
39
44
|
::RSpec.configuration.files_to_run.uniq
|
|
40
45
|
end
|
|
41
46
|
|
data/lib/test_queue/runner.rb
CHANGED
|
@@ -2,8 +2,8 @@ require 'set'
|
|
|
2
2
|
require 'socket'
|
|
3
3
|
require 'fileutils'
|
|
4
4
|
require 'securerandom'
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
require_relative 'stats'
|
|
6
|
+
require_relative 'test_framework'
|
|
7
7
|
|
|
8
8
|
module TestQueue
|
|
9
9
|
class Worker
|
|
@@ -31,7 +31,7 @@ module TestQueue
|
|
|
31
31
|
attr_accessor :concurrency, :exit_when_done
|
|
32
32
|
attr_reader :stats
|
|
33
33
|
|
|
34
|
-
TOKEN_REGEX =
|
|
34
|
+
TOKEN_REGEX = /\ATOKEN=(\w+)/
|
|
35
35
|
|
|
36
36
|
def initialize(test_framework, concurrency=nil, socket=nil, relay=nil)
|
|
37
37
|
@test_framework = test_framework
|
|
@@ -48,12 +48,12 @@ module TestQueue
|
|
|
48
48
|
|
|
49
49
|
@procline = $0
|
|
50
50
|
|
|
51
|
-
@
|
|
51
|
+
@allowlist = if forced = ENV['TEST_QUEUE_FORCE']
|
|
52
52
|
forced.split(/\s*,\s*/)
|
|
53
53
|
else
|
|
54
54
|
[]
|
|
55
55
|
end
|
|
56
|
-
@
|
|
56
|
+
@allowlist.freeze
|
|
57
57
|
|
|
58
58
|
all_files = @test_framework.all_suite_files.to_set
|
|
59
59
|
@queue = @stats.all_suites
|
|
@@ -61,12 +61,12 @@ module TestQueue
|
|
|
61
61
|
.sort_by { |suite| -suite.duration }
|
|
62
62
|
.map { |suite| [suite.name, suite.path] }
|
|
63
63
|
|
|
64
|
-
if @
|
|
65
|
-
@queue.select! { |suite_name, path| @
|
|
66
|
-
@queue.sort_by! { |suite_name, path| @
|
|
64
|
+
if @allowlist.any?
|
|
65
|
+
@queue.select! { |suite_name, path| @allowlist.include?(suite_name) }
|
|
66
|
+
@queue.sort_by! { |suite_name, path| @allowlist.index(suite_name) }
|
|
67
67
|
end
|
|
68
68
|
|
|
69
|
-
@awaited_suites = Set.new(@
|
|
69
|
+
@awaited_suites = Set.new(@allowlist)
|
|
70
70
|
@original_queue = Set.new(@queue).freeze
|
|
71
71
|
|
|
72
72
|
@workers = {}
|
|
@@ -251,7 +251,7 @@ module TestQueue
|
|
|
251
251
|
|
|
252
252
|
def start_master
|
|
253
253
|
if !relay?
|
|
254
|
-
if @socket =~
|
|
254
|
+
if @socket =~ /\A(?:(.+):)?(\d+)\z/
|
|
255
255
|
address = $1 || '0.0.0.0'
|
|
256
256
|
port = $2.to_i
|
|
257
257
|
@socket = "#$1:#$2"
|
|
@@ -318,9 +318,9 @@ module TestQueue
|
|
|
318
318
|
# distributes them to remote masters.
|
|
319
319
|
return if relay?
|
|
320
320
|
|
|
321
|
-
# No need to discover suites if all
|
|
321
|
+
# No need to discover suites if all allowlisted suites are already
|
|
322
322
|
# queued.
|
|
323
|
-
return if @
|
|
323
|
+
return if @allowlist.any? && @awaited_suites.empty?
|
|
324
324
|
|
|
325
325
|
@discovering_suites_pid = fork do
|
|
326
326
|
terminate = false
|
|
@@ -346,7 +346,7 @@ module TestQueue
|
|
|
346
346
|
def awaiting_suites?
|
|
347
347
|
case
|
|
348
348
|
when @awaited_suites.any?
|
|
349
|
-
# We're waiting to find all the
|
|
349
|
+
# We're waiting to find all the allowlisted suites so we can run them
|
|
350
350
|
# in the correct order.
|
|
351
351
|
true
|
|
352
352
|
when @queue.empty? && !!@discovering_suites_pid
|
|
@@ -359,7 +359,7 @@ module TestQueue
|
|
|
359
359
|
end
|
|
360
360
|
|
|
361
361
|
def enqueue_discovered_suite(suite_name, path)
|
|
362
|
-
if @
|
|
362
|
+
if @allowlist.any? && !@allowlist.include?(suite_name)
|
|
363
363
|
return
|
|
364
364
|
end
|
|
365
365
|
|
|
@@ -377,9 +377,9 @@ module TestQueue
|
|
|
377
377
|
@queue.unshift [suite_name, path]
|
|
378
378
|
|
|
379
379
|
if @awaited_suites.delete?(suite_name) && @awaited_suites.empty?
|
|
380
|
-
# We've found all the
|
|
381
|
-
#
|
|
382
|
-
@queue.sort_by! { |suite_name, path| @
|
|
380
|
+
# We've found all the allowlisted suites. Sort the queue to match the
|
|
381
|
+
# allowlist.
|
|
382
|
+
@queue.sort_by! { |suite_name, path| @allowlist.index(suite_name) }
|
|
383
383
|
|
|
384
384
|
kill_suite_discovery_process("INT")
|
|
385
385
|
end
|
|
@@ -500,7 +500,7 @@ module TestQueue
|
|
|
500
500
|
end
|
|
501
501
|
|
|
502
502
|
case cmd
|
|
503
|
-
when
|
|
503
|
+
when /\APOP (\S+) (\d+)/
|
|
504
504
|
hostname = $1
|
|
505
505
|
pid = Integer($2)
|
|
506
506
|
if awaiting_suites?
|
|
@@ -510,7 +510,7 @@ module TestQueue
|
|
|
510
510
|
sock.write(data)
|
|
511
511
|
@assignments[obj] = [hostname, pid]
|
|
512
512
|
end
|
|
513
|
-
when
|
|
513
|
+
when /\AREMOTE MASTER (\d+) ([\w\.-]+)(?: (.+))?/
|
|
514
514
|
num = $1.to_i
|
|
515
515
|
remote_master = $2
|
|
516
516
|
remote_master_message = $3
|
|
@@ -521,15 +521,15 @@ module TestQueue
|
|
|
521
521
|
message = "*** #{num} workers connected from #{remote_master} after #{Time.now-@start_time}s"
|
|
522
522
|
message << " " + remote_master_message if remote_master_message
|
|
523
523
|
STDERR.puts message
|
|
524
|
-
when
|
|
524
|
+
when /\AWORKER (\d+)/
|
|
525
525
|
data = sock.read($1.to_i)
|
|
526
526
|
worker = Marshal.load(data)
|
|
527
527
|
worker_completed(worker)
|
|
528
528
|
remote_workers -= 1
|
|
529
|
-
when
|
|
529
|
+
when /\ANEW SUITE (.+)/
|
|
530
530
|
suite_name, path = Marshal.load($1)
|
|
531
531
|
enqueue_discovered_suite(suite_name, path)
|
|
532
|
-
when
|
|
532
|
+
when /\AKABOOM/
|
|
533
533
|
# worker reporting an abnormal number of test failures;
|
|
534
534
|
# stop everything immediately and report the results.
|
|
535
535
|
break
|
data/lib/test_queue.rb
CHANGED
data/script/bootstrap
CHANGED