mock_em 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,61 @@
1
+ # standard ignores
2
+ log/*
3
+ tmp/*
4
+ TAGS
5
+ .idea/*
6
+
7
+ # Apparently this file should not be checked in, for GEM projects: http://yehudakatz.com/2010/12/16/clarifying-the-roles-of-the-gemspec-and-gemfile/
8
+ Gemfile.lock
9
+
10
+ # Rbenv
11
+ .ruby-version
12
+
13
+ # rcov generated
14
+ coverage
15
+ coverage.data
16
+
17
+ # rdoc generated
18
+ rdoc
19
+
20
+ # yard generated
21
+ doc
22
+ .yardoc
23
+
24
+ # bundler
25
+ .bundle
26
+
27
+ # jeweler generated
28
+ pkg
29
+
30
+ # Have editor/IDE/OS specific files you need to ignore? Consider using a global gitignore:
31
+ #
32
+ # * Create a file at ~/.gitignore
33
+ # * Include files you want ignored
34
+ # * Run: git config --global core.excludesfile ~/.gitignore
35
+ #
36
+ # After doing this, these files will be ignored in all your git projects,
37
+ # saving you from having to 'pollute' every project you touch with them
38
+ #
39
+ # Not sure what to needs to be ignored for particular editors/OSes? Here's some ideas to get you started. (Remember, remove the leading # of the line)
40
+ #
41
+ # For MacOS:
42
+ #
43
+ .DS_Store
44
+
45
+ # For TextMate
46
+ #*.tmproj
47
+ #tmtags
48
+
49
+ # For emacs:
50
+ *~
51
+ \#*
52
+ .\#*
53
+
54
+ # For vim:
55
+ *.swp
56
+
57
+ # For redcar:
58
+ .redcar
59
+
60
+ # For rubinius:
61
+ *.rbc
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --colour
2
+ --format=documentation
3
+ --backtrace
data/CHANGELOG.rdoc ADDED
File without changes
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in mock_em.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009-2014 RightScale, Inc.
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 NONINFRINGEMENT.
17
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
18
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
19
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
20
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,73 @@
1
+ # MockEM
2
+
3
+ MockEM provides the same interface as [EM](https://github.com/eventmachine/eventmachine/) (a.k.a. [EventMachine](https://github.com/eventmachine/eventmachine/)), but simulates the passage of time to execute your
4
+ scheduled actions without delay. It is intended for use in tests.
5
+
6
+ Uses [Timecop](https://github.com/travisjeffery/timecop) for simulating the passage of time.
7
+
8
+ ## Getting Started
9
+ You'll need to add `require 'mock_em'`, as well as `require 'timecop'`.
10
+
11
+ At the beginning of your spec you can use the following snippet to mock EM within the scope of that spec.
12
+
13
+ ```ruby
14
+ # mock & restore EM
15
+ before(:all) do
16
+ @logger = Logger.new(STDOUT) # <-- Choose your own logger, as appropriate
17
+
18
+ # Mock EM
19
+ @orig_EM = EM
20
+ EM = MockEM::MockEM.new(@logger, Timecop)
21
+ end
22
+ after(:all) do
23
+ EM = @orig_EM
24
+ Timecop.return
25
+ end
26
+ ```
27
+
28
+ Any references to `EM` will then be using MockEM.
29
+
30
+ As a quick demonstration, the following code has a timer that would wait for 8 minutes with EM, but with MockEM it completes instantaneously:
31
+
32
+ ```ruby
33
+ require 'timecop'
34
+ require 'mock_em'
35
+ logger = Logger.new(STDOUT)
36
+ em = MockEM::MockEM.new(logger, Timecop)
37
+
38
+ em.run do
39
+ em.add_timer(8 * 60) do
40
+ puts "Done!"
41
+ em.stop
42
+ end
43
+ end
44
+ ```
45
+
46
+ ## Supported Features
47
+ MockEM supports many of the features of EM. Example of supported methods:
48
+
49
+ - Reactor: `run`, `stop`, `reactor_running?`
50
+ - Timers: `next_tick`, `add_timer`, `add_periodic_timer`, `cancel_timer`, `get_max_timer_count`
51
+ - Hooks: `add_shutdown_hook`, `error_handler`
52
+
53
+ Refer to `mock_em_spec.rb` for more details, as it runs the same set of specs against both `MockEM` and `EM`,
54
+ to verify the behavior is identical.
55
+
56
+ ## Unsupported Features
57
+ Your mileage may vary.
58
+
59
+ ## TODO
60
+ - [ ] add Travis CI integration for specs
61
+
62
+ ## Compatibility
63
+ Ruby 1.8.7 and above is supported.
64
+
65
+ ## Contributing
66
+ Pull requests welcome.
67
+
68
+ If you'd like to add missing functionality, you can use `mock_em_spec.rb` to verify that the behavior is identical in both `MockEM` and `EM`.
69
+
70
+ Maintained by the RightScale "Cornsilk_team"
71
+
72
+ ## License
73
+ MIT License, see [LICENSE](LICENSE)
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,27 @@
1
+ module MockEM
2
+
3
+ # Logs all messages with the specified prefix.
4
+ # Warning: this is a not a full-fledged Logger implementation, it just logs string messages.
5
+ class LoggerWithPrefix
6
+
7
+ attr_reader :prefix
8
+ attr_reader :raw_logger
9
+
10
+ def initialize(prefix, logger)
11
+ @prefix = prefix
12
+ @raw_logger = logger
13
+ end
14
+
15
+ def debug(msg); log_with_prefix(:debug, msg) end
16
+ def info(msg); log_with_prefix(:info, msg) end
17
+ def warn(msg); log_with_prefix(:warn, msg) end
18
+ def error(msg); log_with_prefix(:error, msg) end
19
+
20
+ private
21
+
22
+ def log_with_prefix(level, msg)
23
+ @raw_logger.__send__(level, "#{prefix}: #{msg}")
24
+ end
25
+ end
26
+
27
+ end
@@ -0,0 +1,225 @@
1
+ require 'logger'
2
+ require 'mock_em/logger_with_prefix'
3
+ require 'timecop'
4
+
5
+ module MockEM
6
+
7
+ # Fake EM suitable for unit testing.
8
+ # Uses Timecop to accelerate time. Should run Timecop.return after spec, just to be safe.
9
+ class MockEM
10
+
11
+ # @param [Timecop] timecop
12
+ def initialize(logger, timecop)
13
+ @log = LoggerWithPrefix.new("MockEM", logger)
14
+ @timecop = timecop
15
+
16
+ @next_tick_procs = []
17
+ @scheduled_tasks = ScheduledTasks.new(@log)
18
+ @timer_objects = []
19
+ @shutdown_hooks = []
20
+ @is_stopped = false
21
+
22
+ @max_timer_count = 100000 #TODO: not honored
23
+ end
24
+
25
+ def run(&block)
26
+ @reactor_running = true
27
+ @is_stopped = false
28
+ @log.info "run called. executing run block."
29
+
30
+ safely_run { block.call }
31
+
32
+ @log.info("Beginning tick loop.")
33
+ @tick_count = 0
34
+ while (!@is_stopped)
35
+ @tick_count += 1
36
+
37
+ due_tasks = @scheduled_tasks.pop_due_tasks(now_millis)
38
+ @log.info "Tick ##{@tick_count}, clock=#{now_millis}, due_tasks=#{due_tasks.count}, next_tick_procs=#{@next_tick_procs.count}"
39
+ this_tick_procs = due_tasks + @next_tick_procs
40
+ @next_tick_procs = []
41
+
42
+ if this_tick_procs.empty?
43
+ # accelerate time to next scheduled task
44
+ next_time = @scheduled_tasks.time_of_next_task
45
+ if next_time.nil?
46
+ @log.info "Nothing left to do! Returning."
47
+ break
48
+ else
49
+ delta = next_time - now_millis
50
+ @log.info "Nothing in this tick. Accelerating clock by #{delta / 1000.0}s to: #{next_time}"
51
+ set_clock(next_time)
52
+ end
53
+ end
54
+
55
+ this_tick_procs.each_with_index do |proc, index|
56
+ @log.info "Executing tick proc ##{index+1}"
57
+ safely_run { proc.call }
58
+ end
59
+ end
60
+ @log.info("Finished tick loop. Returning.")
61
+ ensure
62
+ @reactor_running = false
63
+ future_time = now_millis
64
+ @timecop.return
65
+ @log.debug "MockEM saved you #{(future_time - now_millis) / 1000} seconds."
66
+ end
67
+
68
+ def stop
69
+ @log.info "stop called"
70
+ @is_stopped = true
71
+ @next_tick_procs = []
72
+ @scheduled_tasks.clear_and_reset
73
+ hooks = @shutdown_hooks
74
+ @shutdown_hooks = []
75
+
76
+ if hooks.count > 0
77
+ @log.info "Executing #{hooks.count} shutdown hooks"
78
+ hooks.reverse.each(&:call)
79
+ end
80
+ end
81
+
82
+ def next_tick(proc = nil, &block)
83
+ proc ||= block
84
+ @log.info "Adding proc to next_tick"
85
+ @next_tick_procs << proc
86
+ end
87
+
88
+ def add_timer(delay_seconds, proc = nil, &block)
89
+ add_timer_internal(delay_seconds, nil, proc, &block)
90
+ end
91
+
92
+ def add_periodic_timer(period_seconds, proc = nil, &block)
93
+ proc ||= block
94
+ timer = MockTimer.new
95
+ @log.info "Creating periodic timer task: id=#{timer.id}, period_seconds=#{period_seconds}"
96
+
97
+ recursive_block = nil
98
+ recursive_block = lambda do
99
+ safely_run { proc.call }
100
+ if !timer.is_cancelled
101
+ @log.info "Rescheduling next run of periodic timer id=#{timer.id}"
102
+ add_timer_internal(period_seconds, timer, recursive_block)
103
+ end
104
+ end
105
+
106
+ add_timer_internal(period_seconds, timer, recursive_block)
107
+ end
108
+
109
+ def cancel_timer(timer)
110
+ #TODO: support looking up by timer ID as well
111
+ @timer_objects.delete(timer)
112
+ timer.cancel
113
+ end
114
+
115
+ def reactor_running?
116
+ !!(@reactor_running)
117
+ end
118
+
119
+ def get_max_timer_count
120
+ @max_timer_count
121
+ end
122
+
123
+ def add_shutdown_hook(&block)
124
+ @shutdown_hooks << block
125
+ end
126
+
127
+ def error_handler(proc = nil, &block)
128
+ proc ||= block
129
+ @log.info("Setting error_handler")
130
+ @error_handler = proc
131
+ end
132
+
133
+
134
+ # Simulates whatever EM.add_timer or EM.add_periodic_timer returns.
135
+ class MockTimer
136
+
137
+ @@id_seq = 0
138
+
139
+ attr_reader :id, :is_cancelled
140
+
141
+ def initialize
142
+ @is_cancelled = false
143
+ @id = @@id_seq += 1
144
+ end
145
+
146
+ def cancel
147
+ @is_cancelled = true
148
+ end
149
+ end
150
+
151
+
152
+ # Keeps track of tasks to execute in the future, each one consisting of a timestamp and proc to execute.
153
+ class ScheduledTasks
154
+ ScheduledTask = Struct.new(:timestamp, :proc)
155
+
156
+ def initialize(log)
157
+ @log = log
158
+ clear_and_reset
159
+ end
160
+
161
+ def add_task(timestamp_millis, &block)
162
+ @tasks << ScheduledTask.new(timestamp_millis, block)
163
+ @tasks = @tasks.sort_by(&:timestamp)
164
+ end
165
+
166
+ def pop_due_tasks(timestamp)
167
+ due_tasks = @tasks.take_while {|t| t.timestamp <= timestamp }
168
+ @tasks = @tasks - due_tasks
169
+ due_tasks.map(&:proc)
170
+ end
171
+
172
+ def time_of_next_task
173
+ task = @tasks.first
174
+ task && task.timestamp
175
+ end
176
+
177
+ def clear_and_reset
178
+ @tasks = []
179
+ end
180
+ end
181
+
182
+
183
+ private
184
+
185
+ def safely_run(&block)
186
+ begin
187
+ block.call
188
+ rescue => e
189
+ if @error_handler
190
+ @error_handler.call(e)
191
+ else
192
+ raise e
193
+ end
194
+ rescue Exception => e
195
+ @error_handler.call(e) if @error_handler
196
+ raise e
197
+ end
198
+ end
199
+
200
+ def set_clock(millis)
201
+ @timecop.travel(Time.at(millis / 1000.0))
202
+ end
203
+
204
+ def now_millis
205
+ (Time.now.utc.to_f * 1000.0).to_i
206
+ end
207
+
208
+ # same as add_timer, but adds an optional parameter: reuse_timer
209
+ def add_timer_internal(delay_seconds, reuse_timer, proc = nil, &block)
210
+ proc ||= block
211
+ timer = reuse_timer || MockTimer.new
212
+ @log.info "Adding timer task: id=#{timer.id}, delay_seconds=#{delay_seconds}"
213
+ @scheduled_tasks.add_task(now_millis + (delay_seconds * 1000)) do
214
+ if timer.is_cancelled
215
+ @log.debug "Skipping this timer task, it's already cancelled"
216
+ else
217
+ safely_run { proc.call }
218
+ end
219
+ end
220
+ @timer_objects << timer
221
+ timer
222
+ end
223
+
224
+ end
225
+ end
@@ -0,0 +1,3 @@
1
+ module MockEM
2
+ VERSION = "0.1.0"
3
+ end
data/lib/mock_em.rb ADDED
@@ -0,0 +1,3 @@
1
+ require 'mock_em/mock_em'
2
+ require 'mock_em/logger_with_prefix'
3
+
data/mock_em.gemspec ADDED
@@ -0,0 +1,33 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'mock_em/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "mock_em"
8
+ gem.version = MockEM::VERSION
9
+
10
+ gem.authors = ['Jim Slattery, Dominic Metzger']
11
+ gem.date = "2014-05-30"
12
+
13
+ gem.summary = %q{Mock for EM for testing.}
14
+ gem.description = %q{Mock EM}
15
+ gem.homepage = "https://github.com/rightscale/mock_em"
16
+ gem.email = 'support@rightscale.com'
17
+ gem.licenses = ["MIT"]
18
+
19
+ gem.files = `git ls-files`.split($/)
20
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
21
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
22
+ gem.require_paths = [ "lib" ]
23
+ gem.extra_rdoc_files = [ "LICENSE", "README.md" ]
24
+ gem.rubygems_version = "1.8.26"
25
+
26
+ gem.add_dependency("timecop", "0.3.4")
27
+ # ---------------------------------------------------------------------
28
+ # Test suite
29
+ # ---------------------------------------------------------------------
30
+ gem.add_development_dependency("rspec", '3.0.0')
31
+ gem.add_development_dependency('ruby-debug', '0.10.4')
32
+ gem.add_development_dependency('eventmachine', '1.0.3')
33
+ end
@@ -0,0 +1,210 @@
1
+ require 'spec/spec_helper'
2
+ require 'mock_em/mock_em'
3
+ require 'eventmachine'
4
+
5
+ describe MockEM::MockEM do
6
+
7
+ # Runs all of these specs on both real EM and MockEM,
8
+ # so we can immediately notice if their behavior is not identical.
9
+ [true, false].each do |use_real_em|
10
+ context "using #{use_real_em ? 'real' : 'fake'} em" do
11
+
12
+ before(:each) do
13
+ @logger = Logger.new(STDOUT)
14
+ @logger.level = Logger::WARN
15
+ @em = use_real_em ? EM : MockEM::MockEM.new(@logger, Timecop)
16
+ end
17
+ after(:each) do
18
+ Timecop.return
19
+ end
20
+
21
+ it "#run and #stop" do
22
+ inside_run = false
23
+ after_stop = false
24
+ @em.run do
25
+ inside_run = true
26
+ @em.stop
27
+ after_stop = true
28
+ end
29
+ expect(inside_run).to be true
30
+ expect(after_stop).to be true
31
+ end
32
+
33
+ it "#next_tick &block" do
34
+ after_stop = false
35
+ @em.run do
36
+ @em.next_tick do
37
+ @em.stop
38
+ after_stop = true
39
+ end
40
+ end
41
+ expect(after_stop).to be true
42
+ end
43
+
44
+ it "#next_tick proc" do
45
+ after_stop = false
46
+ proc = proc {
47
+ @em.stop
48
+ after_stop = true
49
+ }
50
+ @em.run do
51
+ @em.next_tick(proc)
52
+ end
53
+ expect(after_stop).to be true
54
+ end
55
+
56
+ it "#add_timer &block" do
57
+ counter = 0
58
+ @em.run do
59
+ @em.add_timer(0.1) do
60
+ expect(counter).to eq(0)
61
+ counter += 1
62
+ @em.add_timer(0.1) do
63
+ expect(counter).to eq(1)
64
+ @em.stop
65
+ counter +=1
66
+ end
67
+ end
68
+ end
69
+ expect(counter).to eq(2)
70
+ end
71
+
72
+ it "#add_timer proc" do
73
+ counter = 0
74
+ @em.run do
75
+ proc1 = proc do
76
+ expect(counter).to eq(0)
77
+ counter += 1
78
+ proc2 = proc do
79
+ expect(counter).to eq(1)
80
+ @em.stop
81
+ counter +=1
82
+ end
83
+ @em.add_timer(0.1, proc2)
84
+ end
85
+ @em.add_timer(0.1, proc1)
86
+ end
87
+ expect(counter).to eq(2)
88
+ end
89
+
90
+ it "#cancel_timer" do
91
+ @em.run do
92
+ timer = @em.add_timer(0.1) do
93
+ fail
94
+ end
95
+
96
+ @em.cancel_timer(timer)
97
+
98
+ @em.add_timer(0.3) do
99
+ @em.stop
100
+ end
101
+ end
102
+ end
103
+
104
+ it "#add_periodic_timer &block" do
105
+ count = 0
106
+ @em.run do
107
+ @em.add_periodic_timer(0.1) do
108
+ count += 1
109
+ if count > 5
110
+ @em.stop
111
+ end
112
+ end
113
+ end
114
+ expect(count).to eq(6)
115
+ end
116
+
117
+ it "#add_periodic_timer proc" do
118
+ count = 0
119
+ @em.run do
120
+ proc1 = proc do
121
+ count += 1
122
+ if count > 5
123
+ @em.stop
124
+ end
125
+ end
126
+ @logger.info "adding timer"
127
+
128
+ @em.add_periodic_timer(0.1, proc1)
129
+ end
130
+ expect(count).to eq(6)
131
+ end
132
+
133
+ it "cancelling periodic_timer" do
134
+ @em.run do
135
+ count = 0
136
+ timer = nil
137
+ timer = @em.add_periodic_timer(0.1) do
138
+ count += 1
139
+ if count >= 3
140
+ @em.cancel_timer(timer)
141
+ end
142
+ end
143
+
144
+ @em.add_timer(0.5) do
145
+ @em.stop
146
+ expect(count).to eq(3)
147
+ end
148
+ end
149
+ end
150
+
151
+ it "#is_reactor_running?" do
152
+ expect(@em.reactor_running?).to be false
153
+ @em.run do
154
+ expect(@em.reactor_running?).to be true
155
+ @em.stop
156
+ expect(@em.reactor_running?).to be true
157
+ end
158
+ expect(@em.reactor_running?).to be false
159
+ end
160
+
161
+ it "#add_shutdown_hook" do
162
+ sequence = []
163
+ @em.run do
164
+ @em.add_shutdown_hook { sequence.push(1) }
165
+ @em.add_shutdown_hook { sequence.push(2) }
166
+ @em.stop
167
+ end
168
+ expect(sequence).to eq([2,1])
169
+ end
170
+
171
+ it "#get_max_timer_count" do
172
+ expect(@em.get_max_timer_count).to eq(100000)
173
+ end
174
+
175
+ it "#error_handler" do
176
+ error_count = 0
177
+ @em.error_handler do |error|
178
+ @logger.info "Caught error: #{error.inspect}"
179
+ expect(error.message).to match(/fake_error/)
180
+ error_count += 1
181
+ end
182
+
183
+ @em.run do
184
+ @em.next_tick do
185
+ @em.next_tick do
186
+ @em.stop
187
+ end
188
+ raise "fake_error_2"
189
+ end
190
+ raise "fake_error_1"
191
+ end
192
+
193
+ expect(error_count).to eq(2)
194
+ end
195
+
196
+ it "#error_handler not defined, should re-raise error" do
197
+ expect do
198
+ @em.run do
199
+ @em.next_tick do
200
+ @em.next_tick do
201
+ raise "error"
202
+ end
203
+ end
204
+ end
205
+ end.to raise_error
206
+ end
207
+
208
+ end
209
+ end
210
+ end
@@ -0,0 +1,6 @@
1
+ require 'mock_em'
2
+
3
+ require 'logger'
4
+ require 'timecop'
5
+
6
+ require 'ruby-debug' # enable debugger support
metadata ADDED
@@ -0,0 +1,144 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mock_em
3
+ version: !ruby/object:Gem::Version
4
+ hash: 27
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 0
10
+ version: 0.1.0
11
+ platform: ruby
12
+ authors:
13
+ - Jim Slattery, Dominic Metzger
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2014-05-30 00:00:00 Z
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: timecop
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - "="
27
+ - !ruby/object:Gem::Version
28
+ hash: 27
29
+ segments:
30
+ - 0
31
+ - 3
32
+ - 4
33
+ version: 0.3.4
34
+ type: :runtime
35
+ version_requirements: *id001
36
+ - !ruby/object:Gem::Dependency
37
+ name: rspec
38
+ prerelease: false
39
+ requirement: &id002 !ruby/object:Gem::Requirement
40
+ none: false
41
+ requirements:
42
+ - - "="
43
+ - !ruby/object:Gem::Version
44
+ hash: 7
45
+ segments:
46
+ - 3
47
+ - 0
48
+ - 0
49
+ version: 3.0.0
50
+ type: :development
51
+ version_requirements: *id002
52
+ - !ruby/object:Gem::Dependency
53
+ name: ruby-debug
54
+ prerelease: false
55
+ requirement: &id003 !ruby/object:Gem::Requirement
56
+ none: false
57
+ requirements:
58
+ - - "="
59
+ - !ruby/object:Gem::Version
60
+ hash: 63
61
+ segments:
62
+ - 0
63
+ - 10
64
+ - 4
65
+ version: 0.10.4
66
+ type: :development
67
+ version_requirements: *id003
68
+ - !ruby/object:Gem::Dependency
69
+ name: eventmachine
70
+ prerelease: false
71
+ requirement: &id004 !ruby/object:Gem::Requirement
72
+ none: false
73
+ requirements:
74
+ - - "="
75
+ - !ruby/object:Gem::Version
76
+ hash: 17
77
+ segments:
78
+ - 1
79
+ - 0
80
+ - 3
81
+ version: 1.0.3
82
+ type: :development
83
+ version_requirements: *id004
84
+ description: Mock EM
85
+ email: support@rightscale.com
86
+ executables: []
87
+
88
+ extensions: []
89
+
90
+ extra_rdoc_files:
91
+ - LICENSE
92
+ - README.md
93
+ files:
94
+ - .gitignore
95
+ - .rspec
96
+ - CHANGELOG.rdoc
97
+ - Gemfile
98
+ - LICENSE
99
+ - README.md
100
+ - Rakefile
101
+ - lib/mock_em.rb
102
+ - lib/mock_em/logger_with_prefix.rb
103
+ - lib/mock_em/mock_em.rb
104
+ - lib/mock_em/version.rb
105
+ - mock_em.gemspec
106
+ - spec/lib/mock_em/mock_em_spec.rb
107
+ - spec/spec_helper.rb
108
+ homepage: https://github.com/rightscale/mock_em
109
+ licenses:
110
+ - MIT
111
+ post_install_message:
112
+ rdoc_options: []
113
+
114
+ require_paths:
115
+ - lib
116
+ required_ruby_version: !ruby/object:Gem::Requirement
117
+ none: false
118
+ requirements:
119
+ - - ">="
120
+ - !ruby/object:Gem::Version
121
+ hash: 3
122
+ segments:
123
+ - 0
124
+ version: "0"
125
+ required_rubygems_version: !ruby/object:Gem::Requirement
126
+ none: false
127
+ requirements:
128
+ - - ">="
129
+ - !ruby/object:Gem::Version
130
+ hash: 3
131
+ segments:
132
+ - 0
133
+ version: "0"
134
+ requirements: []
135
+
136
+ rubyforge_project:
137
+ rubygems_version: 1.8.15
138
+ signing_key:
139
+ specification_version: 3
140
+ summary: Mock for EM for testing.
141
+ test_files:
142
+ - spec/lib/mock_em/mock_em_spec.rb
143
+ - spec/spec_helper.rb
144
+ has_rdoc: