mock_em 0.1.0

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 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: