em-synchrony-moped 0.9.4 → 1.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.
@@ -0,0 +1,138 @@
1
+ # encoding: utf-8
2
+ require 'spec_helper'
3
+
4
+ require 'moped'
5
+ require 'em-synchrony/moped'
6
+
7
+ describe Moped::Node do
8
+ let(:mongod_options) { {} }
9
+ let(:server) { FakeMongodServer.new(mongod_options) }
10
+ let(:server_port) { server.port }
11
+ after { server.stop }
12
+
13
+ let(:node_options) { {} }
14
+ let(:node) do
15
+ options = node_options.merge(timeout: 1)
16
+ host = options.delete(:host) || 'localhost'
17
+ Moped::Node.new("#{host}:#{server_port}", options)
18
+ end
19
+
20
+ shared_context 'common node' do
21
+ context 'with a running server' do
22
+ it 'should connect' do
23
+ node.refresh
24
+ node.should be_primary
25
+ node.should be_connected
26
+ end
27
+
28
+ it 'should detect a disconnect' do
29
+ node.refresh
30
+ node.should be_primary
31
+ node.should be_connected
32
+ server.stop
33
+ expect do
34
+ node.command('admin', ismaster: 1)
35
+ end.to raise_error(
36
+ Moped::Errors::ConnectionFailure # TODO: check the message
37
+ )
38
+ node.should_not be_connected
39
+ end
40
+ end
41
+
42
+ context 'with an unpresponsive host' do
43
+ # 127.0.0.2 seems to timeout for my tests...
44
+ let(:node_options) { { host: '127.0.0.2' } }
45
+ it 'should raise a timeout error' do
46
+ expect { node.refresh }.to raise_error(
47
+ Moped::Errors::ConnectionFailure,
48
+ /^Timed out connection to Mongo on/)
49
+ end
50
+ end
51
+
52
+ context 'with an unknown host' do
53
+ let(:node_options) { { host: 'this.host-could-not-possibly-exist.com' } }
54
+ it 'should raise an error' do
55
+ # FIXME: this can't be right...
56
+ expect { node.refresh }.not_to raise_error
57
+ end
58
+ end
59
+
60
+ context 'without a server' do
61
+ it 'should raise a connection error on connection refused' do
62
+ server.stop
63
+ expect { node.refresh }.to raise_error(
64
+ Moped::Errors::ConnectionFailure, /ECONNREFUSED/)
65
+ end
66
+ end
67
+ end
68
+
69
+ shared_context 'common node ssl' do
70
+ context 'with ssl server' do
71
+ let(:mongod_options) do
72
+ {
73
+ ssl: {
74
+ private_key_file: "#{SSL_DIR}/server.key",
75
+ cert_chain_file: "#{SSL_DIR}/server.crt",
76
+ verify_peer: false
77
+ }
78
+ }
79
+ end
80
+
81
+ context 'without verifying peer' do
82
+ let(:node_options) { { ssl: { verify_peer: false } } }
83
+ it 'should connect' do
84
+ node.refresh
85
+ node.should be_primary
86
+ end
87
+ end
88
+
89
+ context 'when verifying peer' do
90
+ let(:node_options) do
91
+ { ssl: {
92
+ verify_peer: true,
93
+ verify_cert: "#{SSL_DIR}/ca_cert.pem",
94
+ verify_host: 'localhost'
95
+ }
96
+ }
97
+ end
98
+ it 'should connect' do
99
+ node.refresh
100
+ node.should be_primary
101
+ end
102
+
103
+ context 'with untrusted key on server' do
104
+ let(:mongod_options) do
105
+ {
106
+ ssl: {
107
+ private_key_file: "#{SSL_DIR}/untrusted.key",
108
+ cert_chain_file: "#{SSL_DIR}/untrusted.crt",
109
+ verify_peer: false
110
+ }
111
+ }
112
+ end
113
+
114
+ it 'should connect and fail to verify peer' do
115
+ expect do
116
+ node.refresh
117
+ node.should be_primary
118
+ end.to raise_error(
119
+ Moped::Errors::ConnectionFailure,
120
+ /Failed to verify SSL certificate of peer/
121
+ )
122
+ end
123
+ end
124
+ end
125
+ end
126
+ end
127
+
128
+ context 'evented' do
129
+ include_context 'with em-synchrony'
130
+ include_context 'common node'
131
+ include_context 'common node ssl'
132
+ end
133
+ context 'threaded' do
134
+ include_context 'without em-synchrony'
135
+ include_context 'common node'
136
+ end
137
+
138
+ end
data/spec/spec_helper.rb CHANGED
@@ -1,15 +1,43 @@
1
- $LOAD_PATH.unshift(File.dirname(__FILE__))
2
- $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), "..", "lib"))
1
+ # encoding: UTF-8
3
2
 
