diff options
-rw-r--r-- | lib/external_command.rb | 12 | ||||
-rwxr-xr-x | spec/lib/external_command_scripts/output.sh | 22 | ||||
-rw-r--r-- | spec/lib/external_command_spec.rb | 40 |
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 + |