zk 1.0.0 → 1.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 +1 -0
- data/.travis.yml +6 -8
- data/Gemfile +4 -6
- data/README.markdown +39 -21
- data/Rakefile +4 -2
- data/lib/zk.rb +60 -5
- data/lib/zk/client/base.rb +31 -9
- data/lib/zk/client/threaded.rb +39 -20
- data/lib/zk/election.rb +42 -38
- data/lib/zk/event.rb +8 -0
- data/lib/zk/event_handler.rb +38 -7
- data/lib/zk/event_handler_subscription.rb +19 -55
- data/lib/zk/event_handler_subscription/actor.rb +38 -0
- data/lib/zk/event_handler_subscription/base.rb +76 -0
- data/lib/zk/threaded_callback.rb +56 -0
- data/lib/zk/threadpool.rb +1 -3
- data/lib/zk/version.rb +1 -1
- data/spec/event_catcher_spec.rb +29 -0
- data/spec/message_queue_spec.rb +2 -2
- data/spec/shared/client_contexts.rb +20 -10
- data/spec/shared/client_examples.rb +1 -1
- data/spec/spec_helper.rb +22 -7
- data/spec/support/00_test_port_attr.rb +20 -0
- data/spec/support/event_catcher.rb +73 -5
- data/spec/support/logging.rb +3 -1
- data/spec/support/pendings.rb +52 -0
- data/spec/support/wait_watchers.rb +10 -1
- data/spec/watch_spec.rb +143 -124
- data/spec/zk/client_spec.rb +15 -3
- data/spec/zk/election_spec.rb +12 -14
- data/spec/zk/locker_spec.rb +17 -12
- data/spec/zk/module_spec.rb +20 -12
- data/spec/zk/mongoid_spec.rb +3 -1
- data/spec/zk/pool_spec.rb +3 -3
- data/spec/zookeeper_spec.rb +2 -2
- metadata +13 -4
data/spec/zk/client_spec.rb
CHANGED
@@ -1,11 +1,23 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe ZK::Client::Threaded do
|
4
|
-
|
5
|
-
|
4
|
+
context do
|
5
|
+
include_context 'threaded client connection'
|
6
|
+
it_should_behave_like 'client'
|
7
|
+
end
|
6
8
|
|
7
9
|
describe :close! do
|
8
10
|
describe 'from a threadpool thread' do
|
11
|
+
include_context 'connection opts'
|
12
|
+
|
13
|
+
before do
|
14
|
+
@zk = ZK::Client::Threaded.new(*connection_args).tap { |z| wait_until { z.connected? } }
|
15
|
+
end
|
16
|
+
|
17
|
+
after do
|
18
|
+
@zk.close! unless @zk.closed?
|
19
|
+
end
|
20
|
+
|
9
21
|
it %[should do the right thing and not fail] do
|
10
22
|
# this is an extra special case where the user obviously hates us
|
11
23
|
|
@@ -15,7 +27,7 @@ describe ZK::Client::Threaded do
|
|
15
27
|
@zk.close!
|
16
28
|
end
|
17
29
|
|
18
|
-
wait_until { @zk.closed? }.should be_true
|
30
|
+
wait_until(5) { @zk.closed? }.should be_true
|
19
31
|
end
|
20
32
|
end
|
21
33
|
end
|
data/spec/zk/election_spec.rb
CHANGED
@@ -1,14 +1,16 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe ZK::Election do
|
4
|
+
include_context 'connection opts'
|
5
|
+
|
4
6
|
before do
|
5
|
-
ZK.open(
|
7
|
+
ZK.open(connection_host) do |cnx|
|
6
8
|
ZK.logger.debug { "REMOVING /_zkelection" }
|
7
9
|
cnx.rm_rf('/_zkelection')
|
8
10
|
end
|
9
11
|
|
10
|
-
@zk = ZK.new(
|
11
|
-
@zk2 = ZK.new(
|
12
|
+
@zk = ZK.new(*connection_args)
|
13
|
+
@zk2 = ZK.new(*connection_args)
|
12
14
|
@election_name = '2012'
|
13
15
|
@data1 = 'obama'
|
14
16
|
@data2 = 'palin'
|
@@ -18,7 +20,7 @@ describe ZK::Election do
|
|
18
20
|
@zk.close!
|
19
21
|
@zk2.close!
|
20
22
|
|
21
|
-
ZK.open(
|
23
|
+
ZK.open(connection_host) { |cnx| cnx.rm_rf('/_zkelection') }
|
22
24
|
end
|
23
25
|
|
24
26
|
describe 'Candidate', 'following next_node' do
|
@@ -146,6 +148,8 @@ describe ZK::Election do
|
|
146
148
|
end
|
147
149
|
|
148
150
|
it %[should take over as leader when the current leader goes away] do
|
151
|
+
pending_187("1.8.7's AWESOEM thread scheduler makes this test deadlock")
|
152
|
+
|
149
153
|
@obama.zk.close!
|
150
154
|
wait_until { @palin_won }
|
151
155
|
|
@@ -159,10 +163,11 @@ describe ZK::Election do
|
|
159
163
|
end
|
160
164
|
|
161
165
|
it %[should remain leader if the original leader comes back] do
|
166
|
+
pending_187("1.8.7's AWESOEM thread scheduler makes this test deadlock")
|
162
167
|
@obama.zk.close!
|
163
168
|
wait_until { @palin_won }
|
164
169
|
|
165
|
-
ZK.open(
|
170
|
+
ZK.open(*connection_args) do |zk|
|
166
171
|
newbama = ZK::Election::Candidate.new(zk, @election_name, :data => @data1)
|
167
172
|
|
168
173
|
win_again = false
|
@@ -186,7 +191,7 @@ describe ZK::Election do
|
|
186
191
|
|
187
192
|
describe :Observer do
|
188
193
|
before do
|
189
|
-
@zk3 = ZK.new(
|
194
|
+
@zk3 = ZK.new(*connection_args)
|
190
195
|
|
191
196
|
@zk3.exists?('/_zkelection/2012/leader_ack').should be_false
|
192
197
|
|
@@ -260,16 +265,9 @@ describe ZK::Election do
|
|
260
265
|
end
|
261
266
|
end
|
262
267
|
|
263
|
-
def pending_192(msg)
|
264
|
-
if RUBY_VERSION == '1.9.2' and not defined?(::JRUBY_VERSION)
|
265
|
-
pending(msg) { yield }
|
266
|
-
else
|
267
|
-
yield
|
268
|
-
end
|
269
|
-
end
|
270
|
-
|
271
268
|
describe 'leadership transition' do
|
272
269
|
before do
|
270
|
+
pending_187("1.8.7's AWESOEM thread scheduler makes this test deadlock")
|
273
271
|
@obama.vote!
|
274
272
|
wait_until { @obama.leader? }
|
275
273
|
|
data/spec/zk/locker_spec.rb
CHANGED
@@ -4,11 +4,12 @@ require 'spec_helper'
|
|
4
4
|
# from ZK::Client#locker
|
5
5
|
#
|
6
6
|
describe 'ZK::Client#locker' do
|
7
|
+
include_context 'connection opts'
|
7
8
|
|
8
9
|
before(:each) do
|
9
|
-
@zk = ZK.new("localhost:#{
|
10
|
-
@zk2 = ZK.new("localhost:#{
|
11
|
-
@zk3 = ZK.new("localhost:#{
|
10
|
+
@zk = ZK.new("localhost:#{ZK.test_port}", connection_opts)
|
11
|
+
@zk2 = ZK.new("localhost:#{ZK.test_port}", connection_opts)
|
12
|
+
@zk3 = ZK.new("localhost:#{ZK.test_port}", connection_opts)
|
12
13
|
@connections = [@zk, @zk2, @zk3]
|
13
14
|
wait_until { @connections.all? { |c| c.connected? } }
|
14
15
|
@path_to_lock = "/lock_tester"
|
@@ -79,7 +80,7 @@ end
|
|
79
80
|
# describe 'exception' do
|
80
81
|
# before do
|
81
82
|
# @path = '/zk_test'
|
82
|
-
# @zk = ZK.new("localhost:#{
|
83
|
+
# @zk = ZK.new("localhost:#{ZK.test_port}")
|
83
84
|
# @zk.create(@path) rescue ZK::Exceptions::NodeExists
|
84
85
|
# end
|
85
86
|
|
@@ -406,9 +407,11 @@ end # shared-exclusive interaction
|
|
406
407
|
|
407
408
|
|
408
409
|
describe ZK::Locker do
|
409
|
-
|
410
|
-
|
411
|
-
let(:
|
410
|
+
include_context 'connection opts'
|
411
|
+
|
412
|
+
let(:zk) { ZK.new("localhost:#{ZK.test_port}", connection_opts) }
|
413
|
+
let(:zk2) { ZK.new("localhost:#{ZK.test_port}", connection_opts) }
|
414
|
+
let(:zk3) { ZK.new("localhost:#{ZK.test_port}", connection_opts) }
|
412
415
|
|
413
416
|
let(:connections) { [zk, zk2, zk3] }
|
414
417
|
|
@@ -430,13 +433,15 @@ describe ZK::Locker do
|
|
430
433
|
end # ZK::Locker
|
431
434
|
|
432
435
|
describe "ZK::Locker chrooted" do
|
436
|
+
include_context 'connection opts'
|
437
|
+
|
433
438
|
let(:chroot_path) { '/_zk_chroot_' }
|
434
439
|
|
435
|
-
let(:zk) { ZK.new("localhost:#{
|
440
|
+
let(:zk) { ZK.new("localhost:#{ZK.test_port}#{chroot_path}", connection_opts) }
|
436
441
|
|
437
442
|
describe 'when the chroot exists' do
|
438
|
-
let(:zk2) { ZK.new("localhost:#{
|
439
|
-
let(:zk3) { ZK.new("localhost:#{
|
443
|
+
let(:zk2) { ZK.new("localhost:#{ZK.test_port}#{chroot_path}", connection_opts) }
|
444
|
+
let(:zk3) { ZK.new("localhost:#{ZK.test_port}#{chroot_path}", connection_opts) }
|
440
445
|
|
441
446
|
let(:connections) { [zk, zk2, zk3] }
|
442
447
|
|
@@ -444,7 +449,7 @@ describe "ZK::Locker chrooted" do
|
|
444
449
|
let(:root_lock_path) { "/_zklocking/#{path}" }
|
445
450
|
|
446
451
|
before do
|
447
|
-
ZK.open("localhost:#{
|
452
|
+
ZK.open("localhost:#{ZK.test_port}") do |zk|
|
448
453
|
zk.mkdir_p(chroot_path)
|
449
454
|
end
|
450
455
|
|
@@ -455,7 +460,7 @@ describe "ZK::Locker chrooted" do
|
|
455
460
|
connections.each { |c| c.close! }
|
456
461
|
wait_until { !connections.any?(&:connected?) }
|
457
462
|
|
458
|
-
ZK.open("localhost:#{
|
463
|
+
ZK.open("localhost:#{ZK.test_port}") do |zk|
|
459
464
|
zk.rm_rf(chroot_path)
|
460
465
|
end
|
461
466
|
end
|
data/spec/zk/module_spec.rb
CHANGED
@@ -4,17 +4,24 @@ require 'spec_helper'
|
|
4
4
|
|
5
5
|
describe ZK do
|
6
6
|
describe :new do
|
7
|
+
include_context 'connection opts'
|
8
|
+
|
7
9
|
let(:chroot_path) { '/zktest/path/to/chroot' }
|
8
10
|
|
11
|
+
before do
|
12
|
+
ZK.open(*connection_args) { |z| z.rm_rf('/zktest') }
|
13
|
+
end
|
14
|
+
|
9
15
|
after do
|
10
16
|
mute_logger do
|
11
17
|
@zk.close! if @zk and not @zk.closed?
|
18
|
+
ZK.open(*connection_args) { |z| z.rm_rf('/zktest') }
|
12
19
|
end
|
13
20
|
end
|
14
21
|
|
15
22
|
describe %[with a chrooted connection string and a :chroot => '/path'] do
|
16
23
|
it %[should raise an ArgumentError] do
|
17
|
-
lambda { @zk = ZK.new(
|
24
|
+
lambda { @zk = ZK.new("#{connection_host}/zktest", :chroot => '/zktest') }.should raise_error(ArgumentError)
|
18
25
|
end
|
19
26
|
end
|
20
27
|
|
@@ -29,7 +36,7 @@ describe ZK do
|
|
29
36
|
describe %[with a chroot] do
|
30
37
|
before do
|
31
38
|
mute_logger do
|
32
|
-
@unchroot = ZK.new
|
39
|
+
@unchroot = ZK.new(*connection_args)
|
33
40
|
end
|
34
41
|
end
|
35
42
|
|
@@ -57,7 +64,8 @@ describe ZK do
|
|
57
64
|
describe %[as a connection string] do
|
58
65
|
describe %[and no explicit option] do
|
59
66
|
before do
|
60
|
-
@zk = ZK.new("
|
67
|
+
@zk = ZK.new("#{connection_host}#{chroot_path}") # implicit create
|
68
|
+
wait_until { @zk.connected? }
|
61
69
|
end
|
62
70
|
|
63
71
|
it %[should create the chroot path and then return the connection] do
|
@@ -70,7 +78,7 @@ describe ZK do
|
|
70
78
|
|
71
79
|
describe %[and an explicit :chroot => :create] do
|
72
80
|
before do
|
73
|
-
@zk = ZK.new("
|
81
|
+
@zk = ZK.new("#{connection_host}#{chroot_path}", :chroot => :create)
|
74
82
|
end
|
75
83
|
|
76
84
|
it %[should create the chroot path and then return the connection] do
|
@@ -85,20 +93,20 @@ describe ZK do
|
|
85
93
|
it %[should barf with a ChrootPathDoesNotExistError] do
|
86
94
|
lambda do
|
87
95
|
# assign in case of a bug, that way this connection will get torn down
|
88
|
-
@zk = ZK.new("
|
96
|
+
@zk = ZK.new("#{connection_host}#{chroot_path}", :chroot => :check)
|
89
97
|
end.should raise_error(ZK::Exceptions::ChrootPathDoesNotExistError)
|
90
98
|
end
|
91
99
|
end
|
92
100
|
|
93
101
|
describe %[and :chroot => :do_nothing] do
|
94
102
|
it %[should return a connection in a weird state] do
|
95
|
-
@zk = ZK.new("
|
103
|
+
@zk = ZK.new("#{connection_host}#{chroot_path}", :chroot => :do_nothing)
|
96
104
|
lambda { @zk.get('/') }.should raise_error(ZK::Exceptions::NoNode)
|
97
105
|
end
|
98
106
|
end
|
99
107
|
|
100
108
|
describe %[and :chroot => '/path'] do
|
101
|
-
before { @zk = ZK.new(
|
109
|
+
before { @zk = ZK.new(connection_host, :chroot => chroot_path) }
|
102
110
|
|
103
111
|
it %[should create the chroot path and then return the connection] do
|
104
112
|
@zk.exists?('/').should be_true
|
@@ -127,7 +135,7 @@ describe ZK do
|
|
127
135
|
describe %[as a connection string] do
|
128
136
|
describe %[and no explicit option] do
|
129
137
|
before do
|
130
|
-
@zk = ZK.new("
|
138
|
+
@zk = ZK.new("#{connection_host}#{chroot_path}") # implicit create
|
131
139
|
end
|
132
140
|
|
133
141
|
it %[should totally work] do
|
@@ -140,7 +148,7 @@ describe ZK do
|
|
140
148
|
|
141
149
|
describe %[and an explicit :chroot => :create] do
|
142
150
|
before do
|
143
|
-
@zk = ZK.new("
|
151
|
+
@zk = ZK.new("#{connection_host}#{chroot_path}", :chroot => :create)
|
144
152
|
end
|
145
153
|
|
146
154
|
it %[should totally work] do
|
@@ -155,20 +163,20 @@ describe ZK do
|
|
155
163
|
it %[should totally work] do
|
156
164
|
lambda do
|
157
165
|
# assign in case of a bug, that way this connection will get torn down
|
158
|
-
@zk = ZK.new("
|
166
|
+
@zk = ZK.new("#{connection_host}#{chroot_path}", :chroot => :check)
|
159
167
|
end.should_not raise_error
|
160
168
|
end
|
161
169
|
end
|
162
170
|
|
163
171
|
describe %[and :chroot => :do_nothing] do
|
164
172
|
it %[should totally work] do
|
165
|
-
@zk = ZK.new("
|
173
|
+
@zk = ZK.new("#{connection_host}#{chroot_path}", :chroot => :do_nothing)
|
166
174
|
lambda { @zk.get('/') }.should_not raise_error
|
167
175
|
end
|
168
176
|
end
|
169
177
|
|
170
178
|
describe %[and :chroot => '/path'] do
|
171
|
-
before { @zk = ZK.new(
|
179
|
+
before { @zk = ZK.new(connection_host, :chroot => chroot_path) }
|
172
180
|
|
173
181
|
it %[should totally work] do
|
174
182
|
@zk.exists?('/').should be_true
|
data/spec/zk/mongoid_spec.rb
CHANGED
@@ -1,8 +1,10 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe ZK::Mongoid::Locking do
|
4
|
+
include_context 'connection opts'
|
5
|
+
|
4
6
|
before do
|
5
|
-
ZK::Mongoid::Locking.zk_lock_pool = ZK.new_pool(
|
7
|
+
ZK::Mongoid::Locking.zk_lock_pool = ZK.new_pool(connection_host, :min_clients => 1, :max_clients => 5)
|
6
8
|
|
7
9
|
@doc = BogusMongoid.new
|
8
10
|
@other_doc = BogusMongoid.new
|
data/spec/zk/pool_spec.rb
CHANGED
@@ -6,7 +6,7 @@ describe ZK::Pool do
|
|
6
6
|
before do
|
7
7
|
report_realtime('opening pool') do
|
8
8
|
@pool_size = 2
|
9
|
-
@connection_pool = ZK::Pool::Simple.new("localhost:#{
|
9
|
+
@connection_pool = ZK::Pool::Simple.new("localhost:#{ZK.test_port}", @pool_size, :watcher => :default)
|
10
10
|
@connection_pool.should be_open
|
11
11
|
end
|
12
12
|
end
|
@@ -27,7 +27,7 @@ describe ZK::Pool do
|
|
27
27
|
end
|
28
28
|
|
29
29
|
report_realtime("closing") do
|
30
|
-
ZK.open("localhost:#{
|
30
|
+
ZK.open("localhost:#{ZK.test_port}") do |zk|
|
31
31
|
zk.delete('/test_pool') rescue ZK::Exceptions::NoNode
|
32
32
|
end
|
33
33
|
end
|
@@ -197,7 +197,7 @@ describe ZK::Pool do
|
|
197
197
|
before do
|
198
198
|
@min_clients = 1
|
199
199
|
@max_clients = 2
|
200
|
-
@connection_pool = ZK::Pool::Bounded.new("localhost:#{
|
200
|
+
@connection_pool = ZK::Pool::Bounded.new("localhost:#{ZK.test_port}", :min_clients => @min_clients, :max_clients => @max_clients, :timeout => @timeout)
|
201
201
|
@connection_pool.should be_open
|
202
202
|
wait_until(2) { @connection_pool.available_size > 0 }
|
203
203
|
end
|
data/spec/zookeeper_spec.rb
CHANGED
@@ -39,7 +39,7 @@ shared_examples_for 'ZK basic' do
|
|
39
39
|
wait_until(2) { !@zk.connected? }
|
40
40
|
@zk.should_not be_connected
|
41
41
|
|
42
|
-
@zk = ZK.new(
|
42
|
+
@zk = ZK.new(*connection_args)
|
43
43
|
wait_until{ @zk.connected? }
|
44
44
|
@zk.exists?("#{@base_path}/test").should be_false
|
45
45
|
end
|
@@ -50,7 +50,7 @@ shared_examples_for 'ZK basic' do
|
|
50
50
|
@zk.exists?(created).should_not be_nil
|
51
51
|
@zk.close!
|
52
52
|
|
53
|
-
@zk = ZK.new(
|
53
|
+
@zk = ZK.new(*connection_args)
|
54
54
|
wait_until{ @zk.connected? }
|
55
55
|
@zk.exists?(created).should be_false
|
56
56
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: zk
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 19
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 1
|
8
|
+
- 1
|
8
9
|
- 0
|
9
|
-
|
10
|
-
version: 1.0.0
|
10
|
+
version: 1.1.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Jonathan D. Simms
|
@@ -16,7 +16,7 @@ autorequire:
|
|
16
16
|
bindir: bin
|
17
17
|
cert_chain: []
|
18
18
|
|
19
|
-
date: 2012-
|
19
|
+
date: 2012-05-02 00:00:00 Z
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
22
22
|
name: slyphon-zookeeper
|
@@ -72,6 +72,8 @@ files:
|
|
72
72
|
- lib/zk/event.rb
|
73
73
|
- lib/zk/event_handler.rb
|
74
74
|
- lib/zk/event_handler_subscription.rb
|
75
|
+
- lib/zk/event_handler_subscription/actor.rb
|
76
|
+
- lib/zk/event_handler_subscription/base.rb
|
75
77
|
- lib/zk/exceptions.rb
|
76
78
|
- lib/zk/extensions.rb
|
77
79
|
- lib/zk/find.rb
|
@@ -81,8 +83,10 @@ files:
|
|
81
83
|
- lib/zk/mongoid.rb
|
82
84
|
- lib/zk/pool.rb
|
83
85
|
- lib/zk/stat.rb
|
86
|
+
- lib/zk/threaded_callback.rb
|
84
87
|
- lib/zk/threadpool.rb
|
85
88
|
- lib/zk/version.rb
|
89
|
+
- spec/event_catcher_spec.rb
|
86
90
|
- spec/informal/close-in-event-thread.rb
|
87
91
|
- spec/informal/lock_with_dead_session.rb
|
88
92
|
- spec/informal/what-the-fork.rb
|
@@ -91,11 +95,13 @@ files:
|
|
91
95
|
- spec/shared/client_contexts.rb
|
92
96
|
- spec/shared/client_examples.rb
|
93
97
|
- spec/spec_helper.rb
|
98
|
+
- spec/support/00_test_port_attr.rb
|
94
99
|
- spec/support/bogus_mongoid.rb
|
95
100
|
- spec/support/event_catcher.rb
|
96
101
|
- spec/support/exist_matcher.rb
|
97
102
|
- spec/support/logging.rb
|
98
103
|
- spec/support/logging_progress_bar_formatter.rb
|
104
|
+
- spec/support/pendings.rb
|
99
105
|
- spec/support/queuey_thread.rb
|
100
106
|
- spec/support/special_happy_funtime_error.rb
|
101
107
|
- spec/support/wait_watchers.rb
|
@@ -146,6 +152,7 @@ signing_key:
|
|
146
152
|
specification_version: 3
|
147
153
|
summary: A high-level wrapper around the zookeeper driver
|
148
154
|
test_files:
|
155
|
+
- spec/event_catcher_spec.rb
|
149
156
|
- spec/informal/close-in-event-thread.rb
|
150
157
|
- spec/informal/lock_with_dead_session.rb
|
151
158
|
- spec/informal/what-the-fork.rb
|
@@ -154,11 +161,13 @@ test_files:
|
|
154
161
|
- spec/shared/client_contexts.rb
|
155
162
|
- spec/shared/client_examples.rb
|
156
163
|
- spec/spec_helper.rb
|
164
|
+
- spec/support/00_test_port_attr.rb
|
157
165
|
- spec/support/bogus_mongoid.rb
|
158
166
|
- spec/support/event_catcher.rb
|
159
167
|
- spec/support/exist_matcher.rb
|
160
168
|
- spec/support/logging.rb
|
161
169
|
- spec/support/logging_progress_bar_formatter.rb
|
170
|
+
- spec/support/pendings.rb
|
162
171
|
- spec/support/queuey_thread.rb
|
163
172
|
- spec/support/special_happy_funtime_error.rb
|
164
173
|
- spec/support/wait_watchers.rb
|