mongo 2.1.2 → 2.2.0.rc0

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 (140) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/README.md +10 -3
  5. data/Rakefile +1 -7
  6. data/lib/csasl/csasl.bundle +0 -0
  7. data/lib/mongo/auth/user/view.rb +1 -1
  8. data/lib/mongo/bulk_write.rb +7 -1
  9. data/lib/mongo/client.rb +17 -15
  10. data/lib/mongo/cluster.rb +4 -2
  11. data/lib/mongo/collection.rb +36 -2
  12. data/lib/mongo/collection/view.rb +24 -21
  13. data/lib/mongo/collection/view/aggregation.rb +5 -42
  14. data/lib/mongo/collection/view/builder.rb +20 -0
  15. data/lib/mongo/collection/view/builder/aggregation.rb +98 -0
  16. data/lib/mongo/collection/view/builder/find_command.rb +111 -0
  17. data/lib/mongo/collection/view/builder/flags.rb +62 -0
  18. data/lib/mongo/collection/view/builder/map_reduce.rb +134 -0
  19. data/lib/mongo/collection/view/builder/modifiers.rb +80 -0
  20. data/lib/mongo/collection/view/builder/op_query.rb +83 -0
  21. data/lib/mongo/collection/view/explainable.rb +15 -0
  22. data/lib/mongo/collection/view/immutable.rb +5 -12
  23. data/lib/mongo/collection/view/iterable.rb +24 -2
  24. data/lib/mongo/collection/view/map_reduce.rb +18 -27
  25. data/lib/mongo/collection/view/readable.rb +70 -112
  26. data/lib/mongo/collection/view/writable.rb +23 -7
  27. data/lib/mongo/cursor.rb +76 -25
  28. data/lib/mongo/cursor/builder.rb +18 -0
  29. data/lib/mongo/cursor/builder/get_more_command.rb +71 -0
  30. data/lib/mongo/cursor/builder/kill_cursors_command.rb +62 -0
  31. data/lib/mongo/cursor/builder/op_get_more.rb +61 -0
  32. data/lib/mongo/cursor/builder/op_kill_cursors.rb +56 -0
  33. data/lib/mongo/database.rb +2 -2
  34. data/lib/mongo/database/view.rb +9 -5
  35. data/lib/mongo/dbref.rb +3 -3
  36. data/lib/mongo/error.rb +1 -0
  37. data/lib/mongo/error/invalid_write_concern.rb +35 -0
  38. data/lib/mongo/grid/file/chunk.rb +2 -2
  39. data/lib/mongo/index/view.rb +5 -2
  40. data/lib/mongo/operation.rb +1 -0
  41. data/lib/mongo/operation/commands.rb +2 -0
  42. data/lib/mongo/operation/commands/aggregate.rb +39 -45
  43. data/lib/mongo/operation/commands/aggregate/result.rb +54 -68
  44. data/lib/mongo/operation/commands/collections_info.rb +38 -36
  45. data/lib/mongo/operation/commands/collections_info/result.rb +17 -15
  46. data/lib/mongo/operation/commands/command.rb +24 -22
  47. data/lib/mongo/operation/commands/find.rb +27 -0
  48. data/lib/mongo/operation/commands/find/result.rb +62 -0
  49. data/lib/mongo/operation/commands/get_more.rb +27 -0
  50. data/lib/mongo/operation/commands/get_more/result.rb +62 -0
  51. data/lib/mongo/operation/commands/indexes.rb +41 -39
  52. data/lib/mongo/operation/commands/list_collections.rb +25 -31
  53. data/lib/mongo/operation/commands/list_collections/result.rb +63 -81
  54. data/lib/mongo/operation/commands/list_indexes.rb +27 -35
  55. data/lib/mongo/operation/commands/list_indexes/result.rb +67 -85
  56. data/lib/mongo/operation/commands/map_reduce.rb +29 -37
  57. data/lib/mongo/operation/commands/map_reduce/result.rb +85 -88
  58. data/lib/mongo/operation/commands/parallel_scan.rb +29 -33
  59. data/lib/mongo/operation/commands/parallel_scan/result.rb +34 -42
  60. data/lib/mongo/operation/commands/user_query.rb +40 -38
  61. data/lib/mongo/operation/commands/users_info.rb +24 -29
  62. data/lib/mongo/operation/commands/users_info/result.rb +13 -11
  63. data/lib/mongo/operation/object_id_generator.rb +36 -0
  64. data/lib/mongo/operation/result.rb +30 -0
  65. data/lib/mongo/operation/specifiable.rb +35 -1
  66. data/lib/mongo/operation/write/bulk/bulkable.rb +4 -3
  67. data/lib/mongo/operation/write/bulk/delete/result.rb +18 -25
  68. data/lib/mongo/operation/write/bulk/legacy_mergable.rb +2 -2
  69. data/lib/mongo/operation/write/command/delete.rb +3 -2
  70. data/lib/mongo/operation/write/command/insert.rb +4 -2
  71. data/lib/mongo/operation/write/command/update.rb +6 -3
  72. data/lib/mongo/operation/write/gle.rb +2 -1
  73. data/lib/mongo/operation/write/idable.rb +19 -2
  74. data/lib/mongo/options/mapper.rb +22 -0
  75. data/lib/mongo/protocol/bit_vector.rb +3 -3
  76. data/lib/mongo/protocol/delete.rb +15 -5
  77. data/lib/mongo/protocol/get_more.rb +10 -5
  78. data/lib/mongo/protocol/insert.rb +1 -6
  79. data/lib/mongo/protocol/kill_cursors.rb +14 -1
  80. data/lib/mongo/protocol/message.rb +32 -8
  81. data/lib/mongo/protocol/serializers.rb +15 -16
  82. data/lib/mongo/protocol/update.rb +35 -12
  83. data/lib/mongo/server/connectable.rb +3 -1
  84. data/lib/mongo/server/connection.rb +5 -5
  85. data/lib/mongo/server/description.rb +8 -2
  86. data/lib/mongo/server/description/features.rb +2 -1
  87. data/lib/mongo/server/monitor.rb +1 -12
  88. data/lib/mongo/server/monitor/connection.rb +30 -26
  89. data/lib/mongo/server_selector/selectable.rb +21 -4
  90. data/lib/mongo/uri.rb +2 -0
  91. data/lib/mongo/version.rb +1 -1
  92. data/lib/mongo/write_concern.rb +21 -6
  93. data/mongo.gemspec +1 -2
  94. data/spec/mongo/bulk_write/ordered_combiner_spec.rb +13 -0
  95. data/spec/mongo/bulk_write_spec.rb +58 -0
  96. data/spec/mongo/client_spec.rb +6 -4
  97. data/spec/mongo/collection/view/builder/find_command_spec.rb +167 -0
  98. data/spec/mongo/collection/view/builder/flags_spec.rb +106 -0
  99. data/spec/mongo/collection/view/builder/modifiers_spec.rb +210 -0
  100. data/spec/mongo/collection/view/builder/op_query_spec.rb +154 -0
  101. data/spec/mongo/collection/view/explainable_spec.rb +1 -2
  102. data/spec/mongo/collection/view/immutable_spec.rb +3 -52
  103. data/spec/mongo/collection/view/map_reduce_spec.rb +12 -12
  104. data/spec/mongo/collection/view/readable_spec.rb +86 -80
  105. data/spec/mongo/collection/view_spec.rb +109 -703
  106. data/spec/mongo/collection_spec.rb +594 -11
  107. data/spec/mongo/command_monitoring_spec.rb +40 -27
  108. data/spec/mongo/cursor/builder/get_more_command_spec.rb +160 -0
  109. data/spec/mongo/cursor/builder/op_get_more_spec.rb +52 -0
  110. data/spec/mongo/cursor_spec.rb +10 -60
  111. data/spec/mongo/database_spec.rb +24 -3
  112. data/spec/mongo/dbref_spec.rb +4 -4
  113. data/spec/mongo/grid/file/chunk_spec.rb +1 -1
  114. data/spec/mongo/grid/fs_bucket_spec.rb +3 -3
  115. data/spec/mongo/index/view_spec.rb +41 -0
  116. data/spec/mongo/operation/{aggregate → commands/aggregate}/result_spec.rb +1 -1
  117. data/spec/mongo/operation/commands/aggregate_spec.rb +1 -1
  118. data/spec/mongo/operation/commands/collections_info_spec.rb +1 -1
  119. data/spec/mongo/operation/commands/command_spec.rb +1 -1
  120. data/spec/mongo/operation/commands/indexes_spec.rb +1 -1
  121. data/spec/mongo/operation/commands/map_reduce_spec.rb +1 -1
  122. data/spec/mongo/operation/write/command/delete_spec.rb +25 -0
  123. data/spec/mongo/operation/write/command/insert_spec.rb +25 -0
  124. data/spec/mongo/operation/write/command/update_spec.rb +25 -0
  125. data/spec/mongo/protocol/delete_spec.rb +4 -4
  126. data/spec/mongo/protocol/get_more_spec.rb +4 -4
  127. data/spec/mongo/protocol/insert_spec.rb +3 -3
  128. data/spec/mongo/protocol/kill_cursors_spec.rb +3 -3
  129. data/spec/mongo/protocol/query_spec.rb +7 -7
  130. data/spec/mongo/protocol/update_spec.rb +5 -5
  131. data/spec/mongo/server/description/features_spec.rb +25 -0
  132. data/spec/mongo/write_concern_spec.rb +126 -0
  133. data/spec/spec_helper.rb +9 -19
  134. data/spec/support/command_monitoring.rb +8 -0
  135. data/spec/support/command_monitoring/find.yml +53 -4
  136. data/spec/support/matchers.rb +1 -1
  137. data/spec/support/shared/protocol.rb +5 -5
  138. data/spec/support/travis.rb +1 -1
  139. metadata +43 -10
  140. metadata.gz.sig +0 -0
