right_popen 1.0.11 → 1.0.16

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,178 @@
1
+ #-- -*- mode: ruby; encoding: utf-8 -*-
2
+ # Copyright: Copyright (c) 2011 RightScale, Inc.
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # 'Software'), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18
+ # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19
+ # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20
+ # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21
+ # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ #++
23
+
24
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'spec_helper'))
25
+
26
+ module RightScale::RightPopen
27
+ describe Utilities do
28
+ describe :run do
29
+ it 'should collect stdout and stderr' do
30
+ out, err = Utilities::run("echo foo; echo bar >&2")
31
+ out.should == "foo\n"
32
+ err.should == "bar\n"
33
+ end
34
+
35
+ it 'should handle utilities that expect input' do
36
+ out, err = Utilities::run("echo foo; read; echo bar >&2")
37
+ out.should == "foo\n"
38
+ err.should == "bar\n"
39
+ end
40
+
41
+ it 'should raise an error if the command fails' do
42
+ lambda { Utilities::run("false") }.should raise_exception(/Command "false" failed with exit status 1/)
43
+ end
44
+
45
+ it 'should raise an error if the command gets killed' do
46
+ lambda { Utilities::run("kill $$") }.should raise_exception(/Command ".*" failed due to SIGTERM/)
47
+ end
48
+
49
+ it 'should not invoke the shell when inappropriate' do
50
+ out, err = Utilities::run(["echo", "foo;", "echo", "bar", ">&2"])
51
+ out.should == "foo; echo bar >&2\n"
52
+ err.should be_empty
53
+ end
54
+ end
55
+
56
+ describe :run_collecting_output do
57
+ it 'should work' do
58
+ status, out, err = Utilities::run_collecting_output("echo foo; echo bar >&2")
59
+ status.should be_success
60
+ out.should == "foo\n"
61
+ err.should == "bar\n"
62
+ end
63
+
64
+ it 'should handle the command failing gracefully' do
65
+ status, out, err = Utilities::run_collecting_output("false")
66
+ status.should_not be_success
67
+ status.exitstatus.should == 1
68
+ out.should be_empty
69
+ err.should be_empty
70
+ end
71
+
72
+ it 'should handle the command self terminating gracefully' do
73
+ status, out, err = Utilities::run_collecting_output("kill $$")
74
+ status.should_not be_success
75
+ status.exitstatus.should be_nil
76
+ status.termsig.should == 15
77
+ out.should be_empty
78
+ err.should be_empty
79
+ end
80
+
81
+ it 'should not invoke the shell when inappropriate' do
82
+ status, out, err = Utilities::run_collecting_output(["echo", "foo;", "read", "foo", ";", "echo", "bar", ">&2"])
83
+ status.should be_success
84
+ out.should == "foo; read foo ; echo bar >&2\n"
85
+ err.should be_empty
86
+ end
87
+ end
88
+
89
+ describe :run_with_stdin_collecting_output do
90
+ it 'should work even if subprocess ignores stdin' do
91
+ status, out, err = Utilities::run_with_stdin_collecting_output("echo foo; echo bar >&2", "foo")
92
+ status.should be_success
93
+ out.should == "foo\n"
94
+ err.should == "bar\n"
95
+ end
96
+
97
+ it 'should handle utilities that expect input' do
98
+ status, out, err = Utilities::run_with_stdin_collecting_output("echo foo; read foo; echo $foo >&2", "blotz")
99
+ status.should be_success
100
+ out.should == "foo\n"
101
+ err.should == "blotz\n"
102
+ end
103
+
104
+ it 'should handle the command failing gracefully' do
105
+ status, out, err = Utilities::run_with_stdin_collecting_output("false", "blotz")
106
+ status.should_not be_success
107
+ status.exitstatus.should == 1
108
+ out.should be_empty
109
+ err.should be_empty
110
+ end
111
+
112
+ it 'should handle the command self terminating gracefully' do
113
+ status, out, err = Utilities::run_with_stdin_collecting_output("kill $$", "blotz")
114
+ status.should_not be_success
115
+ status.exitstatus.should be_nil
116
+ status.termsig.should == 15
117
+ out.should be_empty
118
+ err.should be_empty
119
+ end
120
+
121
+ it 'should not invoke the shell when inappropriate' do
122
+ status, out, err = Utilities::run_with_stdin_collecting_output(["echo", "foo;", "read", "foo", ";", "echo", "bar", ">&2"], "blotz")
123
+ status.should be_success
124
+ out.should == "foo; read foo ; echo bar >&2\n"
125
+ err.should be_empty
126
+ end
127
+ end
128
+
129
+ describe :run_with_blocks do
130
+ it 'should work even if subprocess ignores stdin' do
131
+ status = Utilities::run_with_blocks("echo foo; echo bar >&2",
132
+ lambda { "foo" },
133
+ lambda { |b| b.should == "foo\n" },
134
+ lambda { |b| b.should == "bar\n" })
135
+ status.should be_success
136
+ end
137
+
138
+ it 'should handle interaction' do
139
+ output_counter = 0
140
+ seen = {}
141
+ in_block = lambda {
142
+ if seen[output_counter]
143
+ ""
144
+ else
145
+ seen[output_counter] = true
146
+ "foo\n"
147
+ end
148
+ }
149
+ status = Utilities::run_with_blocks("for x in 1 2 3; do read var; echo $var; done; echo bar >&2",
150
+ in_block,
151
+ lambda { |b| output_counter += 1; b.should == "foo\n" },
152
+ lambda { |b| b.should == "bar\n" })
153
+ status.should be_success
154
+ output_counter.should == 3
155
+ end
156
+
157
+ it 'should handle the command failing gracefully' do
158
+ status = Utilities::run_with_blocks("echo foo; echo bar >&2; false",
159
+ lambda { "blotz" }, nil, nil)
160
+ status.should_not be_success
161
+ status.exitstatus.should == 1
162
+ end
163
+
164
+ it 'should handle the command self terminating gracefully' do
165
+ status = Utilities::run_with_blocks("echo foo; echo bar >&2; kill $$",
166
+ lambda { "blotz" }, nil, nil)
167
+ status.should_not be_success
168
+ status.exitstatus.should be_nil
169
+ status.termsig.should == 15
170
+ end
171
+
172
+ it 'should not invoke the shell when inappropriate' do
173
+ status, out, err = Utilities::run_with_blocks(["echo", "foo;", "read", "foo", ";", "echo", "bar", ">&2"], nil, lambda {|b| b.should == "foo; read foo ; echo bar >&2\n"}, nil)
174
+ status.should be_success
175
+ end
176
+ end
177
+ end
178
+ end
@@ -1,298 +1,230 @@
1
- require File.join(File.dirname(__FILE__), 'spec_helper')
1
+ require File.expand_path(File.join(File.dirname(__FILE__), 'spec_helper'))
2
+ require File.expand_path(File.join(File.dirname(__FILE__), 'runner'))
2
3
 
3
- describe 'RightScale::popen3' do
4
-
5
- module RightPopenSpec
6
- class Runner
7
- class RunnerStatus
8
- def initialize(command, block)
9
- @output_text = ""
10
- @error_text = ""
11
- @status = nil
12
- @did_timeout = false
13
- @callback = block
14
- @pid = nil
15
- EM.next_tick do
16
- @timeout = EM::Timer.new(2) do
17
- puts "\n** Failed to run #{command.inspect}: Timeout"
18
- @did_timeout = true
19
- @callback.call(self)
20
- end
21
- end
22
- end
23
-
24
- attr_accessor :output_text, :error_text, :status, :did_timeout, :pid
4
+ module RightScale
5
+ describe 'popen3' do
6
+ def is_windows?
7
+ return !!(RUBY_PLATFORM =~ /mswin/)
8
+ end
25
9
 
26
- def on_read_stdout(data)
27
- @output_text << data
28
- end
10
+ it 'should redirect output' do
11
+ command = "\"#{RUBY_CMD}\" \"#{File.expand_path(File.join(File.dirname(__FILE__), 'produce_output.rb'))}\" \"#{STANDARD_MESSAGE}\" \"#{ERROR_MESSAGE}\""
12
+ runner = Runner.new
13
+ status = runner.run_right_popen(command)
14
+ status.status.exitstatus.should == 0
15
+ status.output_text.should == STANDARD_MESSAGE + "\n"
16
+ status.error_text.should == ERROR_MESSAGE + "\n"
17
+ status.pid.should > 0
18
+ end
29
19
 
30
- def on_read_stderr(data)
31
- @error_text << data
32
- end
20
+ it 'should return the right status' do
21
+ command = "\"#{RUBY_CMD}\" \"#{File.expand_path(File.join(File.dirname(__FILE__), 'produce_status.rb'))}\" #{EXIT_STATUS}"
22
+ runner = Runner.new
23
+ status = runner.run_right_popen(command)
24
+ status.status.exitstatus.should == EXIT_STATUS
25
+ status.output_text.should == ''
26
+ status.error_text.should == ''
27
+ status.pid.should > 0
28
+ end
33
29
 
34
- def on_pid(pid)
35
- raise "PID already set!" unless @pid.nil?
36
- @pid = pid
30
+ it 'should correctly handle many small processes' do
31
+ pending 'Set environment variable TEST_STRESS to enable' unless ENV['TEST_STRESS']
32
+ TO_RUN = 100
33
+ command = is_windows? ? "cmd.exe /c exit 0" : "exit 0"
34
+ runner = Runner.new
35
+ @completed = 0
36
+ @started = 0
37
+ run_cmd = Proc.new do
38
+ runner.do_right_popen(command) do |status|
39
+ @completed += 1
40
+ status.status.exitstatus.should == 0
41
+ status.output_text.should == ''
42
+ status.error_text.should == ''
43
+ status.pid.should > 0
37
44
  end
38
-
39
- def on_exit(status)
40
- @timeout.cancel if @timeout
41
- @status = status
42
- @callback.call(self)
45
+ @started += 1
46
+ if @started < TO_RUN
47
+ EM.next_tick { run_cmd.call }
43
48
  end
44
49
  end
50
+ EM.run do
51
+ EM.next_tick { run_cmd.call }
45
52
 
46
- def initialize
47
- @count = 0
48
- @done = false
49
- @last_exception = nil
50
- @last_iteration = 0
51
- end
52
-
53
- def do_right_popen(command, env=nil, input=nil, &callback)
54
- status = RunnerStatus.new(command, callback)
55
- RightScale.popen3(:command => command,
56
- :input => input,
57
- :target => status,
58
- :environment => env,
59
- :stdout_handler => :on_read_stdout,
60
- :stderr_handler => :on_read_stderr,
61
- :pid_handler => :on_pid,
62
- :exit_handler => :on_exit)
63
- status
64
- end
65
-
66
- def run_right_popen(command, env=nil, input=nil, count=1)
67
- begin
68
- @iterations = 0
69
- EM.run do
70
- EM.next_tick do
71
- do_right_popen(command, env, input) do |status|
72
- maybe_continue(status)
73
- end
74
- end
53
+ EM::PeriodicTimer.new(1) do
54
+ if @completed >= TO_RUN
55
+ EM.stop
75
56
  end
76
- @status
77
- rescue Exception => e
78
- puts "\n** Failed: #{e.message} FROM\n#{e.backtrace.join("\n")}"
79
- raise e
80
- end
81
- end
82
-
83
- def maybe_continue(status)
84
- @iterations += 1
85
- if @iterations < @count
86
- do_right_popen(command, env, input) {|status| maybe_continue(status)}
87
- else
88
- @status = status
89
- EM.stop
90
57
  end
91
58
  end
92
59
  end
93
- end
94
60
 
