amqp-spec 0.2.1 → 0.2.3

Sign up to get free protection for your applications and to get access to all the features.
data/HISTORY CHANGED
@@ -57,3 +57,11 @@
57
57
  == 0.2.1 / 2010-10-28
58
58
 
59
59
  * RSpec2-specific examples added
60
+
61
+ == 0.2.2 / 2010-10-31
62
+
63
+ * Metadata in Rspec 1
64
+
65
+ == 0.2.3 / 2010-10-31
66
+
67
+ * Documentation cleaned up
@@ -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
- RSpec 1:: Default options and default timeout are global across all groups, it is impossible to have separate
39
- defaults for separate groups.
40
- RSpec 2:: Default options and default timeout are local for each example group and inherited by its nested groups,
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
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
@@ -1,95 +1,83 @@
1
1
  require 'fiber' unless Fiber.respond_to?(:current)
2
- require 'mq'
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 'ampq' method that can be safely used inside your specs(examples)
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
- # In order to stop AMQP loop, you should call 'done' AFTER you are sure that your example is finished.
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
- # Initializes new AMQP client/connection without starting another EM loop
27
- def self.start_connection(opts={}, &block)
28
- # puts "!!!!!!!!! Existing connection: #{@conn}" if @conn
29
- @conn = connect opts
30
- @conn.callback(&block) if block
31
- end
32
-
33
- # Closes AMQP connection and raises optional exception AFTER the AMQP connection is 100% closed
34
- def self.stop_connection
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
- def self.included(example_group)
58
-
59
- extended_class = defined?(RSpec) ? example_group : ::Spec::Example::ExampleGroup
60
- unless extended_class.respond_to? :default_timeout
61
- extended_class.instance_exec do
62
- if defined?(RSpec)
63
- metadata[:em_default_options] = {}
64
- metadata[:em_default_timeout] = nil
65
-
66
- def self.default_timeout(spec_timeout=nil)
67
- metadata[:em_default_timeout] = spec_timeout if spec_timeout
68
- metadata[:em_default_timeout]
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
- def self.default_options(opts=nil)
72
- metadata[:em_default_options] = opts if opts
73
- metadata[:em_default_options]
74
- end
75
- else
76
- @@_em_default_options = {}
77
- @@_em_default_timeout = nil
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
- def self.default_timeout(spec_timeout=nil)
80
- @@_em_default_timeout = spec_timeout if spec_timeout
81
- @@_em_default_timeout
82
- end
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
- def self.default_options(opts=nil)
85
- @@_em_default_options = opts if opts
86
- @@_em_default_options
87
- end
88
- end
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 = opts.delete(:spec_timeout) || self.class.default_timeout
98
+ spec_timeout = opts.delete(:spec_timeout) || self.class.default_timeout
111
99
  timeout(spec_timeout) if spec_timeout
112
- @_em_spec_fiber = Fiber.new do
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 = Fiber.new do
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 spec
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(cls)
207
- cls.send(:include, SpecHelper)
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(cls)
219
- cls.send(:include, SpecHelper)
222
+ def self.included(example_group)
223
+ example_group.send(:include, SpecHelper)
220
224
  end
221
225
 
222
226
  def instance_eval(&block)
@@ -9,7 +9,7 @@ shared_examples_for 'SpecHelper examples' do
9
9
  end
10
10
 
11
11
  it "should properly work" do
12
- amqp { done}
12
+ amqp { done }
13
13
  end
14
14
 
15
15
  it "should have timers" do
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: 21
4
+ hash: 17
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 2
9
- - 1
10
- version: 0.2.1
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-28 00:00:00 +04:00
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