rspec-launchbox 0.0.1 → 0.0.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.
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: