mongo 1.3.0 → 1.12.5

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 (185) hide show
  1. checksums.yaml +7 -0
  2. checksums.yaml.gz.sig +0 -0
  3. data/{LICENSE.txt → LICENSE} +1 -1
  4. data/README.md +122 -271
  5. data/Rakefile +25 -209
  6. data/VERSION +1 -0
  7. data/bin/mongo_console +31 -9
  8. data/lib/mongo/bulk_write_collection_view.rb +387 -0
  9. data/lib/mongo/collection.rb +576 -269
  10. data/lib/mongo/collection_writer.rb +364 -0
  11. data/lib/mongo/connection/node.rb +249 -0
  12. data/lib/mongo/connection/pool.rb +340 -0
  13. data/lib/mongo/connection/pool_manager.rb +320 -0
  14. data/lib/mongo/connection/sharding_pool_manager.rb +67 -0
  15. data/lib/mongo/connection/socket/socket_util.rb +37 -0
  16. data/lib/mongo/connection/socket/ssl_socket.rb +95 -0
  17. data/lib/mongo/connection/socket/tcp_socket.rb +87 -0
  18. data/lib/mongo/connection/socket/unix_socket.rb +39 -0
  19. data/lib/mongo/connection/socket.rb +18 -0
  20. data/lib/mongo/connection.rb +7 -875
  21. data/lib/mongo/cursor.rb +403 -117
  22. data/lib/mongo/db.rb +444 -243
  23. data/lib/mongo/exception.rb +145 -0
  24. data/lib/mongo/functional/authentication.rb +455 -0
  25. data/lib/mongo/functional/logging.rb +85 -0
  26. data/lib/mongo/functional/read_preference.rb +183 -0
  27. data/lib/mongo/functional/scram.rb +556 -0
  28. data/lib/mongo/functional/uri_parser.rb +409 -0
  29. data/lib/mongo/functional/write_concern.rb +66 -0
  30. data/lib/mongo/functional.rb +20 -0
  31. data/lib/mongo/gridfs/grid.rb +30 -24
  32. data/lib/mongo/gridfs/grid_ext.rb +6 -10
  33. data/lib/mongo/gridfs/grid_file_system.rb +38 -20
  34. data/lib/mongo/gridfs/grid_io.rb +84 -75
  35. data/lib/mongo/gridfs.rb +18 -0
  36. data/lib/mongo/legacy.rb +140 -0
  37. data/lib/mongo/mongo_client.rb +697 -0
  38. data/lib/mongo/mongo_replica_set_client.rb +535 -0
  39. data/lib/mongo/mongo_sharded_client.rb +159 -0
  40. data/lib/mongo/networking.rb +372 -0
  41. data/lib/mongo/{util → utils}/conversions.rb +29 -8
  42. data/lib/mongo/{util → utils}/core_ext.rb +28 -18
  43. data/lib/mongo/{util → utils}/server_version.rb +4 -6
  44. data/lib/mongo/{util → utils}/support.rb +29 -31
  45. data/lib/mongo/utils/thread_local_variable_manager.rb +25 -0
  46. data/lib/mongo/utils.rb +19 -0
  47. data/lib/mongo.rb +51 -50
  48. data/mongo.gemspec +29 -32
  49. data/test/functional/authentication_test.rb +39 -0
  50. data/test/functional/bulk_api_stress_test.rb +133 -0
  51. data/test/functional/bulk_write_collection_view_test.rb +1198 -0
  52. data/test/functional/client_test.rb +627 -0
  53. data/test/functional/collection_test.rb +2175 -0
  54. data/test/functional/collection_writer_test.rb +83 -0
  55. data/test/{conversions_test.rb → functional/conversions_test.rb} +47 -3
  56. data/test/functional/cursor_fail_test.rb +57 -0
  57. data/test/functional/cursor_message_test.rb +56 -0
  58. data/test/functional/cursor_test.rb +683 -0
  59. data/test/functional/db_api_test.rb +835 -0
  60. data/test/functional/db_connection_test.rb +25 -0
  61. data/test/functional/db_test.rb +348 -0
  62. data/test/functional/grid_file_system_test.rb +285 -0
  63. data/test/{grid_io_test.rb → functional/grid_io_test.rb} +72 -11
  64. data/test/{grid_test.rb → functional/grid_test.rb} +88 -15
  65. data/test/functional/pool_test.rb +136 -0
  66. data/test/functional/safe_test.rb +98 -0
  67. data/test/functional/ssl_test.rb +29 -0
  68. data/test/functional/support_test.rb +62 -0
  69. data/test/functional/timeout_test.rb +60 -0
  70. data/test/functional/uri_test.rb +446 -0
  71. data/test/functional/write_concern_test.rb +118 -0
  72. data/test/helpers/general.rb +50 -0
  73. data/test/helpers/test_unit.rb +476 -0
  74. data/test/replica_set/authentication_test.rb +37 -0
  75. data/test/replica_set/basic_test.rb +189 -0
  76. data/test/replica_set/client_test.rb +393 -0
  77. data/test/replica_set/connection_test.rb +138 -0
  78. data/test/replica_set/count_test.rb +66 -0
  79. data/test/replica_set/cursor_test.rb +220 -0
  80. data/test/replica_set/insert_test.rb +157 -0
  81. data/test/replica_set/max_values_test.rb +151 -0
  82. data/test/replica_set/pinning_test.rb +105 -0
  83. data/test/replica_set/query_test.rb +73 -0
  84. data/test/replica_set/read_preference_test.rb +219 -0
  85. data/test/replica_set/refresh_test.rb +211 -0
  86. data/test/replica_set/replication_ack_test.rb +95 -0
  87. data/test/replica_set/ssl_test.rb +32 -0
  88. data/test/sharded_cluster/basic_test.rb +203 -0
  89. data/test/shared/authentication/basic_auth_shared.rb +260 -0
  90. data/test/shared/authentication/bulk_api_auth_shared.rb +249 -0
  91. data/test/shared/authentication/gssapi_shared.rb +176 -0
  92. data/test/shared/authentication/sasl_plain_shared.rb +96 -0
  93. data/test/shared/authentication/scram_shared.rb +92 -0
  94. data/test/shared/ssl_shared.rb +235 -0
  95. data/test/test_helper.rb +53 -94
  96. data/test/threading/basic_test.rb +120 -0
  97. data/test/tools/mongo_config.rb +708 -0
  98. data/test/tools/mongo_config_test.rb +160 -0
  99. data/test/unit/client_test.rb +381 -0
  100. data/test/unit/collection_test.rb +89 -53
  101. data/test/unit/connection_test.rb +282 -32
  102. data/test/unit/cursor_test.rb +206 -8
  103. data/test/unit/db_test.rb +55 -13
  104. data/test/unit/grid_test.rb +43 -16
  105. data/test/unit/mongo_sharded_client_test.rb +48 -0
  106. data/test/unit/node_test.rb +93 -0
  107. data/test/unit/pool_manager_test.rb +111 -0
  108. data/test/unit/read_pref_test.rb +406 -0
  109. data/test/unit/read_test.rb +159 -0
  110. data/test/unit/safe_test.rb +69 -36
  111. data/test/unit/sharding_pool_manager_test.rb +84 -0
  112. data/test/unit/write_concern_test.rb +175 -0
  113. data.tar.gz.sig +3 -0
  114. metadata +227 -216
  115. metadata.gz.sig +0 -0
  116. data/docs/CREDITS.md +0 -123
  117. data/docs/FAQ.md +0 -116
  118. data/docs/GridFS.md +0 -158
  119. data/docs/HISTORY.md +0 -244
  120. data/docs/RELEASES.md +0 -33
  121. data/docs/REPLICA_SETS.md +0 -72
  122. data/docs/TUTORIAL.md +0 -247
  123. data/docs/WRITE_CONCERN.md +0 -28
  124. data/lib/mongo/exceptions.rb +0 -71
  125. data/lib/mongo/gridfs/grid_io_fix.rb +0 -38
  126. data/lib/mongo/repl_set_connection.rb +0 -342
  127. data/lib/mongo/test.rb +0 -20
  128. data/lib/mongo/util/pool.rb +0 -177
  129. data/lib/mongo/util/uri_parser.rb +0 -185
  130. data/test/async/collection_test.rb +0 -224
  131. data/test/async/connection_test.rb +0 -24
  132. data/test/async/cursor_test.rb +0 -162
  133. data/test/async/worker_pool_test.rb +0 -99
  134. data/test/auxillary/1.4_features.rb +0 -166
  135. data/test/auxillary/authentication_test.rb +0 -68
  136. data/test/auxillary/autoreconnect_test.rb +0 -41
  137. data/test/auxillary/fork_test.rb +0 -30
  138. data/test/auxillary/repl_set_auth_test.rb +0 -58
  139. data/test/auxillary/slave_connection_test.rb +0 -36
  140. data/test/auxillary/threaded_authentication_test.rb +0 -101
  141. data/test/bson/binary_test.rb +0 -15
  142. data/test/bson/bson_test.rb +0 -649
  143. data/test/bson/byte_buffer_test.rb +0 -208
  144. data/test/bson/hash_with_indifferent_access_test.rb +0 -38
  145. data/test/bson/json_test.rb +0 -17
  146. data/test/bson/object_id_test.rb +0 -154
  147. data/test/bson/ordered_hash_test.rb +0 -204
  148. data/test/bson/timestamp_test.rb +0 -24
  149. data/test/collection_test.rb +0 -910
  150. data/test/connection_test.rb +0 -309
  151. data/test/cursor_fail_test.rb +0 -75
  152. data/test/cursor_message_test.rb +0 -43
  153. data/test/cursor_test.rb +0 -483
  154. data/test/db_api_test.rb +0 -726
  155. data/test/db_connection_test.rb +0 -15
  156. data/test/db_test.rb +0 -287
  157. data/test/grid_file_system_test.rb +0 -243
  158. data/test/load/resque/load.rb +0 -21
  159. data/test/load/resque/processor.rb +0 -26
  160. data/test/load/thin/load.rb +0 -24
  161. data/test/load/unicorn/load.rb +0 -23
  162. data/test/load/unicorn/unicorn.rb +0 -29
  163. data/test/replica_sets/connect_test.rb +0 -94
  164. data/test/replica_sets/connection_string_test.rb +0 -32
  165. data/test/replica_sets/count_test.rb +0 -35
  166. data/test/replica_sets/insert_test.rb +0 -53
  167. data/test/replica_sets/pooled_insert_test.rb +0 -55
  168. data/test/replica_sets/query_secondaries.rb +0 -96
  169. data/test/replica_sets/query_test.rb +0 -51
  170. data/test/replica_sets/replication_ack_test.rb +0 -66
  171. data/test/replica_sets/rs_test_helper.rb +0 -27
  172. data/test/safe_test.rb +0 -68
  173. data/test/support/hash_with_indifferent_access.rb +0 -186
  174. data/test/support/keys.rb +0 -45
  175. data/test/support_test.rb +0 -18
  176. data/test/threading/threading_with_large_pool_test.rb +0 -90
  177. data/test/threading_test.rb +0 -87
  178. data/test/tools/auth_repl_set_manager.rb +0 -14
  179. data/test/tools/load.rb +0 -58
  180. data/test/tools/repl_set_manager.rb +0 -266
  181. data/test/tools/sharding_manager.rb +0 -202
  182. data/test/tools/test.rb +0 -4
  183. data/test/unit/pool_test.rb +0 -9
  184. data/test/unit/repl_set_connection_test.rb +0 -59
  185. data/test/uri_test.rb +0 -91
@@ -0,0 +1,835 @@
1
+ # Copyright (C) 2009-2013 MongoDB, Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ require 'test_helper'
16
+
17
+ class DBAPITest < Test::Unit::TestCase
18
+ include Mongo
19
+ include BSON
20
+
21
+ def setup
22
+ @client = standard_connection
23
+ @db = @client.db(TEST_DB)
24
+ @coll = @db.collection('test')
25
+ @version = @client.server_version
26
+ @coll.remove
27
+ @r1 = {'a' => 1}
28
+ @coll.insert(@r1) # collection not created until it's used
29
+ @coll_full_name = "#{TEST_DB}.test"
30
+ end
31
+
32
+ def teardown
33
+ @coll.remove
34
+ @db.get_last_error
35
+ end
36
+
37
+ def test_clear
38
+ assert_equal 1, @coll.count
39
+ @coll.remove
40
+ assert_equal 0, @coll.count
41
+ end
42
+
43
+ def test_insert
44
+ assert_kind_of BSON::ObjectId, @coll.insert('a' => 2)
45
+ assert_kind_of BSON::ObjectId, @coll.insert('b' => 3)
46
+
47
+ assert_equal 3, @coll.count
48
+ docs = @coll.find().to_a
49
+ assert_equal 3, docs.length
50
+ assert docs.detect { |row| row['a'] == 1 }
51
+ assert docs.detect { |row| row['a'] == 2 }
52
+ assert docs.detect { |row| row['b'] == 3 }
53
+
54
+ @coll << {'b' => 4}
55
+ docs = @coll.find().to_a
56
+ assert_equal 4, docs.length
57
+ assert docs.detect { |row| row['b'] == 4 }
58
+ end
59
+
60
+ def test_save_ordered_hash
61
+ oh = BSON::OrderedHash.new
62
+ oh['a'] = -1
63
+ oh['b'] = 'foo'
64
+
65
+ oid = @coll.save(oh)
66
+ assert_equal 'foo', @coll.find_one(oid)['b']
67
+
68
+ oh = BSON::OrderedHash['a' => 1, 'b' => 'foo']
69
+ oid = @coll.save(oh)
70
+ assert_equal 'foo', @coll.find_one(oid)['b']
71
+ end
72
+
73
+ def test_insert_multiple
74
+ ids = @coll.insert([{'a' => 2}, {'b' => 3}])
75
+
76
+ ids.each do |i|
77
+ assert_kind_of BSON::ObjectId, i
78
+ end
79
+
80
+ assert_equal 3, @coll.count
81
+ docs = @coll.find().to_a
82
+ assert_equal 3, docs.length
83
+ assert docs.detect { |row| row['a'] == 1 }
84
+ assert docs.detect { |row| row['a'] == 2 }
85
+ assert docs.detect { |row| row['b'] == 3 }
86
+ end
87
+
88
+ def test_count_on_nonexisting
89
+ @db.drop_collection('foo')
90
+ assert_equal 0, @db.collection('foo').count()
91
+ end
92
+
93
+ def test_find_simple
94
+ @r2 = @coll.insert('a' => 2)
95
+ @r3 = @coll.insert('b' => 3)
96
+ # Check sizes
97
+ docs = @coll.find().to_a
98
+ assert_equal 3, docs.size
99
+ assert_equal 3, @coll.count
100
+
101
+ # Find by other value
102
+ docs = @coll.find('a' => @r1['a']).to_a
103
+ assert_equal 1, docs.size
104
+ doc = docs.first
105
+ # Can't compare _id values because at insert, an _id was added to @r1 by
106
+ # the database but we don't know what it is without re-reading the record
107
+ # (which is what we are doing right now).
108
+ # assert_equal doc['_id'], @r1['_id']
109
+ assert_equal doc['a'], @r1['a']
110
+ end
111
+
112
+ def test_find_advanced
113
+ @coll.insert('a' => 2)
114
+ @coll.insert('b' => 3)
115
+
116
+ # Find by advanced query (less than)
117
+ docs = @coll.find('a' => { '$lt' => 10 }).to_a
118
+ assert_equal 2, docs.size
119
+ assert docs.detect { |row| row['a'] == 1 }
120
+ assert docs.detect { |row| row['a'] == 2 }
121
+
122
+ # Find by advanced query (greater than)
123
+ docs = @coll.find('a' => { '$gt' => 1 }).to_a
124
+ assert_equal 1, docs.size
125
+ assert docs.detect { |row| row['a'] == 2 }
126
+
127
+ # Find by advanced query (less than or equal to)
128
+ docs = @coll.find('a' => { '$lte' => 1 }).to_a
129
+ assert_equal 1, docs.size
130
+ assert docs.detect { |row| row['a'] == 1 }
131
+
132
+ # Find by advanced query (greater than or equal to)
133
+ docs = @coll.find('a' => { '$gte' => 1 }).to_a
134
+ assert_equal 2, docs.size
135
+ assert docs.detect { |row| row['a'] == 1 }
136
+ assert docs.detect { |row| row['a'] == 2 }
137
+
138
+ # Find by advanced query (between)
139
+ docs = @coll.find('a' => { '$gt' => 1, '$lt' => 3 }).to_a
140
+ assert_equal 1, docs.size
141
+ assert docs.detect { |row| row['a'] == 2 }
142
+
143
+ # Find by advanced query (in clause)
144
+ docs = @coll.find('a' => {'$in' => [1,2]}).to_a
145
+ assert_equal 2, docs.size
146
+ assert docs.detect { |row| row['a'] == 1 }
147
+ assert docs.detect { |row| row['a'] == 2 }
148
+ end
149
+
150
+ def test_find_sorting
151
+ @coll.remove
152
+ @coll.insert('a' => 1, 'b' => 2)
153
+ @coll.insert('a' => 2, 'b' => 1)
154
+ @coll.insert('a' => 3, 'b' => 2)
155
+ @coll.insert('a' => 4, 'b' => 1)
156
+
157
+ # Sorting (ascending)
158
+ docs = @coll.find({'a' => { '$lt' => 10 }}, :sort => [['a', 1]]).to_a
159
+ assert_equal 4, docs.size
160
+ assert_equal 1, docs[0]['a']
161
+ assert_equal 2, docs[1]['a']
162
+ assert_equal 3, docs[2]['a']
163
+ assert_equal 4, docs[3]['a']
164
+
165
+ # Sorting (descending)
166
+ docs = @coll.find({'a' => { '$lt' => 10 }}, :sort => [['a', -1]]).to_a
167
+ assert_equal 4, docs.size
168
+ assert_equal 4, docs[0]['a']
169
+ assert_equal 3, docs[1]['a']
170
+ assert_equal 2, docs[2]['a']
171
+ assert_equal 1, docs[3]['a']
172
+
173
+ # Sorting using array of names; assumes ascending order.
174
+ docs = @coll.find({'a' => { '$lt' => 10 }}, :sort => 'a').to_a
175
+ assert_equal 4, docs.size
176
+ assert_equal 1, docs[0]['a']
177
+ assert_equal 2, docs[1]['a']
178
+ assert_equal 3, docs[2]['a']
179
+ assert_equal 4, docs[3]['a']
180
+
181
+ # Sorting using single name; assumes ascending order.
182
+ docs = @coll.find({'a' => { '$lt' => 10 }}, :sort => 'a').to_a
183
+ assert_equal 4, docs.size
184
+ assert_equal 1, docs[0]['a']
185
+ assert_equal 2, docs[1]['a']
186
+ assert_equal 3, docs[2]['a']
187
+ assert_equal 4, docs[3]['a']
188
+
189
+ docs = @coll.find({'a' => { '$lt' => 10 }}, :sort => [['b', 'asc'], ['a', 'asc']]).to_a
190
+ assert_equal 4, docs.size
191
+ assert_equal 2, docs[0]['a']
192
+ assert_equal 4, docs[1]['a']
193
+ assert_equal 1, docs[2]['a']
194
+ assert_equal 3, docs[3]['a']
195
+
196
+ # Sorting using empty array; no order guarantee should not blow up.
197
+ docs = @coll.find({'a' => { '$lt' => 10 }}, :sort => []).to_a
198
+ assert_equal 4, docs.size
199
+ end
200
+
201
+ def test_find_sorting_with_hash
202
+ # Sorting using ordered hash. You can use an unordered one, but then the
203
+ # order of the keys won't be guaranteed thus your sort won't make sense.
204
+
205
+ @coll.remove
206
+ @coll.insert('a' => 1, 'b' => 2)
207
+ @coll.insert('a' => 2, 'b' => 1)
208
+ @coll.insert('a' => 3, 'b' => 2)
209
+ @coll.insert('a' => 4, 'b' => 1)
210
+
211
+ oh = BSON::OrderedHash.new
212
+ oh['a'] = -1
213
+
214
+ # Sort as a method
215
+ docs = @coll.find.sort(oh).to_a
216
+ assert_equal 4, docs.size
217
+ assert_equal 4, docs[0]['a']
218
+ assert_equal 3, docs[1]['a']
219
+ assert_equal 2, docs[2]['a']
220
+ assert_equal 1, docs[3]['a']
221
+
222
+ # Sort as an option
223
+ docs = @coll.find({}, :sort => oh).to_a
224
+ assert_equal 4, docs.size
225
+ assert_equal 4, docs[0]['a']
226
+ assert_equal 3, docs[1]['a']
227
+ assert_equal 2, docs[2]['a']
228
+ assert_equal 1, docs[3]['a']
229
+
230
+ if RUBY_VERSION > '1.9'
231
+ docs = @coll.find({}, :sort => {:a => -1}).to_a
232
+ assert_equal 4, docs.size
233
+ assert_equal 4, docs[0]['a']
234
+ assert_equal 3, docs[1]['a']
235
+ assert_equal 2, docs[2]['a']
236
+ assert_equal 1, docs[3]['a']
237
+
238
+ docs = @coll.find.sort(:a => -1).to_a
239
+ assert_equal 4, docs.size
240
+ assert_equal 4, docs[0]['a']
241
+ assert_equal 3, docs[1]['a']
242
+ assert_equal 2, docs[2]['a']
243
+ assert_equal 1, docs[3]['a']
244
+
245
+ docs = @coll.find.sort(:b => -1, :a => 1).to_a
246
+ assert_equal 4, docs.size
247
+ assert_equal 1, docs[0]['a']
248
+ assert_equal 3, docs[1]['a']
249
+ assert_equal 2, docs[2]['a']
250
+ assert_equal 4, docs[3]['a']
251
+ else
252
+ # Sort as an option
253
+ assert_raise InvalidSortValueError do
254
+ @coll.find({}, :sort => {:a => -1}).to_a
255
+ end
256
+ # Sort as a method
257
+ assert_raise InvalidSortValueError do
258
+ @coll.find.sort(:a => -1).to_a
259
+ end
260
+ end
261
+ end
262
+
263
+ def test_find_limits
264
+ @coll.insert('b' => 2)
265
+ @coll.insert('c' => 3)
266
+ @coll.insert('d' => 4)
267
+
268
+ docs = @coll.find({}, :limit => 1).to_a
269
+ assert_equal 1, docs.size
270
+ docs = @coll.find({}, :limit => 2).to_a
271
+ assert_equal 2, docs.size
272
+ docs = @coll.find({}, :limit => 3).to_a
273
+ assert_equal 3, docs.size
274
+ docs = @coll.find({}, :limit => 4).to_a
275
+ assert_equal 4, docs.size
276
+ docs = @coll.find({}).to_a
277
+ assert_equal 4, docs.size
278
+ docs = @coll.find({}, :limit => 99).to_a
279
+ assert_equal 4, docs.size
280
+ end
281
+
282
+ def test_find_one_no_records
283
+ @coll.remove
284
+ x = @coll.find_one('a' => 1)
285
+ assert_nil x
286
+ end
287
+
288
+ def test_drop_collection
289
+ assert @db.drop_collection(@coll.name), "drop of collection #{@coll.name} failed"
290
+ assert !@db.collection_names.include?(@coll.name)
291
+ end
292
+
293
+ def test_other_drop
294
+ assert @db.collection_names.include?(@coll.name)
295
+ @coll.drop
296
+ assert !@db.collection_names.include?(@coll.name)
297
+ end
298
+
299
+ def test_collection_names
300
+ names = @db.collection_names
301
+ assert names.length >= 1
302
+ assert names.include?(@coll.name)
303
+
304
+ coll2 = @db.collection('test2')
305
+ coll2.insert('a' => 1) # collection not created until it's used
306
+ names = @db.collection_names
307
+ assert names.length >= 2
308
+ assert names.include?(@coll.name)
309
+ assert names.include?('test2')
310
+ ensure
311
+ @db.drop_collection('test2')
312
+ end
313
+
314
+ def test_collections_info
315
+ cursor = @db.collections_info
316
+ rows = cursor.to_a
317
+ assert rows.length >= 1
318
+ if @client.server_version < '2.7.6'
319
+ row = rows.detect { |r| r['name'] == @coll_full_name }
320
+ else
321
+ row = rows.detect { |r| r['name'] == @coll.name }
322
+ end
323
+ assert_not_nil row
324
+ end
325
+
326
+ def test_collections_info_with_name
327
+ cursor = @db.collections_info(@coll.name)
328
+ info = cursor.to_a
329
+ assert_equal 1, info.length
330
+ if @client.server_version < '2.7.6'
331
+ assert_equal "#{@db.name}.#{@coll.name}", info.first['name']
332
+ else
333
+ assert_equal @coll.name, info.first['name']
334
+ end
335
+ end
336
+
337
+ def test_collection_options
338
+ @db.drop_collection('foobar')
339
+ @db.strict = true
340
+
341
+ begin
342
+ coll = @db.create_collection('foobar', :capped => true, :size => 4096)
343
+ options = coll.options
344
+ assert_equal 'foobar', options['create'] if @client.server_version < '2.5.5'
345
+ assert_equal true, options['capped']
346
+ assert_equal 4096, options['size']
347
+ rescue => ex
348
+ @db.drop_collection('foobar')
349
+ fail "did not expect exception \"#{ex.inspect}\""
350
+ ensure
351
+ @db.strict = false
352
+ end
353
+ end
354
+
355
+ def test_collection_options_are_passed_to_the_existing_ones
356
+ @db.drop_collection('foobar')
357
+
358
+ @db.create_collection('foobar')
359
+
360
+ coll = @db.create_collection('foobar')
361
+ assert_equal true, Mongo::WriteConcern.gle?(coll.write_concern)
362
+ end
363
+
364
+
365
+ def test_index_information
366
+ assert_equal @coll.index_information.length, 1
367
+
368
+ name = @coll.create_index('a')
369
+ info = @db.index_information(@coll.name)
370
+ assert_equal name, "a_1"
371
+ assert_equal @coll.index_information, info
372
+ assert_equal 2, info.length
373
+
374
+ assert info.has_key?(name)
375
+ assert_equal info[name]["key"], {"a" => 1}
376
+ ensure
377
+ @db.drop_index(@coll.name, name)
378
+ end
379
+
380
+ def test_index_create_with_symbol
381
+ assert_equal @coll.index_information.length, 1
382
+
383
+ name = @coll.create_index([['a', 1]])
384
+ info = @db.index_information(@coll.name)
385
+ assert_equal name, "a_1"
386
+ assert_equal @coll.index_information, info
387
+ assert_equal 2, info.length
388
+
389
+ assert info.has_key?(name)
390
+ assert_equal info[name]['key'], {"a" => 1}
391
+ ensure
392
+ @db.drop_index(@coll.name, name)
393
+ end
394
+
395
+ def test_multiple_index_cols
396
+ name = @coll.create_index([['a', DESCENDING], ['b', ASCENDING], ['c', DESCENDING]])
397
+ info = @db.index_information(@coll.name)
398
+ assert_equal 2, info.length
399
+
400
+ assert_equal name, 'a_-1_b_1_c_-1'
401
+ assert info.has_key?(name)
402
+ assert_equal info[name]['key'], {"a" => -1, "b" => 1, "c" => -1}
403
+ ensure
404
+ @db.drop_index(@coll.name, name)
405
+ end
406
+
407
+ def test_multiple_index_cols_with_symbols
408
+ name = @coll.create_index([[:a, DESCENDING], [:b, ASCENDING], [:c, DESCENDING]])
409
+ info = @db.index_information(@coll.name)
410
+ assert_equal 2, info.length
411
+
412
+ assert_equal name, 'a_-1_b_1_c_-1'
413
+ assert info.has_key?(name)
414
+ assert_equal info[name]['key'], {"a" => -1, "b" => 1, "c" => -1}
415
+ ensure
416
+ @db.drop_index(@coll.name, name)
417
+ end
418
+
419
+ def test_unique_index
420
+ @db.drop_collection("blah")
421
+ test = @db.collection("blah")
422
+ test.create_index("hello")
423
+
424
+ test.insert("hello" => "world")
425
+ test.insert("hello" => "mike")
426
+ test.insert("hello" => "world")
427
+ assert !@db.error?
428
+
429
+ @db.drop_collection("blah")
430
+ test = @db.collection("blah")
431
+ test.create_index("hello", :unique => true)
432
+
433
+ test.insert("hello" => "world")
434
+ test.insert("hello" => "mike")
435
+ assert_raise OperationFailure do
436
+ test.insert("hello" => "world")
437
+ end
438
+ end
439
+
440
+ def test_index_on_subfield
441
+ @db.drop_collection("blah")
442
+ test = @db.collection("blah")
443
+
444
+ test.insert("hello" => {"a" => 4, "b" => 5})
445
+ test.insert("hello" => {"a" => 7, "b" => 2})
446
+ test.insert("hello" => {"a" => 4, "b" => 10})
447
+ assert !@db.error?
448
+
449
+ @db.drop_collection("blah")
450
+ test = @db.collection("blah")
451
+ test.create_index("hello.a", :unique => true)
452
+
453
+ test.insert("hello" => {"a" => 4, "b" => 5})
454
+ test.insert("hello" => {"a" => 7, "b" => 2})
455
+ assert_raise OperationFailure do
456
+ test.insert("hello" => {"a" => 4, "b" => 10} )
457
+ end
458
+ end
459
+
460
+ def test_array
461
+ @coll.remove({'$atomic' => true})
462
+ @coll.insert({'b' => [1, 2, 3]})
463
+ @coll.insert({'b' => [1, 2, 3]})
464
+ rows = @coll.find({}, {:fields => ['b']}).to_a
465
+ assert_equal 2, rows.length
466
+ assert_equal [1, 2, 3], rows[1]['b']
467
+ end
468
+
469
+ def test_regex
470
+ regex = /foobar/i
471
+ @coll << {'b' => regex}
472
+ rows = @coll.find({}, {:fields => ['b']}).to_a
473
+ if @version < "1.1.3"
474
+ assert_equal 1, rows.length
475
+ assert_equal regex, rows[0]['b']
476
+ else
477
+ assert_equal 2, rows.length
478
+ assert_equal regex, rows[1]['b']
479
+ end
480
+ end
481
+
482
+ def test_regex_multi_line
483
+ if @version >= "1.9.1"
484
+ doc = <<HERE
485
+ the lazy brown
486
+ fox
487
+ HERE
488
+ @coll.save({:doc => doc})
489
+ assert @coll.find_one({:doc => /n.*x/m})
490
+ @coll.remove
491
+ end
492
+ end
493
+
494
+ def test_non_oid_id
495
+ # Note: can't use Time.new because that will include fractional seconds,
496
+ # which Mongo does not store.
497
+ t = Time.at(1234567890)
498
+ @coll << {'_id' => t}
499
+ rows = @coll.find({'_id' => t}).to_a
500
+ assert_equal 1, rows.length
501
+ assert_equal t, rows[0]['_id']
502
+ end
503
+
504
+ def test_strict
505
+ assert !@db.strict?
506
+ @db.strict = true
507
+ assert @db.strict?
508
+ ensure
509
+ @db.strict = false
510
+ end
511
+
512
+ def test_strict_access_collection
513
+ @db.strict = true
514
+ begin
515
+ @db.collection('does-not-exist')
516
+ fail "expected exception"
517
+ rescue => ex
518
+ assert_equal Mongo::MongoDBError, ex.class
519
+ assert_equal "Collection 'does-not-exist' doesn't exist. (strict=true)", ex.to_s
520
+ ensure
521
+ @db.strict = false
522
+ @db.drop_collection('does-not-exist')
523
+ end
524
+ end
525
+
526
+ def test_strict_create_collection
527
+ @db.drop_collection('foobar')
528
+ @db.strict = true
529
+
530
+ begin
531
+ assert @db.create_collection('foobar')
532
+ rescue => ex
533
+ fail "did not expect exception \"#{ex}\""
534
+ end
535
+
536
+ # Now the collection exists. This time we should see an exception.
537
+ assert_raise Mongo::MongoDBError do
538
+ @db.create_collection('foobar')
539
+ end
540
+ @db.strict = false
541
+ @db.drop_collection('foobar')
542
+
543
+ # Now we're not in strict mode - should succeed
544
+ @db.create_collection('foobar')
545
+ @db.create_collection('foobar')
546
+ @db.drop_collection('foobar')
547
+ end
548
+
549
+ def test_where
550
+ @coll.insert('a' => 2)
551
+ @coll.insert('a' => 3)
552
+
553
+ assert_equal 3, @coll.count
554
+ assert_equal 1, @coll.find('$where' => BSON::Code.new('this.a > 2')).count()
555
+ assert_equal 2, @coll.find('$where' => BSON::Code.new('this.a > i', {'i' => 1})).count()
556
+ end
557
+
558
+ def test_eval
559
+ grant_admin_user_eval_role(@client)
560
+
561
+ assert_equal 3, @db.eval('function (x) {return x;}', 3)
562
+
563
+ assert_equal nil, @db.eval("function (x) {db.test_eval.save({y:x});}", 5)
564
+ assert_equal 5, @db.collection('test_eval').find_one['y']
565
+
566
+ assert_equal 5, @db.eval("function (x, y) {return x + y;}", 2, 3)
567
+ assert_equal 5, @db.eval("function () {return 5;}")
568
+ assert_equal 5, @db.eval("2 + 3;")
569
+
570
+ assert_equal 5, @db.eval(Code.new("2 + 3;"))
571
+ assert_equal 2, @db.eval(Code.new("return i;", {"i" => 2}))
572
+ assert_equal 5, @db.eval(Code.new("i + 3;", {"i" => 2}))
573
+
574
+ assert_raise OperationFailure do
575
+ @db.eval("5 ++ 5;")
576
+ end
577
+ end
578
+
579
+ def test_hint
580
+ name = @coll.create_index('a')
581
+ begin
582
+ assert_nil @coll.hint
583
+ assert_equal 1, @coll.find({'a' => 1}, :hint => 'a').to_a.size
584
+ assert_equal 1, @coll.find({'a' => 1}, :hint => ['a']).to_a.size
585
+ assert_equal 1, @coll.find({'a' => 1}, :hint => {'a' => 1}).to_a.size
586
+
587
+ @coll.hint = 'a'
588
+ assert_equal({'a' => 1}, @coll.hint)
589
+ assert_equal 1, @coll.find('a' => 1).to_a.size
590
+
591
+ @coll.hint = ['a']
592
+ assert_equal({'a' => 1}, @coll.hint)
593
+ assert_equal 1, @coll.find('a' => 1).to_a.size
594
+
595
+ @coll.hint = {'a' => 1}
596
+ assert_equal({'a' => 1}, @coll.hint)
597
+ assert_equal 1, @coll.find('a' => 1).to_a.size
598
+
599
+ @coll.hint = nil
600
+ assert_nil @coll.hint
601
+ assert_equal 1, @coll.find('a' => 1).to_a.size
602
+ ensure
603
+ @coll.drop_index(name)
604
+ end
605
+ end
606
+
607
+ def test_named_hint
608
+ name = @coll.create_index('a', :name => 'named_index')
609
+ begin
610
+ assert_nil @coll.hint
611
+ assert_equal 1, @coll.find({'a' => 1}, :named_hint => 'named_index').to_a.size
612
+ assert_equal 1, @coll.find({'a' => 1}, :hint => 'a', :named_hint => "bad_hint").to_a.size
613
+ ensure
614
+ @coll.drop_index('named_index')
615
+ end
616
+ end
617
+
618
+ def test_hash_default_value_id
619
+ val = Hash.new(0)
620
+ val["x"] = 5
621
+ @coll.insert val
622
+ id = @coll.find_one("x" => 5)["_id"]
623
+ assert id != 0
624
+ end
625
+
626
+ def test_group
627
+ @db.drop_collection("test")
628
+ test = @db.collection("test")
629
+
630
+ assert_equal [], test.group(:initial => {"count" => 0}, :reduce => "function (obj, prev) { prev.count++; }")
631
+ assert_equal [], test.group(:initial => {"count" => 0}, :reduce => "function (obj, prev) { prev.count++; }")
632
+
633
+ test.insert("a" => 2)
634
+ test.insert("b" => 5)
635
+ test.insert("a" => 1)
636
+
637
+ assert_equal 3, test.group(:initial => {"count" => 0},
638
+ :reduce => "function (obj, prev) { prev.count++; }")[0]["count"]
639
+ assert_equal 3, test.group(:initial => {"count" => 0},
640
+ :reduce => "function (obj, prev) { prev.count++; }")[0]["count"]
641
+ assert_equal 1, test.group(:cond => {"a" => {"$gt" => 1}},
642
+ :initial => {"count" => 0}, :reduce => "function (obj, prev) { prev.count++; }")[0]["count"]
643
+ assert_equal 1, test.group(:cond => {"a" => {"$gt" => 1}},
644
+ :initial => {"count" => 0}, :reduce => "function (obj, prev) { prev.count++; }")[0]["count"]
645
+
646
+ finalize = "function (obj) { obj.f = obj.count - 1; }"
647
+ assert_equal 2, test.group(:initial => {"count" => 0},
648
+ :reduce => "function (obj, prev) { prev.count++; }", :finalize => finalize)[0]["f"]
649
+
650
+ test.insert("a" => 2, "b" => 3)
651
+ expected = [{"a" => 2, "count" => 2},
652
+ {"a" => nil, "count" => 1},
653
+ {"a" => 1, "count" => 1}]
654
+ assert_equal expected, test.group(:key => ["a"], :initial => {"count" => 0},
655
+ :reduce => "function (obj, prev) { prev.count++; }")
656
+ assert_equal expected, test.group(:key => :a, :initial => {"count" => 0},
657
+ :reduce => "function (obj, prev) { prev.count++; }")
658
+
659
+ assert_raise OperationFailure do
660
+ test.group(:initial => {}, :reduce => "5 ++ 5")
661
+ end
662
+ end
663
+
664
+ def test_deref
665
+ @coll.remove
666
+
667
+ assert_equal nil, @db.dereference(DBRef.new("test", ObjectId.new))
668
+ @coll.insert({"x" => "hello"})
669
+ key = @coll.find_one()["_id"]
670
+ assert_equal "hello", @db.dereference(DBRef.new("test", key))["x"]
671
+
672
+ assert_equal nil, @db.dereference(DBRef.new("test", 4))
673
+ obj = {"_id" => 4}
674
+ @coll.insert(obj)
675
+ assert_equal obj, @db.dereference(DBRef.new("test", 4))
676
+
677
+ @coll.remove
678
+ @coll.insert({"x" => "hello"})
679
+ assert_equal nil, @db.dereference(DBRef.new("test", nil))
680
+ end
681
+
682
+ def test_save
683
+ @coll.remove
684
+
685
+ a = {"hello" => "world"}
686
+
687
+ id = @coll.save(a)
688
+ assert_kind_of ObjectId, id
689
+ assert_equal 1, @coll.count
690
+
691
+ assert_equal id, @coll.save(a)
692
+ assert_equal 1, @coll.count
693
+
694
+ assert_equal "world", @coll.find_one()["hello"]
695
+
696
+ a["hello"] = "mike"
697
+ @coll.save(a)
698
+ assert_equal 1, @coll.count
699
+
700
+ assert_equal "mike", @coll.find_one()["hello"]
701
+
702
+ @coll.save({"hello" => "world"})
703
+ assert_equal 2, @coll.count
704
+ end
705
+
706
+ def test_save_long
707
+ @coll.remove
708
+ @coll.insert("x" => 9223372036854775807)
709
+ assert_equal 9223372036854775807, @coll.find_one()["x"]
710
+ end
711
+
712
+ def test_find_by_oid
713
+ @coll.remove
714
+
715
+ @coll.save("hello" => "mike")
716
+ id = @coll.save("hello" => "world")
717
+ assert_kind_of ObjectId, id
718
+
719
+ assert_equal "world", @coll.find_one(:_id => id)["hello"]
720
+ @coll.find(:_id => id).to_a.each do |doc|
721
+ assert_equal "world", doc["hello"]
722
+ end
723
+
724
+ id = ObjectId.from_string(id.to_s)
725
+ assert_equal "world", @coll.find_one(:_id => id)["hello"]
726
+ end
727
+
728
+ def test_save_with_object_that_has_id_but_does_not_actually_exist_in_collection
729
+ @coll.remove
730
+
731
+ a = {'_id' => '1', 'hello' => 'world'}
732
+ @coll.save(a)
733
+ assert_equal(1, @coll.count)
734
+ assert_equal("world", @coll.find_one()["hello"])
735
+
736
+ a["hello"] = "mike"
737
+ @coll.save(a)
738
+ assert_equal(1, @coll.count)
739
+ assert_equal("mike", @coll.find_one()["hello"])
740
+ end
741
+
742
+ def test_collection_names_errors
743
+ assert_raise TypeError do
744
+ @db.collection(5)
745
+ end
746
+ assert_raise Mongo::InvalidNSName do
747
+ @db.collection("")
748
+ end
749
+ assert_raise Mongo::InvalidNSName do
750
+ @db.collection("te$t")
751
+ end
752
+ assert_raise Mongo::InvalidNSName do
753
+ @db.collection(".test")
754
+ end
755
+ assert_raise Mongo::InvalidNSName do
756
+ @db.collection("test.")
757
+ end
758
+ assert_raise Mongo::InvalidNSName do
759
+ @db.collection("tes..t")
760
+ end
761
+ end
762
+
763
+ def test_rename_collection
764
+ @db.drop_collection("foo")
765
+ @db.drop_collection("bar")
766
+ a = @db.collection("foo")
767
+ b = @db.collection("bar")
768
+
769
+ assert_raise TypeError do
770
+ a.rename(5)
771
+ end
772
+ assert_raise Mongo::InvalidNSName do
773
+ a.rename("")
774
+ end
775
+ assert_raise Mongo::InvalidNSName do
776
+ a.rename("te$t")
777
+ end
778
+ assert_raise Mongo::InvalidNSName do
779
+ a.rename(".test")
780
+ end
781
+ assert_raise Mongo::InvalidNSName do
782
+ a.rename("test.")
783
+ end
784
+ assert_raise Mongo::InvalidNSName do
785
+ a.rename("tes..t")
786
+ end
787
+
788
+ assert_equal 0, a.count()
789
+ assert_equal 0, b.count()
790
+
791
+ a.insert("x" => 1)
792
+ a.insert("x" => 2)
793
+
794
+ assert_equal 2, a.count()
795
+
796
+ a.rename("bar")
797
+
798
+ assert_equal 2, a.count()
799
+ end
800
+
801
+ # doesn't really test functionality, just that the option is set correctly
802
+ def test_snapshot
803
+ @db.collection("test").find({}, :snapshot => true).to_a
804
+ assert_raise OperationFailure do
805
+ @db.collection("test").find({}, :snapshot => true, :sort => 'a').to_a
806
+ end
807
+ end
808
+
809
+ def test_encodings
810
+ if RUBY_VERSION >= '1.9'
811
+ default = "hello world"
812
+ utf8 = "hello world".encode("UTF-8")
813
+ iso8859 = "hello world".encode("ISO-8859-1")
814
+
815
+ if RUBY_PLATFORM =~ /jruby/
816
+ assert_equal "ASCII-8BIT", default.encoding.name
817
+ elsif RUBY_VERSION >= '2.0'
818
+ assert_equal "UTF-8", default.encoding.name
819
+ else
820
+ assert_equal "US-ASCII", default.encoding.name
821
+ end
822
+
823
+ assert_equal "UTF-8", utf8.encoding.name
824
+ assert_equal "ISO-8859-1", iso8859.encoding.name
825
+
826
+ @coll.remove
827
+ @coll.save("default" => default, "utf8" => utf8, "iso8859" => iso8859)
828
+ doc = @coll.find_one()
829
+
830
+ assert_equal "UTF-8", doc["default"].encoding.name
831
+ assert_equal "UTF-8", doc["utf8"].encoding.name
832
+ assert_equal "UTF-8", doc["iso8859"].encoding.name
833
+ end
834
+ end
835
+ end