busser 0.9.0 → 0.9.2

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.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/publish.yml +22 -0
  3. data/.release-please-manifest.json +1 -1
  4. data/.rubocop.yml +1 -4
  5. data/CHANGELOG.md +18 -0
  6. data/Gemfile +12 -5
  7. data/README.md +82 -0
  8. data/Rakefile +19 -1
  9. data/busser.gemspec +11 -8
  10. data/features/plugin_create_command.feature +7 -9
  11. data/lib/busser/command/deserialize.rb +4 -0
  12. data/lib/busser/command/plugin_create.rb +46 -3
  13. data/lib/busser/command/plugin_install.rb +40 -4
  14. data/lib/busser/command/plugin_list.rb +16 -4
  15. data/lib/busser/command/setup.rb +37 -3
  16. data/lib/busser/command/suite_cleanup.rb +3 -0
  17. data/lib/busser/command/suite_path.rb +3 -0
  18. data/lib/busser/command/test.rb +38 -1
  19. data/lib/busser/cucumber/hooks.rb +9 -0
  20. data/lib/busser/helpers.rb +24 -0
  21. data/lib/busser/plugin.rb +51 -9
  22. data/lib/busser/rubygems.rb +20 -0
  23. data/lib/busser/runner_plugin/dummy.rb +3 -0
  24. data/lib/busser/runner_plugin.rb +5 -0
  25. data/lib/busser/thor.rb +23 -0
  26. data/lib/busser/ui.rb +63 -0
  27. data/lib/busser/version.rb +2 -1
  28. data/release-please-config.json +3 -1
  29. data/spec/busser/command/deserialize_spec.rb +0 -1
  30. data/spec/busser/command/plugin_create_spec.rb +174 -0
  31. data/spec/busser/command/plugin_install_spec.rb +44 -0
  32. data/spec/busser/command/plugin_list_spec.rb +49 -0
  33. data/spec/busser/command/setup_spec.rb +120 -0
  34. data/spec/busser/command/test_spec.rb +36 -0
  35. data/spec/busser/helpers_spec.rb +10 -10
  36. data/spec/busser/plugin_spec.rb +0 -1
  37. data/spec/busser/ui_spec.rb +56 -10
  38. data/spec/spec_helper.rb +2 -3
  39. data/templates/plugin/Rakefile.erb +4 -24
  40. data/templates/plugin/features_env.rb.erb +4 -4
  41. data/templates/plugin/gemspec.erb +7 -8
  42. data/templates/plugin/github_workflow.yml.erb +26 -0
  43. metadata +13 -60
  44. data/templates/plugin/tailor.erb +0 -4
  45. data/templates/plugin/travis.yml.erb +0 -11
@@ -0,0 +1,174 @@
1
+ #
2
+ # Licensed under the Apache License, Version 2.0 (the "License");
3
+ # you may not use this file except in compliance with the License.
4
+ # You may obtain a copy of the License at
5
+ #
6
+ # http://www.apache.org/licenses/LICENSE-2.0
7
+ #
8
+ # Unless required by applicable law or agreed to in writing, software
9
+ # distributed under the License is distributed on an "AS IS" BASIS,
10
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
+ # See the License for the specific language governing permissions and
12
+ # limitations under the License.
13
+
14
+ require_relative "../../spec_helper"
15
+
16
+ require "tmpdir"
17
+
18
+ require "busser/command/plugin_create"
19
+
20
+ # The generated project is what a plugin author starts from, so the checks
21
+ # worth having are the ones a new project would trip over on day one.
22
+ describe Busser::Command::PluginCreate do
23
+
24
+ before do
25
+ @tmpdir = Dir.mktmpdir("busser-plugin-create")
26
+ @pwd = Dir.pwd
27
+ Dir.chdir(@tmpdir)
28
+ end
29
+
30
+ after do
31
+ Dir.chdir(@pwd)
32
+ FileUtils.rm_rf(@tmpdir)
33
+ end
34
+
35
+ describe "the generated gemspec" do
36
+
37
+ it "loads" do
38
+ generate
39
+
40
+ _(gemspec.name).must_equal "busser-demo"
41
+ end
42
+
43
+ # RubyGems validates spec.license against the SPDX list and warns on
44
+ # anything else. The generator used to emit "Apache 2.0", the human
45
+ # readable name rather than the identifier.
46
+ it "declares a license RubyGems recognises" do
47
+ generate
48
+
49
+ _(Gem::Licenses.match?(gemspec.license)).must_equal true
50
+ end
51
+
52
+ {
53
+ "apachev2" => "Apache-2.0",
54
+ "mit" => "MIT",
55
+ "lgplv3" => "LGPL-3.0-only",
56
+ }.each do |option, identifier|
57
+ it "maps --license #{option} to #{identifier}" do
58
+ generate(license: option)
59
+
60
+ _(gemspec.license).must_equal identifier
61
+ end
62
+ end
63
+
64
+ # "All rights reserved" has no SPDX identifier, so declaring nothing is
65
+ # the only correct option.
66
+ it "declares no license for an all rights reserved plugin" do
67
+ generate(license: "reserved")
68
+
69
+ _(gemspec.license).must_be_nil
70
+ end
71
+
72
+ # bundler ~> 1.3 cannot be satisfied by any bundler in use today, so a
73
+ # freshly generated plugin failed to resolve before running anything.
74
+ it "does not constrain bundler" do
75
+ generate
76
+
77
+ _(dev_dependencies).wont_include "bundler"
78
+ end
79
+
80
+ # cane, tailor and countloc have been unmaintained for about a decade.
81
+ %w{cane tailor countloc}.each do |gem_name|
82
+ it "does not depend on #{gem_name}" do
83
+ generate
84
+
85
+ _(dev_dependencies).wont_include gem_name
86
+ end
87
+ end
88
+
89
+ it "depends on what the generated Rakefile needs" do
90
+ generate
91
+
92
+ _(dev_dependencies).must_include "rake"
93
+ _(dev_dependencies).must_include "cucumber"
94
+ _(dev_dependencies).must_include "aruba"
95
+ end
96
+
97
+ it "states a supported Ruby version" do
98
+ generate
99
+
100
+ requirement = gemspec.required_ruby_version
101
+
102
+ _(requirement.satisfied_by?(Gem::Version.new("3.2.0"))).must_equal true
103
+ _(requirement.satisfied_by?(Gem::Version.new("2.7.0"))).must_equal false
104
+ end
105
+
106
+ def gemspec
107
+ Gem::Specification.load(File.join(plugin_dir, "busser-demo.gemspec"))
108
+ end
109
+
110
+ def dev_dependencies
111
+ gemspec.development_dependencies.map(&:name)
112
+ end
113
+ end
114
+
115
+ describe "the generated project" do
116
+
117
+ it "ships a CI workflow rather than a Travis config" do
118
+ generate
119
+
120
+ _(File.exist?(File.join(plugin_dir, ".github/workflows/test.yml")))
121
+ .must_equal true
122
+ _(File.exist?(File.join(plugin_dir, ".travis.yml"))).must_equal false
123
+ end
124
+
125
+ # Both linters are long dead, and the Rakefile's default task depended on
126
+ # them, so `rake` failed on a freshly generated plugin.
127
+ it "ships no dead linter configuration" do
128
+ generate
129
+
130
+ _(File.exist?(File.join(plugin_dir, ".tailor"))).must_equal false
131
+ _(File.exist?(File.join(plugin_dir, ".cane"))).must_equal false
132
+ end
133
+
134
+ it "has a Rakefile that only references tasks it defines" do
135
+ generate
136
+
137
+ rakefile = File.read(File.join(plugin_dir, "Rakefile"))
138
+
139
+ _(rakefile).wont_match(/cane|tailor|countloc/)
140
+ _(rakefile).must_match(/Cucumber::Rake::Task/)
141
+ end
142
+
143
+ # aruba 1.0 dropped @aruba_timeout_seconds, and setting it on aruba 2 is
144
+ # silently ignored, so the generated timeout did nothing at all.
145
+ it "configures aruba through the supported API" do
146
+ generate
147
+
148
+ env = File.read(File.join(plugin_dir, "features/support/env.rb"))
149
+
150
+ _(env).wont_match(/@aruba_timeout_seconds/)
151
+ _(env).must_match(/Aruba\.configure/)
152
+ end
153
+ end
154
+
155
+ def generate(license: "apachev2")
156
+ command = Busser::Command::PluginCreate.new(
157
+ ["demo"], { "type" => "runner", "license" => license }
158
+ )
159
+ command.stubs(:initialize_git)
160
+ capture_stdout { command.create }
161
+ end
162
+
163
+ def plugin_dir
164
+ File.join(@tmpdir, "busser-demo")
165
+ end
166
+
167
+ def capture_stdout
168
+ original = $stdout
169
+ $stdout = StringIO.new
170
+ yield
171
+ ensure
172
+ $stdout = original
173
+ end
174
+ end
@@ -0,0 +1,44 @@
1
+ require_relative "../../spec_helper"
2
+
3
+ require "busser/command/plugin_install"
4
+
5
+ describe Busser::Command::PluginInstall do
6
+ let(:command) { Busser::Command::PluginInstall.new([%w{busser-dummy}]) }
7
+
8
+ describe "#drop_ssl_verify_peer" do
9
+ # VERIFY_PEER is a process-global constant, so anything that leaves it
10
+ # lowered affects every later gem download in the same run. `busser plugin
11
+ # install` takes a list of plugins, which is exactly that situation.
12
+ it "lowers verification for the block" do
13
+ inside = nil
14
+ command.send(:drop_ssl_verify_peer) { inside = OpenSSL::SSL::VERIFY_PEER }
15
+
16
+ _(inside).must_equal OpenSSL::SSL::VERIFY_NONE
17
+ end
18
+
19
+ it "restores verification afterwards" do
20
+ before = OpenSSL::SSL::VERIFY_PEER
21
+ command.send(:drop_ssl_verify_peer) { nil }
22
+
23
+ _(OpenSSL::SSL::VERIFY_PEER).must_equal before
24
+ end
25
+
26
+ # The regression this guards. A postinstall raising is not exotic: it is
27
+ # how a plugin reports that it could not install its test framework.
28
+ it "restores verification when the block raises" do
29
+ before = OpenSSL::SSL::VERIFY_PEER
30
+
31
+ _(proc { command.send(:drop_ssl_verify_peer) { raise "postinstall blew up" } })
32
+ .must_raise RuntimeError
33
+
34
+ _(OpenSSL::SSL::VERIFY_PEER).must_equal before
35
+ end
36
+
37
+ it "restores verification when the block throws" do
38
+ before = OpenSSL::SSL::VERIFY_PEER
39
+ catch(:done) { command.send(:drop_ssl_verify_peer) { throw :done } }
40
+
41
+ _(OpenSSL::SSL::VERIFY_PEER).must_equal before
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,49 @@
1
+ require_relative "../../spec_helper"
2
+
3
+ require "busser/command/plugin_list"
4
+
5
+ describe Busser::Command::PluginList do
6
+ let(:command) { Busser::Command::PluginList.new }
7
+
8
+ describe "#plugin_data" do
9
+ def stub_plugins(paths, specs = {})
10
+ Busser::Plugin.stubs(:runner_plugins).returns(paths)
11
+ paths.each do |path|
12
+ Busser::Plugin.stubs(:gem_from_path).with(path).returns(specs[path])
13
+ end
14
+ end
15
+
16
+ def spec_for(name, version)
17
+ Gem::Specification.new { |s| s.name = name; s.version = version }
18
+ end
19
+
20
+ it "reports each plugin's short name and version" do
21
+ stub_plugins(["busser/runner_plugin/bash"],
22
+ "busser/runner_plugin/bash" => spec_for("busser-bash", "0.2.0"))
23
+
24
+ _(command.send(:plugin_data)).must_equal [["bash", Gem::Version.new("0.2.0")]]
25
+ end
26
+
27
+ # dummy is a fixture shipped inside busser for its own tests, not something
28
+ # anyone installed. `busser test` already passes over it, so listing it was
29
+ # inconsistent as well as confusing.
30
+ it "leaves out the internal dummy runner" do
31
+ stub_plugins(["busser/runner_plugin/dummy", "busser/runner_plugin/bash"],
32
+ "busser/runner_plugin/bash" => spec_for("busser-bash", "0.2.0"))
33
+
34
+ _(command.send(:plugin_data).map(&:first)).must_equal %w{bash}
35
+ end
36
+
37
+ it "reports a nil version rather than raising when no spec is found" do
38
+ stub_plugins(["busser/runner_plugin/bash"])
39
+
40
+ _(command.send(:plugin_data)).must_equal [["bash", nil]]
41
+ end
42
+
43
+ it "returns an empty list when dummy is all there is" do
44
+ stub_plugins(["busser/runner_plugin/dummy"])
45
+
46
+ _(command.send(:plugin_data)).must_be_empty
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,120 @@
1
+ #
2
+ # Licensed under the Apache License, Version 2.0 (the "License");
3
+ # you may not use this file except in compliance with the License.
4
+ # You may obtain a copy of the License at
5
+ #
6
+ # http://www.apache.org/licenses/LICENSE-2.0
7
+ #
8
+ # Unless required by applicable law or agreed to in writing, software
9
+ # distributed under the License is distributed on an "AS IS" BASIS,
10
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
+ # See the License for the specific language governing permissions and
12
+ # limitations under the License.
13
+
14
+ require_relative "../../spec_helper"
15
+
16
+ require "tmpdir"
17
+
18
+ require "busser/command/setup"
19
+
20
+ # The binstub exists to give Busser an isolated gem environment on the machine
21
+ # under test, so what it does to the environment before exec is the contract
22
+ # worth pinning down.
23
+ describe Busser::Command::Setup do
24
+
25
+ # Anything left set here lets the calling Ruby environment reach into
26
+ # Busser's. RUBYOPT was once the only way in; RubyGems now requires
27
+ # bundler/setup whenever BUNDLER_SETUP is present, and bundler then resets
28
+ # GEM_HOME to the calling project's bundle.
29
+ LEAKY_VARIABLES = %w{
30
+ RUBYOPT GEMRC RUBYLIB
31
+ BUNDLER_SETUP BUNDLER_VERSION
32
+ BUNDLE_BIN_PATH BUNDLE_GEMFILE BUNDLE_LOCKFILE BUNDLE_PATH
33
+ }.freeze
34
+
35
+ before do
36
+ @tmpdir = Dir.mktmpdir("busser-setup")
37
+ @original_root = ENV["BUSSER_ROOT"]
38
+ ENV["BUSSER_ROOT"] = @tmpdir
39
+ end
40
+
41
+ after do
42
+ ENV["BUSSER_ROOT"] = @original_root
43
+ FileUtils.rm_rf(@tmpdir)
44
+ end
45
+
46
+ describe "the bourne binstub" do
47
+
48
+ it "is created and executable" do
49
+ run_setup
50
+
51
+ _(File.exist?(binstub)).must_equal true
52
+ _(File.stat(binstub).mode & 0o111).wont_equal 0
53
+ end
54
+
55
+ it "pins BUSSER_ROOT and the gem paths" do
56
+ run_setup
57
+
58
+ _(binstub_body).must_match(/BUSSER_ROOT="#{Regexp.escape(@tmpdir)}"/)
59
+ _(binstub_body).must_match(/^GEM_HOME=/)
60
+ _(binstub_body).must_match(/^GEM_PATH=/)
61
+ end
62
+
63
+ LEAKY_VARIABLES.each do |name|
64
+ it "unsets #{name} before exec" do
65
+ run_setup
66
+
67
+ _(unset_variables).must_include name
68
+ end
69
+ end
70
+
71
+ it "unsets everything before handing off to ruby" do
72
+ run_setup
73
+
74
+ unset_line = binstub_body.index("unset ")
75
+ exec_line = binstub_body.index("exec ")
76
+
77
+ _(unset_line).must_be :<, exec_line
78
+ end
79
+
80
+ def binstub
81
+ File.join(@tmpdir, "bin", "busser")
82
+ end
83
+
84
+ def unset_variables
85
+ binstub_body.scan(/^unset (.+)$/).flatten.join(" ").split(/\s+/)
86
+ end
87
+ end
88
+
89
+ describe "the bat binstub" do
90
+
91
+ LEAKY_VARIABLES.each do |name|
92
+ it "clears #{name} before exec" do
93
+ run_setup(type: "bat")
94
+
95
+ _(binstub_body).must_match(/^SET #{name}=\s*$/)
96
+ end
97
+ end
98
+
99
+ def binstub
100
+ File.join(@tmpdir, "bin", "busser.bat")
101
+ end
102
+ end
103
+
104
+ def run_setup(type: "bourne")
105
+ command = Busser::Command::Setup.new([], { "type" => type })
106
+ capture_stdout { command.perform }
107
+ end
108
+
109
+ def binstub_body
110
+ File.read(binstub)
111
+ end
112
+
113
+ def capture_stdout
114
+ original = $stdout
115
+ $stdout = StringIO.new
116
+ yield
117
+ ensure
118
+ $stdout = original
119
+ end
120
+ end
@@ -0,0 +1,36 @@
1
+ require_relative "../../spec_helper"
2
+
3
+ require "shellwords"
4
+ require "busser/command/test"
5
+
6
+ describe Busser::Command::Test do
7
+ describe ".prepare_sh_command" do
8
+ it "runs the script with sh" do
9
+ cmd = Busser::Command::Test.prepare_sh_command("/opt/busser/suites/bats/prepare.sh")
10
+
11
+ _(Shellwords.split(cmd)).must_equal ["/bin/sh", "/opt/busser/suites/bats/prepare.sh"]
12
+ end
13
+
14
+ # BUSSER_ROOT is chosen by whoever runs Busser, and Test Kitchen puts it
15
+ # under a path the user controls. Unquoted, a space split the path and sh
16
+ # was handed a fragment.
17
+ it "quotes a path containing spaces" do
18
+ cmd = Busser::Command::Test.prepare_sh_command("/tmp/my tests/suites/bats/prepare.sh")
19
+
20
+ _(Shellwords.split(cmd))
21
+ .must_equal ["/bin/sh", "/tmp/my tests/suites/bats/prepare.sh"]
22
+ end
23
+
24
+ it "neutralises shell metacharacters in the path" do
25
+ cmd = Busser::Command::Test.prepare_sh_command("/tmp/a;touch pwned/prepare.sh")
26
+
27
+ _(Shellwords.split(cmd)).must_equal ["/bin/sh", "/tmp/a;touch pwned/prepare.sh"]
28
+ end
29
+
30
+ it "accepts a Pathname" do
31
+ cmd = Busser::Command::Test.prepare_sh_command(Pathname.new("/a/prepare.sh"))
32
+
33
+ _(Shellwords.split(cmd).last).must_equal "/a/prepare.sh"
34
+ end
35
+ end
36
+ end
@@ -1,6 +1,6 @@
1
- require_relative '../spec_helper'
1
+ require_relative "../spec_helper"
2
2
 
3
- require 'busser/helpers'
3
+ require "busser/helpers"
4
4
 
5
5
  describe Busser::Helpers do
6
6
 
@@ -25,16 +25,16 @@ describe Busser::Helpers do
25
25
 
26
26
  describe "with a custom root path" do
27
27
 
28
- before { ENV['_SPEC_BUSSER_ROOT'] = ENV['BUSSER_ROOT'] }
29
- after { ENV['BUSSER_ROOT'] = ENV.delete('_SPEC_BUSSER_ROOT') }
28
+ before { ENV["_SPEC_BUSSER_ROOT"] = ENV["BUSSER_ROOT"] }
29
+ after { ENV["BUSSER_ROOT"] = ENV.delete("_SPEC_BUSSER_ROOT") }
30
30
 
31
31
  it "returns a base path if no suite name is given" do
32
- ENV['BUSSER_ROOT'] = "/path/to/busser"
32
+ ENV["BUSSER_ROOT"] = "/path/to/busser"
33
33
  _(suite_path.to_s).must_match %r{/path/to/busser/suites$}
34
34
  end
35
35
 
36
36
  it "returns a suite path given a suite name" do
37
- ENV['BUSSER_ROOT'] = "/path/to/busser"
37
+ ENV["BUSSER_ROOT"] = "/path/to/busser"
38
38
  _(suite_path("fuzzy").to_s).must_match %r{/path/to/busser/suites/fuzzy$}
39
39
  end
40
40
  end
@@ -59,16 +59,16 @@ describe Busser::Helpers do
59
59
 
60
60
  describe "with a custom root path" do
61
61
 
62
- before { ENV['_SPEC_BUSSER_ROOT'] = ENV['BUSSER_ROOT'] }
63
- after { ENV['BUSSER_ROOT'] = ENV.delete('_SPEC_BUSSER_ROOT') }
62
+ before { ENV["_SPEC_BUSSER_ROOT"] = ENV["BUSSER_ROOT"] }
63
+ after { ENV["BUSSER_ROOT"] = ENV.delete("_SPEC_BUSSER_ROOT") }
64
64
 
65
65
  it "returns a base path if no product name is given" do
66
- ENV['BUSSER_ROOT'] = "/path/to/busser"
66
+ ENV["BUSSER_ROOT"] = "/path/to/busser"
67
67
  _(vendor_path.to_s).must_match %r{/path/to/busser/vendor$}
68
68
  end
69
69
 
70
70
  it "returns a suite path given a product name" do
71
- ENV['BUSSER_ROOT'] = "/path/to/busser"
71
+ ENV["BUSSER_ROOT"] = "/path/to/busser"
72
72
  _(vendor_path("maximal").to_s).must_match \
73
73
  %r{/path/to/busser/vendor/maximal$}
74
74
  end
@@ -1,4 +1,3 @@
1
- # -*- encoding: utf-8 -*-
2
1
  #
3
2
  # Licensed under the Apache License, Version 2.0 (the "License");
4
3
  # you may not use this file except in compliance with the License.
@@ -1,6 +1,6 @@
1
- require_relative '../spec_helper'
1
+ require_relative "../spec_helper"
2
2
 
3
- require 'busser/ui'
3
+ require "busser/ui"
4
4
 
5
5
  # Dummy class containing diagnostic methods approximating Thor mixins
6
6
  class SneakyUI
@@ -11,7 +11,7 @@ class SneakyUI
11
11
  attr_accessor :status
12
12
 
13
13
  def say(msg)
14
- msg
14
+ msg
15
15
  end
16
16
 
17
17
  def error(msg)
@@ -45,10 +45,16 @@ end
45
45
  # Stub that mimics a Process::Status object
46
46
  class FakeStatus
47
47
 
48
- attr_reader :exitstatus
48
+ attr_reader :exitstatus, :termsig
49
49
 
50
- def initialize(success = true, exitstatus = 0)
51
- @success, @exitstatus = success, exitstatus
50
+ # A process stopped by a signal reports success? as nil rather than false,
51
+ # carries no exitstatus, and sets termsig instead.
52
+ def self.signalled(termsig)
53
+ new(nil, nil, termsig)
54
+ end
55
+
56
+ def initialize(success = true, exitstatus = 0, termsig = nil)
57
+ @success, @exitstatus, @termsig = success, exitstatus, termsig
52
58
  end
53
59
 
54
60
  def success?
@@ -105,7 +111,7 @@ describe Busser::UI do
105
111
 
106
112
  _(ui.run_args).must_equal([
107
113
  "doitpls",
108
- { :capture => false, :verbose => false}
114
+ { capture: false, verbose: false },
109
115
  ])
110
116
  end
111
117
 
@@ -138,6 +144,26 @@ describe Busser::UI do
138
144
  end
139
145
  end
140
146
 
147
+ # The out of memory killer stops a run with SIGKILL. exitstatus is nil
148
+ # there, and reporting it as an exit code used to raise a TypeError from
149
+ # Kernel#exit, so Busser died with a stack trace instead of saying what
150
+ # happened.
151
+ it "reports the signal when the command was killed" do
152
+ ui.status = FakeStatus.signalled(9)
153
+ output = capture_stderr { ui.invoke_run!("failwhale") }
154
+
155
+ _(output).must_match(/terminated by signal 9/)
156
+ _(ui.died?).must_equal true
157
+ end
158
+
159
+ it "terminates with 128 plus the signal when the command was killed" do
160
+ ui.status = FakeStatus.signalled(9)
161
+
162
+ capture_stderr do
163
+ _(ui.invoke_run!("failwhale")).must_equal 137
164
+ end
165
+ end
166
+
141
167
  it "terminates the program if status is nil" do
142
168
  ui.status = nil
143
169
  output = capture_stderr { ui.invoke_run!("failwhale") }
@@ -155,16 +181,16 @@ describe Busser::UI do
155
181
 
156
182
  _(ui.run_ruby_script_args).must_equal([
157
183
  "theworks.rb",
158
- { :capture => false, :verbose => false }
184
+ { capture: false, verbose: false },
159
185
  ])
160
186
  end
161
187
 
162
188
  it "calls #run_ruby_script with correct default options" do
163
- ui.invoke_run_ruby_script!("theworks.rb", :verbose => true)
189
+ ui.invoke_run_ruby_script!("theworks.rb", verbose: true)
164
190
 
165
191
  _(ui.run_ruby_script_args).must_equal([
166
192
  "theworks.rb",
167
- { :capture => false, :verbose => true }
193
+ { capture: false, verbose: true },
168
194
  ])
169
195
  end
170
196
 
@@ -197,6 +223,26 @@ describe Busser::UI do
197
223
  end
198
224
  end
199
225
 
226
+ # The out of memory killer stops a run with SIGKILL. exitstatus is nil
227
+ # there, and reporting it as an exit code used to raise a TypeError from
228
+ # Kernel#exit, so Busser died with a stack trace instead of saying what
229
+ # happened.
230
+ it "reports the signal when the command was killed" do
231
+ ui.status = FakeStatus.signalled(9)
232
+ output = capture_stderr { ui.invoke_run_ruby_script!("nope.rb") }
233
+
234
+ _(output).must_match(/terminated by signal 9/)
235
+ _(ui.died?).must_equal true
236
+ end
237
+
238
+ it "terminates with 128 plus the signal when the command was killed" do
239
+ ui.status = FakeStatus.signalled(9)
240
+
241
+ capture_stderr do
242
+ _(ui.invoke_run_ruby_script!("nope.rb")).must_equal 137
243
+ end
244
+ end
245
+
200
246
  it "terminates the program if status is nil" do
201
247
  ui.status = nil
202
248
  output = capture_stderr { ui.invoke_run_ruby_script!("nope.rb") }
data/spec/spec_helper.rb CHANGED
@@ -1,4 +1,3 @@
1
- # -*- encoding: utf-8 -*-
2
1
  #
3
2
  # Author:: Fletcher Nichol (<fnichol@nichol.ca>)
4
3
  #
@@ -16,5 +15,5 @@
16
15
  # See the License for the specific language governing permissions and
17
16
  # limitations under the License.
18
17
 
19
- require 'minitest/autorun'
20
- require 'mocha/minitest'
18
+ require "minitest/autorun"
19
+ require "mocha/minitest"
@@ -1,31 +1,11 @@
1
1
  require "bundler/gem_tasks"
2
- require 'cucumber/rake/task'
3
- require 'cane/rake_task'
4
- require 'tailor/rake_task'
2
+ require "cucumber/rake/task"
5
3
 
6
4
  Cucumber::Rake::Task.new(:features) do |t|
7
- t.cucumber_opts = ['features', '-x', '--format progress']
5
+ t.cucumber_opts = ["features", "-x", "--format progress", "--no-color"]
8
6
  end
9
7
 
10
8
  desc "Run all test suites"
11
- task :test => [:features]
9
+ task test: [:features]
12
10
 
13
- desc "Run cane to check quality metrics"
14
- Cane::RakeTask.new do |cane|
15
- cane.canefile = './.cane'
16
- end
17
-
18
- Tailor::RakeTask.new
19
-
20
- desc "Display LOC stats"
21
- task :stats do
22
- puts "\n## Production Code Stats"
23
- sh "countloc -r lib"
24
- puts "\n## Test Code Stats"
25
- sh "countloc -r features"
26
- end
27
-
28
- desc "Run all quality tasks"
29
- task :quality => [:cane, :tailor, :stats]
30
-
31
- task :default => [:test, :quality]
11
+ task default: [:test]
@@ -1,8 +1,8 @@
1
- require 'aruba/cucumber'
2
- require 'busser/cucumber'
1
+ require "aruba/cucumber"
2
+ require "busser/cucumber"
3
3
 
4
- Before do
5
- @aruba_timeout_seconds = 10
4
+ Aruba.configure do |config|
5
+ config.exit_timeout = 20
6
6
  end
7
7
 
8
8
  After do |s|