blue-shell 0.0.1

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.
data/LICENSE ADDED
@@ -0,0 +1,14 @@
1
+ The MIT License (MIT)
2
+ Copyright (c) 2013 Pivotal Labs
3
+
4
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
5
+ documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
6
+ rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit
7
+ persons to whom the Software is furnished to do so, subject to the following conditions:
8
+
9
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
10
+
11
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
12
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
13
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
14
+ OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env rake
2
+
3
+ require 'rspec/core/rake_task'
4
+
5
+ RSpec::Core::RakeTask.new(:spec)
6
+
7
+ task :default => :spec
@@ -0,0 +1,6 @@
1
+ require 'blue-shell/errors'
2
+ require 'blue-shell/matchers'
3
+ require 'blue-shell/matchers/exit_code_matcher'
4
+ require 'blue-shell/matchers/output_matcher'
5
+ require 'blue-shell/runner'
6
+ require 'blue-shell/buffered_reader_expector'
@@ -0,0 +1,73 @@
1
+ module BlueShell
2
+ class BufferedReaderExpector
3
+ attr_reader :output
4
+
5
+ def initialize(out, debug = false)
6
+ @out = out
7
+ @debug = debug
8
+ @unused = ""
9
+ @output = ""
10
+ end
11
+
12
+ def expect(pattern, timeout = 5)
13
+ buffer = ''
14
+
15
+ case pattern
16
+ when String
17
+ pattern = Regexp.new(Regexp.quote(pattern))
18
+ when Regexp
19
+ else
20
+ raise TypeError, "unsupported pattern class: #{pattern.class}"
21
+ end
22
+
23
+ result = nil
24
+ position = 0
25
+ @unused ||= ""
26
+
27
+ while true
28
+ if !@unused.empty?
29
+ c = @unused.slice!(0).chr
30
+ elsif output_ended?(timeout)
31
+ @unused = buffer
32
+ break
33
+ else
34
+ c = @out.getc.chr
35
+ end
36
+
37
+ STDOUT.putc c if @debug
38
+
39
+ # wear your flip flops
40
+ unless (c == "\e") .. (c == "m")
41
+ if c == "\b"
42
+ if position > 0 && buffer[position - 1] && buffer[position - 1].chr != "\n"
43
+ position -= 1
44
+ end
45
+ else
46
+ if buffer.size > position
47
+ buffer[position] = c
48
+ else
49
+ buffer << c
50
+ end
51
+
52
+ position += 1
53
+ end
54
+ end
55
+
56
+ if matches = pattern.match(buffer)
57
+ result = [buffer, *matches.to_a[1..-1]]
58
+ break
59
+ end
60
+ end
61
+
62
+ @output << buffer
63
+
64
+ result
65
+ end
66
+
67
+ private
68
+
69
+ def output_ended?(timeout)
70
+ (@out.is_a?(IO) && !IO.select([@out], nil, nil, timeout)) || @out.eof?
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,12 @@
1
+ module BlueShell
2
+ module Errors
3
+ class InvalidInputError < StandardError; end
4
+
5
+ class NonZeroExitCodeError < StandardError
6
+ attr_reader :exit_code
7
+ def initialize(exit_code)
8
+ @exit_code = exit_code
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,13 @@
1
+ module BlueShell
2
+ module Matchers
3
+ def say(expected_output, timeout = 30)
4
+ OutputMatcher.new(expected_output, timeout)
5
+ end
6
+
7
+ def have_exited_with(expected_code)
8
+ ExitCodeMatcher.new(expected_code)
9
+ end
10
+
11
+ alias :exit_with :have_exited_with
12
+ end
13
+ end
@@ -0,0 +1,40 @@
1
+ module BlueShell
2
+ module Matchers
3
+ class ExitCodeMatcher
4
+ def initialize(expected_code)
5
+ @expected_code = expected_code
6
+ end
7
+
8
+ def matches?(runner)
9
+ raise Errors::InvalidInputError unless runner.respond_to?(:exit_code)
10
+
11
+ begin
12
+ Timeout.timeout(5) do
13
+ @actual_code = runner.exit_code
14
+ end
15
+
16
+ @actual_code == @expected_code
17
+ rescue Timeout::Error
18
+ @timed_out = true
19
+ false
20
+ end
21
+ end
22
+
23
+ def failure_message
24
+ if @timed_out
25
+ "expected process to exit with status #@expected_code, but it did not exit within 5 seconds"
26
+ else
27
+ "expected process to exit with status #{@expected_code}, but it exited with status #{@actual_code}"
28
+ end
29
+ end
30
+
31
+ def negative_failure_message
32
+ if @timed_out
33
+ "expected process to exit with status #@expected_code, but it did not exit within 5 seconds"
34
+ else
35
+ "expected process to not exit with status #{@expected_code}, but it did"
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,38 @@
1
+ module BlueShell
2
+ module Matchers
3
+ class OutputMatcher
4
+ attr_reader :timeout
5
+
6
+ def initialize(expected_output, timeout = 30)
7
+ @expected_output = expected_output
8
+ @timeout = timeout
9
+ end
10
+
11
+ def matches?(runner)
12
+ raise Errors::InvalidInputError unless runner.respond_to?(:expect)
13
+ @matched = runner.expect(@expected_output, @timeout)
14
+ @full_output = runner.output
15
+ !!@matched
16
+ end
17
+
18
+ def failure_message
19
+ if @expected_output.is_a?(Hash)
20
+ expected_keys = @expected_output.keys.map{|key| "'#{key}'"}.join(', ')
21
+ "expected one of #{expected_keys} to be printed, but it wasn't. full output:\n#@full_output"
22
+ else
23
+ "expected '#{@expected_output}' to be printed, but it wasn't. full output:\n#@full_output"
24
+ end
25
+ end
26
+
27
+ def negative_failure_message
28
+ if @expected_output.is_a?(Hash)
29
+ match = @matched
30
+ else
31
+ match = @expected_output
32
+ end
33
+
34
+ "expected '#{match}' to not be printed, but it was. full output:\n#@full_output"
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,98 @@
1
+ require 'pty'
2
+ require 'timeout'
3
+
4
+ module BlueShell
5
+ class Runner
6
+ def initialize(*args)
7
+ @stdout, slave = PTY.open
8
+ system('stty raw', :in => slave)
9
+ read, @stdin = IO.pipe
10
+
11
+ @pid = spawn(*(args.push(:in => read, :out => slave, :err => slave)))
12
+
13
+ @expector = BufferedReaderExpector.new(@stdout, ENV['DEBUG_BACON'])
14
+
15
+ if block_given?
16
+ yield self
17
+ else
18
+ code = exit_code
19
+ raise Errors::NonZeroExitCodeError.new(code) unless code == 0
20
+ end
21
+ end
22
+
23
+ class << self
24
+ alias_method :run, :new
25
+ end
26
+
27
+ def expect(matcher, timeout = 30)
28
+ case matcher
29
+ when Hash
30
+ expect_branches(matcher, timeout)
31
+ else
32
+ @expector.expect(matcher, timeout)
33
+ end
34
+ end
35
+
36
+ def send_keys(text_to_send)
37
+ @stdin.puts(text_to_send)
38
+ end
39
+
40
+ def exit_code
41
+ return @code if @code
42
+
43
+ code = nil
44
+ Timeout.timeout(5) do
45
+ _, code = Process.waitpid2(@pid)
46
+ end
47
+
48
+ @code = numeric_exit_code(code)
49
+ end
50
+
51
+ alias_method :wait_for_exit, :exit_code
52
+
53
+ def exited?
54
+ !running?
55
+ end
56
+
57
+ def success?
58
+ @code.zero?
59
+ end
60
+
61
+ alias_method :successful?, :success?
62
+
63
+ def running?
64
+ !!Process.getpgid(@pid)
65
+ end
66
+
67
+ def output
68
+ @expector.output
69
+ end
70
+
71
+ def debug
72
+ @expector.debug
73
+ end
74
+
75
+ def debug=(x)
76
+ @expector.debug = x
77
+ end
78
+
79
+ private
80
+
81
+ def expect_branches(branches, timeout)
82
+ branch_names = /#{branches.keys.collect { |k| Regexp.quote(k) }.join('|')}/
83
+ expected = @expector.expect(branch_names, timeout)
84
+ return unless expected
85
+
86
+ data = expected.first.match(/(#{branch_names})$/)
87
+ matched = data[1]
88
+ branches[matched].call
89
+ matched
90
+ end
91
+
92
+ def numeric_exit_code(status)
93
+ status.exitstatus
94
+ rescue NoMethodError
95
+ status
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,3 @@
1
+ module BlueShell
2
+ VERSION = "0.0.1".freeze
3
+ end
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $stdout.sync = true
4
+ print "started"
5
+ typed = gets
6
+ print "received #{typed}"
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ print "started"
4
+ sleep 0.5
5
+ print " finished"
@@ -0,0 +1,76 @@
1
+ require 'spec_helper'
2
+
3
+ module BlueShell
4
+ module Matchers
5
+ describe ExitCodeMatcher, :ruby19 => true do
6
+ let(:expected_code) { 0 }
7
+
8
+ subject { ExitCodeMatcher.new(expected_code) }
9
+
10
+ describe "#matches?" do
11
+ context "with something that isn't a runner" do
12
+ it "raises an exception" do
13
+ expect {
14
+ subject.matches?("c'est ne pas une specker runner")
15
+ }.to raise_exception(Errors::InvalidInputError)
16
+ end
17
+ end
18
+
19
+ context "with a valid runner" do
20
+ context "and the command exited with the expected exit code" do
21
+ it "returns true" do
22
+ BlueShell::Runner.run("true") do |runner|
23
+ subject.matches?(runner).should be_true
24
+ end
25
+ end
26
+ end
27
+
28
+ context "and the command exits with a different exit code" do
29
+ it "returns false" do
30
+ BlueShell::Runner.run("false") do |runner|
31
+ subject.matches?(runner).should be_false
32
+ end
33
+ end
34
+ end
35
+
36
+ context "and the command runs for a while" do
37
+ it "waits for it to exit" do
38
+ BlueShell::Runner.run("sleep 0.5") do |runner|
39
+ subject.matches?(runner).should be_true
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+
46
+ context "failure messages" do
47
+ context "with a command that's exited" do
48
+ it "has a correct failure message" do
49
+ BlueShell::Runner.run("false") do |runner|
50
+ subject.matches?(runner)
51
+ runner.wait_for_exit
52
+ subject.failure_message.should == "expected process to exit with status 0, but it exited with status 1"
53
+ end
54
+ end
55
+
56
+ it "has a correct negative failure message" do
57
+ BlueShell::Runner.run("false") do |runner|
58
+ subject.matches?(runner)
59
+ runner.wait_for_exit
60
+ subject.negative_failure_message.should == "expected process to not exit with status 0, but it did"
61
+ end
62
+ end
63
+ end
64
+
65
+ context "with a command that's still running" do
66
+ it "waits for it to exit" do
67
+ BlueShell::Runner.run("ruby -e 'sleep 1; exit 1'") do |runner|
68
+ subject.matches?(runner)
69
+ subject.failure_message.should == "expected process to exit with status 0, but it exited with status 1"
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,79 @@
1
+ require 'spec_helper'
2
+
3
+ module BlueShell
4
+ module Matchers
5
+ describe OutputMatcher, :ruby19 => true do
6
+ let(:expected_output) { "expected_output" }
7
+ let(:timeout) { 1 }
8
+
9
+ subject { OutputMatcher.new(expected_output, timeout) }
10
+
11
+ describe "#matches?" do
12
+ context "with something that isn't a runner" do
13
+ it "raises an exception" do
14
+ expect {
15
+ subject.matches?("c'est ne pas une specker runner")
16
+ }.to raise_exception(Errors::InvalidInputError)
17
+ end
18
+ end
19
+
20
+ context "with a valid runner" do
21
+ context "when the expected output is in the process output" do
22
+ it "finds the expected output" do
23
+ BlueShell::Runner.run("echo -n expected_output") do |runner|
24
+ subject.matches?(runner).should be_true
25
+ end
26
+ end
27
+ end
28
+
29
+ context "when the expected output is not in the process output" do
30
+ let(:runner) { Runner.new('echo -n not_what_we_were_expecting') }
31
+
32
+ it "does not find the expected output" do
33
+ BlueShell::Runner.run("echo -n not_what_we_were_expecting") do |runner|
34
+ subject.matches?(runner).should be_false
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
40
+
41
+ context "failure messages" do
42
+ it "has a correct failure message" do
43
+ BlueShell::Runner.run("echo -n actual_output") do |runner|
44
+ subject.matches?(runner)
45
+ subject.failure_message.should == "expected 'expected_output' to be printed, but it wasn't. full output:\nactual_output"
46
+ end
47
+ end
48
+
49
+ it "has a correct negative failure message" do
50
+ BlueShell::Runner.run("echo -n actual_output") do |runner|
51
+ subject.matches?(runner)
52
+ subject.negative_failure_message.should == "expected 'expected_output' to not be printed, but it was. full output:\nactual_output"
53
+ end
54
+ end
55
+
56
+ context "when expecting branching output" do
57
+ let(:expected_output) { {
58
+ "expected_output" => proc {},
59
+ "other_expected_output" => proc {}
60
+ } }
61
+
62
+ it "has a correct failure message" do
63
+ BlueShell::Runner.run("echo -n actual_output") do |runner|
64
+ subject.matches?(runner)
65
+ subject.failure_message.should == "expected one of 'expected_output', 'other_expected_output' to be printed, but it wasn't. full output:\nactual_output"
66
+ end
67
+ end
68
+
69
+ it "has a correct negative failure message" do
70
+ BlueShell::Runner.run("echo -n expected_output") do |runner|
71
+ subject.matches?(runner)
72
+ subject.negative_failure_message.should == "expected 'expected_output' to not be printed, but it was. full output:\nexpected_output"
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,31 @@
1
+ require 'spec_helper'
2
+
3
+ module BlueShell
4
+ describe Matchers do
5
+ include Matchers
6
+
7
+ describe "#say" do
8
+ it "returns an ExpectOutputMatcher" do
9
+ say("").should be_a(Matchers::OutputMatcher)
10
+ end
11
+
12
+ context "with an explicit timeout" do
13
+ it "returns an ExpectOutputMatcher" do
14
+ matcher = say("", 30)
15
+ matcher.should be_a(Matchers::OutputMatcher)
16
+ matcher.timeout.should == 30
17
+ end
18
+ end
19
+ end
20
+
21
+ describe "#have_exited_with" do
22
+ it "returns an ExitCodeMatcher" do
23
+ have_exited_with(1).should be_a(Matchers::ExitCodeMatcher)
24
+ end
25
+
26
+ it "has synonyms" do
27
+ exit_with(1).should be_a(Matchers::ExitCodeMatcher)
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,194 @@
1
+ require 'spec_helper'
2
+ require 'tempfile'
3
+
4
+ module BlueShell
5
+ describe Runner do
6
+ let(:timeout) { 1 }
7
+
8
+ describe "running a command" do
9
+ let(:file) do
10
+ file = Tempfile.new('blue-shell-runner')
11
+ sleep 1 # wait one second to make sure touching the file does something measurable
12
+ file
13
+ end
14
+
15
+ after { file.unlink }
16
+
17
+ context "with an invalid command" do
18
+ it "raises an exception" do
19
+ expect {
20
+ BlueShell::Runner.run("false")
21
+ }.to raise_error(Errors::NonZeroExitCodeError) { |error| error.exit_code.should == 1 }
22
+ end
23
+ end
24
+
25
+ context "with a valid command" do
26
+ it "runs a command" do
27
+ BlueShell::Runner.run("touch -a #{file.path}")
28
+ file.stat.atime.should > file.stat.mtime
29
+ end
30
+ end
31
+ end
32
+
33
+ describe "#success? and #successful?" do
34
+ context "when the command has a non-zero exit code" do
35
+ it "returns false" do
36
+ runner = BlueShell::Runner.run("false") { |runner|
37
+ runner.wait_for_exit
38
+ }
39
+ runner.should_not be_success
40
+ runner.should_not be_successful
41
+ end
42
+ end
43
+
44
+ context "when the command has a zero exit code" do
45
+ it "returns true" do
46
+ runner = BlueShell::Runner.run("true")
47
+ runner.should be_success
48
+ runner.should be_successful
49
+ end
50
+ end
51
+ end
52
+
53
+ describe "#expect" do
54
+ context "when the expected output shows up" do
55
+ it "returns a truthy value" do
56
+ BlueShell::Runner.run("echo -n foo") do |runner|
57
+ expect(runner.expect('foo')).to be_true
58
+ end
59
+ end
60
+ end
61
+
62
+ context "when the expected output never shows up" do
63
+ it "returns nil" do
64
+ BlueShell::Runner.run("echo the spanish inquisition") do |runner|
65
+ expect(runner.expect("something else", 0.5)).to be_nil
66
+ end
67
+ end
68
+ end
69
+
70
+ context "when the output eventually shows up" do
71
+ it "returns a truthy value" do
72
+ BlueShell::Runner.run("ruby #{asset("pause.rb")}") do |runner|
73
+ expect(runner.expect("finished")).to be_true
74
+ end
75
+ end
76
+ end
77
+
78
+ context "backspace" do
79
+ it "respects the backspace character" do
80
+ BlueShell::Runner.run("ruby -e 'puts \"foo a\\bbar\"'") do |runner|
81
+ expect(runner.expect("foo bar")).to be_true
82
+ end
83
+ end
84
+
85
+ it "does not go beyond the beginning of the line" do
86
+ BlueShell::Runner.run("ruby -e 'print \"foo abc\nx\\b\\bd\"'") do |runner|
87
+ expect(runner.expect("foo abc\nd")).to be_true
88
+ end
89
+ end
90
+
91
+ it "does not go beyond the beginning of the string" do
92
+ BlueShell::Runner.run("ruby -e 'print \"f\\b\\bbar\"'") do |runner|
93
+ expect(runner.expect("bar")).to be_true
94
+ end
95
+ end
96
+
97
+ it "leaves backspaced characters in the buffer until they're overwritten" do
98
+ BlueShell::Runner.run("ruby -e 'print \"foo abc\\b\\bd\"'") do |runner|
99
+ expect(runner.expect("foo adc")).to be_true
100
+ end
101
+ end
102
+ end
103
+
104
+ context "ansi escape sequences" do
105
+ it "filters ansi color sequences" do
106
+ BlueShell::Runner.run("ruby -e 'puts \"\\e[36mblue\\e[0m thing\"'") do |runner|
107
+ expect(runner.expect("blue thing")).to be_true
108
+ end
109
+ end
110
+ end
111
+
112
+ context "expecting multiple branches" do
113
+ context "and one of them matches" do
114
+ it "can be passed a hash of values with callbacks, and returns the matched key" do
115
+ BlueShell::Runner.run("echo 1 3") do |runner|
116
+ branches = {
117
+ "1" => proc { 1 },
118
+ "2" => proc { 2 },
119
+ "3" => proc { 3 }
120
+ }
121
+
122
+ expect(runner.expect(branches)).to eq "1"
123
+ expect(runner.expect(branches)).to eq "3"
124
+ end
125
+ end
126
+
127
+ it "calls the matched callback" do
128
+ callback = mock!
129
+ BlueShell::Runner.run("echo 1 3") do |runner|
130
+ branches = {
131
+ "1" => proc { callback }
132
+ }
133
+ runner.expect(branches)
134
+ end
135
+ end
136
+ end
137
+
138
+ context "and none of them match" do
139
+ it "returns nil when none of the branches match" do
140
+ BlueShell::Runner.run("echo not_a_number") do |runner|
141
+ expect(runner.expect({"1" => proc { 1 }}, timeout)).to be_nil
142
+ end
143
+ end
144
+ end
145
+ end
146
+ end
147
+
148
+ describe "#output" do
149
+ it "makes the entire command output (so far) available" do
150
+ BlueShell::Runner.run("echo 0 1 2 3") do |runner|
151
+ runner.expect("1")
152
+ runner.expect("3")
153
+ expect(runner.output).to eq "0 1 2 3"
154
+ end
155
+
156
+ end
157
+ end
158
+
159
+ describe "#send_keys" do
160
+ it "sends input and expects more output afterward" do
161
+ BlueShell::Runner.run("ruby #{asset("input.rb")}") do |runner|
162
+ expect(runner.expect("started")).to be_true
163
+ runner.send_keys("foo")
164
+ expect(runner.expect("foo")).to be_true
165
+ end
166
+ end
167
+ end
168
+
169
+ context "#exit_code" do
170
+ it "returns the exit code" do
171
+ BlueShell::Runner.run("ruby -e 'exit 42'") do |runner|
172
+ runner.wait_for_exit
173
+ expect(runner.exit_code).to eq(42)
174
+ end
175
+ end
176
+
177
+ context "when the command is still running" do
178
+ it "waits for the command to exit" do
179
+ BlueShell::Runner.run("sleep 0.5") do |runner|
180
+ expect(runner.exit_code).to eq(0)
181
+ end
182
+ end
183
+ end
184
+ end
185
+
186
+ context "#exited?" do
187
+ it "returns false if the command is still running" do
188
+ BlueShell::Runner.run("sleep 10") do |runner|
189
+ expect(runner.exited?).to eq false
190
+ end
191
+ end
192
+ end
193
+ end
194
+ end
@@ -0,0 +1,13 @@
1
+ require 'blue-shell'
2
+ require 'rr'
3
+
4
+ Dir[File.expand_path('../support/**/*.rb', __FILE__)].each do |file|
5
+ require file
6
+ end
7
+
8
+ RSpec.configure do |config|
9
+ config.mock_with :rr
10
+
11
+ config.include BlueShell::Helpers
12
+ end
13
+
@@ -0,0 +1,7 @@
1
+ module BlueShell
2
+ module Helpers
3
+ def asset(file)
4
+ File.expand_path("../../assets/#{file}", __FILE__)
5
+ end
6
+ end
7
+ end
metadata ADDED
@@ -0,0 +1,122 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: blue-shell
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Pivotal Labs
9
+ - Cloud Foundry
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+ date: 2013-04-09 00:00:00.000000000 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: rspec
17
+ requirement: !ruby/object:Gem::Requirement
18
+ none: false
19
+ requirements:
20
+ - - ! '>='
21
+ - !ruby/object:Gem::Version
22
+ version: '0'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ none: false
27
+ requirements:
28
+ - - ! '>='
29
+ - !ruby/object:Gem::Version
30
+ version: '0'
31
+ - !ruby/object:Gem::Dependency
32
+ name: rake
33
+ requirement: !ruby/object:Gem::Requirement
34
+ none: false
35
+ requirements:
36
+ - - ! '>='
37
+ - !ruby/object:Gem::Version
38
+ version: '0'
39
+ type: :development
40
+ prerelease: false
41
+ version_requirements: !ruby/object:Gem::Requirement
42
+ none: false
43
+ requirements:
44
+ - - ! '>='
45
+ - !ruby/object:Gem::Version
46
+ version: '0'
47
+ - !ruby/object:Gem::Dependency
48
+ name: rr
49
+ requirement: !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ type: :development
56
+ prerelease: false
57
+ version_requirements: !ruby/object:Gem::Requirement
58
+ none: false
59
+ requirements:
60
+ - - ! '>='
61
+ - !ruby/object:Gem::Version
62
+ version: '0'
63
+ description:
64
+ email:
65
+ - cfpi-frontend@googlegroups.com
66
+ executables: []
67
+ extensions: []
68
+ extra_rdoc_files: []
69
+ files:
70
+ - LICENSE
71
+ - Rakefile
72
+ - lib/blue-shell/buffered_reader_expector.rb
73
+ - lib/blue-shell/errors.rb
74
+ - lib/blue-shell/matchers/exit_code_matcher.rb
75
+ - lib/blue-shell/matchers/output_matcher.rb
76
+ - lib/blue-shell/matchers.rb
77
+ - lib/blue-shell/runner.rb
78
+ - lib/blue-shell/version.rb
79
+ - lib/blue-shell.rb
80
+ - spec/assets/input.rb
81
+ - spec/assets/pause.rb
82
+ - spec/matchers/exit_code_matcher_spec.rb
83
+ - spec/matchers/output_matcher_spec.rb
84
+ - spec/matchers_spec.rb
85
+ - spec/runner_spec.rb
86
+ - spec/spec_helper.rb
87
+ - spec/support/helpers.rb
88
+ homepage: http://github.com/pivotal/blue-shell
89
+ licenses:
90
+ - MIT
91
+ post_install_message:
92
+ rdoc_options: []
93
+ require_paths:
94
+ - lib
95
+ required_ruby_version: !ruby/object:Gem::Requirement
96
+ none: false
97
+ requirements:
98
+ - - ! '>='
99
+ - !ruby/object:Gem::Version
100
+ version: '0'
101
+ required_rubygems_version: !ruby/object:Gem::Requirement
102
+ none: false
103
+ requirements:
104
+ - - ! '>='
105
+ - !ruby/object:Gem::Version
106
+ version: '0'
107
+ requirements: []
108
+ rubyforge_project:
109
+ rubygems_version: 1.8.24
110
+ signing_key:
111
+ specification_version: 3
112
+ summary: Friendly command-line test runner and matchers for shell scripting in ruby
113
+ using rspec.
114
+ test_files:
115
+ - spec/assets/input.rb
116
+ - spec/assets/pause.rb
117
+ - spec/matchers/exit_code_matcher_spec.rb
118
+ - spec/matchers/output_matcher_spec.rb
119
+ - spec/matchers_spec.rb
120
+ - spec/runner_spec.rb
121
+ - spec/spec_helper.rb
122
+ - spec/support/helpers.rb