Browse files

Error handling and logging

 - Demonstrate begin/rescue/end block
 - Demonstrate mid-method raise
 - Demonstrate switching on object type/existance
  • Loading branch information...
1 parent 7c947af commit 70b5f6e68f5650d94e9ad7cb47f7d942f9335aec @avdi committed Dec 30, 2009
Showing with 47 additions and 11 deletions.
  1. +19 −5 lib/cowsay.rb
  2. +28 −6 spec/cowsay_spec.rb
View
24 lib/cowsay.rb
@@ -1,24 +1,38 @@
require 'active_support'
+require 'logger'
module Cowsay
class Cow
def initialize(options={})
@io_class = options.fetch(:io_class){IO}
+ @logger = options.fetch(:logger){Logger.new($stderr)}
end
def say(message, options={})
command = "cowsay"
if options[:strings] && options[:strings][:eyes]
command << " -e '#{options[:strings][:eyes]}'"
end
- @io_class.popen(command, "w+") do |process|
- process.write(message)
- process.close_write
- result = process.read
+ result = @io_class.popen(command, "w+") do |process|
+ result = begin
+ process.write(message)
+ process.close_write
+ result = process.read
+ rescue Errno::EPIPE
+ message
+ end
if options[:out]
options[:out] << result
end
- options[:out].try(:path) || result
+ destination = options[:out].try(:path) ||
+ options[:out].try(:inspect) ||
+ "return value"
+ @logger.info "Wrote to #{destination}"
+ result
end
+ if $? && ![0,172].include?($?.exitstatus)
+ raise ArgumentError, $?.exitstatus.to_s
+ end
+ result
end
end
end
View
34 spec/cowsay_spec.rb
@@ -2,11 +2,19 @@
module Cowsay
describe Cow do
+
+ def set_child_exit_status(status)
+ # $? is read-only so we can't set it manually. Instead we have to start an
+ # actual process and exit with the given status.
+ open("|-") do |pipe| exit!(status) if pipe.nil? end
+ end
+
before :each do
@process = stub("process", :read => "OUTPUT").as_null_object
@io_class = stub("IO Class")
+ @log = stub("Log").as_null_object
@io_class.stub!(:popen).and_yield(@process)
- @it = Cow.new(:io_class => @io_class)
+ @it = Cow.new(:io_class => @io_class, :logger => @log)
end
it "should be able to say hello" do
@@ -52,23 +60,37 @@ module Cowsay
out.string.should be == "OUTPUT"
end
- it "should return the filename of output file" do
+ it "should log the filename of output file" do
out = StringIO.new
out.stub!(:path).and_return("/OUTPUT_PATH")
- @it.say("moo", :out => out).should be == "/OUTPUT_PATH"
+ @log.should_receive(:info).with(/\/OUTPUT_PATH/)
+ @it.say("moo", :out => out)
end
end
+ context "given a non-file output stream" do
+ it "should log the object in string form" do
+ out = StringIO.new
+ out.stub!(:inspect).and_return("<output>")
+ @log.should_receive(:info).with(/<output>/)
+ @it.say("moo", :out => out)
+ end
+ end
+
context "when cowsay command is missing" do
it "should just output the bare message" do
- pending
+ @process.should_receive(:write).and_raise(Errno::EPIPE)
+ @it.say("cluck").should be == "cluck"
end
end
context "when the command returns a non-zero status" do
- it "should raise an argument error" do
- pending
+ it "should raise an error" do
+ set_child_exit_status(1)
+ lambda do
+ @it.say("moo")
+ end.should raise_error(ArgumentError)
end
end
end

0 comments on commit 70b5f6e

Please sign in to comment.