beetle 0.3.0.rc.12 → 0.3.0.rc.15

Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc CHANGED
@@ -85,7 +85,7 @@ For development, you'll need
85
85
  {Ali Jelveh}[http://github.com/dudemeister] and
86
86
  {Sebastian Roebke}[http://github.com/boosty].
87
87
 
88
- You cand find out more about our work on our {dev blog}[http://devblog.xing.com].
88
+ You can find out more about our work on our {dev blog}[http://devblog.xing.com].
89
89
 
90
90
  Copyright (c) 2010 {XING AG}[http://www.xing.com/]
91
91
 
data/Rakefile CHANGED
@@ -1,6 +1,5 @@
1
1
  require 'rake'
2
2
  require 'rake/testtask'
3
- require 'rcov/rcovtask'
4
3
  require 'bundler/gem_tasks'
5
4
 
6
5
  # rake 0.9.2 hack to supress deprecation warnings caused by cucumber
@@ -11,25 +10,35 @@ require 'cucumber/rake/task'
11
10
  $:.unshift 'lib'
12
11
  require 'beetle'
13
12
 
14
- namespace :test do
15
- namespace :coverage do
16
- desc "Delete aggregate coverage data."
17
- task(:clean) { rm_f "coverage.data" }
18
- end
13
+ if RUBY_VERSION < "1.9"
14
+ require 'rcov/rcovtask'
15
+
16
+ namespace :test do
17
+ namespace :coverage do
18
+ desc "Delete aggregate coverage data."
19
+ task(:clean) { rm_f "coverage.data" }
20
+ end
19
21
 
20
- desc 'Aggregate code coverage'
21
- task :coverage => "test:coverage:clean"
22
+ desc 'Aggregate code coverage'
23
+ task :coverage => "test:coverage:clean"
22
24
 
23
- Rcov::RcovTask.new(:coverage) do |t|
24
- t.libs << "test"
25
- t.test_files = FileList["test/**/*_test.rb"]
26
- t.output_dir = "test/coverage"
27
- t.verbose = true
28
- t.rcov_opts << "--exclude '.*' --include-file 'lib/beetle/'"
25
+ Rcov::RcovTask.new(:coverage) do |t|
26
+ t.libs << "test"
27
+ t.test_files = FileList["test/**/*_test.rb"]
28
+ t.output_dir = "test/coverage"
29
+ t.verbose = true
30
+ t.rcov_opts << "--exclude '.*' --include-file 'lib/beetle/'"
31
+ end
32
+ task :coverage do
33
+ system 'open test/coverage/index.html'
34
+ end if RUBY_PLATFORM =~ /darwin/
35
+ end
36
+ else
37
+ namespace :test do
38
+ task :coverage => :test do
39
+ system 'open coverage/index.html'
40
+ end
29
41
  end
30
- task :coverage do
31
- system 'open test/coverage/index.html'
32
- end if RUBY_PLATFORM =~ /darwin/
33
42
  end
34
43
 
35
44
  namespace :beetle do
@@ -98,7 +107,7 @@ Rake::TestTask.new do |t|
98
107
  t.verbose = true
99
108
  end
100
109
 
101
- require 'rake/rdoctask'
110
+ require 'rdoc/task'
102
111
 
103
112
  Rake::RDocTask.new do |rdoc|
104
113
  rdoc.rdoc_dir = 'site/rdoc'
data/beetle.gemspec CHANGED
@@ -33,19 +33,14 @@ Gem::Specification.new do |s|
33
33
 
34
34
  s.specification_version = 3
35
35
  s.add_runtime_dependency("uuid4r", [">= 0.1.2"])
36
- s.add_runtime_dependency("bunny", ["= 0.7.8"])
37
- s.add_runtime_dependency("redis", ["= 2.2.2"])
38
- s.add_runtime_dependency("hiredis", ["= 0.4.4"])
39
- s.add_runtime_dependency("amq-client", ["= 0.9.1"])
40
- s.add_runtime_dependency("amq-protocol", ["= 0.9.0"])
41
- s.add_runtime_dependency("amqp", ["= 0.9.2"])
36
+ s.add_runtime_dependency("bunny", ["= 0.7.9"])
37
+ s.add_runtime_dependency("redis", ["= 3.0.1"])
38
+ s.add_runtime_dependency("hiredis", ["= 0.4.5"])
39
+ s.add_runtime_dependency("amq-client", ["= 0.9.3"])
40
+ s.add_runtime_dependency("amq-protocol", ["= 0.9.3"])
41
+ s.add_runtime_dependency("amqp", ["= 0.9.6"])
42
42
  s.add_runtime_dependency("activesupport", [">= 2.3.4"])
43
43
  s.add_runtime_dependency("eventmachine_httpserver", [">= 0.2.1"])
44
44
  s.add_runtime_dependency("daemons", [">= 1.0.10"])
45
- s.add_development_dependency("rake", [">= 0.8.7"])
46
- s.add_development_dependency("mocha", [">= 0"])
47
- s.add_development_dependency("rcov", ["~> 0.9.10"])
48
- s.add_development_dependency("cucumber", [">= 0.7.2"])
49
- s.add_development_dependency("daemon_controller", [">= 0"])
50
45
  end
51
46
 
data/examples/simple.rb CHANGED
@@ -1,8 +1,6 @@
1
1
  # simple.rb
2
2
  # this example shows you a very basic message/handler setup
3
3
  #
4
- #
5
- #
6
4
  # ! check the examples/README.rdoc for information on starting your redis/rabbit !
7
5
  #
8
6
  # start it with ruby simple.rb
@@ -5,7 +5,7 @@ end
5
5
 
6
6
  Given /^a redis server "([^\"]*)" exists as slave of "([^\"]*)"$/ do |redis_name, redis_master_name|
7
7
  TestDaemons::Redis[redis_name].start
8
- Given "redis server \"#{redis_name}\" is slave of \"#{redis_master_name}\""
8
+ step "redis server \"#{redis_name}\" is slave of \"#{redis_master_name}\""
9
9
  end
10
10
 
11
11
  Given /^redis server "([^\"]*)" is master$/ do |redis_name|
data/lib/beetle/client.rb CHANGED
@@ -149,9 +149,10 @@ module Beetle
149
149
 
150
150
  # this is a convenience method to configure exchanges, queues, messages and handlers
151
151
  # with a common set of options. allows one to call all register methods without the
152
- # register_ prefix. returns self.
152
+ # register_ prefix. returns self. if the passed in block has no parameters, the block
153
+ # will be evaluated in the context of the client configurator.
153
154
  #
154
- # Example:
155
+ # Example: (block with config argument)
155
156
  # client = Beetle.client.new.configure :exchange => :foobar do |config|
156
157
  # config.queue :q1, :key => "foo"
157
158
  # config.queue :q2, :key => "bar"
@@ -160,8 +161,24 @@ module Beetle
160
161
  # config.handler :q1 { puts "got foo"}
161
162
  # config.handler :q2 { puts "got bar"}
162
163
  # end
163
- def configure(options={}) #:yields: config
164
- yield Configurator.new(self, options)
164
+ #
165
+ # Example: (block without config argument)
166
+ # client = Beetle.client.new.configure :exchange => :foobar do
167
+ # queue :q1, :key => "foo"
168
+ # queue :q2, :key => "bar"
169
+ # message :foo
170
+ # message :bar
171
+ # handler :q1 { puts "got foo"}
172
+ # handler :q2 { puts "got bar"}
173
+ # end
174
+ #
175
+ def configure(options={}, &block)
176
+ configurator = Configurator.new(self, options)
177
+ if block.arity == 1
178
+ yield configurator
179
+ else
180
+ configurator.instance_eval &block
181
+ end
165
182
  self
166
183
  end
167
184
 
@@ -223,18 +240,22 @@ module Beetle
223
240
  end
224
241
 
225
242
  # traces queues without consuming them. useful for debugging message flow.
226
- def trace(queue_names=self.queues.keys, &block)
243
+ def trace(queue_names=self.queues.keys, tracer=nil, &block)
227
244
  queues_to_trace = self.queues.slice(*queue_names)
228
245
  queues_to_trace.each do |name, opts|
229
246
  opts.merge! :durable => false, :auto_delete => true, :amqp_name => queue_name_for_tracing(opts[:amqp_name])
230
247
  end
231
- register_handler(queue_names) do |msg|
232
- puts "-----===== new message =====-----"
233
- puts "SERVER: #{msg.server}"
234
- puts "HEADER: #{msg.header.inspect}"
235
- puts "MSGID: #{msg.msg_id}"
236
- puts "DATA: #{msg.data}"
237
- end
248
+ tracer ||=
249
+ lambda do |msg|
250
+ puts "-----===== new message =====-----"
251
+ puts "SERVER: #{msg.server}"
252
+ puts "HEADER: #{msg.header.attributes[:headers].inspect}"
253
+ puts "EXCHANGE: #{msg.header.method.exchange}"
254
+ puts "KEY: #{msg.header.method.routing_key}"
255
+ puts "MSGID: #{msg.msg_id}"
256
+ puts "DATA: #{msg.data}"
257
+ end
258
+ register_handler(queue_names){|msg| tracer.call msg }
238
259
  listen_queues(queue_names, &block)
239
260
  end
240
261
 
@@ -199,7 +199,7 @@ module Beetle
199
199
  # have we already seen this message? if not, set the status to "incomplete" and store
200
200
  # the message exipration timestamp in the deduplication store.
201
201
  def key_exists?
202
- old_message = 0 == @store.msetnx(msg_id, :status =>"incomplete", :expires => @expires_at, :timeout => now + timeout)
202
+ old_message = !@store.msetnx(msg_id, :status =>"incomplete", :expires => @expires_at, :timeout => now + timeout)
203
203
  if old_message
204
204
  logger.debug "Beetle: received duplicate message: #{msg_id} on queue: #{@queue}"
205
205
  end
@@ -117,16 +117,19 @@ module Beetle
117
117
  end
118
118
 
119
119
  def pong!
120
+ logger.info "Sending pong message with id '#{id}' and token '#{@current_token}'"
120
121
  beetle.publish(:pong, {"id" => id, "token" => @current_token}.to_json)
121
122
  end
122
123
 
123
124
  def client_started!
125
+ logger.info "Sending client_started message with id '#{id}'"
124
126
  beetle.publish(:client_started, {"id" => id}.to_json)
125
127
  end
126
128
 
127
129
  def invalidate!
128
130
  @current_master = nil
129
131
  clear_redis_master_file
132
+ logger.info "Sending client_invalidated message with id '#{id}' and token '#{@current_token}'"
130
133
  beetle.publish(:client_invalidated, {"id" => id, "token" => @current_token}.to_json)
131
134
  end
132
135
 
@@ -86,7 +86,7 @@ module Beetle
86
86
  return unless redeem_token(token)
87
87
  @client_pong_ids_received << id
88
88
  if all_client_pong_ids_received?
89
- logger.debug "All client pong messages received"
89
+ logger.info "All client pong messages received"
90
90
  @available_timer.cancel if @available_timer
91
91
  invalidate_current_master
92
92
  end
@@ -96,10 +96,10 @@ module Beetle
96
96
  def client_started(payload)
97
97
  id = payload["id"]
98
98
  if client_id_valid?(id)
99
- logger.info("Received client_started message from id '#{id}'")
99
+ logger.info "Received client_started message from id '#{id}'"
100
100
  else
101
101
  msg = "Received client_started message from unknown id '#{id}'"
102
- logger.error(msg)
102
+ logger.error msg
103
103
  beetle.publish(:system_notification, {"message" => msg}.to_json)
104
104
  end
105
105
  end
@@ -152,7 +152,7 @@ module Beetle
152
152
  def initiate_master_switch
153
153
  redis.refresh
154
154
  available, switch_in_progress = master_available?, paused?
155
- logger.debug "initiating master switch: already in progress = #{switch_in_progress}"
155
+ logger.debug "Initiating master switch: already in progress = #{switch_in_progress}"
156
156
  unless available || switch_in_progress
157
157
  master_unavailable!
158
158
  end
@@ -205,7 +205,7 @@ module Beetle
205
205
  else
206
206
  write_redis_master_file(current_master.server) if @current_master = redis.auto_detect_master
207
207
  end
208
- current_master or raise NoRedisMaster.new("failed to determine initial redis master")
208
+ current_master or raise NoRedisMaster.new("Failed to determine initial redis master")
209
209
  end
210
210
 
211
211
  def determine_new_master
@@ -215,7 +215,8 @@ module Beetle
215
215
  def validate_pong_client_id(client_id)
216
216
  unless known_client = client_id_valid?(client_id)
217
217
  msg = "Received pong message from unknown id '#{client_id}'"
218
- logger.error(msg)
218
+ logger.error msg
219
+ logger.info "Sending system_notification message with text: #{msg}"
219
220
  beetle.publish(:system_notification, {"message" => msg}.to_json)
220
221
  end
221
222
  known_client
@@ -239,12 +240,14 @@ module Beetle
239
240
 
240
241
  def check_all_clients_available
241
242
  generate_new_token
243
+ logger.info "Sending ping message with token '#{@current_token}'"
242
244
  beetle.publish(:ping, payload_with_current_token)
243
245
  @available_timer = EM::Timer.new(config.redis_configuration_client_timeout) { cancel_invalidation }
244
246
  end
245
247
 
246
248
  def invalidate_current_master
247
249
  generate_new_token
250
+ logger.info "Sending invalidate message with token '#{@current_token}'"
248
251
  beetle.publish(:invalidate, payload_with_current_token)
249
252
  @invalidate_timer = EM::Timer.new(config.redis_configuration_client_timeout) { cancel_invalidation }
250
253
  end
@@ -275,7 +278,8 @@ module Beetle
275
278
  def switch_master
276
279
  if new_master = determine_new_master
277
280
  msg = "Setting redis master to '#{new_master.server}' (was '#{current_master.server}')"
278
- logger.warn(msg)
281
+ logger.warn msg
282
+ logger.info "Sending system_notification message with text: #{msg}"
279
283
  beetle.publish(:system_notification, {"message" => msg}.to_json)
280
284
 
281
285
  new_master.master!
@@ -283,7 +287,8 @@ module Beetle
283
287
  @current_master = new_master
284
288
  else
285
289
  msg = "Redis master could not be switched, no slave available to become new master, promoting old master"
286
- logger.error(msg)
290
+ logger.error msg
291
+ logger.info "Sending system_notification message with text: #{msg}"
287
292
  beetle.publish(:system_notification, {"message" => msg}.to_json)
288
293
  end
289
294
 
@@ -292,7 +297,7 @@ module Beetle
292
297
  end
293
298
 
294
299
  def publish_master(master)
295
- logger.info "Publishing reconfigure message with server '#{master.server}'"
300
+ logger.info "Sending reconfigure message with server '#{master.server}'"
296
301
  beetle.publish(:reconfigure, payload_with_current_token({"server" => master.server}))
297
302
  end
298
303
 
@@ -19,11 +19,6 @@ class Redis #:nodoc:
19
19
  slaveof(host, port)
20
20
  end
21
21
 
22
- # Redis 2 tries to establish a connection on inspect. this is evil!
23
- def inspect
24
- super
25
- end
26
-
27
22
  def info_with_rescue
28
23
  info
29
24
  rescue Exception
@@ -51,23 +46,4 @@ class Redis #:nodoc:
51
46
  info["role"] == "slave" && info["master_host"] == host && info["master_port"] == port.to_s
52
47
  end
53
48
 
54
- # redis 2.2.2 shutdown implementation does not disconnect from the redis server.
55
- # this leaves the connection in an inconsistent state and causes the next command to silently fail.
56
- # this in turn breaks our cucumber test scenarios.
57
- # fix this here, until a new version is released which fixes the problem.
58
-
59
- alias_method :broken_shutdown, :shutdown
60
-
61
- # Synchronously save the dataset to disk and then shut down the server.
62
- def shutdown
63
- synchronize do
64
- begin
65
- @client.call [:shutdown]
66
- rescue Errno::ECONNREFUSED
67
- ensure
68
- @client.disconnect
69
- end
70
- end
71
- end
72
-
73
49
  end
@@ -1,3 +1,3 @@
1
1
  module Beetle
2
- VERSION = "0.3.0.rc.12"
2
+ VERSION = "0.3.0.rc.15"
3
3
  end
data/lib/beetle.rb CHANGED
@@ -10,6 +10,7 @@ require 'socket'
10
10
  require 'beetle/version'
11
11
 
12
12
  module Beetle
13
+ #:nocov:
13
14
  Timer = if RUBY_VERSION < "1.9"
14
15
  begin
15
16
  require 'system_timer'
@@ -23,6 +24,7 @@ module Beetle
23
24
  require 'timeout'
24
25
  Timeout
25
26
  end
27
+ #:nocov:
26
28
 
27
29
  # abstract superclass for Beetle specific exceptions
28
30
  class Error < StandardError; end
@@ -40,7 +42,7 @@ module Beetle
40
42
  # AMQP options for exchange creation
41
43
  EXCHANGE_CREATION_KEYS = [:auto_delete, :durable, :internal, :nowait, :passive]
42
44
  # AMQP options for queue creation
43
- QUEUE_CREATION_KEYS = [:passive, :durable, :exclusive, :auto_delete, :no_wait]
45
+ QUEUE_CREATION_KEYS = [:passive, :durable, :exclusive, :auto_delete, :no_wait, :arguments]
44
46
  # AMQP options for queue bindings
45
47
  QUEUE_BINDING_KEYS = [:key, :no_wait]
46
48
  # AMQP options for message publishing
@@ -52,7 +54,11 @@ module Beetle
52
54
  def self.hostname
53
55
  name = Socket.gethostname
54
56
  parts = name.split('.')
55
- parts.size > 1 ? name : Socket.gethostbyname(parts.first).first
57
+ if parts.size > 1
58
+ name
59
+ else
60
+ Socket.gethostbyname(parts.first).first rescue name
61
+ end
56
62
  end
57
63
 
58
64
  # use ruby's autoload mechanism for loading beetle classes
@@ -76,7 +82,9 @@ module Beetle
76
82
  raise if $!.is_a?(Mocha::ExpectationError)
77
83
  end
78
84
  else
85
+ #:nocov:
79
86
  def self.reraise_expectation_errors! #:nodoc:
80
87
  end
88
+ #:nocov:
81
89
  end
82
90
  end
@@ -0,0 +1,16 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
2
+
3
+ module Beetle
4
+ class HostnameTest < Test::Unit::TestCase
5
+ test "should use Socket.gethostname if returned name name is fully qualified" do
6
+ Socket.expects(:gethostname).returns("a.b.com")
7
+ assert_equal "a.b.com", Beetle.hostname
8
+ end
9
+
10
+ test "should use Socket.gethosbyname if returned name name is not fully qualified" do
11
+ Socket.expects(:gethostname).returns("a")
12
+ Socket.expects(:gethostbyname).with("a").returns(["a.b.com"])
13
+ assert_equal "a.b.com", Beetle.hostname
14
+ end
15
+ end
16
+ end
@@ -151,6 +151,16 @@ module Beetle
151
151
  @client.configure(options) {|config| assert_equal 42, config}
152
152
  end
153
153
 
154
+ test "configure should eval a passed block without arguments in the context of the configurator" do
155
+ options = {:exchange => :foobar}
156
+ m = "mock"
157
+ m.expects(:foo).returns(42)
158
+ Client::Configurator.expects(:new).with(@client, options).returns(m)
159
+ value = nil
160
+ @client.configure(options) { value = foo }
161
+ assert_equal 42, value
162
+ end
163
+
154
164
  test "a configurator should forward all known registration methods to the client" do
155
165
  options = {:foo => :bar}
156
166
  config = Client::Configurator.new(@client, options)
@@ -353,7 +363,7 @@ module Beetle
353
363
  client = Client.new
354
364
  client.register_queue("test")
355
365
  sub = client.send(:subscriber)
356
- sub.expects(:register_handler).with(client.queues.keys, {}, nil).yields(stub_everything("message"))
366
+ sub.expects(:register_handler).with(client.queues.keys, {}, nil).yields(message_stub_for_tracing)
357
367
  sub.expects(:listen_queues)
358
368
  client.stubs(:puts)
359
369
  client.trace
@@ -369,11 +379,19 @@ module Beetle
369
379
  client.register_queue("test")
370
380
  client.register_queue("irrelevant")
371
381
  sub = client.send(:subscriber)
372
- sub.expects(:register_handler).with(["test"], {}, nil).yields(stub_everything("message"))
382
+ sub.expects(:register_handler).with(["test"], {}, nil).yields(message_stub_for_tracing)
373
383
  sub.expects(:listen_queues).with(["test"])
374
384
  client.stubs(:puts)
375
385
  client.trace(["test"])
376
386
  end
377
387
 
388
+ def message_stub_for_tracing
389
+ header_stub = stub_everything("header")
390
+ header_stub.stubs(:method).returns(stub_everything("method"))
391
+ header_stub.stubs(:attributes).returns(stub_everything("attributes"))
392
+ msg_stub = stub_everything("message")
393
+ msg_stub.stubs(:header).returns(header_stub)
394
+ msg_stub
395
+ end
378
396
  end
379
397
  end
@@ -13,6 +13,12 @@ module Beetle
13
13
  assert_equal new_value, config.gc_threshold
14
14
  end
15
15
 
16
+ test "should log an error if the specified file does not exist" do
17
+ config = Configuration.new
18
+ config.logger.expects(:error)
19
+ assert_raises(Errno::ENOENT){ config.config_file = "some/path/to/a/file" }
20
+ end
21
+
16
22
  test "should log to STDOUT if no log_file given" do
17
23
  config = Configuration.new
18
24
  Logger.expects(:new).with(STDOUT).returns(stub_everything)
@@ -13,11 +13,11 @@ module Beetle
13
13
  assert_equal 0, @r.del("hahahaha")
14
14
  end
15
15
 
16
- test "msetnx returns 0 or 1" do
17
- assert_equal 1, @r.msetnx("a", 1, "b", 2)
16
+ test "msetnx returns a boolean" do
17
+ assert_equal true, @r.msetnx("a", 1, "b", 2)
18
18
  assert_equal "1", @r.get("a")
19
19
  assert_equal "2", @r.get("b")
20
- assert_equal 0, @r.msetnx("a", 3, "b", 4)
20
+ assert_equal false, @r.msetnx("a", 3, "b", 4)
21
21
  assert_equal "1", @r.get("a")
22
22
  assert_equal "2", @r.get("b")
23
23
  end
@@ -224,12 +224,12 @@ module Beetle
224
224
  end
225
225
 
226
226
  test "binding a queue should create it using the config and bind it to the exchange with the name specified" do
227
- @client.register_queue("some_queue", :exchange => "some_exchange", :key => "haha.#")
227
+ @client.register_queue("some_queue", :exchange => "some_exchange", :key => "haha.#", :arguments => {"foo" => "fighter"})
228
228
  @pub.expects(:exchange).with("some_exchange").returns(:the_exchange)
229
229
  q = mock("queue")
230
230
  q.expects(:bind).with(:the_exchange, {:key => "haha.#"})
231
231
  m = mock("Bunny")
232
- m.expects(:queue).with("some_queue", :durable => true, :passive => false, :auto_delete => false, :exclusive => false).returns(q)
232
+ m.expects(:queue).with("some_queue", :durable => true, :passive => false, :auto_delete => false, :exclusive => false, :arguments => {"foo" => "fighter"}).returns(q)
233
233
  @pub.expects(:bunny).returns(m)
234
234
 
235
235
  @pub.send(:queue, "some_queue")
@@ -303,38 +303,26 @@ module Beetle
303
303
  end
304
304
  end
305
305
 
306
- class RedisConfigurationServerSystemNotificationAndLoggingTest < Test::Unit::TestCase
306
+ class RedisConfigurationServerSystemNotificationTest < Test::Unit::TestCase
307
307
  def setup
308
308
  Beetle.config.redis_configuration_client_ids = "rc-client-1,rc-client-2"
309
309
  @server = RedisConfigurationServer.new
310
310
  @server.stubs(:beetle).returns(stub(:publish))
311
- @server.stubs(:logger).returns(stub)
312
311
  EventMachine.stubs(:add_timer).yields
313
312
  end
314
313
 
315
- test "should log and send a system notification when pong message from unknown client received" do
314
+ test "should send a system notification when receiving pong message from unknown client" do
316
315
  payload = {"id" => "unknown-client", "token" => @server.current_token}
317
316
  msg = "Received pong message from unknown id 'unknown-client'"
318
317
  @server.beetle.expects(:publish).with(:system_notification, ({:message => msg}).to_json)
319
- @server.logger.expects(:error).with(msg)
320
318
  @server.pong(payload)
321
319
  end
322
320
 
323
- test "should warn about unknown clients when receiving client_started messages" do
321
+ test "should send a system notification when receiving client_started message from unknown client" do
324
322
  payload = {"id" => "unknown-client"}
325
323
  msg = "Received client_started message from unknown id 'unknown-client'"
326
324
  @server.beetle.expects(:publish).with(:system_notification, ({:message => msg}).to_json)
327
- @server.logger.expects(:error).with(msg)
328
325
  @server.client_started(payload)
329
326
  end
330
-
331
- test "should log an info about received client_started client_started messages" do
332
- payload = {"id" => "known-client"}
333
- msg = "Received client_started message from id 'known-client'"
334
- @server.logger.expects(:info).with(msg)
335
- @server.expects(:client_id_valid?).with('known-client').returns(true)
336
- @server.client_started(payload)
337
- end
338
-
339
327
  end
340
328
  end
@@ -61,23 +61,14 @@ module Beetle
61
61
  end
62
62
  end
63
63
 
64
- class BrokenRedisShutdownTest < Test::Unit::TestCase
64
+ class RedisShutdownTest < Test::Unit::TestCase
65
65
  def setup
66
66
  @r = Redis.new(:host => "localhost", :port => 6390)
67
67
  end
68
68
 
69
- # if this test fails after upgrading redis, we can probably remove
70
- # our custom shutdown method from redis_ext.rb
71
- test "orginal redis shutdown implementation is broken" do
72
- @r.client.expects(:call_without_reply).with([:shutdown]).once
73
- @r.client.expects(:disconnect).never
74
- @r.broken_shutdown
75
- end
76
-
77
- test "patched redis shutdown implementation should call :shutdown and rescue Errno::ECONNREFUSED" do
78
- @r.client.expects(:call).with([:shutdown]).once.raises(Errno::ECONNREFUSED)
79
- @r.client.expects(:disconnect).once
80
- @r.shutdown
69
+ test "redis shutdown implementation should call :shutdown and return nil" do
70
+ @r.client.expects(:call).with([:shutdown]).once.raises(Redis::ConnectionError)
71
+ assert_nil @r.shutdown
81
72
  end
82
73
  end
83
74
 
@@ -128,12 +128,12 @@ module Beetle
128
128
  end
129
129
 
130
130
  test "binding a queue should create it using the config and bind it to the exchange with the name specified" do
131
- @client.register_queue("some_queue", "durable" => true, "exchange" => "some_exchange", "key" => "haha.#")
131
+ @client.register_queue("some_queue", "durable" => true, "exchange" => "some_exchange", "key" => "haha.#", "arguments" => {"schmu" => 5})
132
132
  @sub.expects(:exchange).with("some_exchange").returns(:the_exchange)
133
133
  q = mock("queue")
134
134
  q.expects(:bind).with(:the_exchange, {:key => "haha.#"})
135
135
  m = mock("MQ")
136
- m.expects(:queue).with("some_queue", :durable => true, :passive => false, :auto_delete => false, :exclusive => false).returns(q)
136
+ m.expects(:queue).with("some_queue", :durable => true, :passive => false, :auto_delete => false, :exclusive => false, :arguments => {"schmu" => 5}).returns(q)
137
137
  @sub.expects(:channel).returns(m)
138
138
 
139
139
  @sub.send(:queue, "some_queue")
data/test/test_helper.rb CHANGED
@@ -1,4 +1,10 @@
1
1
  require 'rubygems'
2
+ if RUBY_VERSION >= "1.9"
3
+ require 'simplecov'
4
+ SimpleCov.start do
5
+ add_filter "/test/"
6
+ end
7
+ end
2
8
  require 'test/unit'
3
9
  require 'mocha'
4
10
  require 'active_support/testing/declarative'
@@ -7,14 +13,7 @@ require File.expand_path(File.dirname(__FILE__) + '/../lib/beetle')
7
13
  require File.expand_path(File.dirname(__FILE__) + '/colorized_test_output')
8
14
 
9
15
  # we can remove this hack which is needed only for testing
10
- begin
11
- require 'qrack/errors'
12
- rescue LoadError
13
- module Qrack
14
- class BufferOverflowError < StandardError; end
15
- class InvalidTypeError < StandardError; end
16
- end
17
- end
16
+ require 'qrack/errors'
18
17
 
19
18
 
20
19
  class Test::Unit::TestCase
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: beetle
3
3
  version: !ruby/object:Gem::Version
4
- hash: 534360161
5
- prerelease: true
4
+ hash: -946228374
5
+ prerelease: 6
6
6
  segments:
7
7
  - 0
8
8
  - 3
9
9
  - 0
10
10
  - rc
11
- - 12
12
- version: 0.3.0.rc.12
11
+ - 15
12
+ version: 0.3.0.rc.15
13
13
  platform: ruby
14
14
  authors:
15
15
  - Stefan Kaes
@@ -21,12 +21,9 @@ autorequire:
21
21
  bindir: bin
22
22
  cert_chain: []
23
23
 
24
- date: 2012-01-25 00:00:00 +01:00
25
- default_executable: beetle
24
+ date: 2012-07-23 00:00:00 Z
26
25
  dependencies:
27
26
  - !ruby/object:Gem::Dependency
28
- name: uuid4r
29
- prerelease: false
30
27
  requirement: &id001 !ruby/object:Gem::Requirement
31
28
  none: false
32
29
  requirements:
@@ -38,107 +35,107 @@ dependencies:
38
35
  - 1
39
36
  - 2
40
37
  version: 0.1.2
41
- type: :runtime
42
38
  version_requirements: *id001
43
- - !ruby/object:Gem::Dependency
44
- name: bunny
45
39
  prerelease: false
40
+ type: :runtime
41
+ name: uuid4r
42
+ - !ruby/object:Gem::Dependency
46
43
  requirement: &id002 !ruby/object:Gem::Requirement
47
44
  none: false
48
45
  requirements:
49
46
  - - "="
50
47
  - !ruby/object:Gem::Version
51
- hash: 19
48
+ hash: 17
52
49
  segments:
53
50
  - 0
54
51
  - 7
55
- - 8
56
- version: 0.7.8
57
- type: :runtime
52
+ - 9
53
+ version: 0.7.9
58
54
  version_requirements: *id002
59
- - !ruby/object:Gem::Dependency
60
- name: redis
61
55
  prerelease: false
56
+ type: :runtime
57
+ name: bunny
58
+ - !ruby/object:Gem::Dependency
62
59
  requirement: &id003 !ruby/object:Gem::Requirement
63
60
  none: false
64
61
  requirements:
65
62
  - - "="
66
63
  - !ruby/object:Gem::Version
67
- hash: 3
64
+ hash: 5
68
65
  segments:
69
- - 2
70
- - 2
71
- - 2
72
- version: 2.2.2
73
- type: :runtime
66
+ - 3
67
+ - 0
68
+ - 1
69
+ version: 3.0.1
74
70
  version_requirements: *id003
75
- - !ruby/object:Gem::Dependency
76
- name: hiredis
77
71
  prerelease: false
72
+ type: :runtime
73
+ name: redis
74
+ - !ruby/object:Gem::Dependency
78
75
  requirement: &id004 !ruby/object:Gem::Requirement
79
76
  none: false
80
77
  requirements:
81
78
  - - "="
82
79
  - !ruby/object:Gem::Version
83
- hash: 7
80
+ hash: 5
84
81
  segments:
85
82
  - 0
86
83
  - 4
87
- - 4
88
- version: 0.4.4
89
- type: :runtime
84
+ - 5
85
+ version: 0.4.5
90
86
  version_requirements: *id004
91
- - !ruby/object:Gem::Dependency
92
- name: amq-client
93
87
  prerelease: false
88
+ type: :runtime
89
+ name: hiredis
90
+ - !ruby/object:Gem::Dependency
94
91
  requirement: &id005 !ruby/object:Gem::Requirement
95
92
  none: false
96
93
  requirements:
97
94
  - - "="
98
95
  - !ruby/object:Gem::Version
99
- hash: 57
96
+ hash: 61
100
97
  segments:
101
98
  - 0
102
99
  - 9
103
- - 1
104
- version: 0.9.1
105
- type: :runtime
100
+ - 3
101
+ version: 0.9.3
106
102
  version_requirements: *id005
107
- - !ruby/object:Gem::Dependency
108
- name: amq-protocol
109
103
  prerelease: false
104
+ type: :runtime
105
+ name: amq-client
106
+ - !ruby/object:Gem::Dependency
110
107
  requirement: &id006 !ruby/object:Gem::Requirement
111
108
  none: false
112
109
  requirements:
113
110
  - - "="
114
111
  - !ruby/object:Gem::Version
115
- hash: 59
112
+ hash: 61
116
113
  segments:
117
114
  - 0
118
115
  - 9
119
- - 0
120
- version: 0.9.0
121
- type: :runtime
116
+ - 3
117
+ version: 0.9.3
122
118
  version_requirements: *id006
123
- - !ruby/object:Gem::Dependency
124
- name: amqp
125
119
  prerelease: false
120
+ type: :runtime
121
+ name: amq-protocol
122
+ - !ruby/object:Gem::Dependency
126
123
  requirement: &id007 !ruby/object:Gem::Requirement
127
124
  none: false
128
125
  requirements:
129
126
  - - "="
130
127
  - !ruby/object:Gem::Version
131
- hash: 63
128
+ hash: 55
132
129
  segments:
133
130
  - 0
134
131
  - 9
135
- - 2
136
- version: 0.9.2
137
- type: :runtime
132
+ - 6
133
+ version: 0.9.6
138
134
  version_requirements: *id007
139
- - !ruby/object:Gem::Dependency
140
- name: activesupport
141
135
  prerelease: false
136
+ type: :runtime
137
+ name: amqp
138
+ - !ruby/object:Gem::Dependency
142
139
  requirement: &id008 !ruby/object:Gem::Requirement
143
140
  none: false
144
141
  requirements:
@@ -150,11 +147,11 @@ dependencies:
150
147
  - 3
151
148
  - 4
152
149
  version: 2.3.4
153
- type: :runtime
154
150
  version_requirements: *id008
155
- - !ruby/object:Gem::Dependency
156
- name: eventmachine_httpserver
157
151
  prerelease: false
152
+ type: :runtime
153
+ name: activesupport
154
+ - !ruby/object:Gem::Dependency
158
155
  requirement: &id009 !ruby/object:Gem::Requirement
159
156
  none: false
160
157
  requirements:
@@ -166,11 +163,11 @@ dependencies:
166
163
  - 2
167
164
  - 1
168
165
  version: 0.2.1
169
- type: :runtime
170
166
  version_requirements: *id009
171
- - !ruby/object:Gem::Dependency
172
- name: daemons
173
167
  prerelease: false
168
+ type: :runtime
169
+ name: eventmachine_httpserver
170
+ - !ruby/object:Gem::Dependency
174
171
  requirement: &id010 !ruby/object:Gem::Requirement
175
172
  none: false
176
173
  requirements:
@@ -182,84 +179,10 @@ dependencies:
182
179
  - 0
183
180
  - 10
184
181
  version: 1.0.10
185
- type: :runtime
186
182
  version_requirements: *id010
187
- - !ruby/object:Gem::Dependency
188
- name: rake
189
- prerelease: false
190
- requirement: &id011 !ruby/object:Gem::Requirement
191
- none: false
192
- requirements:
193
- - - ">="
194
- - !ruby/object:Gem::Version
195
- hash: 49
196
- segments:
197
- - 0
198
- - 8
199
- - 7
200
- version: 0.8.7
201
- type: :development
202
- version_requirements: *id011
203
- - !ruby/object:Gem::Dependency
204
- name: mocha
205
183
  prerelease: false
206
- requirement: &id012 !ruby/object:Gem::Requirement
207
- none: false
208
- requirements:
209
- - - ">="
210
- - !ruby/object:Gem::Version
211
- hash: 3
212
- segments:
213
- - 0
214
- version: "0"
215
- type: :development
216
- version_requirements: *id012
217
- - !ruby/object:Gem::Dependency
218
- name: rcov
219
- prerelease: false
220
- requirement: &id013 !ruby/object:Gem::Requirement
221
- none: false
222
- requirements:
223
- - - ~>
224
- - !ruby/object:Gem::Version
225
- hash: 47
226
- segments:
227
- - 0
228
- - 9
229
- - 10
230
- version: 0.9.10
231
- type: :development
232
- version_requirements: *id013
233
- - !ruby/object:Gem::Dependency
234
- name: cucumber
235
- prerelease: false
236
- requirement: &id014 !ruby/object:Gem::Requirement
237
- none: false
238
- requirements:
239
- - - ">="
240
- - !ruby/object:Gem::Version
241
- hash: 7
242
- segments:
243
- - 0
244
- - 7
245
- - 2
246
- version: 0.7.2
247
- type: :development
248
- version_requirements: *id014
249
- - !ruby/object:Gem::Dependency
250
- name: daemon_controller
251
- prerelease: false
252
- requirement: &id015 !ruby/object:Gem::Requirement
253
- none: false
254
- requirements:
255
- - - ">="
256
- - !ruby/object:Gem::Version
257
- hash: 3
258
- segments:
259
- - 0
260
- version: "0"
261
- type: :development
262
- version_requirements: *id015
184
+ type: :runtime
185
+ name: daemons
263
186
  description: A highly available, reliable messaging infrastructure
264
187
  email: opensource@xing.com
265
188
  executables:
@@ -326,6 +249,7 @@ files:
326
249
  - MIT-LICENSE
327
250
  - test/beetle/amqp_gem_behavior_test.rb
328
251
  - test/beetle/base_test.rb
252
+ - test/beetle/beetle_test.rb
329
253
  - test/beetle/client_test.rb
330
254
  - test/beetle/configuration_test.rb
331
255
  - test/beetle/deduplication_store_test.rb
@@ -342,7 +266,6 @@ files:
342
266
  - test/colorized_test_output.rb
343
267
  - test/test_helper.rb
344
268
  - bin/beetle
345
- has_rdoc: true
346
269
  homepage: http://xing.github.com/beetle/
347
270
  licenses: []
348
271
 
@@ -374,13 +297,14 @@ required_rubygems_version: !ruby/object:Gem::Requirement
374
297
  requirements: []
375
298
 
376
299
  rubyforge_project:
377
- rubygems_version: 1.3.7
300
+ rubygems_version: 1.8.24
378
301
  signing_key:
379
302
  specification_version: 3
380
303
  summary: High Availability AMQP Messaging with Redundant Queues
381
304
  test_files:
382
305
  - test/beetle/amqp_gem_behavior_test.rb
383
306
  - test/beetle/base_test.rb
307
+ - test/beetle/beetle_test.rb
384
308
  - test/beetle/client_test.rb
385
309
  - test/beetle/configuration_test.rb
386
310
  - test/beetle/deduplication_store_test.rb