aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/external_command.rb12
-rwxr-xr-xspec/lib/external_command_scripts/output.sh22
-rw-r--r--spec/lib/external_command_spec.rb40
3 files changed, 70 insertions, 4 deletions
diff --git a/lib/external_command.rb b/lib/external_command.rb
index de8bfc11e..96292854f 100644
--- a/lib/external_command.rb
+++ b/lib/external_command.rb
@@ -104,20 +104,24 @@ class ExternalCommand
@fhs = {@out_read => @out, @err_read => @err, @fin_read => @fin}
while @fin.empty?
- r = read_data
- if r.nil?
+ ok = read_data
+ if !ok
raise "select() timed out even with a nil (infinite) timeout"
end
end
+ while read_data(0)
+ # Pull out any data that’s left in the pipes
+ end
+
Process::waitpid(@pid)
@status = @fin.to_i
@out_read.close
@err_read.close
end
- def read_data()
- ready_array = IO.select(@fhs.keys, [], [], nil)
+ def read_data(timeout=nil)
+ ready_array = IO.select(@fhs.keys, [], [], timeout)
return false if ready_array.nil?
ready_array[0].each do |fh|
begin
diff --git a/spec/lib/external_command_scripts/output.sh b/spec/lib/external_command_scripts/output.sh
new file mode 100755
index 000000000..0472c89a3
--- /dev/null
+++ b/spec/lib/external_command_scripts/output.sh
@@ -0,0 +1,22 @@
+#!/bin/bash
+
+out_msg=${1:-out}
+err_msg=${2:-}
+repeats=${3:-10}
+exit_status=${4:-0}
+
+n=0
+while [ "$n" -lt "$repeats" ]
+do
+ if [ -n "$out_msg" ]
+ then
+ echo "$out_msg $n"
+ fi
+ if [ -n "$err_msg" ]
+ then
+ echo >&2 "$err_msg $n"
+ fi
+ n=$[$n + 1]
+done
+
+exit "$exit_status"
diff --git a/spec/lib/external_command_spec.rb b/spec/lib/external_command_spec.rb
new file mode 100644
index 000000000..0ff1a9c0a
--- /dev/null
+++ b/spec/lib/external_command_spec.rb
@@ -0,0 +1,40 @@
+# This is a test of the external_command library
+
+require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
+script_dir = File.join(File.dirname(__FILE__), 'external_command_scripts')
+output_script = File.join(script_dir, "output.sh")
+
+require 'external_command'
+
+describe "when running ExternalCommand" do
+
+ it "should get correct status code for /bin/true" do
+ t = ExternalCommand.new("/bin/true").run()
+ t.status.should == 0
+ t.out.should == ""
+ t.err.should == ""
+ end
+
+ it "should get correct status code for /bin/false" do
+ f = ExternalCommand.new("/bin/false").run()
+ f.status.should == 1
+ f.out.should == ""
+ f.err.should == ""
+ end
+
+ it "should get stdout and stderr" do
+ f = ExternalCommand.new(output_script, "out", "err", "10", "23").run()
+ f.status.should == 23
+ f.out.should == (0..9).map {|i| "out #{i}\n"}.join("")
+ f.err.should == (0..9).map {|i| "err #{i}\n"}.join("")
+ end
+
+ it "should work with large amounts of data" do
+ f = ExternalCommand.new(output_script, "a longer output line", "a longer error line", "10000", "5").run()
+ f.status.should == 5
+ f.out.should == (0..9999).map {|i| "a longer output line #{i}\n"}.join("")
+ f.err.should == (0..9999).map {|i| "a longer error line #{i}\n"}.join("")
+ end
+
+end
+