em-synchrony-moped 1.0.0.beta.3 → 2.0.0.beta.1
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.
- checksums.yaml +8 -8
- data/.travis.yml +1 -0
- data/Guardfile +1 -1
- data/em-synchrony-moped.gemspec +4 -4
- data/lib/em-synchrony/moped.rb +1 -0
- data/lib/em-synchrony/moped/address.rb +46 -0
- data/lib/em-synchrony/moped/connection.rb +79 -77
- data/lib/em-synchrony/moped/node.rb +31 -29
- data/spec/lib/em-synchrony/moped/connection_spec.rb +11 -11
- data/spec/support/simulated_mongod.rb +1 -1
- metadata +10 -10
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
ODA5NjIzNDY3MzZiYzk1MTU4ODRmMGE5Mjg3MjcxMWNkYzYxNzAyOA==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
ZjM0ZTVjMTEyZmY0NWZhYTBjNTgyMTFkY2ZjNTNiODAxNmI1MjA5Yg==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
OGM1MWY4YTBjNzY3ZWIzMDhmZjI0ZjBhYWM4NTM1MTU2YzVhMzdkNmJlOWFj
|
10
|
+
N2IzNDk1MTFiZGMyMGYyNmUwNmRlMmJkMWUwNzMwNWUyYTEyYTczNTEzNmRh
|
11
|
+
YjVkNzU5YjliYzU1Zjc5OTE4YTIxMGM5M2IwZTk5NzNmYjQ0MWE=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
OTAzYjhhMGZmMDVkZmFiMzdhNTUzMDA4ZTkwYjM4YWM4N2ZiZDFmOGViZGY3
|
14
|
+
ZDQwZTNkOTAwYWVhMjNjNzM4ZDcwNTkyYmJhNGU5OWUzM2QzMmRmMzQyODgy
|
15
|
+
ZDY0ZTVmNTU3MDU0NDBlMDVmODc2NTIzZmE4NDdmN2U5ODE3Yzk=
|
data/.travis.yml
CHANGED
data/Guardfile
CHANGED
data/em-synchrony-moped.gemspec
CHANGED
@@ -2,12 +2,12 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = 'em-synchrony-moped'
|
5
|
-
s.version = "
|
5
|
+
s.version = "2.0.0.beta.1"
|
6
6
|
|
7
7
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
8
8
|
s.authors = ["Adam Lebsack"]
|
9
9
|
s.email = ["alebsack@gmail.com"]
|
10
|
-
|
10
|
+
|
11
11
|
s.summary = 'Moped driver for EM-Synchrony'
|
12
12
|
s.description = 'EM-Synchrony-Moped is a Moped driver patch for ' +
|
13
13
|
'EM-Synchrony, allowing your asynchronous application use' +
|
@@ -22,11 +22,11 @@ Gem::Specification.new do |s|
|
|
22
22
|
|
23
23
|
s.add_runtime_dependency 'eventmachine', '~> 1.0'
|
24
24
|
s.add_runtime_dependency 'em-synchrony', '~> 1.0.3'
|
25
|
-
s.add_runtime_dependency 'moped', '~>
|
25
|
+
s.add_runtime_dependency 'moped', '~> 2.0.0'
|
26
26
|
s.add_runtime_dependency 'em-resolv-replace'
|
27
27
|
|
28
28
|
s.add_development_dependency 'rake'
|
29
|
-
s.add_development_dependency 'rspec'
|
29
|
+
s.add_development_dependency 'rspec', '~> 2.14.1'
|
30
30
|
s.add_development_dependency 'guard'
|
31
31
|
s.add_development_dependency 'guard-rspec'
|
32
32
|
s.add_development_dependency 'guard-bundler'
|
data/lib/em-synchrony/moped.rb
CHANGED
@@ -0,0 +1,46 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module Moped
|
3
|
+
class Address
|
4
|
+
|
5
|
+
alias_method :super_resolve, :resolve
|
6
|
+
# Override to support non-blocking DNS requests
|
7
|
+
def resolve(node)
|
8
|
+
return super_resolve(node) unless EventMachine.reactor_thread?
|
9
|
+
em_each_address(host).each do |ip|
|
10
|
+
if ip =~ Resolv::IPv4::Regex
|
11
|
+
@ip ||= ip
|
12
|
+
break
|
13
|
+
end
|
14
|
+
end
|
15
|
+
raise Resolv::ResolvError unless @ip
|
16
|
+
@resolved ||= "#{ip}:#{port}"
|
17
|
+
rescue Timeout::Error, Resolv::ResolvError, SocketError
|
18
|
+
Loggable.warn(" MOPED:", "Could not resolve IP for: #{original}", "n/a")
|
19
|
+
node.down! and false
|
20
|
+
end
|
21
|
+
|
22
|
+
def em_each_address(value)
|
23
|
+
puts "em_each_address: #{value.inspect}"
|
24
|
+
|
25
|
+
# Lookup in /etc/hosts
|
26
|
+
result = []
|
27
|
+
@hosts ||= Resolv::Hosts.new
|
28
|
+
@hosts.send(:each_address, value) { |x| result << x.to_s }
|
29
|
+
return result unless result.empty?
|
30
|
+
|
31
|
+
# Nothing, hit DNS
|
32
|
+
fiber = Fiber.current
|
33
|
+
df = EM::DnsResolver.send(:resolve, value)
|
34
|
+
df.callback do |a|
|
35
|
+
fiber.resume(a)
|
36
|
+
end
|
37
|
+
df.errback do |*a|
|
38
|
+
fiber.resume(Resolv::ResolvError.new(a.inspect))
|
39
|
+
end
|
40
|
+
result = Fiber.yield
|
41
|
+
fail result if result.is_a?(StandardError)
|
42
|
+
result
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
end
|
@@ -9,102 +9,104 @@ module Moped
|
|
9
9
|
def connect
|
10
10
|
return super_connect unless EventMachine.reactor_thread?
|
11
11
|
if !!options[:ssl]
|
12
|
-
@sock =
|
12
|
+
@sock = Socket::EmSSL.em_connect(host, port, timeout, options)
|
13
13
|
else
|
14
|
-
@sock =
|
14
|
+
@sock = Socket::EmTCP.em_connect(host, port, timeout, options)
|
15
15
|
end
|
16
16
|
end
|
17
|
-
end
|
18
17
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
18
|
+
module Socket
|
19
|
+
module Connectable
|
20
|
+
# Class methods to extend the Connectable Class
|
21
|
+
module ClassMethods
|
22
|
+
def em_connect(host, port, timeout, options)
|
23
|
+
socket = EventMachine.connect(host, port, self) do |c|
|
24
|
+
c.pending_connect_timeout = timeout
|
25
|
+
c.options = options
|
26
|
+
end
|
27
|
+
# In TCPSocket, new against a closed port raises Errno::ECONNREFUSED.
|
28
|
+
# In EM, connect against a closed port result in a call to unbind
|
29
|
+
# with a reason param of Errno::ECONNREFUSED as a class, not an
|
30
|
+
# instance.
|
31
|
+
unless socket.sync(:in) # wait for connection
|
32
|
+
fail socket.unbind_reason.new if socket.unbind_reason.is_a? Class
|
33
|
+
fail SocketError, socket.unbind_reason
|
34
|
+
end
|
35
|
+
socket
|
36
|
+
rescue Errno::ETIMEDOUT
|
37
|
+
raise Errors::ConnectionFailure,
|
38
|
+
"Timed out connection to Mongo on #{host}:#{port}"
|
39
|
+
rescue Errno::ECONNREFUSED, Errno::EHOSTUNREACH, Errno::EPIPE,
|
40
|
+
Errno::ECONNRESET, IOError => error
|
41
|
+
fail Errors::ConnectionFailure,
|
42
|
+
"#{host}:#{port}: #{error.class.name} (#{error.errno}): " +
|
43
|
+
"#{error.message}"
|
44
|
+
rescue SocketError => error
|
45
|
+
fail Errors::ConnectionFailure,
|
46
|
+
"#{host}:#{port}: #{error.class.name}: #{error.message}"
|
35
47
|
end
|
36
|
-
socket
|
37
|
-
rescue Errno::ETIMEDOUT
|
38
|
-
raise Errors::ConnectionFailure,
|
39
|
-
"Timed out connection to Mongo on #{host}:#{port}"
|
40
|
-
rescue Errno::ECONNREFUSED, Errno::EHOSTUNREACH, Errno::EPIPE,
|
41
|
-
Errno::ECONNRESET, IOError => error
|
42
|
-
fail Errors::ConnectionFailure,
|
43
|
-
"#{host}:#{port}: #{error.class.name} (#{error.errno}): " +
|
44
|
-
"#{error.message}"
|
45
|
-
rescue SocketError => error
|
46
|
-
fail Errors::ConnectionFailure,
|
47
|
-
"#{host}:#{port}: #{error.class.name}: #{error.message}"
|
48
48
|
end
|
49
49
|
end
|
50
|
-
end
|
51
50
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
51
|
+
# The EM-Synchrony flavor of Moped::Socket::TCP
|
52
|
+
class EmTCP < EventMachine::Synchrony::TCPSocket
|
53
|
+
include Connectable
|
54
|
+
attr_accessor :options
|
55
|
+
def alive?
|
56
|
+
!closed?
|
57
|
+
end
|
58
58
|
end
|
59
|
-
end
|
60
59
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
60
|
+
# The EM-Synchrony flavor of Moped::Socket::SSL
|
61
|
+
class EmSSL < EmTCP
|
62
|
+
def connection_completed
|
63
|
+
@verified = false
|
64
|
+
@cert_store = ssl_options.delete(:cert_store)
|
65
|
+
@cert_store ||= OpenSSL::X509::Store.new
|
66
|
+
if (cert_file = ssl_options.delete(:verify_cert))
|
67
|
+
@cert_store.add_file(cert_file)
|
68
|
+
end
|
69
|
+
start_tls(ssl_options)
|
69
70
|
end
|
70
|
-
start_tls(ssl_options)
|
71
|
-
end
|
72
71
|
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
72
|
+
def ssl_verify_peer(pem)
|
73
|
+
return true unless ssl_options[:verify_peer]
|
74
|
+
if (cert = certificate(pem)) && @cert_store.verify(cert)
|
75
|
+
# bypass hostname checking for this cert if it's a CA
|
76
|
+
return true if cert.extensions.find do |e|
|
77
|
+
e.oid == 'basicConstraints' && e.value == 'CA:TRUE'
|
78
|
+
end
|
79
|
+
|
80
|
+
@verified = true if (host = ssl_options[:verify_host]) &&
|
81
|
+
OpenSSL::SSL.verify_certificate_identity(cert, host)
|
79
82
|
end
|
80
83
|
|
81
|
-
|
82
|
-
|
84
|
+
# Always return true. We will evaluate the certificate chain in
|
85
|
+
# ssl_handshake_completed.
|
86
|
+
true
|
83
87
|
end
|
84
88
|
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
unbind 'Failed to verify SSL certificate of peer'
|
93
|
-
else
|
94
|
-
@opening = false
|
95
|
-
@in_req.succeed self
|
89
|
+
def ssl_handshake_completed
|
90
|
+
if ssl_options[:verify_peer] && !@verified
|
91
|
+
unbind 'Failed to verify SSL certificate of peer'
|
92
|
+
else
|
93
|
+
@opening = false
|
94
|
+
@in_req.succeed self
|
95
|
+
end
|
96
96
|
end
|
97
|
-
end
|
98
97
|
|
99
|
-
|
98
|
+
private
|
100
99
|
|
101
|
-
|
102
|
-
|
103
|
-
|
100
|
+
def ssl_options
|
101
|
+
@ssl_options ||= @options[:ssl] == true ? {} : @options[:ssl] || {}
|
102
|
+
end
|
104
103
|
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
104
|
+
def certificate(pem)
|
105
|
+
OpenSSL::X509::Certificate.new(pem)
|
106
|
+
end
|
107
|
+
end # EmSSL
|
108
|
+
end
|
109
109
|
end
|
110
110
|
end
|
111
|
+
|
112
|
+
puts Moped::Connection::Socket::EmSSL.inspect
|
@@ -7,39 +7,41 @@ require 'fiber'
|
|
7
7
|
module Moped
|
8
8
|
# # Our monkey patches to Moped::Node
|
9
9
|
class Node
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
10
|
+
if Moped::VERSION < "2.0.0"
|
11
|
+
alias_method :super_parse_address, :parse_address
|
12
|
+
# Override to support non-blocking DNS requests
|
13
|
+
def parse_address
|
14
|
+
return super_parse_address unless EventMachine.reactor_thread?
|
15
|
+
host, port = address.split(':')
|
16
|
+
@port = (port || 27_017).to_i
|
16
17
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
18
|
+
@ip_address = em_lookup_address(host).grep(/(::){0}/).first
|
19
|
+
fail SocketError unless @ip_address
|
20
|
+
@resolved_address = "#{@ip_address}:#{@port}"
|
21
|
+
rescue Resolv::ResolvError
|
22
|
+
raise SocketError
|
23
|
+
end
|
23
24
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
25
|
+
def em_lookup_address(value)
|
26
|
+
# Lookup in /etc/hosts
|
27
|
+
result = []
|
28
|
+
@hosts ||= Resolv::Hosts.new
|
29
|
+
@hosts.send(:each_address, value) { |x| result << x.to_s if x !~ /::/ }
|
30
|
+
return result unless result.empty?
|
30
31
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
32
|
+
# Nothing, hit DNS
|
33
|
+
fiber = Fiber.current
|
34
|
+
df = EM::DnsResolver.send(:resolve, value)
|
35
|
+
df.callback do |a|
|
36
|
+
fiber.resume(a)
|
37
|
+
end
|
38
|
+
df.errback do |*a|
|
39
|
+
fiber.resume(Resolv::ResolvError.new(a.inspect))
|
40
|
+
end
|
41
|
+
result = Fiber.yield
|
42
|
+
fail result if result.is_a?(StandardError)
|
43
|
+
result
|
39
44
|
end
|
40
|
-
result = Fiber.yield
|
41
|
-
fail result if result.is_a?(StandardError)
|
42
|
-
result
|
43
45
|
end
|
44
46
|
end
|
45
47
|
end
|
@@ -6,7 +6,7 @@ require 'em-synchrony/moped'
|
|
6
6
|
|
7
7
|
describe Moped::Connection do
|
8
8
|
it 'should have patches included' do
|
9
|
-
expect { Moped::
|
9
|
+
expect { Moped::Connection::Socket::EmTCP }.not_to raise_error
|
10
10
|
end
|
11
11
|
|
12
12
|
let(:mongod_options) { {} }
|
@@ -51,7 +51,7 @@ describe Moped::Connection do
|
|
51
51
|
|
52
52
|
context 'evented' do
|
53
53
|
include_context 'with em-synchrony'
|
54
|
-
let(:connection_class) { Moped::
|
54
|
+
let(:connection_class) { Moped::Connection::Socket::EmTCP }
|
55
55
|
include_context 'common connection'
|
56
56
|
context 'with ssl' do
|
57
57
|
let(:ssl_options) { nil }
|
@@ -70,7 +70,7 @@ describe Moped::Connection do
|
|
70
70
|
let(:ssl_options) { nil }
|
71
71
|
let(:options) { {} }
|
72
72
|
it 'should connect (though comms will fail later)' do
|
73
|
-
expect(conn.connect).to be_a(Moped::
|
73
|
+
expect(conn.connect).to be_a(Moped::Connection::Socket::EmTCP)
|
74
74
|
end
|
75
75
|
end
|
76
76
|
|
@@ -78,21 +78,21 @@ describe Moped::Connection do
|
|
78
78
|
context 'when specifying ssl: true' do
|
79
79
|
let(:ssl_options) { true }
|
80
80
|
it 'should connect' do
|
81
|
-
expect(conn.connect).to be_a(Moped::
|
81
|
+
expect(conn.connect).to be_a(Moped::Connection::Socket::EmSSL)
|
82
82
|
end
|
83
83
|
end
|
84
84
|
|
85
85
|
context 'when specifying ssl: {}' do
|
86
86
|
let(:ssl_options) { {} }
|
87
87
|
it 'should connect' do
|
88
|
-
expect(conn.connect).to be_a(Moped::
|
88
|
+
expect(conn.connect).to be_a(Moped::Connection::Socket::EmSSL)
|
89
89
|
end
|
90
90
|
end
|
91
91
|
|
92
92
|
context 'when not verifying peer' do
|
93
93
|
let(:ssl_options) { { verify_peer: false } }
|
94
94
|
it 'should connect' do
|
95
|
-
expect(conn.connect).to be_a(Moped::
|
95
|
+
expect(conn.connect).to be_a(Moped::Connection::Socket::EmSSL)
|
96
96
|
end
|
97
97
|
end
|
98
98
|
|
@@ -149,7 +149,7 @@ describe Moped::Connection do
|
|
149
149
|
}
|
150
150
|
end
|
151
151
|
it 'should connect' do
|
152
|
-
expect(conn.connect).to be_a(Moped::
|
152
|
+
expect(conn.connect).to be_a(Moped::Connection::Socket::EmSSL)
|
153
153
|
end
|
154
154
|
end
|
155
155
|
end # 'and a certificate is provided'
|
@@ -169,21 +169,21 @@ describe Moped::Connection do
|
|
169
169
|
context 'when specifying ssl: true' do
|
170
170
|
let(:ssl_options) { true }
|
171
171
|
it 'should connect' do
|
172
|
-
expect(conn.connect).to be_a(Moped::
|
172
|
+
expect(conn.connect).to be_a(Moped::Connection::Socket::EmSSL)
|
173
173
|
end
|
174
174
|
end
|
175
175
|
|
176
176
|
context 'when specifying ssl: {}' do
|
177
177
|
let(:ssl_options) { {} }
|
178
178
|
it 'should connect' do
|
179
|
-
expect(conn.connect).to be_a(Moped::
|
179
|
+
expect(conn.connect).to be_a(Moped::Connection::Socket::EmSSL)
|
180
180
|
end
|
181
181
|
end
|
182
182
|
|
183
183
|
context 'when not verifying peer' do
|
184
184
|
let(:ssl_options) { { verify_peer: false } }
|
185
185
|
it 'should connect' do
|
186
|
-
expect(conn.connect).to be_a(Moped::
|
186
|
+
expect(conn.connect).to be_a(Moped::Connection::Socket::EmSSL)
|
187
187
|
end
|
188
188
|
end
|
189
189
|
|
@@ -255,7 +255,7 @@ describe Moped::Connection do
|
|
255
255
|
|
256
256
|
context 'threaded' do
|
257
257
|
include_context 'without em-synchrony'
|
258
|
-
let(:connection_class) { Moped::
|
258
|
+
let(:connection_class) { Moped::Connection::Socket::TCP }
|
259
259
|
include_context 'common connection'
|
260
260
|
end
|
261
261
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: em-synchrony-moped
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0.beta.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Adam Lebsack
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2014-09-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: eventmachine
|
@@ -44,14 +44,14 @@ dependencies:
|
|
44
44
|
requirements:
|
45
45
|
- - ~>
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version:
|
47
|
+
version: 2.0.0
|
48
48
|
type: :runtime
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
52
|
- - ~>
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version:
|
54
|
+
version: 2.0.0
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: em-resolv-replace
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -84,16 +84,16 @@ dependencies:
|
|
84
84
|
name: rspec
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
86
86
|
requirements:
|
87
|
-
- -
|
87
|
+
- - ~>
|
88
88
|
- !ruby/object:Gem::Version
|
89
|
-
version:
|
89
|
+
version: 2.14.1
|
90
90
|
type: :development
|
91
91
|
prerelease: false
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
93
93
|
requirements:
|
94
|
-
- -
|
94
|
+
- - ~>
|
95
95
|
- !ruby/object:Gem::Version
|
96
|
-
version:
|
96
|
+
version: 2.14.1
|
97
97
|
- !ruby/object:Gem::Dependency
|
98
98
|
name: guard
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|
@@ -209,6 +209,7 @@ files:
|
|
209
209
|
- Rakefile
|
210
210
|
- em-synchrony-moped.gemspec
|
211
211
|
- lib/em-synchrony/moped.rb
|
212
|
+
- lib/em-synchrony/moped/address.rb
|
212
213
|
- lib/em-synchrony/moped/cluster.rb
|
213
214
|
- lib/em-synchrony/moped/connection.rb
|
214
215
|
- lib/em-synchrony/moped/node.rb
|
@@ -243,7 +244,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
243
244
|
version: '0'
|
244
245
|
requirements: []
|
245
246
|
rubyforge_project:
|
246
|
-
rubygems_version: 2.
|
247
|
+
rubygems_version: 2.2.2
|
247
248
|
signing_key:
|
248
249
|
specification_version: 4
|
249
250
|
summary: Moped driver for EM-Synchrony
|
@@ -259,4 +260,3 @@ test_files:
|
|
259
260
|
- spec/ssl/untrusted.key
|
260
261
|
- spec/support/contexts.rb
|
261
262
|
- spec/support/simulated_mongod.rb
|
262
|
-
has_rdoc:
|