mongo 2.1.0.rc0 → 2.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.
Files changed (110) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +5 -2
  3. data.tar.gz.sig +0 -0
  4. data/Rakefile +2 -2
  5. data/lib/mongo.rb +2 -1
  6. data/lib/mongo/address.rb +11 -5
  7. data/lib/mongo/address/ipv4.rb +6 -1
  8. data/lib/mongo/auth/cr/conversation.rb +1 -1
  9. data/lib/mongo/auth/ldap/conversation.rb +1 -1
  10. data/lib/mongo/auth/scram/conversation.rb +1 -1
  11. data/lib/mongo/auth/user/view.rb +2 -2
  12. data/lib/mongo/auth/x509/conversation.rb +1 -1
  13. data/lib/mongo/bulk_write.rb +12 -9
  14. data/lib/mongo/bulk_write/transformable.rb +20 -5
  15. data/lib/mongo/client.rb +11 -11
  16. data/lib/mongo/cluster.rb +2 -2
  17. data/lib/mongo/collection.rb +21 -8
  18. data/lib/mongo/collection/view.rb +1 -0
  19. data/lib/mongo/collection/view/aggregation.rb +11 -5
  20. data/lib/mongo/collection/view/iterable.rb +6 -2
  21. data/lib/mongo/collection/view/map_reduce.rb +39 -5
  22. data/lib/mongo/collection/view/readable.rb +35 -30
  23. data/lib/mongo/collection/view/writable.rb +26 -18
  24. data/lib/mongo/database.rb +12 -2
  25. data/lib/mongo/database/view.rb +4 -3
  26. data/lib/mongo/dbref.rb +4 -4
  27. data/lib/mongo/grid/fs_bucket.rb +8 -1
  28. data/lib/mongo/grid/stream/read.rb +1 -1
  29. data/lib/mongo/index.rb +5 -0
  30. data/lib/mongo/index/view.rb +2 -2
  31. data/lib/mongo/monitoring/command_log_subscriber.rb +9 -3
  32. data/lib/mongo/monitoring/event.rb +1 -0
  33. data/lib/mongo/monitoring/event/command_started.rb +2 -1
  34. data/lib/mongo/monitoring/event/command_succeeded.rb +6 -3
  35. data/lib/mongo/monitoring/event/secure.rb +58 -0
  36. data/lib/mongo/operation.rb +31 -1
  37. data/lib/mongo/operation/commands/collections_info.rb +2 -0
  38. data/lib/mongo/operation/commands/collections_info/result.rb +39 -0
  39. data/lib/mongo/operation/commands/list_indexes/result.rb +2 -1
  40. data/lib/mongo/operation/commands/map_reduce/result.rb +1 -1
  41. data/lib/mongo/operation/read/query.rb +2 -0
  42. data/lib/mongo/operation/read/query/result.rb +40 -0
  43. data/lib/mongo/operation/result.rb +13 -1
  44. data/lib/mongo/operation/write/bulk/delete.rb +2 -2
  45. data/lib/mongo/operation/write/bulk/update.rb +3 -3
  46. data/lib/mongo/operation/write/delete.rb +2 -2
  47. data/lib/mongo/operation/write/update.rb +9 -4
  48. data/lib/mongo/options.rb +1 -0
  49. data/lib/mongo/options/redacted.rb +156 -0
  50. data/lib/mongo/protocol/insert.rb +25 -6
  51. data/lib/mongo/protocol/query.rb +45 -31
  52. data/lib/mongo/protocol/reply.rb +29 -6
  53. data/lib/mongo/protocol/serializers.rb +1 -1
  54. data/lib/mongo/retryable.rb +83 -0
  55. data/lib/mongo/server.rb +16 -3
  56. data/lib/mongo/server/connectable.rb +21 -3
  57. data/lib/mongo/server/connection.rb +38 -4
  58. data/lib/mongo/server/connection_pool.rb +12 -0
  59. data/lib/mongo/server/connection_pool/queue.rb +15 -0
  60. data/lib/mongo/server/monitor/connection.rb +2 -2
  61. data/lib/mongo/server_selector.rb +5 -0
  62. data/lib/mongo/server_selector/selectable.rb +16 -9
  63. data/lib/mongo/socket.rb +6 -2
  64. data/lib/mongo/uri.rb +1 -1
  65. data/lib/mongo/version.rb +1 -1
  66. data/spec/mongo/bulk_write/ordered_combiner_spec.rb +11 -11
  67. data/spec/mongo/bulk_write/unordered_combiner_spec.rb +10 -10
  68. data/spec/mongo/client_spec.rb +101 -18
  69. data/spec/mongo/collection_spec.rb +44 -0
  70. data/spec/mongo/connection_string_spec.rb +36 -58
  71. data/spec/mongo/database_spec.rb +20 -0
  72. data/spec/mongo/grid/fs_bucket_spec.rb +1 -1
  73. data/spec/mongo/grid/stream/write_spec.rb +2 -2
  74. data/spec/mongo/monitoring/event/command_started_spec.rb +26 -0
  75. data/spec/mongo/monitoring/event/command_succeeded_spec.rb +26 -0
  76. data/spec/mongo/monitoring/event/secure_spec.rb +57 -0
  77. data/spec/mongo/operation/commands/aggregate_spec.rb +0 -16
  78. data/spec/mongo/operation/commands/command_spec.rb +0 -18
  79. data/spec/mongo/operation/kill_cursors_spec.rb +0 -16
  80. data/spec/mongo/operation/read/get_more_spec.rb +0 -16
  81. data/spec/mongo/operation/read/query_spec.rb +19 -16
  82. data/spec/mongo/operation/write/bulk/delete_spec.rb +16 -16
  83. data/spec/mongo/operation/write/bulk/update_spec.rb +6 -6
  84. data/spec/mongo/operation/write/command/delete_spec.rb +0 -16
  85. data/spec/mongo/operation/write/command/insert_spec.rb +0 -16
  86. data/spec/mongo/operation/write/command/update_spec.rb +0 -16
  87. data/spec/mongo/operation/write/delete_spec.rb +3 -3
  88. data/spec/mongo/operation/write/update_spec.rb +6 -6
  89. data/spec/mongo/options/redacted_spec.rb +350 -0
  90. data/spec/mongo/protocol/query_spec.rb +15 -1
  91. data/spec/mongo/retryable_spec.rb +147 -0
  92. data/spec/mongo/server/connection_pool/queue_spec.rb +16 -0
  93. data/spec/mongo/server/connection_pool_spec.rb +32 -0
  94. data/spec/mongo/server/connection_spec.rb +37 -0
  95. data/spec/mongo/server_discovery_and_monitoring_spec.rb +24 -59
  96. data/spec/mongo/server_selection_rtt_spec.rb +37 -57
  97. data/spec/mongo/server_selection_spec.rb +2 -0
  98. data/spec/mongo/server_selector/nearest_spec.rb +1 -0
  99. data/spec/mongo/server_selector/primary_preferred_spec.rb +1 -0
  100. data/spec/mongo/server_selector/primary_spec.rb +8 -2
  101. data/spec/mongo/server_selector/secondary_preferred_spec.rb +1 -0
  102. data/spec/mongo/server_selector/secondary_spec.rb +1 -0
  103. data/spec/mongo/server_spec.rb +68 -1
  104. data/spec/mongo/socket/ssl_spec.rb +29 -5
  105. data/spec/mongo/uri_spec.rb +20 -20
  106. data/spec/support/crud.rb +7 -1
  107. data/spec/support/matchers.rb +1 -1
  108. data/spec/support/shared/server_selector.rb +58 -2
  109. metadata +20 -5
  110. metadata.gz.sig +0 -0
@@ -470,6 +470,50 @@ describe Mongo::Collection do
470
470
  end
471
471
  end
472
472
 
473
+ context 'when the user is not authorized' do
474
+
475
+ let(:view) do
476
+ unauthorized_collection.find
477
+ end
478
+
479
+ it 'iterates over the documents' do
480
+ expect {
481
+ view.each{ |document| document }
482
+ }.to raise_error(Mongo::Error::OperationFailure)
483
+ end
484
+ end
485
+
486
+ context 'when documents contain potential error message fields' do
487
+
488
+ [ Mongo::Error::ERRMSG, Mongo::Error::ERROR, Mongo::Operation::Result::OK ].each do |field|
489
+
490
+ context "when the document contains a '#{field}' field" do
491
+
492
+ let(:value) do
493
+ 'testing'
494
+ end
495
+
496
+ let(:view) do
497
+ authorized_collection.find
498
+ end
499
+
500
+ before do
501
+ authorized_collection.insert_one({ field => value })
502
+ end
503
+
504
+ after do
505
+ authorized_collection.delete_many
506
+ end
507
+
508
+ it 'iterates over the documents' do
509
+ view.each do |document|
510
+ expect(document[field]).to eq(value)
511
+ end
512
+ end
513
+ end
514
+ end
515
+ end
516
+
473
517
  context 'when provided options' do
474
518
 
475
519
  let(:view) do
@@ -11,78 +11,56 @@ describe 'ConnectionString' do
11
11
 
12
12
  before(:all) do
13
13
 
14
- class Mongo::Address
14
+ module Mongo
15
+ class Address
15
16
 
16
- private
17
+ private
17
18
 
18
- def initialize_resolver!(timeout, ssl_options)
19
- family = (host == 'localhost') ? ::Socket::AF_INET : ::Socket::AF_UNSPEC
20
- info = ::Socket.getaddrinfo(host, nil, family, ::Socket::SOCK_STREAM)
21
- FAMILY_MAP[info.first[4]].new(info[3], port, host)
19
+ alias :original_initialize_resolver! :initialize_resolver!
20
+ def initialize_resolver!(timeout, ssl_options)
21
+ family = (host == 'localhost') ? ::Socket::AF_INET : ::Socket::AF_UNSPEC
22
+ info = ::Socket.getaddrinfo(host, nil, family, ::Socket::SOCK_STREAM)
23
+ FAMILY_MAP[info.first[4]].new(info[3], port, host)
24
+ end
22
25
  end
23
- end
24
26
 
25
- class Mongo::Server
27
+ class Server
28
+
29
+ # The constructor keeps the same API, but does not instantiate a
30
+ # monitor and run it.
31
+ alias :original_initialize :initialize
32
+ def initialize(address, cluster, monitoring, event_listeners, options = {})
33
+ @address = address
34
+ @cluster = cluster
35
+ @monitoring = monitoring
36
+ @options = options.freeze
37
+ @monitor = Monitor.new(address, event_listeners, options)
38
+ end
26
39
 
27
- # The constructor keeps the same API, but does not instantiate a
28
- # monitor and run it.
29
- def initialize(address, cluster, monitoring, event_listeners, options = {})
30
- @address = address
31
- @cluster = cluster
32
- @monitoring = monitoring
33
- @options = options.freeze
34
- @monitor = Monitor.new(address, event_listeners, options)
40
+ # Disconnect simply needs to return true since we have no monitor and
41
+ # no connection.
42
+ alias :original_disconnect! :disconnect!
43
+ def disconnect!; true; end
35
44
  end
36
-
37
- # Disconnect simply needs to return true since we have no monitor and
38
- # no connection.
39
- def disconnect!; true; end
40
45
  end
41
46
  end
42
47
 
43
48
  after(:all) do
44
49
 
45
- # Return the server implementation to its original for the other
46
- # tests in the suite.
47
- class Mongo::Server
48
-
49
- # Returns the constructor to its original implementation.
50
- def initialize(address, cluster, monitoring, event_listeners, options = {})
51
- @address = address
52
- @cluster = cluster
53
- @monitoring = monitoring
54
- @options = options.freeze
55
- @monitor = Monitor.new(address, event_listeners, options)
56
- @monitor.scan!
57
- @monitor.run!
50
+ module Mongo
51
+ # Return the implementations to their originals for the other
52
+ # tests in the suite.
53
+ class Address
54
+ alias :initialize_resolver! :original_initialize_resolver!
55
+ remove_method(:original_initialize_resolver!)
58
56
  end
59
57
 
60
- # Returns disconnect! to its original implementation.
61
- def disconnect!
62
- context.with_connection do |connection|
63
- connection.disconnect!
64
- end
65
- @monitor.stop! and true
66
- end
67
- end
58
+ class Server
59
+ alias :initialize :original_initialize
60
+ remove_method(:original_initialize)
68
61
 
69
- class Mongo::Address
70
-
71
- private
72
-
73
- def initialize_resolver!(timeout, ssl_options)
74
- family = (host == 'localhost') ? ::Socket::AF_INET : ::Socket::AF_UNSPEC
75
- error = nil
76
- ::Socket.getaddrinfo(host, nil, family, ::Socket::SOCK_STREAM).each do |info|
77
- begin
78
- res = FAMILY_MAP[info[4]].new(info[3], port, host)
79
- res.socket(timeout, ssl_options).connect!.close
80
- return res
81
- rescue IOError, SystemCallError, Error::SocketError => e
82
- error = e
83
- end
84
- end
85
- raise error
62
+ alias :disconnect! :original_disconnect!
63
+ remove_method(:original_disconnect!)
86
64
  end
87
65
  end
88
66
  end
@@ -93,6 +93,26 @@ describe Mongo::Database do
93
93
  expect(database.collection_names(batch_size: 1).to_a).to include('users')
94
94
  end
95
95
  end
96
+
97
+ context 'when there are more collections than the initial batch size' do
98
+
99
+ before do
100
+ 200.times do |i|
101
+ database["#{i}_dalmatians"].create
102
+ end
103
+ end
104
+
105
+ after do
106
+ 200.times do |i|
107
+ database["#{i}_dalmatians"].drop
108
+ end
109
+ end
110
+
111
+ it 'returns all collections' do
112
+ expect(database.collection_names.select { |c| c =~ /dalmatians/}.size).to eq(200)
113
+ end
114
+
115
+ end
96
116
  end
97
117
 
98
118
  describe '#list_collections' do
@@ -55,7 +55,7 @@ describe Mongo::Grid::FSBucket do
55
55
  end
56
56
 
57
57
  let(:read_pref) do
58
- Mongo::ServerSelector.get(options[:read].merge(authorized_client.options))
58
+ Mongo::ServerSelector.get(Mongo::Options::Redacted.new(options[:read].merge(authorized_client.options)))
59
59
  end
60
60
 
61
61
  it 'sets the read preference' do
@@ -87,14 +87,14 @@ describe Mongo::Grid::FSBucket::Stream::Write do
87
87
  context 'when chunks are inserted' do
88
88
 
89
89
  it 'uses that write concern' do
90
- expect(stream.send(:chunks_collection).write_concern.options).to eq(expected)
90
+ expect(stream.send(:chunks_collection).write_concern.options[:w]).to eq(expected[:w])
91
91
  end
92
92
  end
93
93
 
94
94
  context 'when a files document is inserted' do
95
95
 
96
96
  it 'uses that write concern' do
97
- expect(stream.send(:files_collection).write_concern.options).to eq(expected)
97
+ expect(stream.send(:files_collection).write_concern.options[:w]).to eq(expected[:w])
98
98
  end
99
99
  end
100
100
  end
@@ -0,0 +1,26 @@
1
+ require 'spec_helper'
2
+
3
+ describe Mongo::Monitoring::Event::CommandStarted do
4
+
5
+ describe '#initialize' do
6
+
7
+ let(:address) do
8
+ Mongo::Address.new('127.0.0.1:27017')
9
+ end
10
+
11
+ let(:command) do
12
+ BSON::Document.new(test: 'value')
13
+ end
14
+
15
+ context 'when the command should be redacted' do
16
+
17
+ let(:event) do
18
+ described_class.new('copydb', 'admin', address, 1, 2, command)
19
+ end
20
+
21
+ it 'sets the command to an empty document' do
22
+ expect(event.command).to be_empty
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,26 @@
1
+ require 'spec_helper'
2
+
3
+ describe Mongo::Monitoring::Event::CommandSucceeded do
4
+
5
+ describe '#initialize' do
6
+
7
+ let(:address) do
8
+ Mongo::Address.new('127.0.0.1:27017')
9
+ end
10
+
11
+ let(:reply) do
12
+ BSON::Document.new(test: 'value')
13
+ end
14
+
15
+ context 'when the reply should be redacted' do
16
+
17
+ let(:event) do
18
+ described_class.new('copydb', 'admin', address, 1, 2, reply, 0.5)
19
+ end
20
+
21
+ it 'sets the reply to an empty document' do
22
+ expect(event.reply).to be_empty
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,57 @@
1
+ require 'spec_helper'
2
+
3
+ describe Mongo::Monitoring::Event::Secure do
4
+
5
+ let(:document) do
6
+ BSON::Document.new(test: 'value')
7
+ end
8
+
9
+ let(:klass) do
10
+ Class.new do
11
+ include Mongo::Monitoring::Event::Secure
12
+ end
13
+ end
14
+
15
+ describe '#redacted' do
16
+
17
+ let(:secure) do
18
+ klass.new
19
+ end
20
+
21
+ context 'when the command must be redacted' do
22
+
23
+ context 'when the command name is a string' do
24
+
25
+ let(:redacted) do
26
+ secure.redacted('saslStart', document)
27
+ end
28
+
29
+ it 'returns an empty document' do
30
+ expect(redacted).to be_empty
31
+ end
32
+ end
33
+
34
+ context 'when the command name is a symbol' do
35
+
36
+ let(:redacted) do
37
+ secure.redacted(:saslStart, document)
38
+ end
39
+
40
+ it 'returns an empty document' do
41
+ expect(redacted).to be_empty
42
+ end
43
+ end
44
+ end
45
+
46
+ context 'when the command is not in the redacted list' do
47
+
48
+ let(:redacted) do
49
+ secure.redacted(:find, document)
50
+ end
51
+
52
+ it 'returns the document' do
53
+ expect(redacted).to eq(document)
54
+ end
55
+ end
56
+ end
57
+ end
@@ -49,22 +49,6 @@ describe Mongo::Operation::Aggregate do
49
49
  end
50
50
  end
51
51
 
52
- context '#merge' do
53
- let(:other_op) { described_class.new(spec) }
54
-
55
- it 'is not allowed' do
56
- expect{ op.merge(other_op) }.to raise_exception
57
- end
58
- end
59
-
60
- context '#merge!' do
61
- let(:other_op) { described_class.new(spec) }
62
-
63
- it 'is not allowed' do
64
- expect{ op.merge!(other_op) }.to raise_exception
65
- end
66
- end
67
-
68
52
  describe '#execute' do
69
53
 
70
54
  context 'when the aggregation fails' do
@@ -38,24 +38,6 @@ describe Mongo::Operation::Command do
38
38
  end
39
39
  end
40
40
 
41
- context '#merge' do
42
-
43
- let(:other_op) { described_class.new(spec) }
44
-
45
- it 'raises an exception' do
46
- expect{ op.merge(other_op) }.to raise_exception
47
- end
48
- end
49
-
50
- context '#merge!' do
51
-
52
- let(:other_op) { described_class.new(spec) }
53
-
54
- it 'raises an exception' do
55
- expect{ op.merge!(other_op) }.to raise_exception
56
- end
57
- end
58
-
59
41
  describe '#execute' do
60
42
 
61
43
  context 'when the command succeeds' do
@@ -27,22 +27,6 @@ describe Mongo::Operation::KillCursors do
27
27
  end
28
28
  end
29
29
 
30
- context '#merge' do
31
- let(:other_op) { described_class.new(spec) }
32
-
33
- it 'is not allowed' do
34
- expect{ op.merge(other_op) }.to raise_exception
35
- end
36
- end
37
-
38
- context '#merge!' do
39
- let(:other_op) { described_class.new(spec) }
40
-
41
- it 'is not allowed' do
42
- expect{ op.merge!(other_op) }.to raise_exception
43
- end
44
- end
45
-
46
30
  describe '#execute' do
47
31
 
48
32
  context 'message' do
@@ -39,22 +39,6 @@ describe Mongo::Operation::Read::GetMore do
39
39
  end
40
40
  end
41
41
 
42
- context '#merge' do
43
- let(:other_op) { described_class.new(spec) }
44
-
45
- it 'is not allowed' do
46
- expect{ op.merge(other_op) }.to raise_exception
47
- end
48
- end
49
-
50
- context '#merge!' do
51
- let(:other_op) { described_class.new(spec) }
52
-
53
- it 'is not allowed' do
54
- expect{ op.merge!(other_op) }.to raise_exception
55
- end
56
- end
57
-
58
42
  describe '#execute' do
59
43
 
60
44
  context 'message' do
@@ -42,22 +42,6 @@ describe Mongo::Operation::Read::Query do
42
42
  end
43
43
  end
44
44
 
45
- context '#merge' do
46
- let(:other_op) { described_class.new(spec) }
47
-
48
- it 'is not allowed' do
49
- expect{ op.merge(other_op) }.to raise_exception
50
- end
51
- end
52
-
53
- context '#merge!' do
54
- let(:other_op) { described_class.new(spec) }
55
-
56
- it 'is not allowed' do
57
- expect{ op.merge!(other_op) }.to raise_exception
58
- end
59
- end
60
-
61
45
  describe '#message' do
62
46
 
63
47
  let(:query_options) do
@@ -98,6 +82,25 @@ describe Mongo::Operation::Read::Query do
98
82
  op.execute(primary_context)
99
83
  end
100
84
  end
85
+
86
+ context "when the document contains an 'ok' field" do
87
+
88
+ before do
89
+ authorized_collection.insert_one(ok: false)
90
+ end
91
+
92
+ after do
93
+ authorized_collection.delete_many
94
+ end
95
+
96
+ let(:context) do
97
+ authorized_client.cluster.next_primary.context
98
+ end
99
+
100
+ it 'does not raise an exception' do
101
+ expect(op.execute(context)).to be_a(Mongo::Operation::Read::Query::Result)
102
+ end
103
+ end
101
104
  end
102
105
  end
103
106