4
- require "rspec"
3
+ require 'rubygems'
4
+ require 'spork'
5
+ # uncomment the following line to use spork with the debugger
6
+ # require 'spork/ext/ruby-debug'
5
7
 
6
- require 'em-synchrony'
8
+ Spork.prefork do
9
+ # Loading more in this block will cause your tests to run faster. However,
10
+ # if you change any configuration or code from libraries loaded here, you'll
11
+ # need to restart spork for it take effect.
7
12
 
8
- Dir[File.expand_path("../support/**/*.rb", __FILE__)].each { |f| require f }
13
+ require 'rspec'
14
+ require 'simplecov'
15
+ SimpleCov.start do
16
+ add_group 'Lib', 'lib'
17
+ add_filter '/spec/'
18
+ end
9
19
 
10
- SSL_DIR = File.expand_path("../ssl", __FILE__)
20
+ Dir[File.expand_path('../support/**/*.rb', __FILE__)].each { |f| require f }
11
21
 
12
- RSpec.configure do |config|
22
+ SSL_DIR = File.expand_path('../ssl', __FILE__)
13
23
 
24
+ RSpec.configure do |config|
25
+ config.treat_symbols_as_metadata_keys_with_true_values = true
26
+ config.run_all_when_everything_filtered = true
27
+ config.filter_run :focus
28
+
29
+ # Run specs in random order to surface order dependencies. If you find an
30
+ # order dependency and want to debug it, you can fix the order by providing
31
+ # the seed, which is printed after each run.
32
+ # --seed 1234
33
+ config.order = 'random'
34
+
35
+ # config.before { $stderr.reopen("/dev/null") }
36
+ end
37
+
38
+ end
39
+
40
+ Spork.each_run do
41
+ # This code will be run each time you run your specs.
14
42
 
15
43
  end
@@ -0,0 +1,32 @@
1
+ # encoding: utf-8
2
+
3
+ shared_context 'with em-synchrony' do
4
+ around(:each) do |example|
5
+ require 'em-synchrony'
6
+ EventMachine.error_handler do |e|
7
+ puts "Error in Eventmachine: #{e.inspect}"
8
+ EM.stop
9
+ end
10
+ EventMachine.synchrony do
11
+ example.run
12
+ EM.stop if EM.reactor_running?
13
+ end
14
+ end
15
+ end
16
+
17
+ shared_context 'without em-synchrony' do
18
+ before(:each) do
19
+ EventMachine.error_handler do |e|
20
+ puts "Error in Eventmachine: #{e.inspect}"
21
+ EM.stop
22
+ end
23
+ queue = Queue.new
24
+ @em_thread = Thread.new { EventMachine.run { queue << true } }
25
+ queue.pop
26
+ end
27
+
28
+ after(:each) do
29
+ EM.stop
30
+ @em_thread.join
31
+ end
32
+ end
@@ -1,13 +1,15 @@
1
+ # encoding: utf-8
1
2
  require 'eventmachine'
2
3
 
4
+ # Load order here is important. Message must be loaded so we can
5
+ # add deserialization support to moped/protocol/query
3
6
  require 'moped/protocol/message'
7
+
4
8
  module Moped
5
9
  module Protocol
6
-
7
10
  # This patch is so we can parse a query as a server
8
11
  module Message
9
12
  module ClassMethods
10
-
11
13
  alias_method :_old_cstring, :cstring
12
14
  def cstring(name)
13
15
  class_eval <<-RUBY, __FILE__, __LINE__ + 1
@@ -22,7 +24,7 @@ module Moped
22
24
  RUBY
23
25
  _old_cstring(name)
24
26
  end
25
-
27
+
26
28
  alias_method :_old_document, :document
27
29
  def document(name, options = {})
28
30
  if options[:optional]
@@ -42,8 +44,9 @@ module Moped
42
44
  end
43
45
  end
44
46
  end
45
-
46
- # now that the class DSL is patched, load the message classes we need to patch further
47
+
48
+ # now that the class DSL is patched, load the message classes we need to
49
+ # patch further
47
50
 
48
51
  # This patch is so we can parse a query as a server
49
52
  require 'moped/protocol/query'
@@ -58,8 +61,7 @@ module Moped
58
61
  end
59
62
  end
60
63
  end
61
-
62
-
64
+
63
65
  # This patch is so we can create a Reply object as a server
64
66
  require 'moped/protocol/reply'
65
67
  class Reply
@@ -72,71 +74,98 @@ module Moped
72
74
  @op_code = 1
73
75
  end
74
76
  end
75
-
76
-
77
77
  end
78
78
  end
79
79
 
80
-
80
+ # Eventmachine connection for FakeMongod
81
81
  class FakeMongod < EventMachine::Connection
82
- def initialize(options)
83
- @options = options
82
+ def initialize(options, server)
83
+ @options = {
84
+ master: 1
85
+ }.merge(options)
86
+ @server = server
84
87
  @request_id = 0
85
88
  end
86
-
89
+
87
90
  def post_init
88
- if @options[:ssl]
89
- start_tls(@options[:ssl])
90
- end
91
+ @server.add_connection(self)
92
+ start_tls(@options[:ssl]) if @options[:ssl]
91
93
  end
92
-
94
+
93
95
  def receive_data(data)
94
96
  query = Moped::Protocol::Query.deserialize(StringIO.new(data))
95
97
  if query.full_collection_name == 'admin.$cmd'
96
- if query.selector == {'ismaster' => 1}
97
- send_reply(query,
98
- :ok => 1,
99
- :ismaster => 1
100
- )
101
- elsif query.selector == {'listDatabases' => 1}
102
- send_reply(query,
103
- :ok => 1,
104
- :databases => [{
105
- :name => 'test_db'
106
- }]
107
- )
98
+ if query.selector == { 'ismaster' => 1 }
99
+ if @options[:master] == 1
100
+ send_reply(query, ok: 1, ismaster: 1)
101
+ else
102
+ send_reply(query, ok: 1, secondary: 1)
103
+ end
104
+ elsif query.selector == { 'listDatabases' => 1 }
105
+ send_reply(query, ok: 1, databases: [{ name: 'test_db' }])
108
106
  end
109
107
  end
110
108
  end
111
-
109
+
112
110
  def send_reply(query, *documents)
113
111
  @request_id += 1
114
112
  reply = Moped::Protocol::Reply.new(
115
113
  documents,
116
- :request_id => @request_ud,
117
- :response_to => query.request_id
114
+ request_id: @request_ud,
115
+ response_to: query.request_id
118
116
  )
119
117
  send_data reply.serialize
120
118
  end
121
-
119
+
120
+ def unbind
121
+ @server.remove_connection(self)
122
+ end
122
123
  end
123
124
 
124
- module FakeMongodHelper
125
-
126
- BASE_PORT = 37017
127
-
128
- def start_mongod(options={})
129
- @server = EventMachine.start_server('127.0.0.1', BASE_PORT, FakeMongod, options)
125
+ class FakeMongodServer
126
+ attr_reader :port, :host, :options
127
+
128
+ def initialize(options = {})
129
+ @options = {
130
+ host: '127.0.0.1'
131
+ }.merge(options)
132
+ @host = @options.delete(:host)
133
+ @connections = []
134
+ ensure_reactor do
135
+ @server = EventMachine.start_server(
136
+ @host, 0, FakeMongod, @options, self)
137
+ @port = Socket.unpack_sockaddr_in(EM.get_sockname(@server))[0]
138
+ end
130
139
  end
131
140
 
141
+ def stop
142
+ return unless @server
143
+ ensure_reactor do
144
+ EventMachine.stop_server(@server)
145
+ # stopping the server only stops the listener. We must now stop
146
+ # all current connections
147
+ @connections.each { |c| c.close_connection }
148
+ @server = nil
149
+ end
150
+ end
132
151
 
133
- def stop_mongod
134
- EventMachine.stop_server(@server)
152
+ def add_connection(connection)
153
+ @connections << connection
135
154
  end
136
-
137
- end
138
155
 
139
- RSpec.configure do |config|
140
- config.include FakeMongodHelper
156
+ def remove_connection(connection)
157
+ @connections.delete(connection)
158
+ end
159
+
160
+ private
141
161
 
142
- end
162
+ def ensure_reactor(&block)
163
+ if EventMachine.reactor_thread?
164
+ block.call
165
+ elsif EventMachine.reactor_running?
166
+ queue = Queue.new
167
+ EventMachine.next_tick { queue << block.call }
168
+ queue.pop
169
+ end
170
+ end
171
+ end
metadata CHANGED
@@ -1,36 +1,32 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: em-synchrony-moped
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.4
5
- prerelease:
4
+ version: 1.0.0.beta.1
6
5
  platform: ruby
7
6
  authors:
8
7
  - Adam Lebsack
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2013-05-22 00:00:00.000000000 Z
11
+ date: 2013-11-12 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: eventmachine
16
15
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
16
  requirements:
19
- - - ! '>='
17
+ - - ~>
20
18
  - !ruby/object:Gem::Version
21
- version: '0'
19
+ version: '1.0'
22
20
  type: :runtime
23
21
  prerelease: false
24
22
  version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
23
  requirements:
27
- - - ! '>='
24
+ - - ~>
28
25
  - !ruby/object:Gem::Version
29
- version: '0'
26
+ version: '1.0'
30
27
  - !ruby/object:Gem::Dependency
31
28
  name: em-synchrony
32
29
  requirement: !ruby/object:Gem::Requirement
33
- none: false
34
30
  requirements:
35
31
  - - ~>
36
32
  - !ruby/object:Gem::Version
@@ -38,7 +34,6 @@ dependencies:
38
34
  type: :runtime
39
35
  prerelease: false
40
36
  version_requirements: !ruby/object:Gem::Requirement
41
- none: false
42
37
  requirements:
43
38
  - - ~>
44
39
  - !ruby/object:Gem::Version
@@ -46,23 +41,20 @@ dependencies:
46
41
  - !ruby/object:Gem::Dependency
47
42
  name: moped
48
43
  requirement: !ruby/object:Gem::Requirement
49
- none: false
50
44
  requirements:
51
45
  - - ~>
52
46
  - !ruby/object:Gem::Version
53
- version: 1.4.5
47
+ version: 1.5.1
54
48
  type: :runtime
55
49
  prerelease: false
56
50
  version_requirements: !ruby/object:Gem::Requirement
57
- none: false
58
51
  requirements:
59
52
  - - ~>
60
53
  - !ruby/object:Gem::Version
61
- version: 1.4.5
54
+ version: 1.5.1
62
55
  - !ruby/object:Gem::Dependency
63
56
  name: em-resolv-replace
64
57
  requirement: !ruby/object:Gem::Requirement
65
- none: false
66
58
  requirements:
67
59
  - - ~>
68
60
  - !ruby/object:Gem::Version
@@ -70,7 +62,6 @@ dependencies:
70
62
  type: :runtime
71
63
  prerelease: false
72
64
  version_requirements: !ruby/object:Gem::Requirement
73
- none: false
74
65
  requirements:
75
66
  - - ~>
76
67
  - !ruby/object:Gem::Version
@@ -78,7 +69,6 @@ dependencies:
78
69
  - !ruby/object:Gem::Dependency
79
70
  name: rspec
80
71
  requirement: !ruby/object:Gem::Requirement
81
- none: false
82
72
  requirements:
83
73
  - - ~>
84
74
  - !ruby/object:Gem::Version
@@ -86,11 +76,108 @@ dependencies:
86
76
  type: :development
87
77
  prerelease: false
88
78
  version_requirements: !ruby/object:Gem::Requirement
89
- none: false
90
79
  requirements:
91
80
  - - ~>
92
81
  - !ruby/object:Gem::Version
93
82
  version: 2.12.0
83
+ - !ruby/object:Gem::Dependency
84
+ name: guard
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ! '>='
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ! '>='
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: guard-rspec
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ! '>='
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ! '>='
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: guard-bundler
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ! '>='
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ! '>='
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: guard-rubocop
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ! '>='
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ! '>='
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ - !ruby/object:Gem::Dependency
140
+ name: rubocop
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ! '>='
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ! '>='
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
153
+ - !ruby/object:Gem::Dependency
154
+ name: spork
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - ! '>='
158
+ - !ruby/object:Gem::Version
159
+ version: '0'
160
+ type: :development
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - ! '>='
165
+ - !ruby/object:Gem::Version
166
+ version: '0'
167
+ - !ruby/object:Gem::Dependency
168
+ name: simplecov
169
+ requirement: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - ! '>='
172
+ - !ruby/object:Gem::Version
173
+ version: '0'
174
+ type: :development
175
+ prerelease: false
176
+ version_requirements: !ruby/object:Gem::Requirement
177
+ requirements:
178
+ - - ! '>='
179
+ - !ruby/object:Gem::Version
180
+ version: '0'
94
181
  description: EM-Synchrony-Moped is a Moped driver patch for EM-Synchtony, allowing
95
182
  your asynchronous application use non-blocking connections to MongoDB. Moped is
96
183
  the MongoDB driver for the Mongoid ORM.
@@ -101,49 +188,58 @@ extra_rdoc_files: []
101
188
  files:
102
189
  - .gitignore
103
190
  - Gemfile
191
+ - Guardfile
104
192
  - README.md
105
193
  - Rakefile
106
194
  - em-synchrony-moped.gemspec
107
195
  - lib/em-synchrony/moped.rb
108
- - spec/moped_spec.rb
196
+ - lib/em-synchrony/moped/cluster.rb
197
+ - lib/em-synchrony/moped/connection.rb
198
+ - lib/em-synchrony/moped/node.rb
199
+ - spec/lib/em-synchrony/moped/cluster_spec.rb
200
+ - spec/lib/em-synchrony/moped/connection_spec.rb
201
+ - spec/lib/em-synchrony/moped/node_spec.rb
109
202
  - spec/spec_helper.rb
110
203
  - spec/ssl/ca_cert.pem
111
204
  - spec/ssl/server.crt
112
205
  - spec/ssl/server.key
113
206
  - spec/ssl/untrusted.crt
114
207
  - spec/ssl/untrusted.key
208
+ - spec/support/contexts.rb
115
209
  - spec/support/simulated_mongod.rb
116
210
  homepage:
117
211
  licenses: []
212
+ metadata: {}
118
213
  post_install_message:
119
214
  rdoc_options: []
120
215
  require_paths:
121
216
  - lib
122
217
  required_ruby_version: !ruby/object:Gem::Requirement
123
- none: false
124
218
  requirements:
125
219
  - - ! '>='
126
220
  - !ruby/object:Gem::Version
127
221
  version: '0'
128
222
  required_rubygems_version: !ruby/object:Gem::Requirement
129
- none: false
130
223
  requirements:
131
224
  - - ! '>='
132
225
  - !ruby/object:Gem::Version
133
226
  version: '0'
134
227
  requirements: []
135
228
  rubyforge_project:
136
- rubygems_version: 1.8.25
229
+ rubygems_version: 2.1.7
137
230
  signing_key:
138
- specification_version: 3
231
+ specification_version: 4
139
232
  summary: Moped driver for EM-Synchrony
140
233
  test_files:
141
- - spec/moped_spec.rb
234
+ - spec/lib/em-synchrony/moped/cluster_spec.rb
235
+ - spec/lib/em-synchrony/moped/connection_spec.rb
236
+ - spec/lib/em-synchrony/moped/node_spec.rb
142
237
  - spec/spec_helper.rb
143
238
  - spec/ssl/ca_cert.pem
144
239
  - spec/ssl/server.crt
145
240
  - spec/ssl/server.key
146
241
  - spec/ssl/untrusted.crt
147
242
  - spec/ssl/untrusted.key
243
+ - spec/support/contexts.rb
148
244
  - spec/support/simulated_mongod.rb
149
245
  has_rdoc: