rspec-launchbox 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5c00ce31529ca3732c0fc6e5b930185fac4be632
4
- data.tar.gz: ea7c107c0a5688911f48e2feaaa1ce1ea50eb984
3
+ metadata.gz: 0317ed423bdb78223cf5eb3678021c69c7470d96
4
+ data.tar.gz: b0fc8a904edfae7244cda86a3d9c02328615edb5
5
5
  SHA512:
6
- metadata.gz: d4e73a5fbf734687c39a20ead035f863526c561237a60d612fea8a9f3db37da1a80fc856bb79dd1800bd7f0b4a691b17988a1752d0252d910a6125b5e05b6b58
7
- data.tar.gz: 701a8acfd4ff108e2cdfee8d86061a1f71a22652b3598804ed8b46aacd0413701bfecfcca5e70c5c1dcd0afcd7a951524f5f7649b487ab946415ad42c949ef7a
6
+ metadata.gz: 3d34ae9818ab4e61b2249e394a3cddd6d332e4b5d0b1e78125111d54dfe298861288597d82da2c7aa8b8515e28a8ac25a2258283d749b629c04cf35a0d8da9e1
7
+ data.tar.gz: 915e466f46865992e1f347218f879cf2b5dedd95d95f3eb11160699007743e20cda055e0823b0dfd4e7d7ada3da3a9e21e813612427d2e02f814b5e28332fb85
@@ -5,3 +5,9 @@ require 'rspec/its'
5
5
  require 'rspec/launchbox/timeout_matchers.rb'
6
6
  require 'rspec/launchbox/in_presence_of.rb'
7
7
  require 'rspec/launchbox/describe_executable.rb'
8
+
9
+ include RSpec::DescribeExecutable
10
+ RSpec.configure do |c|
11
+ c.extend RSpec::InPresenceOf
12
+ c.include RSpec::Matchers::Timeout
13
+ end
@@ -1,32 +1,118 @@
1
1
  module RSpec
2
+ # #describe_executable method and some
3
+ # pretty expectations regarding streams.
2
4
  module DescribeExecutable
5
+ # Expectations regarding streams,
6
+ # i.e. stderr, stdout.
7
+ # Meant to be extended in #describe_stderr and
8
+ # #describe_stdout
9
+ module Stream
10
+ # Expects lines in the specified stream
11
+ # to include each of the specified lines
12
+ # @param [Array] lines
13
+ # @example
14
+ # describe_stderr do
15
+ # it_is_expected_to_have_line 'cannot load shared library'
16
+ # end
17
+ def it_is_expected_to_have_line(*lines)
18
+ it "is expected to have line(s) matching '#{lines}'" do
19
+ expect(_watch_stream.lines.map(&:chomp)).to include *lines
20
+ end
21
+ end
22
+
23
+ alias_method :it_is_expected_to_have_lines, :it_is_expected_to_have_line
24
+ alias_method :has_line, :it_is_expected_to_have_lines
25
+ alias_method :has_lines, :it_is_expected_to_have_line
26
+
27
+ # Expects some lines in the specified stream
28
+ # to match specified pattern
29
+ # @param [Regex, String] lines
30
+ # @see #it_is_expected_to_have_line
31
+ def it_is_expected_to_have_lines_matching(pat)
32
+ it "is expected to have line(s) matching pattern '#{pat}'" do
33
+ __grep = _watch_stream.lines.grep(pat)
34
+ expect(__grep.size).to be > 0
35
+ end
36
+ end
37
+
38
+ alias_method :has_line_matching, :it_is_expected_to_have_lines_matching
39
+
40
+ # Expects lines in the specified stream
41
+ # *not* to include each of the specified lines
42
+ # @param [Regex, String] lines
43
+ # @see #it_is_expected_to_have_line
44
+ def it_is_expected_not_to_have_line(*lines)
45
+ it "is expected not to have line(s) matching '#{lines}'" do
46
+ expect(_watch_stream.lines.map(&:chomp)).not_to include *lines
47
+ end
48
+ end
49
+
50
+ alias_method :it_is_expected_not_to_have_lines, :it_is_expected_not_to_have_line
51
+ alias_method :has_no_line, :it_is_expected_not_to_have_line
52
+
53
+ # Expects *none of* the lines in the specified stream
54
+ # to match specified pattern
55
+ # @param [Regex, String] lines
56
+ # @see #it_is_expected_to_have_line
57
+ def it_is_expected_not_to_have_lines_matching(pat)
58
+ it "is expected not to have line(s) matching pattern '#{pat}'" do
59
+ __grep = _watch_stream.lines.grep(pat)
60
+ expect(__grep.size).to be 0
61
+ end
62
+ end
63
+
64
+ alias_method :has_no_line_matching, :it_is_expected_not_to_have_lines_matching
65
+ end
66
+
3
67
  # Outmost describe block.
