mongo 2.1.2 → 2.2.0.rc0

Sign up to get free protection for your applications and to get access to all the features.
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