evented-spec 0.4.0 → 0.4.1
Sign up to get free protection for your applications and to get access to all the features.
- data/HISTORY +8 -1
- data/README.textile +51 -9
- data/Rakefile +3 -4
- data/VERSION +1 -1
- data/lib/evented-spec.rb +22 -1
- data/lib/evented-spec/amqp_spec.rb +27 -0
- data/lib/evented-spec/coolio_spec.rb +26 -0
- data/lib/evented-spec/em_spec.rb +26 -0
- data/lib/evented-spec/evented_example.rb +13 -5
- data/lib/evented-spec/evented_example/amqp_example.rb +8 -7
- data/lib/evented-spec/evented_example/coolio_example.rb +4 -18
- data/lib/evented-spec/evented_example/em_example.rb +6 -12
- data/lib/evented-spec/{amqp.rb → ext/amqp.rb} +31 -2
- data/lib/evented-spec/ext/coolio.rb +14 -0
- data/lib/evented-spec/spec_helper.rb +141 -0
- data/lib/evented-spec/spec_helper/amqp_helpers.rb +55 -0
- data/lib/evented-spec/spec_helper/coolio_helpers.rb +49 -0
- data/lib/evented-spec/spec_helper/event_machine_helpers.rb +52 -0
- data/spec/em_hooks_spec.rb +3 -3
- data/spec/evented-spec/adapters/adapter_seg.rb +156 -0
- data/spec/evented-spec/adapters/amqp_spec.rb +58 -0
- data/spec/evented-spec/adapters/cool_io_spec.rb +30 -0
- data/spec/evented-spec/adapters/em_spec.rb +29 -0
- data/spec/{em_defaults_spec.rb → evented-spec/defaults_options_spec.rb} +0 -0
- data/spec/{em_metadata_spec.rb → evented-spec/evented_spec_metadata_spec.rb} +0 -0
- data/spec/{util_spec.rb → evented-spec/util_spec.rb} +0 -0
- data/spec/{failing_rspec_spec.rb → integration/failing_rspec_spec.rb} +1 -1
- data/spec/spec_helper.rb +18 -9
- data/tasks/spec.rake +7 -2
- metadata +44 -24
- data/lib/evented-spec/rspec.rb +0 -267
- data/spec/cool_io_spec.rb +0 -72
- data/spec/rspec_amqp_spec.rb +0 -116
- data/spec/rspec_em_spec.rb +0 -53
- data/spec/shared_examples.rb +0 -194
data/HISTORY
CHANGED
@@ -94,4 +94,11 @@
|
|
94
94
|
|
95
95
|
* Forked into evented-spec.
|
96
96
|
* cool.io support
|
97
|
-
* Using amqp 0.8.* API instead of 0.7.*
|
97
|
+
* Using amqp 0.8.* API instead of 0.7.*
|
98
|
+
|
99
|
+
== 0.4.1 / 2011-04-29
|
100
|
+
|
101
|
+
* More cool.io goodies:
|
102
|
+
* EventedSpec::CoolioSpec module similar to EMSpec and AMQPSpec
|
103
|
+
* coolio_before / coolio_after hooks
|
104
|
+
* #delayed helper
|
data/README.textile
CHANGED
@@ -4,7 +4,7 @@ Evented-spec is a set of helpers to help you test your asynchronous code.
|
|
4
4
|
|
5
5
|
EventMachine/Cool.io-based code, including asynchronous "AMQP library":https://github.com/ruby-amqp/ruby-amqp is notoriously difficult to test. To the point that many people recommend using either "mocks":https://github.com/danielsdeleo/moqueue or "synchronous libraries":https://github.com/ruby-amqp/bunny instead of EM-based libraries in unit tests. This is not always an option, however -- sometimes your code just has to run inside the event loop, and you want to test a real thing, not just mocks.
|
6
6
|
|
7
|
-
"em-spec":https://github.com/tmm1/em-spec gem made it easier to write evented specs, but it
|
7
|
+
"em-spec":https://github.com/tmm1/em-spec gem made it easier to write evented specs, but it had several drawbacks. First, it is not easy to manage both EM.run and AMQP.start loops at the same time. Second, AMQP is not properly stopped and deactivated upon exceptions and timeouts, resulting in state leak between examples and multiple mystereous failures. amqp-spec, and, subsequently, evented-spec add more helpers to keep your specs from being bloated.
|
8
8
|
|
9
9
|
h2. Usage
|
10
10
|
|
@@ -47,7 +47,7 @@ h3. EventedSpec::SpecHelper
|
|
47
47
|
|
48
48
|
All three accept a hash of options. Look into method documentation to learn more.
|
49
49
|
|
50
|
-
h3. EventedSpec::EMSpec, EventedSpec::AMQPSpec
|
50
|
+
h3. EventedSpec::EMSpec, EventedSpec::AMQPSpec, EventedSpec::CoolioSpec
|
51
51
|
|
52
52
|
@EventedSpec::EMSpec@ wraps every example in em block, so it might save you a couple of lines per example. @EventedSpec::AMQPSpec@ wraps every example in amqp block.
|
53
53
|
|
@@ -83,17 +83,21 @@ end
|
|
83
83
|
|
84
84
|
h2. Hooks
|
85
85
|
|
86
|
-
There are
|
86
|
+
There are 6 hooks available to evented specs:
|
87
87
|
|
88
88
|
* @em_before@ -- launches after reactor started, before example runs
|
89
89
|
* @em_after@ -- launches right before reactor is stopped, after example runs
|
90
90
|
* @amqp_before@ -- launches after amqp connects, before example runs
|
91
91
|
* @amqp_after@ -- launches before amqp disconnects, after example runs
|
92
|
+
* @coolio_before@ -- launches after Cool.io starts, before example runs
|
93
|
+
* @coolio_after@ -- launches before Cool.io stops, after example runs
|
92
94
|
|
93
|
-
So, the order of hooks is as follows: @before(:all)@, @before(:each)@,
|
95
|
+
So, the order of hooks for an AMQP spec is as follows: @before(:all)@, @before(:each)@,
|
94
96
|
@em_before@, @amqp_before@, example, @amqp_after@, @em_after@, @after(:each)@,
|
95
97
|
@after(:all)@
|
96
98
|
|
99
|
+
|
100
|
+
|
97
101
|
bc. describe "using amqp hooks" do
|
98
102
|
include EventedSpec::AMQPSpec
|
99
103
|
default_timeout 0.5
|
@@ -117,10 +121,6 @@ bc. describe "using amqp hooks" do
|
|
117
121
|
end
|
118
122
|
end
|
119
123
|
|
120
|
-
h2. AMQP gem compatibility
|
121
|
-
|
122
|
-
AMQP spec helpers are for newer version of AMQP gem, 0.8. If you need spec-helpers for AMQP gem 0.7, take a look at "amqp-spec":https://github.com/ruby-amqp/amqp-spec, API is mostly the same.
|
123
|
-
|
124
124
|
h2. Words of warning on blocking the reactor
|
125
125
|
|
126
126
|
Evented specs are currently run inside of reactor thread. What this effectively means is that you *should not block* during spec execution.
|
@@ -149,6 +149,48 @@ bc. describe "using amqp" do
|
|
149
149
|
end
|
150
150
|
end
|
151
151
|
|
152
|
+
You can also use #delayed helper method to maintain order of execution when callbacks are not an option.
|
153
|
+
|
154
|
+
bc. describe "using amqp" do
|
155
|
+
include EventedSpec::AMQPSpec
|
156
|
+
it "should do something useful" do
|
157
|
+
channel = AMQP::Channel.new
|
158
|
+
@stage = 0
|
159
|
+
delayed(0.2) {
|
160
|
+
channel.should be_open
|
161
|
+
@stage = 1
|
162
|
+
}
|
163
|
+
delayed(0.3) {
|
164
|
+
@stage.should == 1
|
165
|
+
done
|
166
|
+
}
|
167
|
+
delayed(0.4) {
|
168
|
+
# this block is never going to be executed
|
169
|
+
raise "Help me!"
|
170
|
+
}
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
|
175
|
+
h2. I have an existing reactor running in separate thread, amqp specs won't work for me what should I do?
|
176
|
+
|
177
|
+
Unfortunately, right now there aren't many remedies to your problem, besides stopping the event loop in before(:all) hook like this:
|
178
|
+
|
179
|
+
bc. describe "Example" do
|
180
|
+
before(:all) { EM.stop_event_loop; sleep(0.1) }
|
181
|
+
after(:all) { do_something_to_restart_the_eventmachine }
|
182
|
+
include EventedSpec::SpecHelper
|
183
|
+
it "should do something" do
|
184
|
+
em { done }
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
Reason is simple: if we don't restart event loop every spec example, all kinds of state leaks may occur: stale timers, delayed exceptions, weirdest errors and even segfaults. It isn't impossible but it certainly is very invasive.
|
189
|
+
|
190
|
+
h2. Compatibility
|
191
|
+
|
192
|
+
EventedSpec is tested with RSpec >= 2.5.0, Cool.io ~> 1.0.0, EventMachine >= 0.12.10, and AMQP >= 0.8.0. Running it with RSpec 1.3 and/or AMQP 0.7.0 is not unheard of, although not tested in all its entirety.
|
193
|
+
|
152
194
|
h2. See also
|
153
195
|
|
154
196
|
You can see evented-spec in use in spec suites for our amqp gems, "amq-client":https://github.com/ruby-amqp/amq-client/tree/master/spec and "amqp":https://github.com/ruby-amqp/amqp/tree/master/spec.
|
@@ -159,4 +201,4 @@ h2. Links
|
|
159
201
|
* "amqp-spec":https://github.com/ruby-amqp/amqp-spec
|
160
202
|
* "eventmachine":http://eventmachine.rubyforge.org/
|
161
203
|
* "amqp":https://github.com/ruby-amqp/amqp
|
162
|
-
* "amq-client":https://github.com/ruby-amqp/amq-client
|
204
|
+
* "amq-client":https://github.com/ruby-amqp/amq-client
|
data/Rakefile
CHANGED
@@ -1,14 +1,13 @@
|
|
1
1
|
require 'pathname'
|
2
|
-
NAME = '
|
2
|
+
NAME = 'evented-spec'
|
3
3
|
BASE_PATH = Pathname.new(__FILE__).dirname
|
4
4
|
LIB_PATH = BASE_PATH + 'lib'
|
5
5
|
PKG_PATH = BASE_PATH + 'pkg'
|
6
6
|
DOC_PATH = BASE_PATH + 'rdoc'
|
7
7
|
|
8
8
|
$LOAD_PATH.unshift LIB_PATH.to_s
|
9
|
-
require '
|
10
|
-
|
11
|
-
CLASS_NAME = EventedSpec::AMQPSpec
|
9
|
+
require 'evented-spec'
|
10
|
+
CLASS_NAME = EventedSpec
|
12
11
|
VERSION = CLASS_NAME::VERSION
|
13
12
|
|
14
13
|
begin
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.4.
|
1
|
+
0.4.1
|
data/lib/evented-spec.rb
CHANGED
@@ -1,2 +1,23 @@
|
|
1
|
+
# There's little to no point in requiring only subset of evented-spec code yet,
|
2
|
+
# but in case you really want to, it won't stand in your way.
|
3
|
+
|
4
|
+
# These files are required
|
5
|
+
require 'evented-spec/util'
|
1
6
|
require 'evented-spec/version'
|
2
|
-
require
|
7
|
+
require 'evented-spec/evented_example'
|
8
|
+
require 'evented-spec/spec_helper'
|
9
|
+
|
10
|
+
# As of now, amqp depends on em, em doesn't depend on anyone and
|
11
|
+
# neither does coolio.
|
12
|
+
# Pick the files accordingly.
|
13
|
+
require 'evented-spec/evented_example/em_example'
|
14
|
+
require 'evented-spec/evented_example/amqp_example'
|
15
|
+
require 'evented-spec/evented_example/coolio_example'
|
16
|
+
|
17
|
+
require 'evented-spec/spec_helper/event_machine_helpers'
|
18
|
+
require 'evented-spec/spec_helper/amqp_helpers'
|
19
|
+
require 'evented-spec/spec_helper/coolio_helpers'
|
20
|
+
|
21
|
+
require 'evented-spec/em_spec'
|
22
|
+
require 'evented-spec/amqp_spec'
|
23
|
+
require 'evented-spec/coolio_spec'
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module EventedSpec
|
2
|
+
# If you include EventedSpec::AMQPSpec module into your example group, each example of this group
|
3
|
+
# will run inside AMQP.start loop without the need to explicitly call 'amqp'. In order
|
4
|
+
# to provide options to AMQP loop, default_options class method is defined. Remember,
|
5
|
+
# when using EventedSpec::Specs, you'll have a single set of AMQP.start options for all your
|
6
|
+
# examples.
|
7
|
+
#
|
8
|
+
module AMQPSpec
|
9
|
+
def self.included(example_group)
|
10
|
+
example_group.send(:include, SpecHelper)
|
11
|
+
example_group.extend(ClassMethods)
|
12
|
+
end
|
13
|
+
|
14
|
+
# @private
|
15
|
+
module ClassMethods
|
16
|
+
def it(*args, &block)
|
17
|
+
if block
|
18
|
+
new_block = Proc.new {|example_group_instance| (example_group_instance || self).instance_eval { amqp(&block) } }
|
19
|
+
super(*args, &new_block)
|
20
|
+
else
|
21
|
+
# pending example
|
22
|
+
super
|
23
|
+
end
|
24
|
+
end # it
|
25
|
+
end # ClassMethods
|
26
|
+
end # AMQPSpec
|
27
|
+
end # module EventedSpec
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module EventedSpec
|
2
|
+
# Including EventedSpec::CoolioSpec module into your example group, each example of this group
|
3
|
+
# will run inside cool.io loop without the need to explicitly call 'coolio'.
|
4
|
+
#
|
5
|
+
module CoolioSpec
|
6
|
+
def self.included(example_group)
|
7
|
+
example_group.send(:include, SpecHelper)
|
8
|
+
example_group.extend ClassMethods
|
9
|
+
end
|
10
|
+
|
11
|
+
# @private
|
12
|
+
module ClassMethods
|
13
|
+
def it(*args, &block)
|
14
|
+
if block
|
15
|
+
# Shared example groups seem to pass example group instance
|
16
|
+
# to the actual example block
|
17
|
+
new_block = Proc.new {|example_group_instance| (example_group_instance || self).instance_eval { coolio(&block) } }
|
18
|
+
super(*args, &new_block)
|
19
|
+
else
|
20
|
+
# pending example
|
21
|
+
super
|
22
|
+
end
|
23
|
+
end # it
|
24
|
+
end # ClassMethods
|
25
|
+
end # EMSpec
|
26
|
+
end # module EventedSpec
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module EventedSpec
|
2
|
+
# Including EventedSpec::EMSpec module into your example group, each example of this group
|
3
|
+
# will run inside EM.run loop without the need to explicitly call 'em'.
|
4
|
+
#
|
5
|
+
module EMSpec
|
6
|
+
def self.included(example_group)
|
7
|
+
example_group.send(:include, SpecHelper)
|
8
|
+
example_group.extend ClassMethods
|
9
|
+
end
|
10
|
+
|
11
|
+
# @private
|
12
|
+
module ClassMethods
|
13
|
+
def it(*args, &block)
|
14
|
+
if block
|
15
|
+
# Shared example groups seem to pass example group instance
|
16
|
+
# to the actual example block
|
17
|
+
new_block = Proc.new {|example_group_instance| (example_group_instance || self).instance_eval { em(&block) } }
|
18
|
+
super(*args, &new_block)
|
19
|
+
else
|
20
|
+
# pending example
|
21
|
+
super
|
22
|
+
end
|
23
|
+
end # it
|
24
|
+
end # ClassMethods
|
25
|
+
end # EMSpec
|
26
|
+
end # module EventedSpec
|
@@ -7,7 +7,7 @@ module EventedSpec
|
|
7
7
|
class EventedExample
|
8
8
|
# Default options to use with the examples
|
9
9
|
DEFAULT_OPTIONS = {
|
10
|
-
:spec_timeout =>
|
10
|
+
:spec_timeout => 5
|
11
11
|
}
|
12
12
|
|
13
13
|
# Create new evented example
|
@@ -15,6 +15,16 @@ module EventedSpec
|
|
15
15
|
@opts, @example_group_instance, @block = DEFAULT_OPTIONS.merge(opts), example_group_instance, block
|
16
16
|
end
|
17
17
|
|
18
|
+
# Runs hooks of specified type (hopefully, inside event loop)
|
19
|
+
#
|
20
|
+
# @param hook type
|
21
|
+
def run_hooks(type)
|
22
|
+
@example_group_instance.class.evented_spec_hooks_for(type).each do |hook|
|
23
|
+
@example_group_instance.instance_eval(&hook)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
|
18
28
|
# Called from #run_event_loop when event loop is stopped,
|
19
29
|
# but before the example returns.
|
20
30
|
# Descendant classes may redefine to clean up type-specific state.
|
@@ -47,6 +57,8 @@ module EventedSpec
|
|
47
57
|
|
48
58
|
# Override this method in your descendants
|
49
59
|
#
|
60
|
+
# @note block should be evaluated in EventedExample descendant instance context
|
61
|
+
# (e.g. in EMExample instance)
|
50
62
|
# @note delay may be nil, implying you need to execute the block immediately.
|
51
63
|
# @abstract
|
52
64
|
def delayed(delay = nil, &block)
|
@@ -55,7 +67,3 @@ module EventedSpec
|
|
55
67
|
end # class EventedExample
|
56
68
|
end # module SpecHelper
|
57
69
|
end # module AMQP
|
58
|
-
|
59
|
-
require 'evented-spec/evented_example/em_example'
|
60
|
-
require 'evented-spec/evented_example/amqp_example'
|
61
|
-
require 'evented-spec/evented_example/coolio_example'
|
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'evented-spec/ext/amqp'
|
1
2
|
module EventedSpec
|
2
3
|
module SpecHelper
|
3
4
|
# Represents spec running inside AMQP.start loop
|
@@ -7,8 +8,8 @@ module EventedSpec
|
|
7
8
|
# See {EventedExample#run}
|
8
9
|
def run
|
9
10
|
run_em_loop do
|
10
|
-
AMQP.start_connection(@opts) do
|
11
|
-
|
11
|
+
::AMQP.start_connection(@opts) do
|
12
|
+
run_hooks :amqp_before
|
12
13
|
@example_group_instance.instance_eval(&@block)
|
13
14
|
end
|
14
15
|
end
|
@@ -22,9 +23,9 @@ module EventedSpec
|
|
22
23
|
delayed(delay) do
|
23
24
|
yield if block_given?
|
24
25
|
EM.next_tick do
|
25
|
-
|
26
|
-
if AMQP.connection &&
|
27
|
-
AMQP.stop_connection do
|
26
|
+
run_hooks :amqp_after
|
27
|
+
if ::AMQP.connection && !::AMQP.closing?
|
28
|
+
::AMQP.stop_connection do
|
28
29
|
# Cannot call finish_em_loop before connection is marked as closed
|
29
30
|
# This callback is called before that happens.
|
30
31
|
EM.next_tick { finish_em_loop }
|
@@ -32,7 +33,7 @@ module EventedSpec
|
|
32
33
|
else
|
33
34
|
# Need this branch because if AMQP couldn't connect,
|
34
35
|
# the callback would never trigger
|
35
|
-
AMQP.cleanup_state
|
36
|
+
::AMQP.cleanup_state
|
36
37
|
EM.next_tick { finish_em_loop }
|
37
38
|
end
|
38
39
|
end
|
@@ -44,7 +45,7 @@ module EventedSpec
|
|
44
45
|
#
|
45
46
|
# See {EventedExample#run}
|
46
47
|
def finish_example
|
47
|
-
AMQP.cleanup_state
|
48
|
+
::AMQP.cleanup_state
|
48
49
|
super
|
49
50
|
end
|
50
51
|
end # class AMQPExample < EventedExample
|
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'evented-spec/ext/coolio'
|
1
2
|
#
|
2
3
|
# Cool.io loop is a little bit trickier to test, since it
|
3
4
|
# doesn't go into a loop if there are no watchers.
|
@@ -14,6 +15,7 @@ module EventedSpec
|
|
14
15
|
reset
|
15
16
|
delayed(0) do
|
16
17
|
begin
|
18
|
+
run_hooks :coolio_before
|
17
19
|
@example_group_instance.instance_eval(&@block)
|
18
20
|
rescue Exception => e
|
19
21
|
@spec_exception ||= e
|
@@ -43,6 +45,7 @@ module EventedSpec
|
|
43
45
|
|
44
46
|
# Stops the loop and finalizes the example
|
45
47
|
def finish_loop
|
48
|
+
run_hooks :coolio_after
|
46
49
|
default_loop.stop
|
47
50
|
finish_example
|
48
51
|
end
|
@@ -77,21 +80,4 @@ module EventedSpec
|
|
77
80
|
end
|
78
81
|
end # class CoolioExample
|
79
82
|
end # module SpecHelper
|
80
|
-
end # module EventedSpec
|
81
|
-
|
82
|
-
# Cool.io provides no means to change the default loop which makes sense in
|
83
|
-
# most situations, but not ours.
|
84
|
-
#
|
85
|
-
# @private
|
86
|
-
module Coolio
|
87
|
-
class Loop
|
88
|
-
# Sets cool.io default loop.
|
89
|
-
def self.default_loop=(event_loop)
|
90
|
-
if RUBY_VERSION >= "1.9.0"
|
91
|
-
Thread.current.instance_variable_set :@_coolio_loop, event_loop
|
92
|
-
else
|
93
|
-
@@_coolio_loop = event_loop
|
94
|
-
end
|
95
|
-
end
|
96
|
-
end
|
97
|
-
end
|
83
|
+
end # module EventedSpec
|
@@ -3,13 +3,6 @@ module EventedSpec
|
|
3
3
|
# Represents spec running inside EM.run loop.
|
4
4
|
# See {EventedExample} for details and method descriptions.
|
5
5
|
class EMExample < EventedExample
|
6
|
-
# Runs hooks of specified type (hopefully, inside the event loop)
|
7
|
-
def run_em_hooks(type)
|
8
|
-
@example_group_instance.class.em_hooks[type].each do |hook|
|
9
|
-
@example_group_instance.instance_eval(&hook) #_with_rescue(&hook)
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
6
|
# Runs given block inside EM event loop.
|
14
7
|
# Double-round exception handler needed because some of the exceptions bubble
|
15
8
|
# outside of event loop due to asynchronous nature of evented examples
|
@@ -17,7 +10,7 @@ module EventedSpec
|
|
17
10
|
def run_em_loop
|
18
11
|
begin
|
19
12
|
EM.run do
|
20
|
-
|
13
|
+
run_hooks :em_before
|
21
14
|
|
22
15
|
@spec_exception = nil
|
23
16
|
timeout(@opts[:spec_timeout]) if @opts[:spec_timeout]
|
@@ -32,7 +25,7 @@ module EventedSpec
|
|
32
25
|
rescue Exception => e
|
33
26
|
@spec_exception ||= e
|
34
27
|
# p "Outside loop, caught #{@spec_exception.class.name}: #{@spec_exception}"
|
35
|
-
|
28
|
+
run_hooks :em_after # Event loop broken, but we still need to run em_after hooks
|
36
29
|
ensure
|
37
30
|
finish_example
|
38
31
|
end
|
@@ -41,7 +34,7 @@ module EventedSpec
|
|
41
34
|
# Stops EM event loop. It is called from #done
|
42
35
|
#
|
43
36
|
def finish_em_loop
|
44
|
-
|
37
|
+
run_hooks :em_after
|
45
38
|
EM.stop_event_loop if EM.reactor_running?
|
46
39
|
end
|
47
40
|
|
@@ -76,10 +69,11 @@ module EventedSpec
|
|
76
69
|
|
77
70
|
# See {EventedExample#delayed}
|
78
71
|
def delayed(delay, &block)
|
72
|
+
instance = self
|
79
73
|
if delay
|
80
|
-
EM.add_timer delay, &block
|
74
|
+
EM.add_timer delay, Proc.new { instance.instance_eval(&block) }
|
81
75
|
else
|
82
|
-
|
76
|
+
instance.instance_eval(&block)
|
83
77
|
end
|
84
78
|
end # delayed
|
85
79
|
end # class EMExample < EventedExample
|
@@ -1,8 +1,31 @@
|
|
1
1
|
# Monkey patching some methods into AMQP to make it more testable
|
2
|
+
module EventedSpec
|
3
|
+
module AMQPBackports
|
4
|
+
def self.included(base)
|
5
|
+
base.extend ClassMethods
|
6
|
+
end # self.included
|
7
|
+
|
8
|
+
module ClassMethods
|
9
|
+
def connection
|
10
|
+
@conn
|
11
|
+
end # connection
|
12
|
+
|
13
|
+
def connection=(new_connection)
|
14
|
+
@conn = new_connection
|
15
|
+
end # connection=
|
16
|
+
end # module ClassMethods
|
17
|
+
end # module AMQPBackports
|
18
|
+
end # module EventedSpec
|
19
|
+
|
2
20
|
module AMQP
|
3
21
|
# Initializes new AMQP client/connection without starting another EM loop
|
4
22
|
def self.start_connection(opts={}, &block)
|
5
|
-
|
23
|
+
if amqp_pre_08?
|
24
|
+
self.connection = connect opts
|
25
|
+
self.connection.callback &block
|
26
|
+
else
|
27
|
+
self.connection = connect opts, &block
|
28
|
+
end
|
6
29
|
end
|
7
30
|
|
8
31
|
# Closes AMQP connection gracefully
|
@@ -24,4 +47,10 @@ module AMQP
|
|
24
47
|
self.connection = nil
|
25
48
|
@closing = false
|
26
49
|
end
|
27
|
-
|
50
|
+
|
51
|
+
def self.amqp_pre_08?
|
52
|
+
AMQP::VERSION < "0.8"
|
53
|
+
end # self.amqp_pre_08?
|
54
|
+
|
55
|
+
include EventedSpec::AMQPBackports
|
56
|
+
end
|