require 'gorgon/gem_command_handler' describe GemCommandHandler do let(:exchange) { double("GorgonBunny Exchange", :publish => nil) } let(:bunny) { double("GorgonBunny", :exchange => exchange, :stop => nil) } let(:payload) { {:type => :update, :reply_exchange_name => "name", :body => {:gem_command => "cmd"}} } let(:stdin) { double("IO object", :close => nil)} let(:stdout) { double("IO object", :read => "output", :close => nil)} let(:stderr) { double("IO object", :read => "errors", :close => nil)} let(:status) { double("Process Status", :exitstatus => 0)} describe "#handle" do before do @handler = GemCommandHandler.new bunny @running_response = {:type => :running_command, :hostname => Socket.gethostname} stub_methods end it "publishes 'running_command' message" do bunny.should_receive(:exchange).with("name", anything).and_return(exchange) Yajl::Encoder.should_receive(:encode).with(@running_response).and_return :json_msg exchange.should_receive(:publish).with(:json_msg) @handler.handle payload, {} end it "runs 'gem gorgon' using popen4" do Open4.should_receive(:popen4).with("gem cmd gorgon").and_return([1, stdin, stdout, stderr]) @handler.handle payload, {} end it "uses binary gem from configuration if this was specified" do Open4.should_receive(:popen4).with("path/to/gem cmd gorgon").and_return([1, stdin, stdout, stderr]) @handler.handle payload, {:bin_gem_path => "path/to/gem"} end it "waits for the command to finish" do Open4.should_receive(:popen4).ordered Process.should_receive(:waitpid2).with(1).ordered.and_return([nil, status]) @handler.handle payload, {} end it "closes stding and reads stdout and stderr from process" do stdin.should_receive(:close) stdout.should_receive(:read) stderr.should_receive(:read) @handler.handle payload, {} end it "sends 'command_completed' message when exitstatus is 0" do response = {:type => :command_completed, :hostname => Socket.gethostname, :command => "gem cmd gorgon", :stdout => "output", :stderr => "errors" } Yajl::Encoder.should_receive(:encode).once.ordered.with(@running_response) Yajl::Encoder.should_receive(:encode).once.ordered.with(response).and_return :json_msg exchange.should_receive(:publish).with(:json_msg) @handler.handle payload, {} end it "stops bunny and exit if exitstatus is 0" do bunny.should_receive(:stop).once.ordered @handler.should_receive(:exit).once.ordered @handler.handle payload, {} end it "sends 'command_failed' message when exitstatus is not 0" do status.should_receive(:exitstatus).and_return(99) response = {:type => :command_failed, :hostname => Socket.gethostname, :command => "gem cmd gorgon", :stdout => "output", :stderr => "errors" } Yajl::Encoder.should_receive(:encode).with(response).and_return :json_msg exchange.should_receive(:publish).with(:json_msg) @handler.handle payload, {} end end def stub_methods Open4.stub(:popen4).and_return([1, stdin, stdout, stderr]) Process.stub(:waitpid2).and_return([nil, status]) Yajl::Encoder.stub(:encode).and_return :json_msg @handler.stub(:exit) end end