beaker 7.6.0 → 7.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/release.yml +3 -3
- data/.github/workflows/test.yml +5 -5
- data/CHANGELOG.md +16 -2
- data/lib/beaker/logger.rb +1 -1
- data/lib/beaker/logger_junit.rb +23 -10
- data/lib/beaker/result.rb +18 -4
- data/lib/beaker/version.rb +1 -1
- data/spec/beaker/logger_junit_spec.rb +36 -0
- data/spec/beaker/logger_spec.rb +18 -0
- data/spec/beaker/result_spec.rb +189 -0
- data/spec/beaker/subcommand_spec.rb +2 -2
- metadata +3 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 928c28e0ae2f5c8aa738b8bc402a9e61cc1392175e15bec5151186a63d565e8d
|
|
4
|
+
data.tar.gz: 55e3aabcda095f07e5315e9af08818cc050ea5514cb1409d373fe98b38482942
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: e25abfe8061d6566511bda5c51626e9e0e8c33216e77858104f8c300e07c5521ad524f87fade31a6f963ddcf1b595398747ec4a9ef800762e6348a6d919e64c0
|
|
7
|
+
data.tar.gz: 1b62bd88a3069e9f0b2c11df340d6d9515620cac2ccdf5ec0e5ff0afefc6ad0a0b94a0e0ea3a87484a058a2c6e21e1cf3f56de2da8b0387f8400c8259e3f7072
|
|
@@ -15,9 +15,9 @@ jobs:
|
|
|
15
15
|
name: Build the gem
|
|
16
16
|
runs-on: ubuntu-24.04
|
|
17
17
|
steps:
|
|
18
|
-
- uses: actions/checkout@
|
|
18
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
19
19
|
- name: Install Ruby
|
|
20
|
-
uses: ruby/setup-ruby@
|
|
20
|
+
uses: ruby/setup-ruby@95ef2b042f9d7a56d8268cba8559e2842e2ad01b # v1.321.0
|
|
21
21
|
with:
|
|
22
22
|
ruby-version: 'ruby'
|
|
23
23
|
- name: Build gem
|
|
@@ -96,7 +96,7 @@ jobs:
|
|
|
96
96
|
with:
|
|
97
97
|
name: gem-artifact
|
|
98
98
|
- name: Install Ruby
|
|
99
|
-
uses: ruby/setup-ruby@
|
|
99
|
+
uses: ruby/setup-ruby@95ef2b042f9d7a56d8268cba8559e2842e2ad01b # v1.321.0
|
|
100
100
|
with:
|
|
101
101
|
ruby-version: 'ruby'
|
|
102
102
|
- name: Wait for release to propagate
|
data/.github/workflows/test.yml
CHANGED
|
@@ -16,16 +16,16 @@ jobs:
|
|
|
16
16
|
outputs:
|
|
17
17
|
ruby: ${{ steps.ruby.outputs.versions }}
|
|
18
18
|
steps:
|
|
19
|
-
- uses: actions/checkout@
|
|
19
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
20
20
|
- name: Install Ruby ${{ matrix.ruby }}
|
|
21
|
-
uses: ruby/setup-ruby@
|
|
21
|
+
uses: ruby/setup-ruby@95ef2b042f9d7a56d8268cba8559e2842e2ad01b # v1.321.0
|
|
22
22
|
with:
|
|
23
23
|
ruby-version: '4.0'
|
|
24
24
|
bundler-cache: true
|
|
25
25
|
- name: Run Rubocop
|
|
26
26
|
run: bundle exec rake rubocop
|
|
27
27
|
- id: ruby
|
|
28
|
-
uses: voxpupuli/ruby-version@
|
|
28
|
+
uses: voxpupuli/ruby-version@be0467ce7366d206b2e87f5b7a032a030120b7cb # 2.0.0
|
|
29
29
|
|
|
30
30
|
test:
|
|
31
31
|
name: "Ruby ${{ matrix.ruby }}"
|
|
@@ -38,9 +38,9 @@ jobs:
|
|
|
38
38
|
env:
|
|
39
39
|
BEAKER_HYPERVISOR: docker
|
|
40
40
|
steps:
|
|
41
|
-
- uses: actions/checkout@
|
|
41
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
42
42
|
- name: Install Ruby ${{ matrix.ruby }}
|
|
43
|
-
uses: ruby/setup-ruby@
|
|
43
|
+
uses: ruby/setup-ruby@95ef2b042f9d7a56d8268cba8559e2842e2ad01b # v1.321.0
|
|
44
44
|
with:
|
|
45
45
|
ruby-version: ${{ matrix.ruby }}
|
|
46
46
|
bundler-cache: true
|
data/CHANGELOG.md
CHANGED
|
@@ -2,9 +2,23 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
|
|
5
|
-
## [7.
|
|
5
|
+
## [7.7.0](https://github.com/voxpupuli/beaker/tree/7.7.0) (2026-08-14)
|
|
6
6
|
|
|
7
|
-
[Full Changelog](https://github.com/voxpupuli/beaker/compare/v7.
|
|
7
|
+
[Full Changelog](https://github.com/voxpupuli/beaker/compare/v7.6.0...7.7.0)
|
|
8
|
+
|
|
9
|
+
**Implemented enhancements:**
|
|
10
|
+
|
|
11
|
+
- Add Ruby 4.0 support [\#2015](https://github.com/voxpupuli/beaker/pull/2015) ([dependabot[bot]](https://github.com/apps/dependabot))
|
|
12
|
+
|
|
13
|
+
**Fixed bugs:**
|
|
14
|
+
|
|
15
|
+
- Stop Logger\#convert allocating a String per character [\#2021](https://github.com/voxpupuli/beaker/pull/2021) ([joshcooper](https://github.com/joshcooper))
|
|
16
|
+
- Reduce Result allocations [\#2020](https://github.com/voxpupuli/beaker/pull/2020) ([joshcooper](https://github.com/joshcooper))
|
|
17
|
+
- Reduce string allocations for junit results [\#2019](https://github.com/voxpupuli/beaker/pull/2019) ([joshcooper](https://github.com/joshcooper))
|
|
18
|
+
|
|
19
|
+
## [v7.6.0](https://github.com/voxpupuli/beaker/tree/v7.6.0) (2026-07-13)
|
|
20
|
+
|
|
21
|
+
[Full Changelog](https://github.com/voxpupuli/beaker/compare/v7.5.0...v7.6.0)
|
|
8
22
|
|
|
9
23
|
**Implemented enhancements:**
|
|
10
24
|
|
data/lib/beaker/logger.rb
CHANGED
data/lib/beaker/logger_junit.rb
CHANGED
|
@@ -120,21 +120,34 @@ module Beaker
|
|
|
120
120
|
self.escape_invalid_xml_chars(Logger.strip_color_codes(string))
|
|
121
121
|
end
|
|
122
122
|
|
|
123
|
+
# Every character {is_valid_xml} rejects, as one pattern. Note that this
|
|
124
|
+
# tracks that method rather than the specification it cites: #xD is absent
|
|
125
|
+
# from both, and both take the last range as 0x100000 rather than the
|
|
126
|
+
# 0x10000 the specification gives. Changing either would change the
|
|
127
|
+
# contents of every junit report, so they are left alone here and the specs
|
|
128
|
+
# walk the whole range to keep the two in step.
|
|
129
|
+
INVALID_XML_CHARS = /[^\u{9}\u{A}\u{20}-\u{D7FF}\u{E000}-\u{FFFD}\u{100000}-\u{10FFFF}]/
|
|
130
|
+
|
|
123
131
|
# Escape invalid XML UTF-8 codes from provided string, see http://www.w3.org/TR/xml/#charsets for valid
|
|
124
132
|
# character specification
|
|
125
133
|
# @param [String] string The string to remove invalid codes from
|
|
126
134
|
# @return [String] Properly escaped string
|
|
127
135
|
def self.escape_invalid_xml_chars string
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
136
|
+
# Bytes that are not valid in their own encoding cannot be represented in
|
|
137
|
+
# xml at all, and would make the gsub below raise. Drop them, the same
|
|
138
|
+
# way Logger#convert does further upstream. Raising matters more here
|
|
139
|
+
# than it might look: TestSuiteResult calls #format_cdata from inside a
|
|
140
|
+
# blanket rescue that abandons the whole junit document, so one stray
|
|
141
|
+
# byte in one sublog loses every test result for the run.
|
|
142
|
+
string = string.dup.force_encoding(Encoding::UTF_8) unless string.encoding == Encoding::UTF_8
|
|
143
|
+
string = string.scrub('') unless string.valid_encoding?
|
|
144
|
+
|
|
145
|
+
# This walked the string a character at a time, unpacking each one into
|
|
146
|
+
# an array and joining it back into a string just to read its codepoint.
|
|
147
|
+
# That is around four objects per character, and it runs over the whole
|
|
148
|
+
# sublog of every test case at the end of a run: 28 million objects, and
|
|
149
|
+
# 98MB of permanently grown ruby heap, for a 6MB suite.
|
|
150
|
+
string.gsub(INVALID_XML_CHARS) { |char| "\\#{char.ord}" }
|
|
138
151
|
end
|
|
139
152
|
|
|
140
153
|
# Determine if the provided number falls in the range of accepted xml unicode values
|
data/lib/beaker/result.rb
CHANGED
|
@@ -31,10 +31,24 @@ module Beaker
|
|
|
31
31
|
return string.gsub(/\r\n?/, "\n")
|
|
32
32
|
end
|
|
33
33
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
34
|
+
# This method behaves differently when given a string instance, subclass
|
|
35
|
+
# or something else. The latter two cases should be deprecated.
|
|
36
|
+
def convert(string)
|
|
37
|
+
# guard against nil, which never worked on accident
|
|
38
|
+
raise TypeError, "Beaker::Result#convert cannot convert nil to a String" if string.nil?
|
|
39
|
+
|
|
40
|
+
unless string.instance_of?(String)
|
|
41
|
+
# For a string subclass, `string.to_s` returns a copy, so calling
|
|
42
|
+
# `force_encoding` on it was meaningless.
|
|
43
|
+
return string.to_s.scrub('')
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Data collected from the connection is binary (ASCII-8BIT). In that
|
|
47
|
+
# encoding, every byte is a valid character, so we tag the string as UTF-8
|
|
48
|
+
string.force_encoding('UTF-8')
|
|
49
|
+
|
|
50
|
+
# And remove invalid and undefined UTF-8 character encodings.
|
|
51
|
+
string.scrub('')
|
|
38
52
|
end
|
|
39
53
|
|
|
40
54
|
def log(logger)
|
data/lib/beaker/version.rb
CHANGED
|
@@ -32,6 +32,42 @@ module Beaker
|
|
|
32
32
|
testing_string = 'pants man, pants!'
|
|
33
33
|
expect(described_class.escape_invalid_xml_chars(testing_string)).to be === testing_string
|
|
34
34
|
end
|
|
35
|
+
|
|
36
|
+
it 'escapes carriage returns, which is_valid_xml does not accept' do
|
|
37
|
+
expect(described_class.escape_invalid_xml_chars("a\rb")).to be === 'a\13b'
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
it 'agrees with is_valid_xml on every codepoint' do
|
|
41
|
+
# INVALID_XML_CHARS has to track is_valid_xml rather than the spec that
|
|
42
|
+
# method cites, so walk the whole range instead of trusting either.
|
|
43
|
+
codepoints = (0..0xD7FF).to_a + (0xE000..0x10FFFF).to_a # surrogates cannot be in a String
|
|
44
|
+
codepoints.each_slice(50_000) do |slice|
|
|
45
|
+
string = slice.map { |c| c.chr(Encoding::UTF_8) }.join
|
|
46
|
+
expected = slice.map { |c| described_class.is_valid_xml(c) ? c.chr(Encoding::UTF_8) : "\\#{c}" }.join
|
|
47
|
+
expect(described_class.escape_invalid_xml_chars(string)).to eq(expected)
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
it 'drops invalid encodings rather than raising' do
|
|
52
|
+
# TestSuiteResult calls format_cdata from inside a blanket rescue that
|
|
53
|
+
# abandons the whole junit document, so an exception raised here would
|
|
54
|
+
# cost the run its entire test report.
|
|
55
|
+
expect(described_class.escape_invalid_xml_chars("ok\xFFbad".b)).to eq('okbad')
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
it 'accepts a frozen string' do
|
|
59
|
+
expect(described_class.escape_invalid_xml_chars('pants'.freeze)).to eq('pants')
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
describe '#format_cdata' do
|
|
64
|
+
it 'strips colour codes and escapes what is left' do
|
|
65
|
+
expect(described_class.format_cdata("\e[00;33mpants\e[00;00m")).to eq('pants')
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
it 'survives invalid encodings' do
|
|
69
|
+
expect(described_class.format_cdata("\e[00;33mok\xFFbad".b)).to eq('okbad')
|
|
70
|
+
end
|
|
35
71
|
end
|
|
36
72
|
|
|
37
73
|
describe '#copy_stylesheet_into_xml_dir' do
|
data/spec/beaker/logger_spec.rb
CHANGED
|
@@ -24,6 +24,24 @@ module Beaker
|
|
|
24
24
|
valid_utf8.freeze
|
|
25
25
|
expect(logger.convert(valid_utf8)).to be === valid_utf8
|
|
26
26
|
end
|
|
27
|
+
|
|
28
|
+
it 'leaves the string it was given alone' do
|
|
29
|
+
expect(logger.convert(invalid_utf8)).not_to equal(invalid_utf8)
|
|
30
|
+
expect(invalid_utf8.bytes).to include(0xAD)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
it 'converts each item of an array' do
|
|
34
|
+
expect(logger.convert([valid_utf8, invalid_utf8])).to eq([valid_utf8, valid_utf8])
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
it 'converts arrays of arrays' do
|
|
38
|
+
expect(logger.convert([[invalid_utf8], valid_utf8])).to eq([[valid_utf8], valid_utf8])
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
it 'converts anything that can describe itself' do
|
|
42
|
+
expect(logger.convert(42)).to eq('42')
|
|
43
|
+
expect(logger.convert(nil)).to eq('')
|
|
44
|
+
end
|
|
27
45
|
end
|
|
28
46
|
|
|
29
47
|
describe '#generate_dated_log_folder' do
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
module Beaker
|
|
4
|
+
describe Result do
|
|
5
|
+
subject(:result) { described_class.new(host, cmd) }
|
|
6
|
+
|
|
7
|
+
let(:host) { 'my_host' }
|
|
8
|
+
let(:cmd) { 'ls -la' }
|
|
9
|
+
|
|
10
|
+
# Command output reaches a Result the way net-ssh hands it over: as chunks
|
|
11
|
+
# of binary data, appended as they arrive.
|
|
12
|
+
def binary(string)
|
|
13
|
+
string.dup.force_encoding('ASCII-8BIT')
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
describe '#initialize' do
|
|
17
|
+
it 'starts with empty streams and no exit code' do
|
|
18
|
+
expect(result.stdout).to eq('')
|
|
19
|
+
expect(result.stderr).to eq('')
|
|
20
|
+
expect(result.output).to eq('')
|
|
21
|
+
expect(result.exit_code).to be_nil
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
describe '#convert' do
|
|
26
|
+
let(:valid_utf8) { "modules\n├── jimmy-appleseed (v1.1.0)\n└── jimmy-crakorn (v0.4.0)\n" }
|
|
27
|
+
|
|
28
|
+
it 'preserves valid utf-8' do
|
|
29
|
+
expect(result.convert(valid_utf8.dup)).to eq(valid_utf8)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
it 'strips invalid utf-8 byte sequences' do
|
|
33
|
+
expect(result.convert(binary("ok\xFFbad"))).to eq('okbad')
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
it 'strips a truncated multi-byte sequence' do
|
|
37
|
+
expect(result.convert(binary("ok\xE3\x81"))).to eq('ok')
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
it 'returns utf-8 whatever encoding it was handed' do
|
|
41
|
+
expect(result.convert(binary('plain')).encoding).to eq(Encoding::UTF_8)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
it 'modifies the argument encoding in place' do
|
|
45
|
+
string = binary('plain')
|
|
46
|
+
result.convert(string)
|
|
47
|
+
expect(string.encoding).to eq(Encoding::UTF_8)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
it 'returns a new string rather than scrubbing the one it was given' do
|
|
51
|
+
string = binary("ok\xFFbad")
|
|
52
|
+
expect(result.convert(string)).not_to equal(string)
|
|
53
|
+
expect(string.bytes).to include(0xFF)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
context 'when handed String subclass' do
|
|
57
|
+
let(:string_subclass) { Class.new(String) }
|
|
58
|
+
|
|
59
|
+
it 'accepts String subclass' do
|
|
60
|
+
expect(result.convert(string_subclass.new('plain'))).to eq('plain')
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
it 'leaves invalid encodings in place, as it always has' do
|
|
64
|
+
subclass = string_subclass.new(binary("ok\xFFbad"))
|
|
65
|
+
expect(result.convert(subclass).bytes).to include(0xFF)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
it 'converts anything else that can describe itself' do
|
|
69
|
+
expect(result.convert(5)).to eq('5')
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
it 'raises TypeError on nil' do
|
|
73
|
+
expect { result.convert(nil) }.to raise_error(TypeError, /cannot convert nil to a String/)
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
describe '#normalize_line_endings' do
|
|
79
|
+
it 'converts crlf to lf' do
|
|
80
|
+
expect(result.normalize_line_endings("a\r\nb")).to eq("a\nb")
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
it 'converts a lone cr to lf' do
|
|
84
|
+
expect(result.normalize_line_endings("a\rb")).to eq("a\nb")
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
it 'leaves lf alone' do
|
|
88
|
+
expect(result.normalize_line_endings("a\nb")).to eq("a\nb")
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
describe '#finalize!' do
|
|
93
|
+
before do
|
|
94
|
+
result.stdout << binary("out\xFF\r\n")
|
|
95
|
+
result.stderr << binary("err\xFF\r\n")
|
|
96
|
+
result.output << binary("out\xFF\r\nerr\xFF\r\n")
|
|
97
|
+
result.finalize!
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
it 'scrubs and normalizes every stream' do
|
|
101
|
+
expect(result.stdout).to eq("out\n")
|
|
102
|
+
expect(result.stderr).to eq("err\n")
|
|
103
|
+
expect(result.output).to eq("out\nerr\n")
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
it 'keeps the unscrubbed bytes in the raw_ attributes' do
|
|
107
|
+
expect(result.raw_stdout.bytes).to include(0xFF)
|
|
108
|
+
expect(result.raw_stderr.bytes).to include(0xFF)
|
|
109
|
+
expect(result.raw_output.bytes).to include(0xFF)
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
it 'leaves the raw_ line endings alone' do
|
|
113
|
+
expect(result.raw_stdout).to include("\r\n")
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
describe '#formatted_output' do
|
|
118
|
+
before do
|
|
119
|
+
result.output << (1..15).map { |i| "line #{i}" }.join("\n")
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
it 'returns the last ten lines by default, tab indented' do
|
|
123
|
+
expect(result.formatted_output).to eq((6..15).map { |i| "\tline #{i}" }.join("\n"))
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
it 'honours a limit' do
|
|
127
|
+
expect(result.formatted_output(2)).to eq("\tline 14\n\tline 15")
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
describe '#exit_code_in?' do
|
|
132
|
+
it 'is true when the exit code is in the range' do
|
|
133
|
+
result.exit_code = 2
|
|
134
|
+
expect(result.exit_code_in?([0, 2])).to be true
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
it 'is false when it is not' do
|
|
138
|
+
result.exit_code = 1
|
|
139
|
+
expect(result.exit_code_in?([0, 2])).to be false
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
describe '#success?' do
|
|
144
|
+
it 'is true only for an exit code of zero' do
|
|
145
|
+
result.exit_code = 0
|
|
146
|
+
expect(result).to be_success
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
it 'is false for a non-zero exit code' do
|
|
150
|
+
result.exit_code = 1
|
|
151
|
+
expect(result).not_to be_success
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
it 'is false when no exit code was collected' do
|
|
155
|
+
expect(result).not_to be_success
|
|
156
|
+
end
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
describe '#log' do
|
|
160
|
+
let(:logger) { instance_double(Beaker::Logger) }
|
|
161
|
+
|
|
162
|
+
it 'reports a non-zero exit code' do
|
|
163
|
+
result.exit_code = 1
|
|
164
|
+
expect(logger).to receive(:debug).with('Exited: 1')
|
|
165
|
+
result.log(logger)
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
it 'says nothing for a successful command' do
|
|
169
|
+
result.exit_code = 0
|
|
170
|
+
expect(logger).not_to receive(:debug)
|
|
171
|
+
result.log(logger)
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
it 'says nothing when no exit code was collected' do
|
|
175
|
+
expect(logger).not_to receive(:debug)
|
|
176
|
+
result.log(logger)
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
describe NullResult do
|
|
182
|
+
subject(:result) { described_class.new('my_host', 'ls -la') }
|
|
183
|
+
|
|
184
|
+
it 'succeeds without having run anything' do
|
|
185
|
+
expect(result.exit_code).to eq(0)
|
|
186
|
+
expect(result).to be_success
|
|
187
|
+
end
|
|
188
|
+
end
|
|
189
|
+
end
|
|
@@ -120,8 +120,8 @@ module Beaker
|
|
|
120
120
|
end
|
|
121
121
|
|
|
122
122
|
it 'requires hosts flag' do
|
|
123
|
-
|
|
124
|
-
|
|
123
|
+
expect { described_class.start(['init']) }
|
|
124
|
+
.to output(/No value provided for required options '--hosts'/).to_stderr
|
|
125
125
|
end
|
|
126
126
|
end
|
|
127
127
|
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: beaker
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 7.
|
|
4
|
+
version: 7.7.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Puppet
|
|
@@ -721,6 +721,7 @@ files:
|
|
|
721
721
|
- spec/beaker/options/validator_spec.rb
|
|
722
722
|
- spec/beaker/perf_spec.rb
|
|
723
723
|
- spec/beaker/platform_spec.rb
|
|
724
|
+
- spec/beaker/result_spec.rb
|
|
724
725
|
- spec/beaker/shared/error_handler_spec.rb
|
|
725
726
|
- spec/beaker/shared/fog_credentials_spec.rb
|
|
726
727
|
- spec/beaker/shared/host_manager_spec.rb
|
|
@@ -754,7 +755,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
754
755
|
- !ruby/object:Gem::Version
|
|
755
756
|
version: '0'
|
|
756
757
|
requirements: []
|
|
757
|
-
rubygems_version: 4.0.
|
|
758
|
+
rubygems_version: 4.0.16
|
|
758
759
|
specification_version: 4
|
|
759
760
|
summary: Let's test Puppet!
|
|
760
761
|
test_files: []
|