em-synchrony-moped 1.0.0.beta.1 → 1.0.0.beta.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/.travis.yml +5 -0
- data/Gemfile +1 -1
- data/Guardfile +1 -1
- data/README.md +9 -3
- data/em-synchrony-moped.gemspec +5 -4
- data/lib/em-synchrony/moped/cluster.rb +1 -5
- data/lib/em-synchrony/moped/connection.rb +40 -52
- data/lib/em-synchrony/moped/node.rb +8 -11
- data/spec/lib/em-synchrony/moped/connection_spec.rb +196 -71
- data/spec/lib/em-synchrony/moped/node_spec.rb +5 -3
- data/spec/spec_helper.rb +8 -0
- data/spec/support/contexts.rb +6 -4
- data/spec/support/simulated_mongod.rb +1 -1
- metadata +27 -12
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
YzlmYzgxNjFkMDA3MjZmY2RkYjQwMjU5NjBkMTQ4Nzc1Yzk0ZjY2NQ==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
ZjM4ZmMxNTJlZTU1MWQ1YTJhNDU3YjY3OTE3MzVhMGM2YjMzYTA5Mg==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
MTgyMzg5YTI5NmE0ZTI0MWU5NTA0Y2UzYjc0ZTc0M2ZlZDA1OGE1NzQ1MTlj
|
10
|
+
YTEyY2IwM2UxMjIxYmFmYzRjNzQ0NDQzYmYwN2ZlYjUzYTJmODNmZTZkM2Ex
|
11
|
+
ZmIyOTAzY2IyODMxZjlmZjljMmVhOTUxZDNhZTRhYjE5ZDc4NTU=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
YmVkZTRhOTYwNjBmMjc1MjdlZDM4MTIxNzAxNzhmMThjZDdmYjJkYjdjNTFj
|
14
|
+
NGFmMGUxNWMwNGQ0YjcwNmM5YjhmMjZiMjJhMGZjZjdhMzc4ZGFjNmJjZmU0
|
15
|
+
MGRmZGQ0ZDRmYzhhNGJiNWVkOTdlNWExODk4NWJkOGExZWFkOWI=
|
data/.travis.yml
ADDED
data/Gemfile
CHANGED
data/Guardfile
CHANGED
data/README.md
CHANGED
@@ -1,8 +1,14 @@
|
|
1
|
-
|
1
|
+
EM-Synchrony-Moped
|
2
|
+
=====
|
3
|
+
[![Gem Version](https://badge.fury.io/rb/em-synchrony-moped.png)](http://badge.fury.io/rb/em-synchrony-moped) [![Dependency Status](https://gemnasium.com/alebsack/em-synchrony-moped.png)](https://gemnasium.com/alebsack/em-synchrony-moped) [![Build Status](https://travis-ci.org/alebsack/em-synchrony-moped.png?branch=master)](https://travis-ci.org/alebsack/em-synchrony-moped) [![Coverage Status](https://coveralls.io/repos/alebsack/em-synchrony-moped/badge.png?branch=master)](https://coveralls.io/r/alebsack/em-synchrony-moped?branch=master) [![Code Climate](https://codeclimate.com/github/alebsack/em-synchrony-moped.png)](https://codeclimate.com/github/alebsack/em-synchrony-moped)
|
2
4
|
|
3
|
-
EM-Synchrony-Moped is a [Moped](https://github.com/mongoid/
|
5
|
+
EM-Synchrony-Moped is a [Moped](https://github.com/mongoid/moped) driver patch for [EM-Synchrony](http://github.com/igrigorik/em-synchrony). Moped is the MongoDB driver for the [Mongoid](http://github.com/mongoid/mongoid) ORM.
|
4
6
|
|
5
|
-
|
7
|
+
## Features
|
8
|
+
* Supports SSL connections and server certificate checking
|
9
|
+
* Uses an EventMachine-aware DNS lookup
|
10
|
+
* Can be included in threaded applications
|
11
|
+
* Unit tested against the threaded (original driver) behavior
|
6
12
|
|
7
13
|
## Usage
|
8
14
|
|
data/em-synchrony-moped.gemspec
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = 'em-synchrony-moped'
|
5
|
-
s.version = "1.0.0.beta.
|
5
|
+
s.version = "1.0.0.beta.2"
|
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"]
|
@@ -19,11 +19,12 @@ Gem::Specification.new do |s|
|
|
19
19
|
s.require_paths = ["lib"]
|
20
20
|
|
21
21
|
s.add_runtime_dependency 'eventmachine', '~> 1.0'
|
22
|
-
s.add_runtime_dependency 'em-synchrony', '~> 1.0'
|
22
|
+
s.add_runtime_dependency 'em-synchrony', '~> 1.0.3'
|
23
23
|
s.add_runtime_dependency 'moped', '~> 1.5.1'
|
24
|
-
s.add_runtime_dependency 'em-resolv-replace'
|
24
|
+
s.add_runtime_dependency 'em-resolv-replace'
|
25
25
|
|
26
|
-
s.add_development_dependency '
|
26
|
+
s.add_development_dependency 'rake'
|
27
|
+
s.add_development_dependency 'rspec'
|
27
28
|
s.add_development_dependency 'guard'
|
28
29
|
s.add_development_dependency 'guard-rspec'
|
29
30
|
s.add_development_dependency 'guard-bundler'
|
@@ -4,7 +4,7 @@ require 'moped/cluster'
|
|
4
4
|
|
5
5
|
module Moped
|
6
6
|
# Our patches to Moped::Cluster
|
7
|
-
|
7
|
+
class Cluster
|
8
8
|
def sleep(seconds)
|
9
9
|
if EventMachine.reactor_thread?
|
10
10
|
EM::Synchrony.sleep(seconds)
|
@@ -13,8 +13,4 @@ module Moped
|
|
13
13
|
end
|
14
14
|
end
|
15
15
|
end
|
16
|
-
|
17
|
-
class Cluster
|
18
|
-
include EventedCluster
|
19
|
-
end
|
20
16
|
end
|
@@ -1,26 +1,24 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
|
+
require 'moped/connection'
|
4
|
+
|
3
5
|
module Moped
|
6
|
+
# Em-Synchrony overrides for Moped::Connection
|
4
7
|
class Connection
|
8
|
+
alias_method :super_connect, :connect
|
5
9
|
def connect
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
end
|
12
|
-
else # use old driver
|
13
|
-
if !!options[:ssl]
|
14
|
-
@sock = Sockets::SSL.connect(host, port, timeout)
|
15
|
-
else
|
16
|
-
@sock = Sockets::TCP.connect(host, port, timeout)
|
17
|
-
end
|
10
|
+
return super_connect unless EventMachine.reactor_thread?
|
11
|
+
if !!options[:ssl]
|
12
|
+
@sock = Sockets::EmSSL.em_connect(host, port, timeout, options)
|
13
|
+
else
|
14
|
+
@sock = Sockets::EmTCP.em_connect(host, port, timeout, options)
|
18
15
|
end
|
19
16
|
end
|
20
|
-
end
|
17
|
+
end
|
21
18
|
|
22
19
|
module Sockets
|
23
20
|
module Connectable
|
21
|
+
# Class methods to extend the Connectable Class
|
24
22
|
module ClassMethods
|
25
23
|
def em_connect(host, port, timeout, options)
|
26
24
|
socket = EventMachine.connect(host, port, self) do |c|
|
@@ -36,10 +34,9 @@ module Moped
|
|
36
34
|
fail SocketError, socket.unbind_reason
|
37
35
|
end
|
38
36
|
socket
|
39
|
-
|
40
37
|
rescue Errno::ETIMEDOUT
|
41
|
-
|
42
|
-
|
38
|
+
raise Errors::ConnectionFailure,
|
39
|
+
"Timed out connection to Mongo on #{host}:#{port}"
|
43
40
|
rescue Errno::ECONNREFUSED, Errno::EHOSTUNREACH, Errno::EPIPE,
|
44
41
|
Errno::ECONNRESET, IOError => error
|
45
42
|
fail Errors::ConnectionFailure,
|
@@ -48,10 +45,6 @@ module Moped
|
|
48
45
|
rescue SocketError => error
|
49
46
|
fail Errors::ConnectionFailure,
|
50
47
|
"#{host}:#{port}: #{error.class.name}: #{error.message}"
|
51
|
-
rescue OpenSSL::SSL::SSLError => error
|
52
|
-
fail Errors::ConnectionFailure,
|
53
|
-
"#{host}:#{port}: #{error.class.name} (#{error.errno}): " +
|
54
|
-
"#{error.message}"
|
55
48
|
end
|
56
49
|
end
|
57
50
|
end
|
@@ -59,11 +52,7 @@ module Moped
|
|
59
52
|
# The EM-Synchrony flavor of Moped::Sockets::TCP
|
60
53
|
class EmTCP < EventMachine::Synchrony::TCPSocket
|
61
54
|
include Connectable
|
62
|
-
|
63
|
-
# TODO: re-evaluate the options call. Can't we pass the caller
|
64
|
-
# up to the connection or something?
|
65
55
|
attr_accessor :options
|
66
|
-
|
67
56
|
def alive?
|
68
57
|
!closed?
|
69
58
|
end
|
@@ -73,50 +62,49 @@ module Moped
|
|
73
62
|
class EmSSL < EmTCP
|
74
63
|
def connection_completed
|
75
64
|
@verified = false
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
65
|
+
@cert_store = ssl_options.delete(:cert_store)
|
66
|
+
@cert_store ||= OpenSSL::X509::Store.new
|
67
|
+
if (cert_file = ssl_options.delete(:verify_cert))
|
68
|
+
@cert_store.add_file(cert_file)
|
80
69
|
end
|
70
|
+
start_tls(ssl_options)
|
81
71
|
end
|
82
72
|
|
83
73
|
def ssl_verify_peer(pem)
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
if (cert = OpenSSL::X509::Certificate.new(pem) rescue nil)
|
90
|
-
if cert_store.verify(cert)
|
91
|
-
|
92
|
-
cert.extensions.each do |e|
|
93
|
-
if e.oid == 'basicConstraints' && e.value == 'CA:TRUE'
|
94
|
-
return true
|
95
|
-
end
|
96
|
-
end
|
97
|
-
|
98
|
-
host = @options[:ssl][:verify_host]
|
99
|
-
if OpenSSL::SSL.verify_certificate_identity(cert, host)
|
100
|
-
@verified = true
|
101
|
-
return true
|
102
|
-
end
|
74
|
+
return true unless ssl_options[:verify_peer]
|
75
|
+
if (cert = certificate(pem)) && @cert_store.verify(cert)
|
76
|
+
# bypass hostname checking for this cert if it's a CA
|
77
|
+
return true if cert.extensions.find do |e|
|
78
|
+
e.oid == 'basicConstraints' && e.value == 'CA:TRUE'
|
103
79
|
end
|
80
|
+
|
81
|
+
@verified = true if (host = ssl_options[:verify_host]) &&
|
82
|
+
OpenSSL::SSL.verify_certificate_identity(cert, host)
|
104
83
|
end
|
105
84
|
|
85
|
+
# Always return true. We will evaluate the certificate chain in
|
86
|
+
# ssl_handshake_completed.
|
106
87
|
true
|
107
|
-
rescue
|
108
|
-
unbind 'Failed to verify SSL certificate of peer'
|
109
|
-
false
|
110
88
|
end
|
111
89
|
|
112
90
|
def ssl_handshake_completed
|
113
|
-
if
|
91
|
+
if ssl_options[:verify_peer] && !@verified
|
114
92
|
unbind 'Failed to verify SSL certificate of peer'
|
115
93
|
else
|
116
94
|
@opening = false
|
117
95
|
@in_req.succeed self
|
118
96
|
end
|
119
97
|
end
|
120
|
-
|
98
|
+
|
99
|
+
private
|
100
|
+
|
101
|
+
def ssl_options
|
102
|
+
@ssl_options ||= @options[:ssl] == true ? {} : @options[:ssl] || {}
|
103
|
+
end
|
104
|
+
|
105
|
+
def certificate(pem)
|
106
|
+
OpenSSL::X509::Certificate.new(pem)
|
107
|
+
end
|
108
|
+
end # EmSSL
|
121
109
|
end
|
122
110
|
end
|
@@ -5,15 +5,16 @@ require 'em-dns-resolver'
|
|
5
5
|
require 'fiber'
|
6
6
|
|
7
7
|
module Moped
|
8
|
-
# Our monkey patches to Moped::Node
|
9
|
-
|
8
|
+
# # Our monkey patches to Moped::Node
|
9
|
+
class Node
|
10
|
+
alias_method :super_parse_address, :parse_address
|
10
11
|
# Override to support non-blocking DNS requests
|
11
12
|
def parse_address
|
12
|
-
return
|
13
|
+
return super_parse_address unless EventMachine.reactor_thread?
|
13
14
|
host, port = address.split(':')
|
14
15
|
@port = (port || 27_017).to_i
|
15
16
|
|
16
|
-
@ip_address = em_lookup_address(host)
|
17
|
+
@ip_address = em_lookup_address(host).grep(/(::){0}/).first
|
17
18
|
fail SocketError unless @ip_address
|
18
19
|
@resolved_address = "#{@ip_address}:#{@port}"
|
19
20
|
rescue Resolv::ResolvError
|
@@ -24,7 +25,7 @@ module Moped
|
|
24
25
|
# Lookup in /etc/hosts
|
25
26
|
result = []
|
26
27
|
@hosts ||= Resolv::Hosts.new
|
27
|
-
@hosts.send(:each_address, value) { |x| result << x.to_s }
|
28
|
+
@hosts.send(:each_address, value) { |x| result << x.to_s if x !~ /::/ }
|
28
29
|
return result unless result.empty?
|
29
30
|
|
30
31
|
# Nothing, hit DNS
|
@@ -34,15 +35,11 @@ module Moped
|
|
34
35
|
fiber.resume(a)
|
35
36
|
end
|
36
37
|
df.errback do |*a|
|
37
|
-
fiber.resume(ResolvError.new(a.inspect))
|
38
|
+
fiber.resume(Resolv::ResolvError.new(a.inspect))
|
38
39
|
end
|
39
40
|
result = Fiber.yield
|
40
|
-
|
41
|
+
fail result if result.is_a?(StandardError)
|
41
42
|
result
|
42
43
|
end
|
43
44
|
end
|
44
|
-
|
45
|
-
class Node
|
46
|
-
include EventedNode
|
47
|
-
end
|
48
45
|
end
|
@@ -4,12 +4,9 @@ require 'spec_helper'
|
|
4
4
|
require 'moped'
|
5
5
|
require 'em-synchrony/moped'
|
6
6
|
|
7
|
-
# TODO: clean up a bit. we're basically testing Connection through Node.
|
8
|
-
# we should be able to test Connection by itself.
|
9
|
-
|
10
7
|
describe Moped::Connection do
|
11
8
|
it 'should have patches included' do
|
12
|
-
expect { Moped::Sockets::EmTCP }.not_to raise_error
|
9
|
+
expect { Moped::Sockets::EmTCP }.not_to raise_error
|
13
10
|
end
|
14
11
|
|
15
12
|
let(:mongod_options) { {} }
|
@@ -17,56 +14,48 @@ describe Moped::Connection do
|
|
17
14
|
let(:server_port) { server.port }
|
18
15
|
after { server.stop }
|
19
16
|
|
20
|
-
let(:
|
21
|
-
let(:
|
22
|
-
|
23
|
-
host = options.delete(:host) || '
|
24
|
-
|
17
|
+
let(:options) { {} }
|
18
|
+
let(:conn) do
|
19
|
+
timeout = 1
|
20
|
+
host = options.delete(:host) || '127.0.0.1'
|
21
|
+
port = options.delete(:port) || server_port
|
22
|
+
Moped::Connection.new(host, port, timeout, options)
|
25
23
|
end
|
26
24
|
|
27
25
|
shared_context 'common connection' do
|
28
26
|
context 'with a running server' do
|
29
27
|
it 'should connect' do
|
30
|
-
|
31
|
-
node.should be_primary
|
32
|
-
node.should be_connected
|
28
|
+
expect(conn.connect).to be_a(connection_class)
|
33
29
|
end
|
30
|
+
end
|
34
31
|
|
35
|
-
|
36
|
-
node.refresh
|
37
|
-
node.should be_primary
|
38
|
-
node.should be_connected
|
39
|
-
server.stop
|
40
|
-
expect do
|
41
|
-
node.command('admin', ismaster: 1)
|
42
|
-
end.to raise_error(
|
43
|
-
Moped::Errors::ConnectionFailure # TODO: check the message
|
44
|
-
)
|
45
|
-
node.should_not be_connected
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
context 'with an unpresponsive host' do
|
32
|
+
context 'with an unresponsive host' do
|
50
33
|
# 127.0.0.2 seems to timeout for my tests...
|
51
|
-
let(:
|
34
|
+
let(:options) { { host: ENV['TIMEOUT_HOST'] } }
|
52
35
|
it 'should raise a timeout error' do
|
53
|
-
expect {
|
36
|
+
expect { conn.connect }.to raise_error(
|
54
37
|
Moped::Errors::ConnectionFailure,
|
55
38
|
/^Timed out connection to Mongo on/)
|
56
39
|
end
|
57
40
|
end
|
58
41
|
|
59
42
|
context 'without a server' do
|
43
|
+
let(:options) { { port: 2 } }
|
60
44
|
it 'should raise a connection error on connection refused' do
|
61
45
|
server.stop
|
62
|
-
expect {
|
46
|
+
expect { conn.connect }.to raise_error(
|
63
47
|
Moped::Errors::ConnectionFailure, /ECONNREFUSED/)
|
64
48
|
end
|
65
49
|
end
|
66
50
|
end
|
67
51
|
|
68
|
-
|
69
|
-
|
52
|
+
context 'evented' do
|
53
|
+
include_context 'with em-synchrony'
|
54
|
+
let(:connection_class) { Moped::Sockets::EmTCP }
|
55
|
+
include_context 'common connection'
|
56
|
+
context 'with ssl' do
|
57
|
+
let(:ssl_options) { nil }
|
58
|
+
let(:options) { { ssl: ssl_options } }
|
70
59
|
let(:mongod_options) do
|
71
60
|
{
|
72
61
|
ssl: {
|
@@ -77,60 +66,196 @@ describe Moped::Connection do
|
|
77
66
|
}
|
78
67
|
end
|
79
68
|
|
80
|
-
context 'without
|
81
|
-
let(:
|
82
|
-
|
83
|
-
|
84
|
-
|
69
|
+
context 'without specifying ssl' do
|
70
|
+
let(:ssl_options) { nil }
|
71
|
+
let(:options) { {} }
|
72
|
+
it 'should connect (though comms will fail later)' do
|
73
|
+
expect(conn.connect).to be_a(Moped::Sockets::EmTCP)
|
85
74
|
end
|
86
75
|
end
|
87
76
|
|
88
|
-
context '
|
89
|
-
|
90
|
-
{
|
91
|
-
|
92
|
-
|
93
|
-
|
77
|
+
context 'and a server with a trusted certificate' do
|
78
|
+
context 'when specifying ssl: true' do
|
79
|
+
let(:ssl_options) { true }
|
80
|
+
it 'should connect' do
|
81
|
+
expect(conn.connect).to be_a(Moped::Sockets::EmSSL)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
context 'when specifying ssl: {}' do
|
86
|
+
let(:ssl_options) { {} }
|
87
|
+
it 'should connect' do
|
88
|
+
expect(conn.connect).to be_a(Moped::Sockets::EmSSL)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
context 'when not verifying peer' do
|
93
|
+
let(:ssl_options) { { verify_peer: false } }
|
94
|
+
it 'should connect' do
|
95
|
+
expect(conn.connect).to be_a(Moped::Sockets::EmSSL)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
context 'when verifying peer' do
|
100
|
+
context 'and no certificate provided' do
|
101
|
+
let(:ssl_options) { { verify_peer: true } }
|
102
|
+
it 'should raise an error' do
|
103
|
+
expect { conn.connect }
|
104
|
+
.to raise_error(
|
105
|
+
Moped::Errors::ConnectionFailure,
|
106
|
+
/Failed to verify SSL certificate of peer/
|
107
|
+
)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
context 'and a certificate is provided' do
|
112
|
+
context 'and verify_host is not provided' do
|
113
|
+
let(:ssl_options) do
|
114
|
+
{
|
115
|
+
verify_peer: true,
|
116
|
+
verify_cert: "#{SSL_DIR}/ca_cert.pem"
|
117
|
+
}
|
118
|
+
end
|
119
|
+
it 'should raise an error' do
|
120
|
+
expect { conn.connect }
|
121
|
+
.to raise_error(
|
122
|
+
Moped::Errors::ConnectionFailure,
|
123
|
+
/Failed to verify SSL certificate of peer/
|
124
|
+
)
|
125
|
+
end
|
126
|
+
end
|
127
|
+
context 'and verify_host does not match the server cert' do
|
128
|
+
let(:ssl_options) do
|
129
|
+
{
|
130
|
+
verify_peer: true,
|
131
|
+
verify_cert: "#{SSL_DIR}/ca_cert.pem",
|
132
|
+
verify_host: 'remotehost'
|
133
|
+
}
|
134
|
+
end
|
135
|
+
it 'should raise an error' do
|
136
|
+
expect { conn.connect }
|
137
|
+
.to raise_error(
|
138
|
+
Moped::Errors::ConnectionFailure,
|
139
|
+
/Failed to verify SSL certificate of peer/
|
140
|
+
)
|
141
|
+
end
|
142
|
+
end
|
143
|
+
context 'and verify_host matches the server cert' do
|
144
|
+
let(:ssl_options) do
|
145
|
+
{
|
146
|
+
verify_peer: true,
|
147
|
+
verify_cert: "#{SSL_DIR}/ca_cert.pem",
|
148
|
+
verify_host: 'localhost'
|
149
|
+
}
|
150
|
+
end
|
151
|
+
it 'should connect' do
|
152
|
+
expect(conn.connect).to be_a(Moped::Sockets::EmSSL)
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end # 'and a certificate is provided'
|
156
|
+
end # 'when verifying peer'
|
157
|
+
end # server with a trusted certificate
|
158
|
+
context 'and a server with an untrusted certificate' do
|
159
|
+
let(:mongod_options) do
|
160
|
+
{
|
161
|
+
ssl: {
|
162
|
+
private_key_file: "#{SSL_DIR}/untrusted.key",
|
163
|
+
cert_chain_file: "#{SSL_DIR}/untrusted.crt",
|
164
|
+
verify_peer: false
|
94
165
|
}
|
95
166
|
}
|
96
167
|
end
|
97
|
-
|
98
|
-
|
99
|
-
|
168
|
+
|
169
|
+
context 'when specifying ssl: true' do
|
170
|
+
let(:ssl_options) { true }
|
171
|
+
it 'should connect' do
|
172
|
+
expect(conn.connect).to be_a(Moped::Sockets::EmSSL)
|
173
|
+
end
|
100
174
|
end
|
101
175
|
|
102
|
-
context '
|
103
|
-
let(:
|
104
|
-
|
105
|
-
|
106
|
-
private_key_file: "#{SSL_DIR}/untrusted.key",
|
107
|
-
cert_chain_file: "#{SSL_DIR}/untrusted.crt",
|
108
|
-
verify_peer: false
|
109
|
-
}
|
110
|
-
}
|
176
|
+
context 'when specifying ssl: {}' do
|
177
|
+
let(:ssl_options) { {} }
|
178
|
+
it 'should connect' do
|
179
|
+
expect(conn.connect).to be_a(Moped::Sockets::EmSSL)
|
111
180
|
end
|
181
|
+
end
|
112
182
|
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
end.to raise_error(
|
118
|
-
Moped::Errors::ConnectionFailure,
|
119
|
-
/Failed to verify SSL certificate of peer/
|
120
|
-
)
|
183
|
+
context 'when not verifying peer' do
|
184
|
+
let(:ssl_options) { { verify_peer: false } }
|
185
|
+
it 'should connect' do
|
186
|
+
expect(conn.connect).to be_a(Moped::Sockets::EmSSL)
|
121
187
|
end
|
122
188
|
end
|
123
|
-
end
|
124
|
-
end
|
125
|
-
end
|
126
189
|
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
190
|
+
context 'when verifying peer' do
|
191
|
+
context 'and no certificate provided' do
|
192
|
+
let(:ssl_options) { { verify_peer: true } }
|
193
|
+
it 'should raise an error' do
|
194
|
+
expect { conn.connect }
|
195
|
+
.to raise_error(
|
196
|
+
Moped::Errors::ConnectionFailure,
|
197
|
+
/Failed to verify SSL certificate of peer/
|
198
|
+
)
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
context 'and a certificate is provided' do
|
203
|
+
context 'and verify_host is not provided' do
|
204
|
+
let(:ssl_options) do
|
205
|
+
{
|
206
|
+
verify_peer: true,
|
207
|
+
verify_cert: "#{SSL_DIR}/ca_cert.pem"
|
208
|
+
}
|
209
|
+
end
|
210
|
+
it 'should raise an error' do
|
211
|
+
expect { conn.connect }
|
212
|
+
.to raise_error(
|
213
|
+
Moped::Errors::ConnectionFailure,
|
214
|
+
/Failed to verify SSL certificate of peer/
|
215
|
+
)
|
216
|
+
end
|
217
|
+
end
|
218
|
+
context 'and verify_host does not match the server cert' do
|
219
|
+
let(:ssl_options) do
|
220
|
+
{
|
221
|
+
verify_peer: true,
|
222
|
+
verify_cert: "#{SSL_DIR}/ca_cert.pem",
|
223
|
+
verify_host: 'remotehost'
|
224
|
+
}
|
225
|
+
end
|
226
|
+
it 'should raise an error' do
|
227
|
+
expect { conn.connect }
|
228
|
+
.to raise_error(
|
229
|
+
Moped::Errors::ConnectionFailure,
|
230
|
+
/Failed to verify SSL certificate of peer/
|
231
|
+
)
|
232
|
+
end
|
233
|
+
end
|
234
|
+
context 'and verify_host matches the server cert' do
|
235
|
+
let(:ssl_options) do
|
236
|
+
{
|
237
|
+
verify_peer: true,
|
238
|
+
verify_cert: "#{SSL_DIR}/ca_cert.pem",
|
239
|
+
verify_host: 'localhost'
|
240
|
+
}
|
241
|
+
end
|
242
|
+
it 'should raise an error' do
|
243
|
+
expect { conn.connect }
|
244
|
+
.to raise_error(
|
245
|
+
Moped::Errors::ConnectionFailure,
|
246
|
+
/Failed to verify SSL certificate of peer/
|
247
|
+
)
|
248
|
+
end
|
249
|
+
end
|
250
|
+
end # 'and a certificate is provided'
|
251
|
+
end # 'when verifying peer'
|
252
|
+
end # 'and a server with an untrusted certificate'
|
253
|
+
end # 'with ssl'
|
254
|
+
end # 'evented'
|
255
|
+
|
132
256
|
context 'threaded' do
|
133
257
|
include_context 'without em-synchrony'
|
258
|
+
let(:connection_class) { Moped::Sockets::TCP }
|
134
259
|
include_context 'common connection'
|
135
260
|
end
|
136
261
|
|
@@ -14,7 +14,8 @@ describe Moped::Node do
|
|
14
14
|
let(:node) do
|
15
15
|
options = node_options.merge(timeout: 1)
|
16
16
|
host = options.delete(:host) || 'localhost'
|
17
|
-
|
17
|
+
port = options.delete(:port) || server_port
|
18
|
+
Moped::Node.new("#{host}:#{port}", options)
|
18
19
|
end
|
19
20
|
|
20
21
|
shared_context 'common node' do
|
@@ -39,9 +40,9 @@ describe Moped::Node do
|
|
39
40
|
end
|
40
41
|
end
|
41
42
|
|
42
|
-
context 'with an
|
43
|
+
context 'with an unresponsive host' do
|
43
44
|
# 127.0.0.2 seems to timeout for my tests...
|
44
|
-
let(:node_options) { { host: '
|
45
|
+
let(:node_options) { { host: ENV['TIMEOUT_HOST'] } }
|
45
46
|
it 'should raise a timeout error' do
|
46
47
|
expect { node.refresh }.to raise_error(
|
47
48
|
Moped::Errors::ConnectionFailure,
|
@@ -58,6 +59,7 @@ describe Moped::Node do
|
|
58
59
|
end
|
59
60
|
|
60
61
|
context 'without a server' do
|
62
|
+
let(:node_options) { { port: 2 } }
|
61
63
|
it 'should raise a connection error on connection refused' do
|
62
64
|
server.stop
|
63
65
|
expect { node.refresh }.to raise_error(
|
data/spec/spec_helper.rb
CHANGED
@@ -10,8 +10,16 @@ Spork.prefork do
|
|
10
10
|
# if you change any configuration or code from libraries loaded here, you'll
|
11
11
|
# need to restart spork for it take effect.
|
12
12
|
|
13
|
+
ENV['TIMEOUT_HOST'] ||= 'www.google.com'
|
14
|
+
|
13
15
|
require 'rspec'
|
14
16
|
require 'simplecov'
|
17
|
+
require 'coveralls'
|
18
|
+
|
19
|
+
SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
|
20
|
+
SimpleCov::Formatter::HTMLFormatter,
|
21
|
+
Coveralls::SimpleCov::Formatter
|
22
|
+
]
|
15
23
|
SimpleCov.start do
|
16
24
|
add_group 'Lib', 'lib'
|
17
25
|
add_filter '/spec/'
|
data/spec/support/contexts.rb
CHANGED
@@ -5,11 +5,12 @@ shared_context 'with em-synchrony' do
|
|
5
5
|
require 'em-synchrony'
|
6
6
|
EventMachine.error_handler do |e|
|
7
7
|
puts "Error in Eventmachine: #{e.inspect}"
|
8
|
-
|
8
|
+
puts e.backtrace.join("\n")
|
9
|
+
EventMachine.stop
|
9
10
|
end
|
10
11
|
EventMachine.synchrony do
|
11
12
|
example.run
|
12
|
-
|
13
|
+
EventMachine.stop if EventMachine.reactor_running?
|
13
14
|
end
|
14
15
|
end
|
15
16
|
end
|
@@ -18,7 +19,8 @@ shared_context 'without em-synchrony' do
|
|
18
19
|
before(:each) do
|
19
20
|
EventMachine.error_handler do |e|
|
20
21
|
puts "Error in Eventmachine: #{e.inspect}"
|
21
|
-
|
22
|
+
puts e.backtrace.join("\n")
|
23
|
+
EventMachine.stop
|
22
24
|
end
|
23
25
|
queue = Queue.new
|
24
26
|
@em_thread = Thread.new { EventMachine.run { queue << true } }
|
@@ -26,7 +28,7 @@ shared_context 'without em-synchrony' do
|
|
26
28
|
end
|
27
29
|
|
28
30
|
after(:each) do
|
29
|
-
|
31
|
+
EventMachine.stop
|
30
32
|
@em_thread.join
|
31
33
|
end
|
32
34
|
end
|
@@ -134,7 +134,7 @@ class FakeMongodServer
|
|
134
134
|
ensure_reactor do
|
135
135
|
@server = EventMachine.start_server(
|
136
136
|
@host, 0, FakeMongod, @options, self)
|
137
|
-
@port = Socket.unpack_sockaddr_in(
|
137
|
+
@port = Socket.unpack_sockaddr_in(EventMachine.get_sockname(@server))[0]
|
138
138
|
end
|
139
139
|
end
|
140
140
|
|
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: 1.0.0.beta.
|
4
|
+
version: 1.0.0.beta.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Adam Lebsack
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-11-
|
11
|
+
date: 2013-11-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: eventmachine
|
@@ -30,14 +30,14 @@ dependencies:
|
|
30
30
|
requirements:
|
31
31
|
- - ~>
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version:
|
33
|
+
version: 1.0.3
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - ~>
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version:
|
40
|
+
version: 1.0.3
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: moped
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -56,30 +56,44 @@ dependencies:
|
|
56
56
|
name: em-resolv-replace
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
|
-
- -
|
59
|
+
- - ! '>='
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version:
|
61
|
+
version: '0'
|
62
62
|
type: :runtime
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
|
-
- -
|
66
|
+
- - ! '>='
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version:
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rake
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ! '>='
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ! '>='
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
69
83
|
- !ruby/object:Gem::Dependency
|
70
84
|
name: rspec
|
71
85
|
requirement: !ruby/object:Gem::Requirement
|
72
86
|
requirements:
|
73
|
-
- -
|
87
|
+
- - ! '>='
|
74
88
|
- !ruby/object:Gem::Version
|
75
|
-
version:
|
89
|
+
version: '0'
|
76
90
|
type: :development
|
77
91
|
prerelease: false
|
78
92
|
version_requirements: !ruby/object:Gem::Requirement
|
79
93
|
requirements:
|
80
|
-
- -
|
94
|
+
- - ! '>='
|
81
95
|
- !ruby/object:Gem::Version
|
82
|
-
version:
|
96
|
+
version: '0'
|
83
97
|
- !ruby/object:Gem::Dependency
|
84
98
|
name: guard
|
85
99
|
requirement: !ruby/object:Gem::Requirement
|
@@ -187,6 +201,7 @@ extensions: []
|
|
187
201
|
extra_rdoc_files: []
|
188
202
|
files:
|
189
203
|
- .gitignore
|
204
|
+
- .travis.yml
|
190
205
|
- Gemfile
|
191
206
|
- Guardfile
|
192
207
|
- README.md
|