@@ -25,6 +25,7 @@ module Mongo
25
25
  #
26
26
  # @since 2.0.0
27
27
  MAPPINGS = {
28
+ :find_command => 4,
28
29
  :list_collections => 3,
29
30
  :list_indexes => 3,
30
31
  :scram_sha_1 => 3,
@@ -35,7 +36,7 @@ module Mongo
35
36
  # The wire protocol versions that this version of the driver supports.
36
37
  #
37
38
  # @since 2.0.0
38
- DRIVER_WIRE_VERSIONS = (0..3).freeze
39
+ DRIVER_WIRE_VERSIONS = (0..4).freeze
39
40
 
40
41
  # Create the methods for each mapping to tell if they are supported.
41
42
  #
@@ -35,16 +35,6 @@ module Mongo
35
35
  # @since 2.0.0
36
36
  MIN_SCAN_FREQUENCY = 0.5.freeze
37
37
 
38
- # The command used for determining server status.
39
- #
40
- # @since 2.0.0
41
- STATUS = { :ismaster => 1 }.freeze
42
-
43
- # The constant for the ismaster command.
44
- #
45
- # @since 2.0.0
46
- ISMASTER = Protocol::Query.new(Database::ADMIN, Database::COMMAND, STATUS, :limit => -1)
47
-
48
38
  # The weighting factor (alpha) for calculating the average moving round trip time.
49
39
  #
50
40
  # @since 2.0.0
@@ -170,8 +160,7 @@ module Mongo
170
160
  @mutex.synchronize do
171
161
  start = Time.now
172
162
  begin
173
- result = connection.dispatch([ ISMASTER ]).documents[0]
174
- return result, calculate_average_round_trip_time(start)
163
+ return connection.ismaster, calculate_average_round_trip_time(start)
175
164
  rescue Exception => e
176
165
  log_debug(e.message)
177
166
  return {}, calculate_average_round_trip_time(start)
@@ -22,11 +22,41 @@ module Mongo
22
22
  class Connection
23
23
  include Connectable
24
24
 
25
+ # The command used for determining server status.
26
+ #
27
+ # @since 2.2.0
28
+ ISMASTER = { :ismaster => 1 }.freeze
29
+
30
+ # The constant for the ismaster command.
31
+ #
32
+ # @since 2.2.0
33
+ ISMASTER_MESSAGE = Protocol::Query.new(Database::ADMIN, Database::COMMAND, ISMASTER, :limit => -1)
34
+
35
+ # The raw bytes for the ismaster message.
36
+ #
37
+ # @since 2.2.0
38
+ ISMASTER_BYTES = ISMASTER_MESSAGE.serialize.to_s.freeze
39
+
25
40
  # The default time in seconds to timeout a connection attempt.
26
41
  #
27
42
  # @since 2.1.2
28
43
  CONNECT_TIMEOUT = 10.freeze
29
44
 
45
+ # Send the preserialized ismaster call.
46
+ #
47
+ # @example Send a preserialized ismaster message.
48
+ # connection.ismaster
49
+ #
50
+ # @return [ BSON::Document ] The ismaster result.
51
+ #
52
+ # @since 2.2.0
53
+ def ismaster
54
+ ensure_connected do |socket|
55
+ socket.write(ISMASTER_BYTES)
56
+ Protocol::Reply.deserialize(socket).documents[0]
57
+ end
58
+ end
59
+
30
60
  # Get the connection timeout.
31
61
  #
32
62
  # @example Get the connection timeout.
@@ -77,25 +107,6 @@ module Mongo
77
107
  true
78
108
  end
79
109
 
80
- # Dispatch the provided messages to the connection. If the last message
81
- # requires a response a reply will be returned.
82
- #
83
- # @example Dispatch the messages.
84
- # connection.dispatch([ insert, command ])
85
- #
86
- # @note This method is named dispatch since 'send' is a core Ruby method on
87
- # all objects.
88
- #
89
- # @param [ Array<Message> ] messages The messages to dispatch.
90
- #
91
- # @return [ Protocol::Reply ] The reply if needed.
92
- #
93
- # @since 2.0.0
94
- def dispatch(messages)
95
- write(messages)
96
- messages.last.replyable? ? read : nil
97
- end
98
-
99
110
  # Initialize a new socket connection from the client to the server.
100
111
  #
101
112
  # @api private
@@ -117,13 +128,6 @@ module Mongo
117
128
  @socket = nil
118
129
  @pid = Process.pid
119
130
  end
120
-
121
- private
122
-
123
- def write(messages, buffer = '')
124
- messages.each{ |message| message.serialize(buffer) }
125
- ensure_connected{ |socket| socket.write(buffer) }
126
- end
127
131
  end
128
132
  end
129
133
  end
@@ -67,6 +67,19 @@ module Mongo
67
67
  @tag_sets = tag_sets.freeze
68
68
  end
69
69
 
70
+ # Inspect the server selector.
71
+ #
72
+ # @example Inspect the server selector.
73
+ # selector.inspect
74
+ #
75
+ # @return [ String ] The inspection.
76
+ #
77
+ # @since 2.2.0
78
+ def inspect
79
+ "#<#{self.class.name}:0x#{object_id} tag_sets=#{tag_sets.inspect} " +
80
+ "server_selection_timeout=#{server_selection_timeout} local_threshold=#{local_threshold}>"
81
+ end
82
+
70
83
  # Select a server from eligible candidates.
71
84
  #
72
85
  # @example Select a server from the cluster.
@@ -77,13 +90,19 @@ module Mongo
77
90
  # @return [ Mongo::Server ] A server matching the server preference.
78
91
  #
79
92
  # @since 2.0.0
80
- def select_server(cluster)
93
+ def select_server(cluster, ping = true)
81
94
  deadline = Time.now + server_selection_timeout
82
95
  while (deadline - Time.now) > 0
83
96
  servers = candidates(cluster)
84
97
  if servers && !servers.compact.empty?
85
98
  server = servers.first
86
- return server if server.connectable?
99
+ # There is no point pinging a standalone as the subsequent scan is
100
+ # not going to change anything about the cluster.
101
+ if ping && !cluster.single?
102
+ return server if server.connectable?
103
+ else
104
+ return server
105
+ end
87
106
  end
88
107
  cluster.scan!
89
108
  end
@@ -188,8 +207,6 @@ module Mongo
188
207
  matches || []
189
208
  end
190
209
 
191
- private
192
-
193
210
  def validate_tag_sets!(tag_sets)
194
211
  if !tag_sets.all? { |set| set.empty? } && !tags_allowed?
195
212
  raise Error::InvalidServerPreference.new(name)
@@ -12,6 +12,8 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
+ require 'uri'
16
+
15
17
  module Mongo
16
18
 
17
19
  # The URI class provides a way for users to parse the MongoDB uri as
@@ -17,5 +17,5 @@ module Mongo
17
17
  # The current version of the driver.
18
18
  #
19
19
  # @since 2.0.0
20
- VERSION = '2.1.2'.freeze
20
+ VERSION = '2.2.0.rc0'.freeze
21
21
  end
@@ -52,7 +52,7 @@ module Mongo
52
52
  # The default write concern is to acknowledge on a single server.
53
53
  #
54
54
  # @since 2.0.0
55
- DEFAULT = { W => 1 }.freeze
55
+ DEFAULT = { }.freeze
56
56
 
57
57
  # Get a write concern mode for the provided options.
58
58
  #
@@ -72,17 +72,32 @@ module Mongo
72
72
  #
73
73
  # @return [ Unacknowledged, Acknowledged ] The appropriate concern.
74
74
  #
75
+ # @raise [ Error::InvalidWriteConcern ] If the write concern is invalid.
76
+ #
75
77
  # @since 2.0.0
76
78
  def get(options)
77
- if unacknowledged?(options)
78
- Unacknowledged.new(options)
79
- else
80
- Acknowledged.new(options || DEFAULT)
79
+ if options
80
+ validate!(options)
81
+ if unacknowledged?(options)
82
+ Unacknowledged.new(options)
83
+ else
84
+ Acknowledged.new(options)
85
+ end
81
86
  end
82
87
  end
83
88
 
84
89
  private
85
90
 
91
+ def validate!(options)
92
+ if options[W]
93
+ if options[W] == 0 && (options[J] || options[FSYNC])
94
+ raise Mongo::Error::InvalidWriteConcern.new
95
+ elsif options[W].is_a?(Integer) && options[W] < 0
96
+ raise Mongo::Error::InvalidWriteConcern.new
97
+ end
98
+ end
99
+ end
100
+
86
101
  # Determine if the options are for an unacknowledged write concern.
87
102
  #
88
103
  # @api private
@@ -93,7 +108,7 @@ module Mongo
93
108
  #
94
109
  # @since 2.0.0
95
110
  def unacknowledged?(options)
96
- options && (options[W] == 0 || options[W] == -1)
111
+ options[W] == 0
97
112
  end
98
113
  end
99
114
  end
@@ -4,7 +4,6 @@ require 'mongo/version'
4
4
 
5
5
  Gem::Specification.new do |s|
6
6
  s.name = 'mongo'
7
- s.rubyforge_project = 'mongo'
8
7
  s.version = Mongo::VERSION
9
8
  s.platform = Gem::Platform::RUBY
10
9
 
@@ -30,5 +29,5 @@ Gem::Specification.new do |s|
30
29
  s.has_rdoc = 'yard'
31
30
  s.bindir = 'bin'
32
31
 
33
- s.add_dependency 'bson', '~> 3.0'
32
+ s.add_dependency 'bson', '~> 4.0.0.rc0'
34
33
  end
@@ -94,6 +94,19 @@ describe Mongo::BulkWrite::OrderedCombiner do
94
94
 
95
95
  context 'when provided a series of insert one' do
96
96
 
97
+ context 'when providing only one operation' do
98
+
99
+ let(:requests) do
100
+ [{ insert_one: { _id: 0 }}]
101
+ end
102
+
103
+ it 'returns a single insert one' do
104
+ expect(combiner.combine).to eq(
105
+ [{ insert_one: [{ _id: 0 }]}]
106
+ )
107
+ end
108
+ end
109
+
97
110
  context 'when the documents are valid' do
98
111
 
99
112
  let(:requests) do
@@ -8,6 +8,14 @@ describe Mongo::BulkWrite do
8
8
 
9
9
  after do
10
10
  authorized_collection.delete_many
11
+ collection_with_validator.drop()
12
+ end
13
+
14
+ let(:collection_with_validator) do
15
+ authorized_client[:validating,
16
+ :validator => { :a => { '$exists' => true } }].tap do |c|
17
+ c.create
18
+ end
11
19
  end
12
20
 
13
21
  describe '#execute' do
@@ -425,4 +433,54 @@ describe Mongo::BulkWrite do
425
433
  end
426
434
  end
427
435
  end
436
+
437
+ describe 'when the collection has a validator', if: find_command_enabled? do
438
+
439
+ before do
440
+ collection_with_validator.insert_many([{ :a => 1 }, { :a => 2 }])
441
+ end
442
+
443
+ after do
444
+ collection_with_validator.delete_many
445
+ end
446
+
447
+ context 'when the documents are invalid' do
448
+
449
+ let(:ops) do
450
+ [
451
+ { insert_one: { :x => 1 } },
452
+ { update_one: { filter: { :a => 1 },
453
+ update: { '$unset' => { :a => '' } } } },
454
+ { replace_one: { filter: { :a => 2 },
455
+ replacement: { :x => 2 } } }
456
+ ]
457
+ end
458
+
459
+ context 'when bypass_document_validation is not set' do
460
+
461
+ let(:result) do
462
+ collection_with_validator.bulk_write(ops)
463
+ end
464
+
465
+ it 'raises BulkWriteError' do
466
+ expect {
467
+ result
468
+ }.to raise_exception(Mongo::Error::BulkWriteError)
469
+ end
470
+ end
471
+
472
+ context 'when bypass_document_validation is true' do
473
+
474
+ let(:result2) do
475
+ collection_with_validator.bulk_write(
476
+ ops, :bypass_document_validation => true)
477
+ end
478
+
479
+ it 'executes successfully' do
480
+ expect(result2.modified_count).to eq(2)
481
+ expect(result2.inserted_count).to eq(1)
482
+ end
483
+ end
484
+ end
485
+ end
428
486
  end
@@ -674,8 +674,8 @@ describe Mongo::Client do
674
674
 
675
675
  let(:client) { described_class.new(['127.0.0.1:27017'], :database => TEST_DB) }
676
676
 
677
- it 'returns a acknowledged write concern' do
678
- expect(concern.get_last_error).to eq(:getlasterror => 1, :w => 1)
677
+ it 'does not set the write concern' do
678
+ expect(concern).to be_nil
679
679
  end
680
680
  end
681
681
 
@@ -711,8 +711,10 @@ describe Mongo::Client do
711
711
  described_class.new(['127.0.0.1:27017'], :write => { :w => -1 }, :database => TEST_DB)
712
712
  end
713
713
 
714
- it 'returns an unacknowledged write concern' do
715
- expect(concern.get_last_error).to be_nil
714
+ it 'raises an error' do
715
+ expect {
716
+ concern
717
+ }.to raise_error(Mongo::Error::InvalidWriteConcern)
716
718
  end
717
719
  end
718
720
  end
@@ -0,0 +1,167 @@
1
+ require 'spec_helper'
2
+
3
+ describe Mongo::Collection::View::Builder::FindCommand do
4
+
5
+ describe '#specification' do
6
+
7
+ let(:view) do
8
+ Mongo::Collection::View.new(authorized_collection, filter, options)
9
+ end
10
+
11
+ let(:builder) do
12
+ described_class.new(view)
13
+ end
14
+
15
+ let(:specification) do
16
+ builder.specification
17
+ end
18
+
19
+ let(:selector) do
20
+ specification[:selector]
21
+ end
22
+
23
+ context 'when the options are standard' do
24
+
25
+ let(:filter) do
26
+ { 'name' => 'test' }
27
+ end
28
+
29
+ let(:options) do
30
+ {
31
+ sort: { _id: 1 },
32
+ projection: { name: 1 },
33
+ hint: { name: 1 },
34
+ skip: 10,
35
+ limit: 20,
36
+ batch_size: 5,
37
+ single_batch: false,
38
+ comment: "testing",
39
+ max_scan: 200,
40
+ max_time_ms: 40,
41
+ max_value: { name: 'joe' },
42
+ min_value: { name: 'albert' },
43
+ return_key: true,
44
+ show_disk_loc: true,
45
+ snapshot: true,
46
+ tailable: true,
47
+ oplog_replay: true,
48
+ no_cursor_timeout: true,
49
+ await_data: true,
50
+ allow_partial_results: true,
51
+ read_concern: { level: 'local' }
52
+ }
53
+ end
54
+
55
+ it 'maps the collection name' do
56
+ expect(selector['find']).to eq(authorized_collection.name)
57
+ end
58
+
59
+ it 'maps the filter' do
60
+ expect(selector['filter']).to eq(filter)
61
+ end
62
+
63
+ it 'maps sort' do
64
+ expect(selector['sort']).to eq('_id' => 1)
65
+ end
66
+
67
+ it 'maps projection' do
68
+ expect(selector['projection']).to eq('name' => 1)
69
+ end
70
+
71
+ it 'maps hint' do
72
+ expect(selector['hint']).to eq('name' => 1)
73
+ end
74
+
75
+ it 'maps skip' do
76
+ expect(selector['skip']).to eq(10)
77
+ end
78
+
79
+ it 'maps limit' do
80
+ expect(selector['limit']).to eq(20)
81
+ end
82
+
83
+ it 'maps batch size' do
84
+ expect(selector['batchSize']).to eq(5)
85
+ end
86
+
87
+ it 'maps single batch' do
88
+ expect(selector['singleBatch']).to be false
89
+ end
90
+
91
+ it 'maps comment' do
92
+ expect(selector['comment']).to eq('testing')
93
+ end
94
+
95
+ it 'maps max scan' do
96
+ expect(selector['maxScan']).to eq(200)
97
+ end
98
+
99
+ it 'maps max time ms' do
100
+ expect(selector['maxTimeMS']).to eq(40)
101
+ end
102
+
103
+ it 'maps max' do
104
+ expect(selector['max']).to eq('name' => 'joe')
105
+ end
106
+
107
+ it 'maps min' do
108
+ expect(selector['min']).to eq('name' => 'albert')
109
+ end
110
+
111
+ it 'maps read concern' do
112
+ expect(selector['readConcern']).to eq('level' => 'local')
113
+ end
114
+
115
+ it 'maps return key' do
116
+ expect(selector['returnKey']).to be true
117
+ end
118
+
119
+ it 'maps show record id' do
120
+ expect(selector['showRecordId']).to be true
121
+ end
122
+
123
+ it 'maps snapshot' do
124
+ expect(selector['snapshot']).to be true
125
+ end
126
+
127
+ it 'maps tailable' do
128
+ expect(selector['tailable']).to be true
129
+ end
130
+
131
+ it 'maps oplog replay' do
132
+ expect(selector['oplogReplay']).to be true
133
+ end
134
+
135
+ it 'maps no cursor timeout' do
136
+ expect(selector['noCursorTimeout']).to be true
137
+ end
138
+
139
+ it 'maps await data' do
140
+ expect(selector['awaitData']).to be true
141
+ end
142
+
143
+ it 'maps allow partial results' do
144
+ expect(selector['allowPartialResults']).to be true
145
+ end
146
+ end
147
+
148
+ context 'when limit is negative' do
149
+
150
+ let(:filter) do
151
+ { 'name' => 'test' }
152
+ end
153
+
154
+ let(:options) do
155
+ { limit: -1 }
156
+ end
157
+
158
+ it 'sets single batch to true' do
159
+ expect(selector['singleBatch']).to be true
160
+ end
161
+
162
+ it 'removes the limit from the command' do
163
+ expect(selector['limit']).to be_nil
164
+ end
165
+ end
166
+ end
167
+ end