Commits

Michael Granger  committed 9781207

Add some more Task specs, add a placeholder for Daemon specs.

  • Participants
  • Parent commits 5ae518a

Comments (0)

Files changed (7)

File Manifest.txt

 lib/symphony/tasks/ssh.rb
 lib/symphony/tasks/sshscript.rb
 spec/helpers.rb
+spec/symphony/daemon_spec.rb
 spec/symphony/mixins_spec.rb
 spec/symphony/queue_spec.rb
 spec/symphony/task_spec.rb
 [ ] Update pinger/ssh/sshscript
 [ ] Per Task throttling for daemon
 [ ] Task scaling (min/max settings), check queue backlog during received message
-
+[ ] Make the block of routes declared with on() method accept various arities

File lib/symphony/daemon.rb

 			self.reload_config
 
 		when :CHLD
-			self.log.warn "Got SIGCHLD."
+			self.log.info "Got SIGCHLD."
 			# Just need to wake up, nothing else necessary
 
 		else

File lib/symphony/task.rb

 	def self::after_fork
 		self.log.debug "After fork [%d]: Threads: %p" % [ Process.pid, ThreadGroup::Default.list ]
 		Process.setpgrp
-		Symphony.config.install
+		Symphony.config.install if Symphony.config
 	end
 
 

File spec/symphony/daemon_spec.rb

+# -*- ruby -*-
+#encoding: utf-8
+
+require_relative '../helpers'
+
+require 'symphony/daemon'
+
+describe Symphony::Daemon do
+
+
+
+end
+

File spec/symphony/task_spec.rb

 				def self::name; 'ACME::TestingTask'; end
 			end
 		end
+		let( :payload ) {{ "the" => "payload" }}
+		let( :serialized_payload ) { Yajl.dump(payload) }
+		let( :metadata ) {{ :content_type => 'application/json' }}
 		let( :queue ) do
-			Symphony::Queue.for_task( task_class )
+			obj = Symphony::Queue.for_task( task_class )
+			# Don't really talk to AMQP for messages
+			allow( obj ).to receive( :wait_for_message ) do |oneshot, &callback|
+				callback.call( serialized_payload, metadata )
+			end
+			obj
+		end
+
+
+		it "puts the process into its own process group after a fork" do
+			expect( Process ).to receive( :setpgrp ).with( no_args )
+			task_class.after_fork
 		end
 
 
 		end
 
 
+		it "can set the number of messages to prefetch" do
+			task_class.prefetch( 10 )
+			expect( task_class.prefetch ).to eq( 10 )
+		end
+
+
 		it "can retry on timeout instead of rejecting" do
 			task_class.timeout_action( :retry )
 			expect( task_class.timeout_action ).to eq( :retry )
 
 		context "an instance" do
 
+			let( :task_class ) do
+				Class.new( described_class ) do
+					def initialize( * )
+						super
+						@received_messages = []
+					end
+					attr_reader :received_messages
+
+					def work( payload, metadata )
+						self.received_messages << [ payload, metadata ]
+						true
+					end
+				end
+			end
+
 			let( :task ) { task_class.new(queue) }
 
 
-			it "raises an exception if it doesn't declare a #work method" do
+			it "handles received messages by calling its work method" do
+				expect( queue ).to receive( :wait_for_message ) do |oneshot, &callback|
+					callback.call( serialized_payload, metadata )
+				end
+
+				task.start_handling_messages
+
+				expect( task.received_messages ).to eq([ [payload, metadata] ])
+			end
+
+
+		end
+
+
+		context "an instance with a timeout" do
+
+			let( :task_class ) do
+				Class.new( described_class ) do
+					timeout 0.2
+					def initialize( * )
+						super
+						@received_messages = []
+						@sleeptime = 0
+					end
+					attr_reader :received_messages
+					attr_accessor :sleeptime
+
+					def work( payload, metadata )
+						self.received_messages << [ payload, metadata ]
+						sleep( self.sleeptime )
+						true
+					end
+				end
+			end
+
+			let( :task ) { task_class.new(queue) }
+
+
+			it "returns true if the work completes before the timeout" do
+				task.sleeptime = 0
+				expect( task.start_handling_messages ).to be_truthy
+			end
+
+
+			it "raises a Timeout::Error if the work takes longer than the timeout" do
+				task.sleeptime = task_class.timeout + 2
+				expect {
+					task.start_handling_messages
+				}.to raise_error( Timeout::Error, /execution expired/ )
+			end
+
+
+			it "returns false if the work takes longer than the timeout and the timeout_action is set to :retry" do
+				task_class.timeout_action( :retry )
+				task.sleeptime = task_class.timeout + 2
+				expect( task.start_handling_messages ).to be_falsey
+			end
+
+		end
+
+
+
+		context "an instance with no #work method" do
+
+			let( :task ) { task_class.new(queue) }
+
+			it "raises an exception when told to do work" do
 				expect {
 					task.work( 'payload', {} )
 				}.to raise_error( NotImplementedError, /#work/ )
 			end
 
+		end
 
-			it "sets signal handlers and waits for messages when started"
 
-		end
 
 	end
 
+
+
 end
 

File spec/symphony_spec.rb

 
 describe Symphony do
 
+	before( :each ) do
+		ENV.delete( 'SYMPHONY_CONFIG' )
+	end
 
 
+	it "will load a default config file if none is specified" do
+		config_object = double( "Configurability::Config object" )
+		expect( Configurability ).to receive( :gather_defaults ).
+			and_return( {} )
+		expect( Configurability::Config ).to receive( :load ).
+			with( described_class::DEFAULT_CONFIG_FILE, {} ).
+			and_return( config_object )
+		expect( config_object ).to receive( :install )
+
+		described_class.load_config
+	end
+
+
+	it "will load a config file given in an environment variable if none is specified" do
+		ENV['SYMPHONY_CONFIG'] = '/usr/local/etc/config.yml'
+
+		config_object = double( "Configurability::Config object" )
+		expect( Configurability ).to receive( :gather_defaults ).
+			and_return( {} )
+		expect( Configurability::Config ).to receive( :load ).
+			with( '/usr/local/etc/config.yml', {} ).
+			and_return( config_object )
+		expect( config_object ).to receive( :install )
+
+		described_class.load_config
+	end
+
+
+	it "will load a config file and install it if one is given" do
+		config_object = double( "Configurability::Config object" )
+		expect( Configurability ).to receive( :gather_defaults ).
+			and_return( {} )
+		expect( Configurability::Config ).to receive( :load ).
+			with( 'a/configfile.yml', {} ).
+			and_return( config_object )
+		expect( config_object ).to receive( :install )
+
+		described_class.load_config( 'a/configfile.yml' )
+	end
+
+
+	it "will override default values when loading the config if they're given" do
+		config_object = double( "Configurability::Config object" )
+		expect( Configurability ).to_not receive( :gather_defaults )
+		expect( Configurability::Config ).to receive( :load ).
+			with( 'a/different/configfile.yml', {database: {dbname: 'test'}} ).
+			and_return( config_object )
+		expect( config_object ).to receive( :install )
+
+		described_class.load_config( 'a/different/configfile.yml', database: {dbname: 'test'} )
+	end
+
 end