95
- def is_windows?
96
- return !!(RUBY_PLATFORM =~ /mswin/)
97
- end
98
-
99
- it 'should redirect output' do
100
- command = "\"#{RUBY_CMD}\" \"#{File.expand_path(File.join(File.dirname(__FILE__), 'produce_output.rb'))}\" \"#{STANDARD_MESSAGE}\" \"#{ERROR_MESSAGE}\""
101
- runner = RightPopenSpec::Runner.new
102
- status = runner.run_right_popen(command)
103
- status.status.exitstatus.should == 0
104
- status.output_text.should == STANDARD_MESSAGE + "\n"
105
- status.error_text.should == ERROR_MESSAGE + "\n"
106
- status.pid.should > 0
107
- end
108
-
109
- it 'should return the right status' do
110
- command = "\"#{RUBY_CMD}\" \"#{File.expand_path(File.join(File.dirname(__FILE__), 'produce_status.rb'))}\" #{EXIT_STATUS}"
111
- runner = RightPopenSpec::Runner.new
112
- status = runner.run_right_popen(command)
113
- status.status.exitstatus.should == EXIT_STATUS
114
- status.output_text.should == ''
115
- status.error_text.should == ''
116
- status.pid.should > 0
117
- end
118
-
119
- it 'should correctly handle many small processes' do
120
- pending 'Set environment variable TEST_STRESS to enable' unless ENV['TEST_STRESS']
121
- TO_RUN = 100
122
- command = is_windows? ? "cmd.exe /c exit 0" : "exit 0"
123
- runner = RightPopenSpec::Runner.new
124
- @completed = 0
125
- @started = 0
126
- run_cmd = Proc.new do
127
- runner.do_right_popen(command) do |status|
128
- @completed += 1
129
- status.status.exitstatus.should == 0
130
- status.output_text.should == ''
131
- status.error_text.should == ''
132
- status.pid.should > 0
133
- end
134
- @started += 1
135
- if @started < TO_RUN
136
- EM.next_tick { run_cmd.call }
137
- end
138
- end
139
- EM.run do
140
- EM.next_tick { run_cmd.call }
61
+ it 'should preserve the integrity of stdout when stderr is unavailable' do
62
+ count = LARGE_OUTPUT_COUNTER
63
+ command = "\"#{RUBY_CMD}\" \"#{File.expand_path(File.join(File.dirname(__FILE__), 'produce_stdout_only.rb'))}\" #{count}"
64
+ runner = Runner.new
65
+ status = runner.run_right_popen(command)
66
+ status.status.exitstatus.should == 0
141
67
 
142
- EM::PeriodicTimer.new(1) do
143
- if @completed >= TO_RUN
144
- EM.stop
145
- end
68
+ results = ''
69
+ count.times do |i|
70
+ results << "stdout #{i}\n"
146
71
  end
72
+ status.output_text.should == results
73
+ status.error_text.should == ''
74
+ status.pid.should > 0
147
75
  end
148
- end
149
-
150
- it 'should preserve the integrity of stdout when stderr is unavailable' do
151
- count = LARGE_OUTPUT_COUNTER
152
- command = "\"#{RUBY_CMD}\" \"#{File.expand_path(File.join(File.dirname(__FILE__), 'produce_stdout_only.rb'))}\" #{count}"
153
- runner = RightPopenSpec::Runner.new
154
- status = runner.run_right_popen(command)
155
- status.status.exitstatus.should == 0
156
-
157
- results = ''
158
- count.times do |i|
159
- results << "stdout #{i}\n"
160
- end
161
- status.output_text.should == results
162
- status.error_text.should == ''
163
- status.pid.should > 0
164
- end
165
76
 
166
- it 'should preserve the integrity of stderr when stdout is unavailable' do
167
- count = LARGE_OUTPUT_COUNTER
168
- command = "\"#{RUBY_CMD}\" \"#{File.expand_path(File.join(File.dirname(__FILE__), 'produce_stderr_only.rb'))}\" #{count}"
169
- runner = RightPopenSpec::Runner.new
170
- status = runner.run_right_popen(command)
171
- status.status.exitstatus.should == 0
77
+ it 'should preserve the integrity of stderr when stdout is unavailable' do
78
+ count = LARGE_OUTPUT_COUNTER
79
+ command = "\"#{RUBY_CMD}\" \"#{File.expand_path(File.join(File.dirname(__FILE__), 'produce_stderr_only.rb'))}\" #{count}"
80
+ runner = Runner.new
81
+ status = runner.run_right_popen(command)
82
+ status.status.exitstatus.should == 0
172
83
 
173
- results = ''
174
- count.times do |i|
175
- results << "stderr #{i}\n"
84
+ results = ''
85
+ count.times do |i|
86
+ results << "stderr #{i}\n"
87
+ end
88
+ status.error_text.should == results
89
+ status.output_text.should == ''
90
+ status.pid.should > 0
176
91
  end
177
- status.error_text.should == results
178
- status.output_text.should == ''
179
- status.pid.should > 0
180
- end
181
92
 
182
- it 'should preserve the integrity of stdout and stderr despite interleaving' do
183
- count = LARGE_OUTPUT_COUNTER
184
- command = "\"#{RUBY_CMD}\" \"#{File.expand_path(File.join(File.dirname(__FILE__), 'produce_mixed_output.rb'))}\" #{count}"
185
- runner = RightPopenSpec::Runner.new
186
- status = runner.run_right_popen(command)
187
- status.status.exitstatus.should == 99
93
+ it 'should preserve the integrity of stdout and stderr despite interleaving' do
94
+ count = LARGE_OUTPUT_COUNTER
95
+ command = "\"#{RUBY_CMD}\" \"#{File.expand_path(File.join(File.dirname(__FILE__), 'produce_mixed_output.rb'))}\" #{count}"
96
+ runner = Runner.new
97
+ status = runner.run_right_popen(command)
98
+ status.status.exitstatus.should == 99
188
99
 
189
- results = ''
190
- count.times do |i|
191
- results << "stdout #{i}\n"
192
- end
193
- status.output_text.should == results
100
+ results = ''
101
+ count.times do |i|
102
+ results << "stdout #{i}\n"
103
+ end
104
+ status.output_text.should == results
194
105
 
195
- results = ''
196
- count.times do |i|
197
- (results << "stderr #{i}\n") if 0 == i % 10
106
+ results = ''
107
+ count.times do |i|
108
+ (results << "stderr #{i}\n") if 0 == i % 10
109
+ end
110
+ status.error_text.should == results
111
+ status.pid.should > 0
198
112
  end
199
- status.error_text.should == results
200
- status.pid.should > 0
201
- end
202
113
 
203
- it 'should setup environment variables' do
204
- command = "\"#{RUBY_CMD}\" \"#{File.expand_path(File.join(File.dirname(__FILE__), 'print_env.rb'))}\""
205
- runner = RightPopenSpec::Runner.new
206
- status = runner.run_right_popen(command)
207
- status.status.exitstatus.should == 0
208
- status.output_text.should_not include('_test_')
209
- status = runner.run_right_popen(command, :__test__ => '42')
210
- status.status.exitstatus.should == 0
211
- status.output_text.should match(/^__test__=42$/)
212
- status.pid.should > 0
213
- end
214
-
215
- it 'should restore environment variables' do
216
- begin
217
- ENV['__test__'] = '41'
218
- old_envs = {}
219
- ENV.each { |k, v| old_envs[k] = v }
114
+ it 'should setup environment variables' do
220
115
  command = "\"#{RUBY_CMD}\" \"#{File.expand_path(File.join(File.dirname(__FILE__), 'print_env.rb'))}\""
221
- runner = RightPopenSpec::Runner.new
116
+ runner = Runner.new
117
+ status = runner.run_right_popen(command)
118
+ status.status.exitstatus.should == 0
119
+ status.output_text.should_not include('_test_')
222
120
  status = runner.run_right_popen(command, :__test__ => '42')
223
121
  status.status.exitstatus.should == 0
224
122
  status.output_text.should match(/^__test__=42$/)
225
- ENV.each { |k, v| old_envs[k].should == v }
226
- old_envs.each { |k, v| ENV[k].should == v }
227
123
  status.pid.should > 0
228
- ensure
229
- ENV.delete('__test__')
230
124
  end
231
- end
232
125
 
233
- if is_windows?
234
- # FIX: this behavior is currently specific to Windows but should probably be
235
- # implemented for Linux.
236
- it 'should merge the PATH variable instead of overriding it' do
237
- command = "\"#{RUBY_CMD}\" \"#{File.expand_path(File.join(File.dirname(__FILE__), 'print_env.rb'))}\""
238
- runner = RightPopenSpec::Runner.new
239
- status = runner.run_right_popen(command, 'PATH' => "c:/bogus\\bin")
240
- status.status.exitstatus.should == 0
241
- status.output_text.should include('PATH=c:\\bogus\\bin;')
242
- status.pid.should > 0
126
+ it 'should restore environment variables' do
127
+ begin
128
+ ENV['__test__'] = '41'
129
+ old_envs = {}
130
+ ENV.each { |k, v| old_envs[k] = v }
131
+ command = "\"#{RUBY_CMD}\" \"#{File.expand_path(File.join(File.dirname(__FILE__), 'print_env.rb'))}\""
132
+ runner = Runner.new
133
+ status = runner.run_right_popen(command, :__test__ => '42')
134
+ status.status.exitstatus.should == 0
135
+ status.output_text.should match(/^__test__=42$/)
136
+ ENV.each { |k, v| old_envs[k].should == v }
137
+ old_envs.each { |k, v| ENV[k].should == v }
138
+ status.pid.should > 0
139
+ ensure
140
+ ENV.delete('__test__')
141
+ end
142
+ end
143
+
144
+ if is_windows?
145
+ # FIX: this behavior is currently specific to Windows but should probably be
146
+ # implemented for Linux.
147
+ it 'should merge the PATH variable instead of overriding it' do
148
+ command = "\"#{RUBY_CMD}\" \"#{File.expand_path(File.join(File.dirname(__FILE__), 'print_env.rb'))}\""
149
+ runner = Runner.new
150
+ status = runner.run_right_popen(command, 'PATH' => "c:/bogus\\bin")
151
+ status.status.exitstatus.should == 0
152
+ status.output_text.should include('c:\\bogus\\bin;')
153
+ status.pid.should > 0
154
+ end
155
+ else
156
+ it 'should allow running bash command lines starting with a built-in command' do
157
+ command = "for i in 1 2 3 4 5; do echo $i;done"
158
+ runner = Runner.new
159
+ status = runner.run_right_popen(command)
160
+ status.status.exitstatus.should == 0
161
+ status.output_text.should == "1\n2\n3\n4\n5\n"
162
+ status.pid.should > 0
163
+ end
164
+
165
+ it 'should support running background processes' do
166
+ command = "(sleep 20)&"
167
+ now = Time.now
168
+ runner = Runner.new
169
+ status = runner.run_right_popen(command)
170
+ finished = Time.now
171
+ (finished - now).should < 20
172
+ status.did_timeout.should be_false
173
+ status.status.exitstatus.should == 0
174
+ status.output_text.should == ""
175
+ status.pid.should > 0
176
+ end
243
177
  end
244
- else
245
- it 'should allow running bash command lines starting with a built-in command' do
246
- command = "for i in 1 2 3 4 5; do echo $i;done"
247
- runner = RightPopenSpec::Runner.new
178
+
179
+ it 'should support raw command arguments' do
180
+ command = is_windows? ? ["cmd.exe", "/c", "echo", "*"] : ["echo", "*"]
181
+ runner = Runner.new
248
182
  status = runner.run_right_popen(command)
249
183
  status.status.exitstatus.should == 0
250
- status.output_text.should == "1\n2\n3\n4\n5\n"
184
+ status.output_text.should == "*\n"
251
185
  status.pid.should > 0
252
186
  end
253
187
 
254
- it 'should support running background processes' do
255
- command = "(sleep 20)&"
256
- now = Time.now
257
- runner = RightPopenSpec::Runner.new
258
- status = runner.run_right_popen(command)
259
- finished = Time.now
260
- (finished - now).should < 20
261
- status.did_timeout.should be_false
188
+ it 'should run repeatedly without leaking resources' do
189
+ pending 'Set environment variable TEST_LEAK to enable' unless ENV['TEST_LEAK']
190
+ command = "\"#{RUBY_CMD}\" \"#{File.expand_path(File.join(File.dirname(__FILE__), 'produce_output.rb'))}\" \"#{STANDARD_MESSAGE}\" \"#{ERROR_MESSAGE}\""
191
+ runner = Runner.new
192
+ status = runner.run_right_popen(command, nil, nil, REPEAT_TEST_COUNTER)
262
193
  status.status.exitstatus.should == 0
263
- status.output_text.should == ""
194
+ status.output_text.should == STANDARD_MESSAGE + "\n"
195
+ status.error_text.should == ERROR_MESSAGE + "\n"
264
196
  status.pid.should > 0
265
197
  end
266
- end
267
198
 
268
- it 'should support raw command arguments' do
269
- command = is_windows? ? ["cmd.exe", "/c", "echo", "*"] : ["echo", "*"]
270
- runner = RightPopenSpec::Runner.new
271
- status = runner.run_right_popen(command)
272
- status.status.exitstatus.should == 0
273
- status.output_text.should == "*\n"
274
- status.pid.should > 0
275
- end
199
+ it 'should pass input to child process' do
200
+ command = "\"#{RUBY_CMD}\" \"#{File.expand_path(File.join(File.dirname(__FILE__), 'increment.rb'))}\""
201
+ runner = Runner.new
202
+ status = runner.run_right_popen(command, nil, "42\n")
203
+ status.status.exitstatus.should == 0
204
+ status.output_text.should == "43\n"
205
+ status.error_text.should be_empty
206
+ status.pid.should > 0
207
+ end
276
208
 
277
- it 'should run repeatedly without leaking resources' do
278
- pending 'Set environment variable TEST_LEAK to enable' unless ENV['TEST_LEAK']
279
- command = "\"#{RUBY_CMD}\" \"#{File.expand_path(File.join(File.dirname(__FILE__), 'produce_output.rb'))}\" \"#{STANDARD_MESSAGE}\" \"#{ERROR_MESSAGE}\""
280
- runner = RightPopenSpec::Runner.new
281
- status = runner.run_right_popen(command, nil, nil, REPEAT_TEST_COUNTER)
282
- status.status.exitstatus.should == 0
283
- status.output_text.should == STANDARD_MESSAGE + "\n"
284
- status.error_text.should == ERROR_MESSAGE + "\n"
285
- status.pid.should > 0
286
- end
209
+ it 'should handle child processes that close stdout but keep running' do
210
+ pending 'not implemented for windows' if is_windows?
211
+ command = "\"#{RUBY_CMD}\" \"#{File.expand_path(File.join(File.dirname(__FILE__), 'stdout.rb'))}\""
212
+ runner = Runner.new
213
+ status = runner.run_right_popen(command, nil, nil)
214
+ status.did_timeout.should be_true
215
+ status.output_text.should be_empty
216
+ status.error_text.should == "Closing stdout\n"
217
+ end
287
218
 
288
- it 'should pass input to child process' do
289
- command = "\"#{RUBY_CMD}\" \"#{File.expand_path(File.join(File.dirname(__FILE__), 'increment.rb'))}\""
290
- runner = RightPopenSpec::Runner.new
291
- status = runner.run_right_popen(command, nil, "42\n")
292
- status.status.exitstatus.should == 0
293
- status.output_text.should == "43\n"
294
- status.error_text.should be_empty
295
- status.pid.should > 0
219
+ it 'should handle child processes that spawn long running background processes' do
220
+ pending 'not implemented for windows' if is_windows?
221
+ command = "\"#{RUBY_CMD}\" \"#{File.expand_path(File.join(File.dirname(__FILE__), 'background.rb'))}\""
222
+ runner = Runner.new
223
+ status = runner.run_right_popen(command, nil, nil)
224
+ status.status.exitstatus.should == 0
225
+ status.did_timeout.should be_false
226
+ status.output_text.should be_empty
227
+ status.error_text.should be_empty
228
+ end
296
229
  end
297
-
298
230
  end