right_popen 1.0.21-x86-mswin32-60 → 1.1.3-x86-mswin32-60

Sign up to get free protection for your applications and to get access to all the features.
Binary file
@@ -47,8 +47,8 @@ EOF
47
47
  end
48
48
  spec.files = candidates.sort!
49
49
 
50
- # Current implementation supports >= 0.12.11
51
- spec.add_runtime_dependency(%q<eventmachine>, [">= 0.12.11"])
50
+ # Current implementation supports >= 1.0.0
51
+ spec.add_development_dependency(%q<eventmachine>, [">= 1.0.0"])
52
52
  if is_windows
53
53
  spec.add_runtime_dependency(%q<win32-process>, [">= 0.6.1"])
54
54
  end
@@ -1,6 +1,9 @@
1
1
  count = ARGV[0] ? ARGV[0].to_i : 1
2
2
  exit_code = ARGV[1] ? ARGV[1].to_i : 0
3
3
 
4
+ STDOUT.sync=true
5
+ STDERR.sync=true
6
+
4
7
  count.times do |i|
5
8
  $stderr.puts "stderr #{i}" if 0 == i % 10
6
9
  $stdout.puts "stdout #{i}"
@@ -0,0 +1,26 @@
1
+ require ::File.expand_path(::File.join(::File.dirname(__FILE__), '..', 'spec_helper'))
2
+ require ::File.expand_path(::File.join(::File.dirname(__FILE__), '..', '..', 'lib', 'right_popen', 'safe_output_buffer'))
3
+
4
+ describe RightScale::RightPopen::SafeOutputBuffer do
5
+
6
+ context 'given a default buffer' do
7
+ subject { described_class.new }
8
+
9
+ it 'should limit line count and length' do
10
+ (described_class::DEFAULT_MAX_LINE_COUNT * 2).times do |line_index|
11
+ data = 'x' * rand(described_class::DEFAULT_MAX_LINE_LENGTH * 3)
12
+ subject.safe_buffer_data(data).should be_true
13
+ end
14
+ subject.buffer.size.should == described_class::DEFAULT_MAX_LINE_COUNT
15
+ subject.buffer.first.should == described_class::ELLIPSIS
16
+ subject.buffer.last.should_not == described_class::ELLIPSIS
17
+ subject.buffer.each do |line|
18
+ (line.length <= described_class::DEFAULT_MAX_LINE_LENGTH).should be_true
19
+ end
20
+ text = subject.display_text
21
+ text.should_not be_empty
22
+ text.lines.count.should == subject.buffer.size
23
+ end
24
+ end
25
+
26
+ end
@@ -1,286 +1,331 @@
1
1
  require File.expand_path(File.join(File.dirname(__FILE__), 'spec_helper'))
2
2
  require File.expand_path(File.join(File.dirname(__FILE__), 'runner'))
3
+
3
4
  require 'stringio'
5
+ require 'tmpdir'
4
6
 
5
- module RightScale
6
- describe 'popen3' do
7
- def is_windows?
8
- return !!(RUBY_PLATFORM =~ /mswin/)
9
- end
7
+ describe 'RightScale::RightPopen' do
8
+ def is_windows?
9
+ return !!(RUBY_PLATFORM =~ /mswin|mingw/)
10
+ end
10
11
 
11
- it 'should redirect output' do
12
- command = "\"#{RUBY_CMD}\" \"#{File.expand_path(File.join(File.dirname(__FILE__), 'produce_output.rb'))}\" \"#{STANDARD_MESSAGE}\" \"#{ERROR_MESSAGE}\""
13
- runner = Runner.new
14
- status = runner.run_right_popen(command)
15
- status.status.exitstatus.should == 0
16
- status.output_text.should == STANDARD_MESSAGE + "\n"
17
- status.error_text.should == ERROR_MESSAGE + "\n"
18
- status.pid.should > 0
19
- end
12
+ let(:runner) { ::RightScale::RightPopen::Runner.new }
20
13
 
