amqp-spec 0.0.4
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/.gitignore +21 -0
- data/HISTORY +19 -0
- data/LICENSE +20 -0
- data/README.rdoc +169 -0
- data/Rakefile +24 -0
- data/VERSION +1 -0
- data/lib/amqp-spec.rb +27 -0
- data/lib/amqp-spec/rspec.rb +195 -0
- data/lib/version.rb +10 -0
- data/spec/amqp.yml +28 -0
- data/spec/failing_rspec_spec.rb +62 -0
- data/spec/rspec_amqp_spec.rb +273 -0
- data/spec/rspec_em_spec.rb +67 -0
- data/spec/spec.opts +2 -0
- data/spec/spec_helper.rb +35 -0
- data/tasks/common.rake +18 -0
- data/tasks/doc.rake +14 -0
- data/tasks/gem.rake +40 -0
- data/tasks/git.rake +34 -0
- data/tasks/spec.rake +19 -0
- data/tasks/version.rake +71 -0
- metadata +114 -0
data/.gitignore
ADDED
data/HISTORY
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
== 0.0.0 / 2010-10-13
|
2
|
+
|
3
|
+
* Birthday!
|
4
|
+
|
5
|
+
== 0.0.1 / 2010-10-13
|
6
|
+
|
7
|
+
* Initial code import from EM-Spec and AMQPHelper
|
8
|
+
|
9
|
+
== 0.0.2 / 2010-10-13
|
10
|
+
|
11
|
+
* Minimal functionality implemented
|
12
|
+
|
13
|
+
== 0.0.3 / 2010-10-13
|
14
|
+
|
15
|
+
* Bunch of non-working specs added
|
16
|
+
|
17
|
+
== 0.0.4 / 2010-10-14
|
18
|
+
|
19
|
+
* Problems with default_options resolved
|
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2010 Arvicco
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,169 @@
|
|
1
|
+
= amqp-spec
|
2
|
+
by: Arvicco
|
3
|
+
url: http://github.com/arvicco/amqp-spec
|
4
|
+
|
5
|
+
== Summary
|
6
|
+
|
7
|
+
Simple API for testing asynchronous EventMachine/AMQP code.
|
8
|
+
|
9
|
+
== Description
|
10
|
+
|
11
|
+
EventMachine-based code, including synchronous {AMQP library}[http://github.com/tmm1/amqp] is
|
12
|
+
notoriously difficult to test. To the point that many people recommend using either
|
13
|
+
Mocks[http://github.com/danielsdeleo/moqueue] or {synchronous libraries}[http://github.com/celldee/bunny]
|
14
|
+
instead of EM-based libraries in unit tests. This is not always an option, however - sometimes your code
|
15
|
+
is supposed to run inside event loop, and you want to test a real thing, not mocks.
|
16
|
+
|
17
|
+
EM-Spec[http://github.com/tmm1/em-spec] gem made it easier to write evented specs, but it has several drawbacks.
|
18
|
+
First, it is not easy to manage both EM.run and AMQP.start loops at the same time. Second, AMQP is not
|
19
|
+
properly stopped and deactivated upon exceptions and timeouts, resulting in AMQP library state leak
|
20
|
+
between examples and multiple mystereous failures.
|
21
|
+
|
22
|
+
AMQP-Spec is built upon EM-Spec code but makes it easier to test AMQP event loops specifically. API is
|
23
|
+
very similar to EM-Spec, only a bit extended. The final goal is to make writing AMQP specs reasonably
|
24
|
+
pleasant experience and dispel the notion that evented AMQP-based libs are impossible to unit-test.
|
25
|
+
|
26
|
+
Mind you, you still have to properly manage your AMQP broker in order to prevent broker state from leaking
|
27
|
+
between examples. You can try to combine AMQP-Spec and Moqueue[http://github.com/danielsdeleo/moqueue]
|
28
|
+
if you want to abstract away actual broker interactions, but still specify some event-based expectations.
|
29
|
+
|
30
|
+
==Rspec
|
31
|
+
There are several ways to use amqp-spec. To use it as a helper, include AMQP::SpecHelper in your describe block.
|
32
|
+
You then use either 'amqp' or 'em' methods to wrap your evented test code. Inside the amqp/em block, you must call
|
33
|
+
#done after your expectations. Everything works normally otherwise. You can use default_timeout and default_options
|
34
|
+
macros to avoid manually setting AMQP options in each example. However, if you DO manually set options inside
|
35
|
+
the example, they override the defaults. Only one set of default options and default timeout is used across groups,
|
36
|
+
it is not possible to have separate defaults for separate groups.
|
37
|
+
|
38
|
+
require "amqp-spec/rspec"
|
39
|
+
describe AMQP do
|
40
|
+
include AMQP::SpecHelper
|
41
|
+
|
42
|
+
before(:each) do
|
43
|
+
puts EM.reactor_running?
|
44
|
+
end
|
45
|
+
|
46
|
+
it "works normally when not using #amqp or #em" do
|
47
|
+
1.should == 1
|
48
|
+
end
|
49
|
+
|
50
|
+
it "makes testing evented code easy with #em" do
|
51
|
+
em do
|
52
|
+
start = Time.now
|
53
|
+
|
54
|
+
EM.add_timer(0.5){
|
55
|
+
(Time.now-start).should be_close( 0.5, 0.1 )
|
56
|
+
done
|
57
|
+
}
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
it "runs AMQP.start loop with options given to #amqp" do
|
62
|
+
amqp(:host => 'my.amqp.broker.org', :port => '21118')do
|
63
|
+
AMQP.conn.should be_connected
|
64
|
+
done
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
it "optionally raises timeout exception if your loop hangs for some reason" do
|
69
|
+
proc {
|
70
|
+
amqp(:spec_timeout => 3){}
|
71
|
+
}.should raise_error SpecTimeoutExceededError
|
72
|
+
end
|
73
|
+
|
74
|
+
default_timeout 1 # Can be used to set default :spec_timeout for all your amqp-based specs
|
75
|
+
end
|
76
|
+
|
77
|
+
Another option is to include AMQP::Spec in your describe block. This will patch Rspec so that all of your
|
78
|
+
examples run inside an amqp block automatically. A word of caution about before{} and after{} hooks in your example
|
79
|
+
groups including AMQP::Spec. Each of these hooks will run in its separate EM loop that you'll need to shut down
|
80
|
+
either manually (done) or via default_timeout. Essentially, this means that any EM-related state that you'd like
|
81
|
+
to setup/teardown using these hooks will be lost as each example will run in a separate thread. In order to
|
82
|
+
run setup/teardown hooks inside the EM loop, you'll need to use before_amqp{} and after_amqp{} hooks that run
|
83
|
+
inside the EM loop but before/after AMQP loop (these hooks are currently not implemented)
|
84
|
+
|
85
|
+
require "amqp-spec/rspec"
|
86
|
+
describe AMQP do
|
87
|
+
include AMQP::Spec
|
88
|
+
|
89
|
+
before(:each) do
|
90
|
+
puts EM.reactor_running?
|
91
|
+
done
|
92
|
+
end
|
93
|
+
|
94
|
+
default_options :host => 'my.amqp.broker.org', :port => '21118'
|
95
|
+
# Can be used to set default options for all your (implied) amqp{} event loops
|
96
|
+
|
97
|
+
it "requires a call to #done in every example" do
|
98
|
+
1.should == 1
|
99
|
+
done
|
100
|
+
end
|
101
|
+
|
102
|
+
it "runs test code in an amqp block automatically" do
|
103
|
+
start = Time.now
|
104
|
+
|
105
|
+
EM.add_timer(0.5){
|
106
|
+
(Time.now-start).should be_close( 0.5, 0.1 )
|
107
|
+
done
|
108
|
+
}
|
109
|
+
end
|
110
|
+
|
111
|
+
it "runs AMQP.start loop with default_options" do
|
112
|
+
AMQP.conn.should be_connected
|
113
|
+
done
|
114
|
+
end
|
115
|
+
|
116
|
+
it "raises timeout exception ONLY if default_timeout was set" do
|
117
|
+
proc{}.should raise_error SpecTimeoutExceededError
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
Finally, you can include AMQP::EMSpec in your describe block. This will run all the group examples
|
122
|
+
inside em block instead of amqp. before{} and after{} hooks should be finished with 'done', same as
|
123
|
+
when including AMQP::Spec, and same caution about using them applies.
|
124
|
+
|
125
|
+
require "amqp-spec/rspec"
|
126
|
+
describe AMQP do
|
127
|
+
include AMQP::EMSpec
|
128
|
+
|
129
|
+
it "requires a call to #done in every example" do
|
130
|
+
1.should == 1
|
131
|
+
done
|
132
|
+
end
|
133
|
+
|
134
|
+
it "runs test code in an amqp block automatically" do
|
135
|
+
start = Time.now
|
136
|
+
|
137
|
+
EM.add_timer(0.5){
|
138
|
+
(Time.now-start).should be_close( 0.5, 0.1 )
|
139
|
+
done
|
140
|
+
}
|
141
|
+
end
|
142
|
+
|
143
|
+
default_timeout 1
|
144
|
+
# Default spec timeouts can be used same as with AMQP::Spec, default_options (if defined) are not used
|
145
|
+
end
|
146
|
+
|
147
|
+
|
148
|
+
==Bacon
|
149
|
+
|
150
|
+
...
|
151
|
+
|
152
|
+
==Test::Unit
|
153
|
+
|
154
|
+
...
|
155
|
+
|
156
|
+
==Limitations
|
157
|
+
|
158
|
+
AMQP-Spec can be currently used with rspec only. I suppose, there is nothing special in extending EM-Spec's
|
159
|
+
test unit and bacon support, I just do not have experience dealing with these platforms. Another limitation,
|
160
|
+
it uses native Fibers and therefore not compatible with Ruby 1.8. Again, it seems possible to rewrite it in
|
161
|
+
1.8-compatible style, with string evals and Fiber backport, but I'd rather leave this work to someone else.
|
162
|
+
|
163
|
+
Any help improving this library is greatly appreciated...
|
164
|
+
|
165
|
+
== LICENSE:
|
166
|
+
Copyright (c) 2010 Arvicco.
|
167
|
+
Original EM-Spec code copyright (c) 2008 Aman Gupta (tmm1)
|
168
|
+
|
169
|
+
See LICENSE for details.
|
data/Rakefile
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
NAME = 'amqp-spec'
|
3
|
+
BASE_PATH = Pathname.new(__FILE__).dirname
|
4
|
+
LIB_PATH = BASE_PATH + 'lib'
|
5
|
+
PKG_PATH = BASE_PATH + 'pkg'
|
6
|
+
DOC_PATH = BASE_PATH + 'rdoc'
|
7
|
+
|
8
|
+
$LOAD_PATH.unshift LIB_PATH.to_s
|
9
|
+
require 'version'
|
10
|
+
|
11
|
+
CLASS_NAME = AMQP::Spec
|
12
|
+
VERSION = CLASS_NAME::VERSION
|
13
|
+
|
14
|
+
begin
|
15
|
+
require 'rake'
|
16
|
+
rescue LoadError
|
17
|
+
require 'rubygems'
|
18
|
+
gem 'rake', '~> 0.8.3.1'
|
19
|
+
require 'rake'
|
20
|
+
end
|
21
|
+
|
22
|
+
# Load rakefile tasks
|
23
|
+
Dir['tasks/*.rake'].sort.each { |file| load file }
|
24
|
+
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.0.4
|
data/lib/amqp-spec.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'version'
|
2
|
+
|
3
|
+
module AMQP
|
4
|
+
module Spec
|
5
|
+
|
6
|
+
# require "bundler"
|
7
|
+
# Bundler.setup
|
8
|
+
|
9
|
+
# Requires ruby source file(s). Accepts either single filename/glob or Array of filenames/globs.
|
10
|
+
# Accepts following options:
|
11
|
+
# :*file*:: Lib(s) required relative to this file - defaults to __FILE__
|
12
|
+
# :*dir*:: Required lib(s) located under this dir name - defaults to gem name
|
13
|
+
#
|
14
|
+
def self.require_libs(libs, opts={})
|
15
|
+
file = Pathname.new(opts[:file] || __FILE__)
|
16
|
+
[libs].flatten.each do |lib|
|
17
|
+
name = file.dirname + (opts[:dir] || file.basename('.*')) + lib.gsub(/(?<!.rb)$/, '.rb')
|
18
|
+
Pathname.glob(name.to_s).sort.each { |rb| require rb }
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
# Require all ruby source files located under directory lib/amqp-spec
|
25
|
+
# If you need files in specific order, you should specify it here before the glob
|
26
|
+
AMQP::Spec.require_libs %W[**/*]
|
27
|
+
|
@@ -0,0 +1,195 @@
|
|
1
|
+
require 'mq'
|
2
|
+
require 'fiber' unless Fiber.respond_to?(:current)
|
3
|
+
|
4
|
+
# You can include one of the following modules into your example groups:
|
5
|
+
# AMQP::SpecHelper
|
6
|
+
# AMQP::Spec
|
7
|
+
#
|
8
|
+
# AMQP::SpecHelper module defines 'ampq' method that can be safely used inside your specs(examples)
|
9
|
+
# 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).
|
12
|
+
#
|
13
|
+
# If you include AMQP::Spec module into your example group, each example of this group will run
|
14
|
+
# inside AMQP.start loop without the need to explicitly call 'amqp'. In order to provide options
|
15
|
+
# to AMQP loop, default_options class method is defined. Remember, when using AMQP::Specs, you
|
16
|
+
# will have a single set of AMQP.start options for all your examples.
|
17
|
+
#
|
18
|
+
# In order to stop AMQP loop, you should call 'done' AFTER you are sure that your example is finished.
|
19
|
+
# For example, if you are using subscribe block that tests expectations on messages, 'done' should be
|
20
|
+
# probably called at the end of this block.
|
21
|
+
#
|
22
|
+
# TODO: Define 'async' method wrapping async requests and returning results... 'async_loop' too for subscribe?
|
23
|
+
# TODO: 'evented_before', 'evented_after' that will be run inside EM before the example
|
24
|
+
module AMQP
|
25
|
+
module SpecHelper
|
26
|
+
|
27
|
+
SpecTimeoutExceededError = Class.new(RuntimeError)
|
28
|
+
|
29
|
+
def self.included(example_group)
|
30
|
+
::Spec::Example::ExampleGroup.instance_exec do
|
31
|
+
unless defined? default_spec_timeout
|
32
|
+
|
33
|
+
@@_em_default_options = {}
|
34
|
+
@@_em_default_timeout = nil
|
35
|
+
|
36
|
+
def self.default_spec_timeout(spec_timeout=nil)
|
37
|
+
if spec_timeout
|
38
|
+
@@_em_default_timeout = spec_timeout
|
39
|
+
else
|
40
|
+
@@_em_default_timeout
|
41
|
+
end
|
42
|
+
end
|
43
|
+
alias default_timeout default_spec_timeout
|
44
|
+
|
45
|
+
def self.default_options(opts=nil)
|
46
|
+
if opts
|
47
|
+
@@_em_default_options = opts
|
48
|
+
else
|
49
|
+
@@_em_default_options
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
# Yields to given block inside EM.run and AMQP.start loops. This method takes any option that is
|
57
|
+
# also accepted by EventMachine::connect. Also, options for AMQP.start include:
|
58
|
+
# * :user => String (default ‘guest’) - The username as defined by the AMQP server.
|
59
|
+
# * :pass => String (default ‘guest’) - The password for the associated :user as defined by the AMQP server.
|
60
|
+
# * :vhost => String (default ’/’) - The virtual host as defined by the AMQP server.
|
61
|
+
# * :timeout => Numeric (default nil) - *Connection* timeout, measured in seconds.
|
62
|
+
# * :logging => true | false (default false) - Toggle the extremely verbose AMQP logging.
|
63
|
+
#
|
64
|
+
# In addition to EM and AMQP options, :spec_timeout option (in seconds) is used to force spec to timeout
|
65
|
+
# if something goes wrong and EM/AMQP loop hangs for some reason. SpecTimeoutExceededError is raised.
|
66
|
+
|
67
|
+
def amqp opts={}, &block
|
68
|
+
opts = @@_em_default_options.merge opts
|
69
|
+
EM.run do
|
70
|
+
# begin ?
|
71
|
+
@_em_spec_with_amqp = true
|
72
|
+
@_em_spec_exception = nil
|
73
|
+
spec_timeout = opts.delete(:spec_timeout) || @@_em_default_timeout
|
74
|
+
timeout(spec_timeout) if spec_timeout
|
75
|
+
@_em_spec_fiber = Fiber.new do
|
76
|
+
begin
|
77
|
+
amqp_start opts, &block
|
78
|
+
rescue Exception => @_em_spec_exception
|
79
|
+
p @_em_spec_exception
|
80
|
+
done
|
81
|
+
end
|
82
|
+
Fiber.yield
|
83
|
+
end
|
84
|
+
|
85
|
+
@_em_spec_fiber.resume
|
86
|
+
# raise @_em_spec_exception if @_em_spec_exception
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
# Yields to block inside EM loop, :spec_timeout option (in seconds) is used to force spec to timeout
|
91
|
+
# if something goes wrong and EM/AMQP loop hangs for some reason. SpecTimeoutExceededError is raised.
|
92
|
+
# TODO: accept :spec_timeout =>1 as a Hash for compatibility with amqp interface
|
93
|
+
def em(spec_timeout = @@_em_default_timeout, &block)
|
94
|
+
EM.run do
|
95
|
+
@_em_spec_with_amqp = false
|
96
|
+
@_em_spec_exception = nil
|
97
|
+
timeout(spec_timeout) if spec_timeout
|
98
|
+
@_em_spec_fiber = Fiber.new do
|
99
|
+
begin
|
100
|
+
block.call
|
101
|
+
rescue Exception => @_em_spec_exception
|
102
|
+
done
|
103
|
+
end
|
104
|
+
Fiber.yield
|
105
|
+
end
|
106
|
+
|
107
|
+
@_em_spec_fiber.resume
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
# Sets timeout for current spec
|
112
|
+
def timeout(spec_timeout)
|
113
|
+
EM.cancel_timer(@_em_timer) if @_em_timer
|
114
|
+
@_em_timer = EM.add_timer(spec_timeout) do
|
115
|
+
@_em_spec_exception = SpecTimeoutExceededError.new
|
116
|
+
done
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
# Stops AMQP and EM event loop
|
121
|
+
def done
|
122
|
+
EM.next_tick do
|
123
|
+
if @_em_spec_with_amqp
|
124
|
+
amqp_stop(@_em_spec_exception) do
|
125
|
+
finish_em_spec_fiber
|
126
|
+
end
|
127
|
+
else
|
128
|
+
finish_em_spec_fiber
|
129
|
+
raise @_em_spec_exception if @_em_spec_exception
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
private
|
135
|
+
|
136
|
+
def finish_em_spec_fiber
|
137
|
+
EM.stop_event_loop if EM.reactor_running?
|
138
|
+
# p Thread.current, Thread.current[:mq], __LINE__
|
139
|
+
@_em_spec_fiber.resume if @_em_spec_fiber.alive?
|
140
|
+
end
|
141
|
+
|
142
|
+
# Private method that initializes AMQP client/connection without starting another EM loop
|
143
|
+
def amqp_start opts={}, &block
|
144
|
+
AMQP.instance_exec do
|
145
|
+
# p Thread.current, Thread.current[:mq]
|
146
|
+
puts "!!!!!!!!! Existing connection: #{@conn}" if @conn
|
147
|
+
@conn = connect opts
|
148
|
+
# @conn ||= connect opts
|
149
|
+
@conn.callback(&block) if block
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
# Private method that closes AMQP connection and raises optional
|
154
|
+
# exception AFTER the AMQP connection is 100% closed
|
155
|
+
def amqp_stop exception
|
156
|
+
if AMQP.conn and not AMQP.closing
|
157
|
+
AMQP.instance_exec do #(@_em_spec_exception) do |exception|
|
158
|
+
@closing = true
|
159
|
+
@conn.close {
|
160
|
+
yield if block_given?
|
161
|
+
@conn = nil
|
162
|
+
@closing = false
|
163
|
+
raise exception if exception
|
164
|
+
}
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
module Spec
|
171
|
+
def self.included(cls)
|
172
|
+
cls.send(:include, SpecHelper)
|
173
|
+
end
|
174
|
+
|
175
|
+
def instance_eval(&block)
|
176
|
+
amqp do
|
177
|
+
super(&block)
|
178
|
+
end
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
module EMSpec
|
183
|
+
def self.included(cls)
|
184
|
+
cls.send(:include, SpecHelper)
|
185
|
+
end
|
186
|
+
|
187
|
+
def instance_eval(&block)
|
188
|
+
em do
|
189
|
+
super(&block)
|
190
|
+
end
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
|
data/lib/version.rb
ADDED
data/spec/amqp.yml
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
# AMQP client configuration file
|
2
|
+
|
3
|
+
# These values will be used to configure the ampq gem, any values
|
4
|
+
# omitted will let the gem use it's own defaults.
|
5
|
+
|
6
|
+
# The configuration specifies the following keys:
|
7
|
+
# * user - Username for the broker
|
8
|
+
# * pass - Password for the broker
|
9
|
+
# * host - Hostname where the broker is running
|
10
|
+
# * vhost - Vhost to connect to
|
11
|
+
# * port - Port where the broker is running
|
12
|
+
# * ssl - Use ssl or not
|
13
|
+
# * timeout - Timeout
|
14
|
+
|
15
|
+
defaults: &defaults
|
16
|
+
user: guest
|
17
|
+
pass: guest
|
18
|
+
host: 10.211.55.2
|
19
|
+
vhost: /
|
20
|
+
|
21
|
+
development:
|
22
|
+
<<: *defaults
|
23
|
+
|
24
|
+
test:
|
25
|
+
<<: *defaults
|
26
|
+
|
27
|
+
production:
|
28
|
+
<<: *defaults
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require_relative 'spec_helper.rb'
|
2
|
+
|
3
|
+
context 'Following examples should all be failing:' do
|
4
|
+
describe EventMachine, " when running failing examples" do
|
5
|
+
include AMQP::EMSpec
|
6
|
+
|
7
|
+
it "should not bubble failures beyond rspec" do
|
8
|
+
EM.add_timer(0.1) do
|
9
|
+
:should_not_bubble.should == :failures
|
10
|
+
done
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should not block on failure" do
|
15
|
+
1.should == 2
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe EventMachine, " when testing with AMQP::EMSpec with a maximum execution time per test" do
|
20
|
+
|
21
|
+
include AMQP::EMSpec
|
22
|
+
it 'should timeout before reaching done' do
|
23
|
+
EM.add_timer(2) {
|
24
|
+
done
|
25
|
+
}
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'should timeout before reaching done' do
|
29
|
+
timeout(0.3)
|
30
|
+
EM.add_timer(0.6) {
|
31
|
+
done
|
32
|
+
}
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe AMQP, " when testing with AMQP::Spec with a maximum execution time per test" do
|
37
|
+
|
38
|
+
include AMQP::Spec
|
39
|
+
|
40
|
+
default_timeout 1
|
41
|
+
|
42
|
+
it 'should timeout before reaching done' do
|
43
|
+
EM.add_timer(2) {
|
44
|
+
done
|
45
|
+
}
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'should timeout before reaching done' do
|
49
|
+
timeout(0.2)
|
50
|
+
EM.add_timer(0.5) {
|
51
|
+
done
|
52
|
+
}
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'should fail due to timeout, not hang up' do
|
56
|
+
timeout(0.2)
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'should fail due to default timeout, not hang up' do
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,273 @@
|
|
1
|
+
require_relative 'spec_helper.rb'
|
2
|
+
|
3
|
+
describe 'Rspec' do
|
4
|
+
it 'should work as normal without AMQP-Spec' do
|
5
|
+
1.should == 1
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
context 'Evented AMQP specs' do
|
10
|
+
describe AMQP, " when testing with AMQP::SpecHelper" do
|
11
|
+
include AMQP::SpecHelper
|
12
|
+
after(:each) do
|
13
|
+
EM.reactor_running?.should == false
|
14
|
+
AMQP.conn.should be_nil
|
15
|
+
end
|
16
|
+
|
17
|
+
default_options AMQP_OPTS if defined? AMQP_OPTS
|
18
|
+
default_timeout 1 # Can be used to set default :spec_timeout for all your amqp-based specs
|
19
|
+
|
20
|
+
p default_timeout, default_options
|
21
|
+
|
22
|
+
it "should not require a call to done when #em/#amqp is not used" do
|
23
|
+
1.should == 1
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should properly work" do
|
27
|
+
amqp do
|
28
|
+
done
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should have timers" do
|
33
|
+
amqp do
|
34
|
+
start = Time.now
|
35
|
+
|
36
|
+
EM.add_timer(0.5) {
|
37
|
+
(Time.now-start).should be_close(0.5, 0.1)
|
38
|
+
done
|
39
|
+
}
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
it "should run AMQP.start loop with options given to #amqp" do
|
44
|
+
amqp(:vhost => '/', :user => 'guest') do
|
45
|
+
AMQP.conn.should be_connected
|
46
|
+
done
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should properly close AMQP connection if block completes normally" do
|
51
|
+
amqp do
|
52
|
+
AMQP.conn.should be_connected
|
53
|
+
done
|
54
|
+
end
|
55
|
+
AMQP.conn.should be_nil
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'should have deferrables' do
|
59
|
+
amqp do
|
60
|
+
defr = EM::DefaultDeferrable.new
|
61
|
+
defr.timeout(0.5)
|
62
|
+
defr.errback {
|
63
|
+
done
|
64
|
+
}
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
context 'on exceptions/failures' do
|
69
|
+
# default_timeout 1 # Can be used to set default :spec_timeout for all your amqp-based specs
|
70
|
+
|
71
|
+
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
describe AMQP, " when testing with AMQP::Spec" do
|
76
|
+
include AMQP::Spec
|
77
|
+
after(:each) do
|
78
|
+
EM.reactor_running?.should == true
|
79
|
+
done
|
80
|
+
end
|
81
|
+
|
82
|
+
it 'should work' do
|
83
|
+
done
|
84
|
+
end
|
85
|
+
|
86
|
+
it 'should have timers' do
|
87
|
+
start = Time.now
|
88
|
+
|
89
|
+
EM.add_timer(0.5) {
|
90
|
+
(Time.now-start).should be_close(0.5, 0.1)
|
91
|
+
done
|
92
|
+
}
|
93
|
+
end
|
94
|
+
|
95
|
+
it 'should have periodic timers' do
|
96
|
+
num = 0
|
97
|
+
start = Time.now
|
98
|
+
|
99
|
+
timer = EM.add_periodic_timer(0.25) {
|
100
|
+
if (num += 1) == 2
|
101
|
+
(Time.now-start).should be_close(0.5, 0.1)
|
102
|
+
EM.cancel_timer timer
|
103
|
+
done
|
104
|
+
end
|
105
|
+
}
|
106
|
+
end
|
107
|
+
|
108
|
+
it 'should have deferrables' do
|
109
|
+
defr = EM::DefaultDeferrable.new
|
110
|
+
defr.timeout(0.5)
|
111
|
+
defr.errback {
|
112
|
+
done
|
113
|
+
}
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
shared_examples_for 'timeout examples' do
|
118
|
+
include AMQP::SpecHelper
|
119
|
+
before(:each) { @start = Time.now }
|
120
|
+
|
121
|
+
it 'should timeout before reaching done because of default spec timeout' do
|
122
|
+
proc {
|
123
|
+
amqp do
|
124
|
+
EM.add_timer(2) { done }
|
125
|
+
end
|
126
|
+
}.should raise_error SpecTimeoutExceededError
|
127
|
+
(Time.now-@start).should be_close(1.0, 0.1)
|
128
|
+
end
|
129
|
+
|
130
|
+
it 'should timeout before reaching done because of explicit in-loop timeout' do
|
131
|
+
proc {
|
132
|
+
amqp do
|
133
|
+
timeout(0.2)
|
134
|
+
EM.add_timer(0.5) { done }
|
135
|
+
end
|
136
|
+
}.should raise_error SpecTimeoutExceededError
|
137
|
+
(Time.now-@start).should be_close(0.2, 0.1)
|
138
|
+
end
|
139
|
+
|
140
|
+
specify "spec timeout given in amqp options has higher priority than default" do
|
141
|
+
proc {
|
142
|
+
amqp(:spec_timeout => 0.2) {}
|
143
|
+
}.should raise_error SpecTimeoutExceededError
|
144
|
+
(Time.now-@start).should be_close(0.2, 0.1)
|
145
|
+
end
|
146
|
+
|
147
|
+
specify "but timeout call inside amqp loop has even higher priority" do
|
148
|
+
proc {
|
149
|
+
amqp(:spec_timeout => 0.5) { timeout(0.2) }
|
150
|
+
}.should raise_error SpecTimeoutExceededError
|
151
|
+
(Time.now-@start).should be_close(0.2, 0.1)
|
152
|
+
end
|
153
|
+
|
154
|
+
specify "AMQP connection should not leak between examples" do
|
155
|
+
AMQP.conn.should be_nil
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
describe AMQP, " when testing with AMQP::SpecHelper with spec timeouts" do
|
160
|
+
it_should_behave_like 'timeout examples'
|
161
|
+
|
162
|
+
context 'inside embedded context / example group' do
|
163
|
+
it_should_behave_like 'timeout examples'
|
164
|
+
# it "should properly timeout " do
|
165
|
+
# amqp do
|
166
|
+
# timeout(0.2)
|
167
|
+
# end
|
168
|
+
# end
|
169
|
+
# it "should properly timeout inside embedded context/describe blocks" do
|
170
|
+
# amqp do
|
171
|
+
# end
|
172
|
+
# end
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
# PROBLEMATIC !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
177
|
+
describe AMQP, " when testing with AMQP::SpecHelper with spec timeouts" do
|
178
|
+
include AMQP::SpecHelper
|
179
|
+
|
180
|
+
it "should fail to provide context to next spec" do
|
181
|
+
begin
|
182
|
+
amqp do
|
183
|
+
:this.should == :fail
|
184
|
+
end
|
185
|
+
rescue => e
|
186
|
+
p e
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
it "should properly close AMQP connection after Rspec failures" do
|
191
|
+
AMQP.conn.should == nil
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
# describe MQ, " when MQ.queue or MQ.fanout etc is trying to access Thread-local mq across examples" do
|
196
|
+
# include AMQP::SpecHelper
|
197
|
+
#
|
198
|
+
# default_timeout 1
|
199
|
+
#
|
200
|
+
# it 'sends data to queue' do
|
201
|
+
# amqp do
|
202
|
+
# q = MQ.new.queue("test_sink")
|
203
|
+
# q.subscribe do |hdr, data|
|
204
|
+
# p hdr, data
|
205
|
+
# EM.next_tick {
|
206
|
+
# q.unsubscribe; q.delete
|
207
|
+
# AMQP.stop { EM.stop_event_loop }
|
208
|
+
# }
|
209
|
+
# end
|
210
|
+
# EM.add_timer(0.2) do
|
211
|
+
# p Thread.current, Thread.current[:mq]
|
212
|
+
# MQ.queue('test_sink').publish 'data' # MQ.new. !!!!!!!!!!!
|
213
|
+
# end
|
214
|
+
# end
|
215
|
+
# end
|
216
|
+
#
|
217
|
+
# it 'sends data to queue' do
|
218
|
+
# amqp do
|
219
|
+
# q = MQ.new.queue("test_sink")
|
220
|
+
# q.subscribe do |hdr, data|
|
221
|
+
# p hdr, data
|
222
|
+
# EM.next_tick {
|
223
|
+
# q.unsubscribe; q.delete
|
224
|
+
# AMQP.stop { EM.stop_event_loop }
|
225
|
+
# }
|
226
|
+
# end
|
227
|
+
# EM.add_timer(0.2) do
|
228
|
+
# p Thread.current, Thread.current[:mq]
|
229
|
+
# MQ.queue('test_sink').publish 'data' # MQ.new. !!!!!!!!!!!
|
230
|
+
# end
|
231
|
+
# end
|
232
|
+
# end
|
233
|
+
#
|
234
|
+
# end
|
235
|
+
end
|
236
|
+
|
237
|
+
context '!!!!!!!!!!! LEAKING !!!!!!!!!!!!!!!!!!' do
|
238
|
+
describe EventMachine, " when running failing examples" do
|
239
|
+
include AMQP::SpecHelper
|
240
|
+
|
241
|
+
it "should not bubble failures beyond rspec" do
|
242
|
+
amqp do
|
243
|
+
EM.add_timer(0.1) do
|
244
|
+
:should_not_bubble.should == :failures
|
245
|
+
done
|
246
|
+
end
|
247
|
+
end
|
248
|
+
AMQP.conn.should == nil
|
249
|
+
end
|
250
|
+
|
251
|
+
it "should not block on failure" do
|
252
|
+
1.should == 2
|
253
|
+
end
|
254
|
+
end
|
255
|
+
|
256
|
+
describe EventMachine, " when testing with AMQP::Spec with a maximum execution time per test" do
|
257
|
+
|
258
|
+
include AMQP::Spec
|
259
|
+
|
260
|
+
it 'should timeout before reaching done' do
|
261
|
+
EM.add_timer(2) {
|
262
|
+
done
|
263
|
+
}
|
264
|
+
end
|
265
|
+
end
|
266
|
+
end
|
267
|
+
|
268
|
+
|
269
|
+
describe "Rspec", " when running an example group after another group that uses AMQP-Spec " do
|
270
|
+
it "should work normally" do
|
271
|
+
:does_not_hang.should_not be_false
|
272
|
+
end
|
273
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require_relative 'spec_helper.rb'
|
2
|
+
|
3
|
+
context 'Plain EM, no AMQP' do
|
4
|
+
describe EventMachine, " when testing with AMQP::SpecHelper" do
|
5
|
+
include AMQP::SpecHelper
|
6
|
+
|
7
|
+
it "should not require a call to done when #em is not used" do
|
8
|
+
1.should == 1
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should have timers" do
|
12
|
+
em do
|
13
|
+
start = Time.now
|
14
|
+
|
15
|
+
EM.add_timer(0.5) {
|
16
|
+
(Time.now-start).should be_close(0.5, 0.1)
|
17
|
+
done
|
18
|
+
}
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe EventMachine, " when testing with AMQP::Spec" do
|
24
|
+
include AMQP::EMSpec
|
25
|
+
|
26
|
+
it 'should work' do
|
27
|
+
done
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'should have timers' do
|
31
|
+
start = Time.now
|
32
|
+
|
33
|
+
EM.add_timer(0.5) {
|
34
|
+
(Time.now-start).should be_close(0.5, 0.1)
|
35
|
+
done
|
36
|
+
}
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'should have periodic timers' do
|
40
|
+
num = 0
|
41
|
+
start = Time.now
|
42
|
+
|
43
|
+
timer = EM.add_periodic_timer(0.2) {
|
44
|
+
if (num += 1) == 2
|
45
|
+
(Time.now-start).should be_close(0.4, 0.1)
|
46
|
+
EM.__send__ :cancel_timer, timer
|
47
|
+
done
|
48
|
+
end
|
49
|
+
}
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'should have deferrables' do
|
53
|
+
defr = EM::DefaultDeferrable.new
|
54
|
+
defr.timeout(0.5)
|
55
|
+
defr.errback {
|
56
|
+
done
|
57
|
+
}
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
describe "Rspec", " when running an example group after groups that uses EM specs " do
|
64
|
+
it "should work normally" do
|
65
|
+
:does_not_hang.should_not be_false
|
66
|
+
end
|
67
|
+
end
|
data/spec/spec.opts
ADDED
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
#$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
2
|
+
|
3
|
+
$LOAD_PATH << "." unless $LOAD_PATH.include? "." # moronic 1.9.2 breaks things bad
|
4
|
+
|
5
|
+
require 'spec'
|
6
|
+
require 'yaml'
|
7
|
+
|
8
|
+
require File.join(File.dirname(__FILE__), '..', 'lib', 'amqp-spec', 'rspec.rb')
|
9
|
+
|
10
|
+
amqp_config = File.dirname(__FILE__) + '/amqp.yml'
|
11
|
+
if File.exists? amqp_config
|
12
|
+
|
13
|
+
class Hash
|
14
|
+
def symbolize_keys
|
15
|
+
self.inject({}) { |result, (key, value)|
|
16
|
+
new_key = case key
|
17
|
+
when String then
|
18
|
+
key.to_sym
|
19
|
+
else
|
20
|
+
key
|
21
|
+
end
|
22
|
+
new_value = case value
|
23
|
+
when Hash then
|
24
|
+
value.symbolize_keys
|
25
|
+
else
|
26
|
+
value
|
27
|
+
end
|
28
|
+
result[new_key] = new_value
|
29
|
+
result
|
30
|
+
}
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
AMQP_OPTS = YAML::load_file(amqp_config).symbolize_keys[:test]
|
35
|
+
end
|
data/tasks/common.rake
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
#task :default => 'test:run'
|
2
|
+
#task 'gem:release' => 'test:run'
|
3
|
+
|
4
|
+
task :notes do
|
5
|
+
puts 'Output annotations (TBD)'
|
6
|
+
end
|
7
|
+
|
8
|
+
#Bundler not ready for prime time just yet
|
9
|
+
#desc 'Bundle dependencies'
|
10
|
+
#task :bundle do
|
11
|
+
# output = `bundle check 2>&1`
|
12
|
+
#
|
13
|
+
# unless $?.to_i == 0
|
14
|
+
# puts output
|
15
|
+
# system "bundle install"
|
16
|
+
# puts
|
17
|
+
# end
|
18
|
+
#end
|
data/tasks/doc.rake
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
desc 'Alias to doc:rdoc'
|
2
|
+
task :doc => 'doc:rdoc'
|
3
|
+
|
4
|
+
namespace :doc do
|
5
|
+
require 'rake/rdoctask'
|
6
|
+
Rake::RDocTask.new do |rdoc|
|
7
|
+
# Rake::RDocTask.new(:rdoc => "rdoc", :clobber_rdoc => "clobber", :rerdoc => "rerdoc") do |rdoc|
|
8
|
+
rdoc.rdoc_dir = DOC_PATH.basename.to_s
|
9
|
+
rdoc.title = "#{NAME} #{VERSION} Documentation"
|
10
|
+
rdoc.main = "README.doc"
|
11
|
+
rdoc.rdoc_files.include('README*')
|
12
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
13
|
+
end
|
14
|
+
end
|
data/tasks/gem.rake
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
desc "Alias to gem:release"
|
2
|
+
task :release => 'gem:release'
|
3
|
+
|
4
|
+
desc "Alias to gem:install"
|
5
|
+
task :install => 'gem:install'
|
6
|
+
|
7
|
+
desc "Alias to gem:build"
|
8
|
+
task :gem => 'gem:build'
|
9
|
+
|
10
|
+
namespace :gem do
|
11
|
+
gem_file = "#{NAME}-#{VERSION}.gem"
|
12
|
+
|
13
|
+
desc "(Re-)Build gem"
|
14
|
+
task :build do
|
15
|
+
puts "Remove existing gem package"
|
16
|
+
rm_rf PKG_PATH
|
17
|
+
puts "Build new gem package"
|
18
|
+
system "gem build #{NAME}.gemspec"
|
19
|
+
puts "Move built gem to package dir"
|
20
|
+
mkdir_p PKG_PATH
|
21
|
+
mv gem_file, PKG_PATH
|
22
|
+
end
|
23
|
+
|
24
|
+
desc "Cleanup already installed gem(s)"
|
25
|
+
task :cleanup do
|
26
|
+
puts "Cleaning up installed gem(s)"
|
27
|
+
system "gem cleanup #{NAME}"
|
28
|
+
end
|
29
|
+
|
30
|
+
desc "Build and install gem"
|
31
|
+
task :install => :build do
|
32
|
+
system "gem install #{PKG_PATH}/#{gem_file}"
|
33
|
+
end
|
34
|
+
|
35
|
+
desc "Build and push gem to Gemcutter"
|
36
|
+
task :release => [:build, 'git:tag'] do
|
37
|
+
puts "Pushing gem to Gemcutter"
|
38
|
+
system "gem push #{PKG_PATH}/#{gem_file}"
|
39
|
+
end
|
40
|
+
end
|
data/tasks/git.rake
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
desc "Alias to git:commit"
|
2
|
+
task :git => 'git:commit'
|
3
|
+
|
4
|
+
namespace :git do
|
5
|
+
|
6
|
+
desc "Stage and commit your work [with message]"
|
7
|
+
task :commit, [:message] do |t, args|
|
8
|
+
puts "Staging new (unversioned) files"
|
9
|
+
system "git add --all"
|
10
|
+
if args.message
|
11
|
+
puts "Committing with message: #{args.message}"
|
12
|
+
system %Q[git commit -a -m "#{args.message}" --author arvicco]
|
13
|
+
else
|
14
|
+
puts "Committing"
|
15
|
+
system %Q[git commit -a -m "No message" --author arvicco]
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
desc "Push local changes to Github"
|
20
|
+
task :push => :commit do
|
21
|
+
puts "Pushing local changes to remote"
|
22
|
+
system "git push"
|
23
|
+
end
|
24
|
+
|
25
|
+
desc "Create (release) tag on Github"
|
26
|
+
task :tag => :push do
|
27
|
+
tag = VERSION
|
28
|
+
puts "Creating git tag: #{tag}"
|
29
|
+
system %Q{git tag -a -m "Release tag #{tag}" #{tag}}
|
30
|
+
puts "Pushing #{tag} to remote"
|
31
|
+
system "git push origin #{tag}"
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
data/tasks/spec.rake
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
desc 'Alias to spec:spec'
|
2
|
+
task :spec => 'spec:spec'
|
3
|
+
|
4
|
+
namespace :spec do
|
5
|
+
require 'spec/rake/spectask'
|
6
|
+
|
7
|
+
desc "Run all specs"
|
8
|
+
Spec::Rake::SpecTask.new(:spec) do |t|
|
9
|
+
t.spec_opts = ['--options', %Q{"#{BASE_PATH}/spec/spec.opts"}]
|
10
|
+
t.spec_files = FileList['spec/**/*_spec.rb']
|
11
|
+
end
|
12
|
+
|
13
|
+
desc "Run specs with RCov"
|
14
|
+
Spec::Rake::SpecTask.new(:rcov) do |t|
|
15
|
+
t.spec_files = FileList['spec/**/*_spec.rb']
|
16
|
+
t.rcov = true
|
17
|
+
t.rcov_opts = ['--exclude', 'spec']
|
18
|
+
end
|
19
|
+
end
|
data/tasks/version.rake
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
class Version
|
2
|
+
attr_accessor :major, :minor, :patch, :build
|
3
|
+
|
4
|
+
def initialize(version_string)
|
5
|
+
raise "Invalid version #{version_string}" unless version_string =~ /^(\d+)\.(\d+)\.(\d+)(?:\.(.*?))?$/
|
6
|
+
@major = $1.to_i
|
7
|
+
@minor = $2.to_i
|
8
|
+
@patch = $3.to_i
|
9
|
+
@build = $4
|
10
|
+
end
|
11
|
+
|
12
|
+
def bump_major(x)
|
13
|
+
@major += x.to_i
|
14
|
+
@minor = 0
|
15
|
+
@patch = 0
|
16
|
+
@build = nil
|
17
|
+
end
|
18
|
+
|
19
|
+
def bump_minor(x)
|
20
|
+
@minor += x.to_i
|
21
|
+
@patch = 0
|
22
|
+
@build = nil
|
23
|
+
end
|
24
|
+
|
25
|
+
def bump_patch(x)
|
26
|
+
@patch += x.to_i
|
27
|
+
@build = nil
|
28
|
+
end
|
29
|
+
|
30
|
+
def update(major, minor, patch, build=nil)
|
31
|
+
@major = major
|
32
|
+
@minor = minor
|
33
|
+
@patch = patch
|
34
|
+
@build = build
|
35
|
+
end
|
36
|
+
|
37
|
+
def write(desc = nil)
|
38
|
+
CLASS_NAME::VERSION_FILE.open('w') {|file| file.puts to_s }
|
39
|
+
(BASE_PATH + 'HISTORY').open('a') do |file|
|
40
|
+
file.puts "\n== #{to_s} / #{Time.now.strftime '%Y-%m-%d'}\n"
|
41
|
+
file.puts "\n* #{desc}\n" if desc
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def to_s
|
46
|
+
[major, minor, patch, build].compact.join('.')
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
desc 'Set version: [x.y.z] - explicitly, [1/10/100] - bump major/minor/patch, [.build] - build'
|
51
|
+
task :version, [:command, :desc] do |t, args|
|
52
|
+
version = Version.new(VERSION)
|
53
|
+
case args.command
|
54
|
+
when /^(\d+)\.(\d+)\.(\d+)(?:\.(.*?))?$/ # Set version explicitly
|
55
|
+
version.update($1, $2, $3, $4)
|
56
|
+
when /^\.(.*?)$/ # Set build
|
57
|
+
version.build = $1
|
58
|
+
when /^(\d{1})$/ # Bump patch
|
59
|
+
version.bump_patch $1
|
60
|
+
when /^(\d{1})0$/ # Bump minor
|
61
|
+
version.bump_minor $1
|
62
|
+
when /^(\d{1})00$/ # Bump major
|
63
|
+
version.bump_major $1
|
64
|
+
else # Unknown command, just display VERSION
|
65
|
+
puts "#{NAME} #{version}"
|
66
|
+
next
|
67
|
+
end
|
68
|
+
|
69
|
+
puts "Writing version #{version} to VERSION file"
|
70
|
+
version.write args.desc
|
71
|
+
end
|
metadata
ADDED
@@ -0,0 +1,114 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: amqp-spec
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 23
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 4
|
10
|
+
version: 0.0.4
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Arvicco
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2010-10-14 00:00:00 +04:00
|
19
|
+
default_executable:
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
name: rspec
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 13
|
30
|
+
segments:
|
31
|
+
- 1
|
32
|
+
- 2
|
33
|
+
- 9
|
34
|
+
version: 1.2.9
|
35
|
+
type: :development
|
36
|
+
version_requirements: *id001
|
37
|
+
description: Simple API for writing (asynchronous) AMQP specs
|
38
|
+
email: arvitallian@gmail.com
|
39
|
+
executables: []
|
40
|
+
|
41
|
+
extensions: []
|
42
|
+
|
43
|
+
extra_rdoc_files:
|
44
|
+
- LICENSE
|
45
|
+
- HISTORY
|
46
|
+
- README.rdoc
|
47
|
+
files:
|
48
|
+
- lib/amqp-spec/rspec.rb
|
49
|
+
- lib/amqp-spec.rb
|
50
|
+
- lib/version.rb
|
51
|
+
- spec/amqp.yml
|
52
|
+
- spec/failing_rspec_spec.rb
|
53
|
+
- spec/rspec_amqp_spec.rb
|
54
|
+
- spec/rspec_em_spec.rb
|
55
|
+
- spec/spec.opts
|
56
|
+
- spec/spec_helper.rb
|
57
|
+
- tasks/common.rake
|
58
|
+
- tasks/doc.rake
|
59
|
+
- tasks/gem.rake
|
60
|
+
- tasks/git.rake
|
61
|
+
- tasks/spec.rake
|
62
|
+
- tasks/version.rake
|
63
|
+
- Rakefile
|
64
|
+
- README.rdoc
|
65
|
+
- LICENSE
|
66
|
+
- VERSION
|
67
|
+
- HISTORY
|
68
|
+
- .gitignore
|
69
|
+
has_rdoc: true
|
70
|
+
homepage: http://github.com/arvicco/amqp-spec
|
71
|
+
licenses: []
|
72
|
+
|
73
|
+
post_install_message:
|
74
|
+
rdoc_options:
|
75
|
+
- --charset
|
76
|
+
- UTF-8
|
77
|
+
- --main
|
78
|
+
- README.rdoc
|
79
|
+
- --title
|
80
|
+
- amqp-spec
|
81
|
+
require_paths:
|
82
|
+
- lib
|
83
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
84
|
+
none: false
|
85
|
+
requirements:
|
86
|
+
- - ">="
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
hash: 3
|
89
|
+
segments:
|
90
|
+
- 0
|
91
|
+
version: "0"
|
92
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
93
|
+
none: false
|
94
|
+
requirements:
|
95
|
+
- - ">="
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
hash: 3
|
98
|
+
segments:
|
99
|
+
- 0
|
100
|
+
version: "0"
|
101
|
+
requirements: []
|
102
|
+
|
103
|
+
rubyforge_project:
|
104
|
+
rubygems_version: 1.3.7
|
105
|
+
signing_key:
|
106
|
+
specification_version: 3
|
107
|
+
summary: Simple API for writing (asynchronous) AMQP specs
|
108
|
+
test_files:
|
109
|
+
- spec/amqp.yml
|
110
|
+
- spec/failing_rspec_spec.rb
|
111
|
+
- spec/rspec_amqp_spec.rb
|
112
|
+
- spec/rspec_em_spec.rb
|
113
|
+
- spec/spec.opts
|
114
|
+
- spec/spec_helper.rb
|