Skip to content

Commit 82e3b6f

Browse files
committed
Refactor Runner to support run all tests in parallel with a summary table
1 parent b00a18c commit 82e3b6f

File tree

8 files changed

+146
-20
lines changed

8 files changed

+146
-20
lines changed

Gemfile.lock

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,24 @@ PATH
22
remote: .
33
specs:
44
matrixeval-ruby (0.1.0)
5+
concurrent-ruby
56
rainbow (~> 3.1)
7+
terminal-table
68

79
GEM
810
remote: https://rubygems.org/
911
specs:
1012
byebug (11.1.3)
13+
concurrent-ruby (1.1.9)
1114
minitest (5.15.0)
1215
minitest-focus (1.3.1)
1316
minitest (>= 4, < 6)
1417
mocha (1.13.0)
1518
rainbow (3.1.1)
1619
rake (13.0.6)
20+
terminal-table (3.0.2)
21+
unicode-display_width (>= 1.1.1, < 3)
22+
unicode-display_width (2.1.0)
1723

1824
PLATFORMS
1925
x86_64-darwin-19

lib/matrixeval/ruby/command_line.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ def seperator_index
3939
end
4040

4141
def seperator_commands
42-
['rake', 'rspec', 'bundle']
42+
['rake', 'rspec', 'bundle', 'bash']
4343
end
4444

4545
end

lib/matrixeval/ruby/config.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,10 @@ def exclusions
4545
YAML["exclude"] || []
4646
end
4747

48+
def parallel_workers
49+
YAML["parallel_workers"] || "number_of_processors"
50+
end
51+
4852
end
4953
end
5054
end

lib/matrixeval/ruby/docker_compose.rb

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,6 @@ def initialize(context)
1313

1414
def run(arguments)
1515
forward_arguments = arguments.join(" ")
16-
puts Rainbow("[ MatrixEval ] ").blue.bright + Rainbow(" #{context.name} ").white.bright.bg(:blue)
17-
puts Rainbow("[ MatrixEval ] Run \"#{forward_arguments}\"").blue.bright
1816

1917
system(
2018
<<~DOCKER_COMPOSE_COMMAND

lib/matrixeval/ruby/runner.rb

Lines changed: 131 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
require 'fileutils'
44
require 'matrixeval/ruby/config'
55
require 'matrixeval/ruby/command_line'
6+
require "concurrent/utility/processor_counter"
7+
require 'terminal-table'
68

79
module Matrixeval
810
module Ruby
@@ -13,35 +15,147 @@ def start(argv)
1315
end
1416
end
1517

16-
attr_reader :argv
18+
attr_reader :argv, :command
1719

1820
def initialize(argv)
1921
@argv = argv
22+
@command = CommandLine.new(argv)
2023
end
2124

2225
def start
23-
command = CommandLine.new(argv)
2426
if command.init?
25-
Config::YAML.create
26-
Gitignore.update
27+
init
28+
elsif command.all?
29+
run_all_contexts
2730
else
28-
Config::YAML.create
29-
DockerCompose::YAML.create
30-
GemfileLocks.create
31-
Gitignore.update
32-
33-
if command.all?
34-
Context.all.each do |context|
35-
docker_compose = DockerCompose.new(context)
36-
docker_compose.run(command.rest_arguments)
37-
end
38-
else
39-
context = Context.find_by_command_options!(command.context_options)
31+
run_a_specific_context
32+
end
33+
ensure
34+
turn_on_stty_opost
35+
end
36+
37+
private
38+
39+
def init
40+
Config::YAML.create
41+
Gitignore.update
42+
end
43+
44+
def run_all_contexts
45+
Config::YAML.create
46+
DockerCompose::YAML.create
47+
GemfileLocks.create
48+
Gitignore.update
49+
50+
if workers_count == 1
51+
run_all_contexts_sequentially
52+
else
53+
run_all_contexts_in_parallel
54+
end
55+
end
56+
57+
def run_all_contexts_sequentially
58+
Context.all.each do |context|
59+
puts Rainbow("[ MatrixEval ] ").blue.bright + Rainbow(" #{context.name} ").white.bright.bg(:blue)
60+
puts Rainbow("[ MatrixEval ] Run \"#{command.rest_arguments.join(" ")}\"").blue.bright
61+
62+
docker_compose = DockerCompose.new(context)
63+
success = docker_compose.run(command.rest_arguments)
64+
65+
matrixeval_results << [context, !!success]
66+
end
67+
68+
report
69+
end
70+
71+
def run_all_contexts_in_parallel
72+
parallel do |contexts|
73+
Thread.current[:matrixeval_results] = []
4074

75+
contexts.each do |context|
4176
docker_compose = DockerCompose.new(context)
42-
docker_compose.run(command.rest_arguments)
77+
success = docker_compose.run(command.rest_arguments)
78+
79+
Thread.current[:matrixeval_results] << [context, !!success]
4380
end
4481
end
82+
83+
report
84+
end
85+
86+
def run_a_specific_context
87+
Config::YAML.create
88+
DockerCompose::YAML.create
89+
GemfileLocks.create
90+
Gitignore.update
91+
92+
context = Context.find_by_command_options!(command.context_options)
93+
94+
puts Rainbow("[ MatrixEval ] ").blue.bright + Rainbow(" #{context.name} ").white.bright.bg(:blue)
95+
puts Rainbow("[ MatrixEval ] Run \"#{command.rest_arguments.join(" ")}\"").blue.bright
96+
97+
docker_compose = DockerCompose.new(context)
98+
docker_compose.run(command.rest_arguments)
99+
end
100+
101+
def report
102+
turn_on_stty_opost
103+
104+
table = Terminal::Table.new(title: Rainbow("MatrixEval").blue.bright + " Summary", alignment: :center) do |table|
105+
106+
table.add_row(Config.vectors.map(&:key) + ['result'])
107+
table.add_separator
108+
109+
matrixeval_results.each do |context, success|
110+
success_cell = [success ? Rainbow('Success').green : Rainbow('Failed').red]
111+
row = (context.variants.map(&:key) + success_cell).map do |value|
112+
{ value: value, alignment: :center }
113+
end
114+
115+
table.add_row row
116+
end
117+
118+
end
119+
120+
puts table
121+
end
122+
123+
def parallel
124+
contexts = Context.all
125+
126+
contexts.each_slice(contexts.count / workers_count) do |sub_contexts|
127+
threads << Thread.new do
128+
yield sub_contexts
129+
end
130+
end
131+
132+
threads.each(&:join)
133+
134+
threads.each do |thread|
135+
matrixeval_results += thread[:matrixeval_results]
136+
end
137+
end
138+
139+
def threads
140+
@threads ||= []
141+
end
142+
143+
def matrixeval_results
144+
@matrixeval_results ||= []
145+
end
146+
147+
def workers_count
148+
count = if Config.parallel_workers == "number_of_processors"
149+
Concurrent.physical_processor_count
150+
else
151+
Integer(Config.parallel_workers)
152+
end
153+
154+
[count, 1].max
155+
end
156+
157+
def turn_on_stty_opost
158+
system("stty opost")
45159
end
46160

47161
end

lib/matrixeval/ruby/templates/matrixeval.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
version: 0.1
22
target: ruby
3+
parallel_workers: number_of_processors
34
matrix:
45
ruby:
56
variants:

matrixeval-ruby.gemspec

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ Gem::Specification.new do |spec|
3131

3232
# Uncomment to register a new dependency of your gem
3333
spec.add_dependency "rainbow", "~> 3.1"
34+
spec.add_dependency "concurrent-ruby"
35+
spec.add_dependency "terminal-table"
3436

3537
# For more information and examples about making a new gem, checkout our
3638
# guide at: https://bundler.io/guides/creating_gem.html

test/matrixeval/ruby/runner_test.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ def test_start_with_existing_config_file
4242
file.puts(<<~MATRIXEVAL_YAML
4343
version: 0.1
4444
target: ruby
45+
parallel_workers: 1
4546
matrix:
4647
ruby:
4748
variants:

0 commit comments

Comments
 (0)