amqp-spec 0.2.1 → 0.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/HISTORY +8 -0
- data/README.rdoc +3 -9
- data/VERSION +1 -1
- data/lib/amqp-spec/amqp.rb +32 -0
- data/lib/amqp-spec/rspec.rb +81 -77
- data/spec/shared_examples.rb +1 -1
- metadata +5 -4
data/HISTORY
CHANGED
data/README.rdoc
CHANGED
@@ -35,10 +35,9 @@ You then use either 'amqp' or 'em' methods to wrap your evented test code. Insid
|
|
35
35
|
macros to avoid manually setting AMQP options in each example. However, if you DO manually set options inside
|
36
36
|
the example, they override the defaults.
|
37
37
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
different example groups can have separate defaults.
|
38
|
+
Default options and default timeout are local for each example group and inherited by its nested groups,
|
39
|
+
different example groups can have separate defaults. Please note that this is different from em-spec where
|
40
|
+
default_timeout is effectively a global setting.
|
42
41
|
|
43
42
|
require "amqp-spec/rspec"
|
44
43
|
describe AMQP do
|
@@ -96,11 +95,6 @@ inside the EM loop but before/after AMQP loop (these hooks are currently not imp
|
|
96
95
|
describe AMQP do
|
97
96
|
include AMQP::Spec
|
98
97
|
|
99
|
-
before(:each) do
|
100
|
-
puts EM.reactor_running?
|
101
|
-
done
|
102
|
-
end
|
103
|
-
|
104
98
|
it "requires a call to #done in every example" do
|
105
99
|
1.should == 1
|
106
100
|
done
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.2.
|
1
|
+
0.2.3
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'mq'
|
2
|
+
|
3
|
+
module AMQP
|
4
|
+
|
5
|
+
# Initializes new AMQP client/connection without starting another EM loop
|
6
|
+
def self.start_connection(opts={}, &block)
|
7
|
+
# puts "!!!!!!!!! Existing connection: #{@conn}" if @conn
|
8
|
+
@conn = connect opts
|
9
|
+
@conn.callback(&block) if block
|
10
|
+
end
|
11
|
+
|
12
|
+
# Closes AMQP connection gracefully
|
13
|
+
def self.stop_connection
|
14
|
+
if AMQP.conn and not AMQP.closing
|
15
|
+
# MQ.reset ?
|
16
|
+
@closing = true
|
17
|
+
@conn.close {
|
18
|
+
yield if block_given?
|
19
|
+
cleanup_state
|
20
|
+
}
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
# Cleans up AMQP state after AMQP connection closes
|
25
|
+
def self.cleanup_state
|
26
|
+
# MQ.reset ?
|
27
|
+
Thread.current[:mq] = nil
|
28
|
+
Thread.current[:mq_id] = nil
|
29
|
+
@conn = nil
|
30
|
+
@closing = false
|
31
|
+
end
|
32
|
+
end
|
data/lib/amqp-spec/rspec.rb
CHANGED
@@ -1,95 +1,83 @@
|
|
1
1
|
require 'fiber' unless Fiber.respond_to?(:current)
|
2
|
-
require '
|
2
|
+
require 'amqp-spec/amqp'
|
3
3
|
|
4
4
|
# You can include one of the following modules into your example groups:
|
5
|
-
# AMQP::SpecHelper
|
6
|
-
# AMQP::Spec
|
5
|
+
# AMQP::SpecHelper,
|
6
|
+
# AMQP::Spec,
|
7
|
+
# AMQP::EMSpec.
|
7
8
|
#
|
8
|
-
# AMQP::SpecHelper module defines
|
9
|
+
# AMQP::SpecHelper module defines #ampq method that can be safely used inside your specs(examples)
|
9
10
|
# to test expectations inside running AMQP.start loop. Each loop is running in a separate Fiber,
|
10
|
-
# and you can control for timeouts using either :spec_timeout option given to amqp method,
|
11
|
-
# or setting default timeout with class method default_timeout(timeout).
|
11
|
+
# and you can control for timeouts using either :spec_timeout option given to #amqp method,
|
12
|
+
# or setting default timeout with class method default_timeout(timeout). In addition to #amqp
|
13
|
+
# method, you can use #em method - it creates plain EM.run loop without starting AMQP.
|
12
14
|
#
|
13
15
|
# If you include AMQP::Spec module into your example group, each example of this group will run
|
14
16
|
# inside AMQP.start loop without the need to explicitly call 'amqp'. In order to provide options
|
15
17
|
# to AMQP loop, default_options class method is defined. Remember, when using AMQP::Specs, you
|
16
18
|
# will have a single set of AMQP.start options for all your examples.
|
17
19
|
#
|
18
|
-
#
|
20
|
+
# Including AMQP::EMSpec module into your example group, each example of this group will run
|
21
|
+
# inside EM.run loop without the need to explicitly call 'em'.
|
22
|
+
#
|
23
|
+
# In order to stop AMQP/EM loop, you should call 'done' AFTER you are sure that your example is finished.
|
19
24
|
# For example, if you are using subscribe block that tests expectations on messages, 'done' should be
|
20
25
|
# probably called at the end of this block.
|
21
26
|
#
|
22
|
-
# TODO: Define 'async' method wrapping async requests and returning results... 'async_loop' too for subscribe block?
|
23
|
-
# TODO: 'evented_before', 'evented_after' that will be run inside EM before the example
|
24
27
|
module AMQP
|
25
|
-
|
26
|
-
#
|
27
|
-
|
28
|
-
#
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
#
|
34
|
-
|
35
|
-
if AMQP.conn and not AMQP.closing
|
36
|
-
# MQ.reset ?
|
37
|
-
@closing = true
|
38
|
-
@conn.close {
|
39
|
-
yield if block_given?
|
40
|
-
cleanup_state
|
41
|
-
}
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
def self.cleanup_state
|
46
|
-
# MQ.reset ?
|
47
|
-
Thread.current[:mq] = nil
|
48
|
-
Thread.current[:mq_id] = nil
|
49
|
-
@conn = nil
|
50
|
-
@closing = false
|
51
|
-
end
|
52
|
-
|
28
|
+
# AMQP::SpecHelper module defines #ampq method that can be safely used inside your specs(examples)
|
29
|
+
# to test expectations inside running AMQP.start loop. Each loop is running in a separate Fiber,
|
30
|
+
# and you can control for timeouts using either :spec_timeout option given to #amqp method,
|
31
|
+
# or setting default timeout with class method default_timeout(timeout). In addition to #amqp
|
32
|
+
# method, you can use #em method - it creates plain EM.run loop without starting AMQP.
|
33
|
+
#
|
34
|
+
# TODO: Define 'async' method wrapping async requests and returning results... 'async_loop' too for subscribe block?
|
35
|
+
# TODO: 'evented_before', 'evented_after' that will be run inside EM before the example
|
36
|
+
#
|
37
|
+
# noinspection RubyArgCount
|
53
38
|
module SpecHelper
|
54
39
|
|
55
40
|
SpecTimeoutExceededError = Class.new(RuntimeError)
|
56
41
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
unless
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
end
|
42
|
+
# Class methods (macros) for example group that includes SpecHelper
|
43
|
+
#
|
44
|
+
module GroupMethods
|
45
|
+
unless respond_to?(:metadata)
|
46
|
+
# Hacking in metadata into RSpec1 to imitate Rspec2's metadata.
|
47
|
+
# You can add to metadata Hash to pass options into examples and
|
48
|
+
# nested groups.
|
49
|
+
#
|
50
|
+
def metadata
|
51
|
+
@metadata ||= superclass.metadata.dup rescue {}
|
52
|
+
end
|
53
|
+
end
|
70
54
|
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
55
|
+
# Sets/retrieves default timeout for running evented specs for this
|
56
|
+
# example group and its nested groups.
|
57
|
+
#
|
58
|
+
def default_timeout(spec_timeout=nil)
|
59
|
+
metadata[:em_default_timeout] = spec_timeout if spec_timeout
|
60
|
+
metadata[:em_default_timeout]
|
61
|
+
end
|
78
62
|
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
63
|
+
# Sets/retrieves default AMQP.start options for this example group
|
64
|
+
# and its nested groups.
|
65
|
+
#
|
66
|
+
def default_options(opts=nil)
|
67
|
+
metadata[:em_default_options] = opts if opts
|
68
|
+
metadata[:em_default_options]
|
69
|
+
end
|
70
|
+
end
|
83
71
|
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
end
|
72
|
+
def self.included(example_group)
|
73
|
+
unless example_group.respond_to? :default_timeout
|
74
|
+
example_group.extend(GroupMethods)
|
75
|
+
example_group.metadata[:em_default_options] = {}
|
76
|
+
example_group.metadata[:em_default_timeout] = nil
|
90
77
|
end
|
91
78
|
end
|
92
79
|
|
80
|
+
|
93
81
|
# Yields to given block inside EM.run and AMQP.start loops. This method takes any option that is
|
94
82
|
# also accepted by EventMachine::connect. Also, options for AMQP.start include:
|
95
83
|
# * :user => String (default ‘guest’) - The username as defined by the AMQP server.
|
@@ -107,13 +95,12 @@ module AMQP
|
|
107
95
|
EM.run do
|
108
96
|
@_em_spec_with_amqp = true
|
109
97
|
@_em_spec_exception = nil
|
110
|
-
spec_timeout
|
98
|
+
spec_timeout = opts.delete(:spec_timeout) || self.class.default_timeout
|
111
99
|
timeout(spec_timeout) if spec_timeout
|
112
|
-
@_em_spec_fiber
|
100
|
+
@_em_spec_fiber = Fiber.new do
|
113
101
|
begin
|
114
102
|
AMQP.start_connection opts, &block
|
115
103
|
rescue Exception => @_em_spec_exception
|
116
|
-
# p "inner", @_em_spec_exception
|
117
104
|
done
|
118
105
|
end
|
119
106
|
Fiber.yield
|
@@ -122,7 +109,6 @@ module AMQP
|
|
122
109
|
@_em_spec_fiber.resume
|
123
110
|
end
|
124
111
|
rescue Exception => outer_spec_exception
|
125
|
-
# p "outer", outer_spec_exception unless outer_spec_exception.is_a? SpecTimeoutExceededError
|
126
112
|
# Make sure AMQP state is cleaned even after Rspec failures
|
127
113
|
AMQP.cleanup_state
|
128
114
|
raise outer_spec_exception
|
@@ -131,13 +117,14 @@ module AMQP
|
|
131
117
|
|
132
118
|
# Yields to block inside EM loop, :spec_timeout option (in seconds) is used to force spec to timeout
|
133
119
|
# if something goes wrong and EM/AMQP loop hangs for some reason. SpecTimeoutExceededError is raised.
|
120
|
+
#
|
134
121
|
def em(spec_timeout = self.class.default_timeout, &block)
|
135
122
|
spec_timeout = spec_timeout[:spec_timeout] || self.class.default_timeout if spec_timeout.is_a?(Hash)
|
136
123
|
EM.run do
|
137
124
|
@_em_spec_with_amqp = false
|
138
125
|
@_em_spec_exception = nil
|
139
126
|
timeout(spec_timeout) if spec_timeout
|
140
|
-
@_em_spec_fiber
|
127
|
+
@_em_spec_fiber = Fiber.new do
|
141
128
|
begin
|
142
129
|
block.call
|
143
130
|
rescue Exception => @_em_spec_exception
|
@@ -150,7 +137,8 @@ module AMQP
|
|
150
137
|
end
|
151
138
|
end
|
152
139
|
|
153
|
-
# Sets timeout for current
|
140
|
+
# Sets timeout for current running example
|
141
|
+
#
|
154
142
|
def timeout(spec_timeout)
|
155
143
|
EM.cancel_timer(@_em_timer) if @_em_timer
|
156
144
|
@_em_timer = EM.add_timer(spec_timeout) do
|
@@ -167,6 +155,7 @@ module AMQP
|
|
167
155
|
# You may pass delay (in seconds) to done. If you do so, please keep in mind
|
168
156
|
# that your (default or explicit) spec timeout may fire before your delayed done
|
169
157
|
# callback is due, leading to SpecTimeoutExceededError
|
158
|
+
#
|
170
159
|
def done(delay=nil)
|
171
160
|
done_proc = proc do
|
172
161
|
yield if block_given?
|
@@ -191,9 +180,16 @@ module AMQP
|
|
191
180
|
end
|
192
181
|
end
|
193
182
|
|
183
|
+
# Retrieves metadata passed in from enclosing example groups
|
184
|
+
#
|
185
|
+
def metadata
|
186
|
+
@metadata ||= self.class.metadata.dup rescue {}
|
187
|
+
end
|
188
|
+
|
194
189
|
private
|
195
190
|
|
196
191
|
# Stops EM loop, executes optional block, finishes off fiber and raises exception if any
|
192
|
+
#
|
197
193
|
def finish_em_spec_fiber
|
198
194
|
EM.stop_event_loop if EM.reactor_running?
|
199
195
|
yield if block_given?
|
@@ -202,9 +198,14 @@ module AMQP
|
|
202
198
|
end
|
203
199
|
end
|
204
200
|
|
201
|
+
# If you include AMQP::Spec module into your example group, each example of this group will run
|
202
|
+
# inside AMQP.start loop without the need to explicitly call 'amqp'. In order to provide options
|
203
|
+
# to AMQP loop, default_options class method is defined. Remember, when using AMQP::Specs, you
|
204
|
+
# will have a single set of AMQP.start options for all your examples.
|
205
|
+
#
|
205
206
|
module Spec
|
206
|
-
def self.included(
|
207
|
-
|
207
|
+
def self.included(example_group)
|
208
|
+
example_group.send(:include, SpecHelper)
|
208
209
|
end
|
209
210
|
|
210
211
|
def instance_eval(&block)
|
@@ -214,9 +215,12 @@ module AMQP
|
|
214
215
|
end
|
215
216
|
end
|
216
217
|
|
218
|
+
# Including AMQP::EMSpec module into your example group, each example of this group will run
|
219
|
+
# inside EM.run loop without the need to explicitly call 'em'.
|
220
|
+
#
|
217
221
|
module EMSpec
|
218
|
-
def self.included(
|
219
|
-
|
222
|
+
def self.included(example_group)
|
223
|
+
example_group.send(:include, SpecHelper)
|
220
224
|
end
|
221
225
|
|
222
226
|
def instance_eval(&block)
|
data/spec/shared_examples.rb
CHANGED
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: amqp-spec
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 17
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 2
|
9
|
-
-
|
10
|
-
version: 0.2.
|
9
|
+
- 3
|
10
|
+
version: 0.2.3
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Arvicco
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2010-10-
|
18
|
+
date: 2010-10-31 00:00:00 +04:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -61,6 +61,7 @@ extra_rdoc_files:
|
|
61
61
|
- HISTORY
|
62
62
|
- README.rdoc
|
63
63
|
files:
|
64
|
+
- lib/amqp-spec/amqp.rb
|
64
65
|
- lib/amqp-spec/rspec.rb
|
65
66
|
- lib/amqp-spec.rb
|
66
67
|
- lib/version.rb
|