21
- it 'should return the right status' do
22
- command = "\"#{RUBY_CMD}\" \"#{File.expand_path(File.join(File.dirname(__FILE__), 'produce_status.rb'))}\" #{EXIT_STATUS}"
23
- runner = Runner.new
24
- status = runner.run_right_popen(command)
25
- status.status.exitstatus.should == EXIT_STATUS
26
- status.output_text.should == ''
27
- status.error_text.should == ''
28
- status.pid.should > 0
14
+ it "should correctly handle many small processes [async]" do
15
+ pending 'Set environment variable TEST_STRESS to enable' unless ENV['TEST_STRESS']
16
+ run_count = 100
17
+ command = is_windows? ? ['cmd.exe', '/c', 'exit 0'] : ['sh', '-c', 'exit 0']
18
+ @completed = 0
19
+ @started = 0
20
+ run_cmd = Proc.new do
21
+ runner.do_right_popen3_async(command, runner_options={}, popen3_options={}) do |runner_status|
22
+ @completed += 1
23
+ runner_status.status.exitstatus.should == 0
24
+ runner_status.output_text.should == ''
25
+ runner_status.error_text.should == ''
26
+ runner_status.pid.should > 0
27
+ end
28
+ @started += 1
29
+ if @started < run_count
30
+ EM.next_tick { run_cmd.call }
31
+ end
29
32
  end
33
+ EM.run do
34
+ EM.next_tick { run_cmd.call }
30
35
 
31
- it 'should correctly handle many small processes' do
32
- pending 'Set environment variable TEST_STRESS to enable' unless ENV['TEST_STRESS']
33
- TO_RUN = 100
34
- command = is_windows? ? "cmd.exe /c exit 0" : "exit 0"
35
- runner = Runner.new
36
- @completed = 0
37
- @started = 0
38
- run_cmd = Proc.new do
39
- runner.do_right_popen(command) do |status|
40
- @completed += 1
41
- status.status.exitstatus.should == 0
42
- status.output_text.should == ''
43
- status.error_text.should == ''
44
- status.pid.should > 0
45
- end
46
- @started += 1
47
- if @started < TO_RUN
48
- EM.next_tick { run_cmd.call }
36
+ EM::PeriodicTimer.new(1) do
37
+ if @completed >= run_count
38
+ EM.stop
49
39
  end
50
40
  end
51
- EM.run do
52
- EM.next_tick { run_cmd.call }
41
+ end
42
+ end
43
+
44
+ [:sync, :async].each do |synchronicity|
45
+
46
+ context synchronicity do
47
+
48
+ it "should redirect output" do
49
+ command = "\"#{RUBY_CMD}\" \"#{File.expand_path(File.join(File.dirname(__FILE__), 'produce_output.rb'))}\" \"#{STANDARD_MESSAGE}\" \"#{ERROR_MESSAGE}\""
50
+ runner_status = runner.run_right_popen3(synchronicity, command)
51
+ runner_status.should_not be_nil
52
+ runner_status.status.should_not be_nil
53
+ runner_status.status.exitstatus.should == 0
54
+ runner_status.output_text.should == STANDARD_MESSAGE + "\n"
55
+ runner_status.error_text.should == ERROR_MESSAGE + "\n"
56
+ runner_status.pid.should > 0
57
+ end
58
+
59
+ it "should return the right status" do
60
+ ruby = `which ruby`.chomp # which is assumed to be on the PATH for the Windows case
61
+ command = [
62
+ ruby,
63
+ File.expand_path(File.join(File.dirname(__FILE__), 'produce_status.rb')),
64
+ EXIT_STATUS
65
+ ]
66
+ status = runner.run_right_popen3(synchronicity, command)
67
+ status.status.exitstatus.should == EXIT_STATUS
68
+ status.output_text.should == ''
69
+ status.error_text.should == ''
70
+ status.pid.should > 0
71
+ end
53
72
 
54
- EM::PeriodicTimer.new(1) do
55
- if @completed >= TO_RUN
56
- EM.stop
73
+ it "should close all IO handlers, except STDIN, STDOUT and STDERR" do
74
+ GC.start
75
+ command = [
76
+ RUBY_CMD,
77
+ File.expand_path(File.join(File.dirname(__FILE__), 'produce_status.rb')),
78
+ EXIT_STATUS
79
+ ]
80
+ status = runner.run_right_popen3(synchronicity, command)
81
+ status.status.exitstatus.should == EXIT_STATUS
82
+ useless_handlers = 0
83
+ ObjectSpace.each_object(IO) do |io|
84
+ if ![STDIN, STDOUT, STDERR].include?(io)
85
+ useless_handlers += 1 unless io.closed?
57
86
  end
58
87
  end
88
+ useless_handlers.should == 0
59
89
  end
60
- end
61
90
 
62
- it 'should close all IO handlers, except STDIN, STDOUT and STDERR' do
63
- GC.start
64
- command = "\"#{RUBY_CMD}\" \"#{File.expand_path(File.join(File.dirname(__FILE__), 'produce_status.rb'))}\" #{EXIT_STATUS}"
65
- runner = Runner.new
66
- status = runner.run_right_popen(command)
67
- status.status.exitstatus.should == EXIT_STATUS
68
- useless_handlers = 0
69
- ObjectSpace.each_object(IO) do |io|
70
- if ![STDIN, STDOUT, STDERR].include?(io)
71
- useless_handlers += 1 unless io.closed?
91
+ it "should preserve the integrity of stdout when stderr is unavailable" do
92
+ count = LARGE_OUTPUT_COUNTER
93
+ command = "\"#{RUBY_CMD}\" \"#{File.expand_path(File.join(File.dirname(__FILE__), 'produce_stdout_only.rb'))}\" #{count}"
94
+ status = runner.run_right_popen3(synchronicity, command)
95
+ status.status.exitstatus.should == 0
96
+
97
+ results = ''
98
+ count.times do |i|
99
+ results << "stdout #{i}\n"
72
100
  end
101
+ status.output_text.should == results
102
+ status.error_text.should == ''
103
+ status.pid.should > 0
73
104
  end
74
- useless_handlers.should == 0
75
- end
76
105
 
77
- it 'should preserve the integrity of stdout when stderr is unavailable' do
78
- count = LARGE_OUTPUT_COUNTER
79
- command = "\"#{RUBY_CMD}\" \"#{File.expand_path(File.join(File.dirname(__FILE__), 'produce_stdout_only.rb'))}\" #{count}"
80
- runner = Runner.new
81
- status = runner.run_right_popen(command)
82
- status.status.exitstatus.should == 0
106
+ it "should preserve the integrity of stderr when stdout is unavailable" do
107
+ count = LARGE_OUTPUT_COUNTER
108
+ command = "\"#{RUBY_CMD}\" \"#{File.expand_path(File.join(File.dirname(__FILE__), 'produce_stderr_only.rb'))}\" #{count}"
109
+ status = runner.run_right_popen3(synchronicity, command)
110
+ status.status.exitstatus.should == 0
83
111
 
84
- results = ''
85
- count.times do |i|
86
- results << "stdout #{i}\n"
112
+ results = ''
113
+ count.times do |i|
114
+ results << "stderr #{i}\n"
115
+ end
116
+ status.error_text.should == results
117
+ status.output_text.should == ''
118
+ status.pid.should > 0
87
119
  end
88
- status.output_text.should == results
89
- status.error_text.should == ''
90
- status.pid.should > 0
91
- end
92
120
 
93
- it 'should preserve the integrity of stderr when stdout is unavailable' do
94
- count = LARGE_OUTPUT_COUNTER
95
- command = "\"#{RUBY_CMD}\" \"#{File.expand_path(File.join(File.dirname(__FILE__), 'produce_stderr_only.rb'))}\" #{count}"
96
- runner = Runner.new
97
- status = runner.run_right_popen(command)
98
- status.status.exitstatus.should == 0
121
+ it "should preserve interleaved output when yielding CPU on consumer thread" do
122
+ lines = 11
123
+ exit_code = 42
124
+ repeats = 5
125
+ force_yield = 0.1
126
+ command = "\"#{RUBY_CMD}\" \"#{File.expand_path(File.join(File.dirname(__FILE__), 'produce_mixed_output.rb'))}\" #{lines} #{exit_code}"
127
+ actual_output = StringIO.new
128
+ actual_error = StringIO.new
129
+ puts
130
+ stats = runner.run_right_popen3(synchronicity, command, :repeats=>repeats, :force_yield=>force_yield) do |status|
131
+ status.status.exitstatus.should == exit_code
132
+ status.pid.should > 0
133
+ actual_output << status.output_text
134
+ actual_error << status.error_text
135
+ end
136
+ puts
137
+ stats.size.should == repeats
138
+
139
+ expected_output = StringIO.new
140
+ repeats.times do
141
+ lines.times do |i|
142
+ expected_output << "stdout #{i}\n"
143
+ end
144
+ end
145
+ actual_output.string.should == expected_output.string
99
146
 
100
- results = ''
101
- count.times do |i|
102
- results << "stderr #{i}\n"
147
+ expected_error = StringIO.new
148
+ repeats.times do
149
+ lines.times do |i|
150
+ (expected_error << "stderr #{i}\n") if 0 == i % 10
151
+ end
152
+ end
153
+ actual_error.string.should == expected_error.string
103
154
  end
104
- status.error_text.should == results
105
- status.output_text.should == ''
106
- status.pid.should > 0
107
- end
108
155
 
109
- it 'should preserve interleaved output when yielding CPU on consumer thread' do
110
- lines = 11
111
- exit_code = 42
112
- repeats = 5
113
- force_yield = 0.1
114
- command = "\"#{RUBY_CMD}\" \"#{File.expand_path(File.join(File.dirname(__FILE__), 'produce_mixed_output.rb'))}\" #{lines} #{exit_code}"
115
- runner = Runner.new
116
- actual_output = StringIO.new
117
- actual_error = StringIO.new
118
- puts
119
- stats = runner.run_right_popen(command, :repeats=>repeats, :force_yield=>force_yield) do |status|
156
+ it "should preserve interleaved output when process is spewing rapidly" do
157
+ lines = LARGE_OUTPUT_COUNTER
158
+ exit_code = 99
159
+ command = "\"#{RUBY_CMD}\" \"#{File.expand_path(File.join(File.dirname(__FILE__), 'produce_mixed_output.rb'))}\" #{lines} #{exit_code}"
160
+ status = runner.run_right_popen3(synchronicity, command, :timeout=>10)
120
161
  status.status.exitstatus.should == exit_code
121
- status.pid.should > 0
122
- actual_output << status.output_text
123
- actual_error << status.error_text
124
- print '+'
125
- end
126
- puts
127
- stats.size.should == repeats
128
162
 
129
- expected_output = StringIO.new
130
- repeats.times do
163
+ expected_output = StringIO.new
131
164
  lines.times do |i|
132
165
  expected_output << "stdout #{i}\n"
133
166
  end
134
- end
135
- actual_output.string.should == expected_output.string
167
+ status.output_text.should == expected_output.string
136
168
 
137
- expected_error = StringIO.new
138
- repeats.times do
169
+ expected_error = StringIO.new
139
170
  lines.times do |i|
140
171
  (expected_error << "stderr #{i}\n") if 0 == i % 10
141
172
  end
173
+ status.error_text.should == expected_error.string
174
+ status.pid.should > 0
142
175
  end
143
- actual_error.string.should == expected_error.string
144
- end
145
176
 
146
- it 'should preserve interleaved output when process is spewing rapidly' do
147
- lines = LARGE_OUTPUT_COUNTER
148
- exit_code = 99
149
- command = "\"#{RUBY_CMD}\" \"#{File.expand_path(File.join(File.dirname(__FILE__), 'produce_mixed_output.rb'))}\" #{lines} #{exit_code}"
150
- runner = Runner.new
151
- status = runner.run_right_popen(command)
152
- status.status.exitstatus.should == exit_code
153
-
154
- expected_output = StringIO.new
155
- lines.times do |i|
156
- expected_output << "stdout #{i}\n"
177
+ it "should setup environment variables" do
178
+ command = "\"#{RUBY_CMD}\" \"#{File.expand_path(File.join(File.dirname(__FILE__), 'print_env.rb'))}\""
179
+ status = runner.run_right_popen3(synchronicity, command)
180
+ status.status.exitstatus.should == 0
181
+ status.output_text.should_not include('_test_')
182
+ status = runner.run_right_popen3(synchronicity, command, :env=>{ :__test__ => '42' })
183
+ status.status.exitstatus.should == 0
184
+ status.output_text.should match(/^__test__=42$/)
185
+ status.pid.should > 0
157
186
  end
158
- status.output_text.should == expected_output.string
159
187
 
160
- expected_error = StringIO.new
161
- lines.times do |i|
162
- (expected_error << "stderr #{i}\n") if 0 == i % 10
188
+ it "should restore environment variables" do
189
+ begin
190
+ ENV['__test__'] = '41'
191
+ old_envs = {}
192
+ ENV.each { |k, v| old_envs[k] = v }
193
+ command = "\"#{RUBY_CMD}\" \"#{File.expand_path(File.join(File.dirname(__FILE__), 'print_env.rb'))}\""
194
+ status = runner.run_right_popen3(synchronicity, command, :env=>{ :__test__ => '42' })
195
+ status.status.exitstatus.should == 0
196
+ status.output_text.should match(/^__test__=42$/)
197
+ ENV.each { |k, v| old_envs[k].should == v }
198
+ old_envs.each { |k, v| ENV[k].should == v }
199
+ status.pid.should > 0
200
+ ensure
201
+ ENV.delete('__test__')
202
+ end
163
203
  end
164
- status.error_text.should == expected_error.string
165
- status.pid.should > 0
166
- end
167
204
 
168
- it 'should setup environment variables' do
169
- command = "\"#{RUBY_CMD}\" \"#{File.expand_path(File.join(File.dirname(__FILE__), 'print_env.rb'))}\""
170
- runner = Runner.new
171
- status = runner.run_right_popen(command)
172
- status.status.exitstatus.should == 0
173
- status.output_text.should_not include('_test_')
174
- status = runner.run_right_popen(command, :env=>{ :__test__ => '42' })
175
- status.status.exitstatus.should == 0
176
- status.output_text.should match(/^__test__=42$/)
177
- status.pid.should > 0
178
- end
205
+ if is_windows?
206
+ # FIX: this behavior is currently specific to Windows but should probably be
207
+ # implemented for Linux.
208
+ it "should merge the PATH variable instead of overriding it" do
209
+ command = "\"#{RUBY_CMD}\" \"#{File.expand_path(File.join(File.dirname(__FILE__), 'print_env.rb'))}\""
210
+ status = runner.run_right_popen3(synchronicity, command, :env=>{ 'PATH' => "c:/bogus\\bin" })
211
+ status.status.exitstatus.should == 0
212
+ status.output_text.should include('c:\\bogus\\bin;')
213
+ status.pid.should > 0
214
+ end
215
+ else
216
+ it "should allow running bash command lines starting with a built-in command" do
217
+ command = "for i in 1 2 3 4 5; do echo $i;done"
218
+ status = runner.run_right_popen3(synchronicity, command)
219
+ status.status.exitstatus.should == 0
220
+ status.output_text.should == "1\n2\n3\n4\n5\n"
221
+ status.pid.should > 0
222
+ end
179
223
 
180
- it 'should restore environment variables' do
181
- begin
182
- ENV['__test__'] = '41'
183
- old_envs = {}
184
- ENV.each { |k, v| old_envs[k] = v }
185
- command = "\"#{RUBY_CMD}\" \"#{File.expand_path(File.join(File.dirname(__FILE__), 'print_env.rb'))}\""
186
- runner = Runner.new
187
- status = runner.run_right_popen(command, :env=>{ :__test__ => '42' })
188
- status.status.exitstatus.should == 0
189
- status.output_text.should match(/^__test__=42$/)
190
- ENV.each { |k, v| old_envs[k].should == v }
191
- old_envs.each { |k, v| ENV[k].should == v }
192
- status.pid.should > 0
193
- ensure
194
- ENV.delete('__test__')
224
+ it "should support running background processes" do
225
+ command = "(sleep 20)&"
226
+ now = Time.now
227
+ status = runner.run_right_popen3(synchronicity, command)
228
+ finished = Time.now
229
+ (finished - now).should < 20
230
+ status.did_timeout.should be_false
231
+ status.status.exitstatus.should == 0
232
+ status.output_text.should == ""
233
+ status.pid.should > 0
234
+ end
195
235
  end
196
- end
197
236
 
198
- if is_windows?
199
- # FIX: this behavior is currently specific to Windows but should probably be
200
- # implemented for Linux.
201
- it 'should merge the PATH variable instead of overriding it' do
202
- command = "\"#{RUBY_CMD}\" \"#{File.expand_path(File.join(File.dirname(__FILE__), 'print_env.rb'))}\""
203
- runner = Runner.new
204
- status = runner.run_right_popen(command, :env=>{ 'PATH' => "c:/bogus\\bin" })
237
+ it "should support raw command arguments" do
238
+ command = is_windows? ? ["cmd.exe", "/c", "echo", "*"] : ["echo", "*"]
239
+ status = runner.run_right_popen3(synchronicity, command)
205
240
  status.status.exitstatus.should == 0
206
- status.output_text.should include('c:\\bogus\\bin;')
241
+ status.output_text.should == "*\n"
207
242
  status.pid.should > 0
208
243
  end
209
- else
210
- it 'should allow running bash command lines starting with a built-in command' do
211
- command = "for i in 1 2 3 4 5; do echo $i;done"
212
- runner = Runner.new
213
- status = runner.run_right_popen(command)
214
- status.status.exitstatus.should == 0
215
- status.output_text.should == "1\n2\n3\n4\n5\n"
216
- status.pid.should > 0
244
+
245
+ it "should run repeatedly without leaking resources" do
246
+ pending 'Set environment variable TEST_LEAK to enable' unless ENV['TEST_LEAK']
247
+ command = "\"#{RUBY_CMD}\" \"#{File.expand_path(File.join(File.dirname(__FILE__), 'produce_output.rb'))}\" \"#{STANDARD_MESSAGE}\" \"#{ERROR_MESSAGE}\""
248
+ stats = runner.run_right_popen3(synchronicity, command, :repeats=>REPEAT_TEST_COUNTER)
249
+ stats.each do |status|
250
+ status.status.exitstatus.should == 0
251
+ status.output_text.should == STANDARD_MESSAGE + "\n"
252
+ status.error_text.should == ERROR_MESSAGE + "\n"
253
+ status.pid.should > 0
254
+ end
217
255
  end
218
256
 
219
- it 'should support running background processes' do
220
- command = "(sleep 20)&"
221
- now = Time.now
222
- runner = Runner.new
223
- status = runner.run_right_popen(command)
224
- finished = Time.now
225
- (finished - now).should < 20
226
- status.did_timeout.should be_false
257
+ it "should pass input to child process" do
258
+ command = "\"#{RUBY_CMD}\" \"#{File.expand_path(File.join(File.dirname(__FILE__), 'increment.rb'))}\""
259
+ status = runner.run_right_popen3(synchronicity, command, :input=>"42\n")
227
260
  status.status.exitstatus.should == 0
228
- status.output_text.should == ""
261
+ status.output_text.should == "43\n"
262
+ status.error_text.should be_empty
229
263
  status.pid.should > 0
230
264
  end
231
- end
232
265
 
233
- it 'should support raw command arguments' do
234
- command = is_windows? ? ["cmd.exe", "/c", "echo", "*"] : ["echo", "*"]
235
- runner = Runner.new
236
- status = runner.run_right_popen(command)
237
- status.status.exitstatus.should == 0
238
- status.output_text.should == "*\n"
239
- status.pid.should > 0
240
- end
266
+ it "should run long child process without any watches by default" do
267
+ command = "\"#{RUBY_CMD}\" \"#{File.expand_path(File.join(File.dirname(__FILE__), 'sleeper.rb'))}\""
268
+ runner_status = runner.run_right_popen3(synchronicity, command, :timeout=>nil)
269
+ runner_status.status.exitstatus.should == 0
270
+ runner_status.did_timeout.should be_false
271
+ runner_status.output_text.should == "To sleep... 0\nTo sleep... 1\nTo sleep... 2\nTo sleep... 3\nThe sleeper must awaken.\n"
272
+ runner_status.error_text.should == "Perchance to dream... 0\nPerchance to dream... 1\nPerchance to dream... 2\nPerchance to dream... 3\n"
273
+ end
241
274
 
242
- it 'should run repeatedly without leaking resources' do
243
- pending 'Set environment variable TEST_LEAK to enable' unless ENV['TEST_LEAK']
244
- command = "\"#{RUBY_CMD}\" \"#{File.expand_path(File.join(File.dirname(__FILE__), 'produce_output.rb'))}\" \"#{STANDARD_MESSAGE}\" \"#{ERROR_MESSAGE}\""
245
- runner = Runner.new
246
- stats = runner.run_right_popen(command, :repeats=>REPEAT_TEST_COUNTER)
247
- stats.each do |status|
248
- status.status.exitstatus.should == 0
249
- status.output_text.should == STANDARD_MESSAGE + "\n"
250
- status.error_text.should == ERROR_MESSAGE + "\n"
251
- status.pid.should > 0
275
+ it "should interrupt watched child process when timeout expires" do
276
+ command = "\"#{RUBY_CMD}\" \"#{File.expand_path(File.join(File.dirname(__FILE__), 'sleeper.rb'))}\" 10"
277
+ runner_status = runner.run_right_popen3(synchronicity, command, :expect_timeout=>true, :timeout=>0.1)
278
+ runner_status.status.success?.should be_false
279
+ runner_status.did_timeout.should be_true
280
+ runner_status.output_text.should_not be_empty
281
+ runner_status.error_text.should_not be_empty
252
282
  end
253
- end
254
283
 
255
- it 'should pass input to child process' do
256
- command = "\"#{RUBY_CMD}\" \"#{File.expand_path(File.join(File.dirname(__FILE__), 'increment.rb'))}\""
257
- runner = Runner.new
258
- status = runner.run_right_popen(command, :input=>"42\n")
259
- status.status.exitstatus.should == 0
260
- status.output_text.should == "43\n"
261
- status.error_text.should be_empty
262
- status.pid.should > 0
263
- end
284
+ it "should allow watched child to write files up to size limit" do
285
+ ::Dir.mktmpdir do |watched_dir|
286
+ command = "\"#{RUBY_CMD}\" \"#{File.expand_path(File.join(File.dirname(__FILE__), 'writer.rb'))}\" \"#{watched_dir}\""
287
+ runner_status = runner.run_right_popen3(synchronicity, command, :size_limit_bytes=>1000, :watch_directory=>watched_dir, :timeout=>10)
288
+ runner_status.status.success?.should be_true
289
+ runner_status.did_size_limit.should be_false
290
+ end
291
+ end
264
292
 
265
- it 'should handle child processes that close stdout but keep running' do
266
- pending 'not implemented for windows' if is_windows?
267
- command = "\"#{RUBY_CMD}\" \"#{File.expand_path(File.join(File.dirname(__FILE__), 'stdout.rb'))}\""
268
- runner = Runner.new
269
- status = runner.run_right_popen(command, :expect_timeout=>true, :timeout=>2)
270
- status.did_timeout.should be_true
271
- status.output_text.should be_empty
272
- status.error_text.should == "Closing stdout\n"
273
- end
293
+ it "should interrupt watched child at size limit" do
294
+ ::Dir.mktmpdir do |watched_dir|
295
+ command = "\"#{RUBY_CMD}\" \"#{File.expand_path(File.join(File.dirname(__FILE__), 'writer.rb'))}\" \"#{watched_dir}\""
296
+ runner_status = runner.run_right_popen3(synchronicity, command, :expect_size_limit=>true, :size_limit_bytes=>100, :watch_directory=>watched_dir, :timeout=>10)
297
+ runner_status.status.success?.should be_false
298
+ runner_status.did_size_limit.should be_true
299
+ end
300
+ end
301
+
302
+ it "should handle child processes that close stdout but keep running" do
303
+ pending 'not implemented for windows' if is_windows? && :sync != synchronicity
304
+ command = "\"#{RUBY_CMD}\" \"#{File.expand_path(File.join(File.dirname(__FILE__), 'stdout.rb'))}\""
305
+ runner_status = runner.run_right_popen3(synchronicity, command, :expect_timeout=>true, :timeout=>2)
306
+ runner_status.output_text.should be_empty
307
+ runner_status.error_text.should == "Closing stdout\n"
308
+ runner_status.did_timeout.should be_true
309
+ end
274
310
 
275
- it 'should handle child processes that spawn long running background processes' do
276
- pending 'not implemented for windows' if is_windows?
277
- command = "\"#{RUBY_CMD}\" \"#{File.expand_path(File.join(File.dirname(__FILE__), 'background.rb'))}\""
278
- runner = Runner.new
279
- status = runner.run_right_popen(command)
280
- status.status.exitstatus.should == 0
281
- status.did_timeout.should be_false
282
- status.output_text.should be_empty
283
- status.error_text.should be_empty
311
+ it "should handle child processes that spawn long running background processes" do
312
+ pending 'not implemented for windows' if is_windows?
313
+ command = "\"#{RUBY_CMD}\" \"#{File.expand_path(File.join(File.dirname(__FILE__), 'background.rb'))}\""
314
+ status = runner.run_right_popen3(synchronicity, command)
315
+ status.status.exitstatus.should == 0
316
+ status.did_timeout.should be_false
317
+ status.output_text.should be_empty
318
+ status.error_text.should be_empty
319
+ end
320
+
321
+ it "should run long child process without any watches by default" do
322
+ command = "\"#{RUBY_CMD}\" \"#{File.expand_path(File.join(File.dirname(__FILE__), 'sleeper.rb'))}\""
323
+ runner_status = runner.run_right_popen3(synchronicity, command, :timeout=>nil)
324
+ runner_status.status.exitstatus.should == 0
325
+ runner_status.did_timeout.should be_false
326
+ runner_status.output_text.should == "To sleep... 0\nTo sleep... 1\nTo sleep... 2\nTo sleep... 3\nThe sleeper must awaken.\n"
327
+ runner_status.error_text.should == "Perchance to dream... 0\nPerchance to dream... 1\nPerchance to dream... 2\nPerchance to dream... 3\n"
328
+ end
284
329
  end
285
330
  end
286
331
  end