4
68
  # @param [String] cmd executable name
5
69
  # @yields block like ordinary #describe
6
70
  # @example
7
71
  # describe_executable 'ls' do
8
- # its_stdout do
72
+ # describe_stdout do
9
73
  # it { is_expected.to be_a String }
10
74
  # end
11
75
  # end
12
76
  def describe_executable(cmd, &block)
13
- $_command_line = cmd
14
- $_process_stdout = ''
15
77
  RSpec.describe "#{$_command_line} executable" do
78
+ $_command_line = cmd
79
+ $_flags = []
80
+ $_process_stdout = ''
81
+ $_process_stderr = ''
82
+
16
83
  before(:each) do
84
+ $_command_line = cmd
85
+ $_process_stdout = ''
86
+ $_process_pid = nil
87
+ $_piper_o, $_pipew_o = IO.pipe
88
+ $_piper_e, $_pipew_e = IO.pipe
89
+ $_process_pid = fork do
90
+ $_piper_o.close
91
+ $_piper_e.close
92
+ $stdout.reopen $_pipew_o
93
+ $stderr.reopen $_pipew_e
94
+ exec($_command_line + ' ' + $_flags.join(' '))
95
+ end
96
+ $_pipew_o.close
97
+ $_pipew_e.close
17
98
  Thread.abort_on_exception = true
18
99
  Thread.new do
19
- IO.popen($_command_line) do |io|
20
- $_process_stdout << io.read(256) until io.eof?
100
+ maybe_read = [$_piper_o, $_piper_e]
101
+ can_read = []
102
+ loop do
103
+ can_read = select([$_piper_o, $_piper_e]).first.map!(&:fileno)
104
+ $_process_stdout << ($_piper_o.read(16) || '') if can_read.include? $_piper_o.fileno
105
+ $_process_stderr << ($_piper_e.read(16) || '') if can_read.include? $_piper_e.fileno
106
+ maybe_read.delete_if { |io| io.eof? }
107
+ break if maybe_read.empty?
21
108
  end
22
- end
23
- sleep 1
109
+ end.join
24
110
  end
25
111
 
26
112
  after(:each) do
27
- `killall -INT #{$_command_line.split(/\W/)[0]} &>/dev/null`
113
+ `kill -INT #{$_process_pid} &>/dev/null`
28
114
  sleep 0.1
29
- `killall -KILL #{$_command_line.split(/\W/)[0]} &>/dev/null`
115
+ `kill -KILL #{$_process_pid} &>/dev/null`
30
116
  end
31
117
 
32
118
  class_eval &block
@@ -37,14 +123,30 @@ module RSpec
37
123
  # sets it's subject to process stdout
38
124
  # @yields block like ordinary describe
39
125
  # @see #describe_executable for an example
40
- def its_stdout(&block)
126
+ def describe_stdout(&block)
41
127
  describe "it's stdout" do
128
+ let(:_watch_stream) { $_process_stdout.dup }
129
+ extend Stream
130
+
42
131
  subject { $_process_stdout }
43
132
 
44
133
  class_eval &block
45
134
  end
46
135
  end
47
136
 
137
+ # Same as #describe_stdout
138
+ # for stderr
139
+ def describe_stderr(&block)
140
+ describe "it's stderr" do
141
+ let(:_watch_stream) { $_process_stderr.dup }
142
+ extend Stream
143
+
144
+ subject { $_process_stderr }
145
+
146
+ class_eval &block
147
+ end
148
+ end
149
+
48
150
  # Opens new 'context',
49
151
  # where options are appended to
50
152
  # command line before execution.
@@ -53,19 +155,54 @@ module RSpec
53
155
  # @example
54
156
  # describe_executable 'ls' do
55
157
  # given_option '-a' do
56
- # its_stdout do
158
+ # describe_stdout do
57
159
  # #you need rspec-its gem for `its`
58
160
  # its(:lines) { is_expected.to include ".\n" }
161
+ # # much prettier:
162
+ # has_line '.'
59
163
  # end
60
164
  # end
61
165
  # end
62
- def given_option(flag, parameter = nil, &block)
63
- context "given option #{flag}#{parameter ? parameter + ' ' : nil}" do
64
- $_command_line__old = $_command_line.dup
65
- $_command_line << ' ' << [flag, parameter].join(' ')
166
+ def given_option(flag, &block)
167
+ context "given option #{flag}" do
168
+ before(:context) do
169
+ $_flags << flag
170
+ end
171
+
172
+ after(:context) do
173
+ $_flags.pop
174
+ end
175
+
176
+ class_eval &block
177
+ end
178
+ end
179
+
180
+ # Waits for `timeout` seconds, then
181
+ # sends signal to the process.
182
+ # @param [Integer] timeout
183
+ # @param [Hash] options
184
+ # @option options [Symbol | String] signal
185
+ # @example
186
+ # describe_executable 'some_long_running_executable' do
187
+ # running_for(10, signal: :INT) do
188
+ # describe_stdout do
189
+ # #...
190
+ # end
191
+ # end
192
+ # end
193
+ def running_for(timeout, options = {}, &block)
194
+ $_signal = options[:signal] && options[:signal].to_s.upcase.prepend('-')
195
+ context "when sent #{$_signal} after #{timeout} seconds" do
196
+ before(:each) do
197
+ Thread.new do
198
+ sleep timeout
199
+ `kill #{$_signal} #{$_process_pid} &>/dev/null`
200
+ end.join
201
+ end
66
202
 
67
203
  class_eval &block
68
204
  end
69
205
  end
70
206
  end
207
+
71
208
  end
@@ -1,5 +1,5 @@
1
1
  module Rspec
2
2
  module Launchbox
3
- VERSION = "0.0.1"
3
+ VERSION = "0.0.2"
4
4
  end
5
5
  end
@@ -1,14 +1,46 @@
1
1
  describe_executable 'ls' do
2
- its_stdout do
2
+ describe_stdout do
3
3
  it { is_expected.to be_a String }
4
4
  it { is_expected.not_to be_empty }
5
+ it_is_expected_to_have_line 'spec'
6
+ it_is_expected_to_have_line 'spec', 'lib'
7
+ it_is_expected_not_to_have_line 'blaargs'
8
+ it_is_expected_to_have_lines_matching /spec/
9
+ it_is_expected_not_to_have_lines_matching /blaargh/
5
10
  end
6
11
 
7
12
  given_option '-a' do
8
- its_stdout do
13
+ describe_stdout do
9
14
  it { is_expected.to be_a String }
10
15
  its(:lines) { is_expected.to include ".\n" }
11
16
  its(:lines) { is_expected.not_to include "ohwowwhatisit\n" }
12
17
  end
13
18
  end
19
+
20
+ given_option '-h' do
21
+ describe_stdout do
22
+ it 'command line should be cleaned up after each example' do
23
+ expect($_command_line).not_to include '-a'
24
+ end
25
+ its(:lines) { is_expected.not_to include ".\n" }
26
+ end
27
+
28
+ given_option '-a' do
29
+ describe_stdout do
30
+ its(:lines) { is_expected.to include ".\n" }
31
+ end
32
+ end
33
+ end
34
+
35
+ given_option '1>&2' do
36
+ describe_stderr do
37
+ its(:lines) { is_expected.to include "spec\n" }
38
+ end
39
+ end
40
+
41
+ running_for(2, signal: :INT) do
42
+ describe_stdout do
43
+ it { is_expected.to be_a String }
44
+ end
45
+ end
14
46
  end
@@ -7,8 +7,4 @@ RSpec.configure do |config|
7
7
  config.mock_with :rspec do |mocks|
8
8
  mocks.verify_partial_doubles = true
9
9
  end
10
- config.extend RSpec::InPresenceOf
11
- config.include RSpec::Matchers::Timeout
12
10
  end
13
-
14
- include RSpec::DescribeExecutable
@@ -1,15 +1,23 @@
1
1
  describe '#persist' do
2
2
  context 'with jush value passed' do
3
3
  it 'raises exceptions' do
4
- expect(5).to persist 5
4
+ begin
5
+ expect(5).to persist 5
6
+ rescue RuntimeError => e
7
+ raise e unless e.message.include? 'Block expected'
8
+ end
5
9
  end
6
10
  end
7
11
  context 'with block passed' do
8
12
  context 'with no boundary' do
9
13
  it 'd' do
10
- expect do
11
- 'string'
12
- end.to persist
14
+ begin
15
+ expect do
16
+ 'string'
17
+ end.to persist
18
+ rescue RuntimeError => e
19
+ raise e unless e.message.include? 'Expected'
20
+ end
13
21
  end
14
22
  end
15
23
 
@@ -29,10 +37,14 @@ describe '#persist' do
29
37
 
30
38
  context 'with block which raises exception' do
31
39
  it 'rethrows' do
32
- expect do
33
- 'string'
34
- fail 'Exception in subject block'
35
- end.to persist
40
+ begin
41
+ expect do
42
+ 'string'
43
+ fail 'Exception in subject block'
44
+ end.to persist.at_most(1)
45
+ rescue RuntimeError => e
46
+ raise e unless e.message.include? 'Exception in subject block'
47
+ end
36
48
  end
37
49
  end
38
50
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rspec-launchbox
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - d-theus
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-02-06 00:00:00.000000000 Z
11
+ date: 2015-02-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -118,4 +118,3 @@ test_files:
118
118
  - spec/in-presence-of_spec.rb
119
119
  - spec/spec_helper.rb
120
120
  - spec/timeouts_spec.rb
121
- has_rdoc: