15
15
"""Test the pymongo common module."""
21
20
sys.path[0:0] = [""]
23
from nose.plugins.skip import SkipTest
25
from bson.binary import UUIDLegacy, OLD_UUID_SUBTYPE, UUID_SUBTYPE
22
from bson.binary import UUIDLegacy, PYTHON_LEGACY, STANDARD
26
23
from bson.code import Code
24
from bson.codec_options import CodecOptions
27
25
from bson.objectid import ObjectId
28
from bson.son import SON
29
from pymongo.connection import Connection
30
26
from pymongo.mongo_client import MongoClient
31
from pymongo.mongo_replica_set_client import MongoReplicaSetClient
32
from pymongo.errors import ConfigurationError, OperationFailure
33
from test import host, port, pair, version
34
from test.utils import catch_warnings, drop_collections
43
class TestCommon(unittest.TestCase):
45
def test_baseobject(self):
47
ctx = catch_warnings()
49
warnings.simplefilter("error", UserWarning)
50
self.assertRaises(UserWarning, lambda:
51
MongoClient(host, port, wtimeout=1000, w=0))
53
MongoClient(host, port, wtimeout=1000, w=1)
58
MongoClient(host, port, wtimeout=1000)
65
ctx = catch_warnings()
67
warnings.simplefilter("ignore", DeprecationWarning)
69
self.assertFalse(c.slave_okay)
70
self.assertFalse(c.safe)
71
self.assertEqual({}, c.get_lasterror_options())
73
db.drop_collection("test")
74
self.assertFalse(db.slave_okay)
75
self.assertFalse(db.safe)
76
self.assertEqual({}, db.get_lasterror_options())
78
self.assertFalse(coll.slave_okay)
79
self.assertFalse(coll.safe)
80
self.assertEqual({}, coll.get_lasterror_options())
82
self.assertEqual((False, {}), coll._get_write_mode())
84
coll.write_concern.update(w=1)
85
self.assertEqual((True, {}), coll._get_write_mode())
86
coll.write_concern.update(w=3)
87
self.assertEqual((True, {'w': 3}), coll._get_write_mode())
90
coll.write_concern.update(w=0)
91
self.assertEqual((False, {}), coll._get_write_mode())
95
self.assertFalse(cursor._Cursor__slave_okay)
96
cursor = coll.find(slave_okay=True)
97
self.assertTrue(cursor._Cursor__slave_okay)
100
c = MongoClient(pair)
101
self.assertFalse(c.slave_okay)
102
self.assertTrue(c.safe)
103
self.assertEqual({}, c.get_lasterror_options())
105
db.drop_collection("test")
106
self.assertFalse(db.slave_okay)
107
self.assertTrue(db.safe)
108
self.assertEqual({}, db.get_lasterror_options())
110
self.assertFalse(coll.slave_okay)
111
self.assertTrue(coll.safe)
112
self.assertEqual({}, coll.get_lasterror_options())
114
self.assertEqual((True, {}), coll._get_write_mode())
116
coll.write_concern.update(w=1)
117
self.assertEqual((True, {}), coll._get_write_mode())
118
coll.write_concern.update(w=3)
119
self.assertEqual((True, {'w': 3}), coll._get_write_mode())
122
coll.write_concern.update(w=0)
123
self.assertEqual((False, {}), coll._get_write_mode())
127
self.assertFalse(cursor._Cursor__slave_okay)
128
cursor = coll.find(slave_okay=True)
129
self.assertTrue(cursor._Cursor__slave_okay)
131
# Setting any safe operations overrides explicit safe
132
self.assertTrue(MongoClient(host, port, wtimeout=1000, safe=False).safe)
134
c = MongoClient(pair, slaveok=True, w='majority',
135
wtimeout=300, fsync=True, j=True)
136
self.assertTrue(c.slave_okay)
137
self.assertTrue(c.safe)
138
d = {'w': 'majority', 'wtimeout': 300, 'fsync': True, 'j': True}
139
self.assertEqual(d, c.get_lasterror_options())
141
self.assertTrue(db.slave_okay)
142
self.assertTrue(db.safe)
143
self.assertEqual(d, db.get_lasterror_options())
145
self.assertTrue(coll.slave_okay)
146
self.assertTrue(coll.safe)
147
self.assertEqual(d, coll.get_lasterror_options())
149
self.assertTrue(cursor._Cursor__slave_okay)
150
cursor = coll.find(slave_okay=False)
151
self.assertFalse(cursor._Cursor__slave_okay)
153
c = MongoClient('mongodb://%s/?'
154
'w=2;wtimeoutMS=300;fsync=true;'
155
'journal=true' % (pair,))
156
self.assertTrue(c.safe)
157
d = {'w': 2, 'wtimeout': 300, 'fsync': True, 'j': True}
158
self.assertEqual(d, c.get_lasterror_options())
160
c = MongoClient('mongodb://%s/?'
161
'slaveok=true;w=1;wtimeout=300;'
162
'fsync=true;j=true' % (pair,))
163
self.assertTrue(c.slave_okay)
164
self.assertTrue(c.safe)
165
d = {'w': 1, 'wtimeout': 300, 'fsync': True, 'j': True}
166
self.assertEqual(d, c.get_lasterror_options())
167
self.assertEqual(d, c.write_concern)
169
self.assertTrue(db.slave_okay)
170
self.assertTrue(db.safe)
171
self.assertEqual(d, db.get_lasterror_options())
172
self.assertEqual(d, db.write_concern)
174
self.assertTrue(coll.slave_okay)
175
self.assertTrue(coll.safe)
176
self.assertEqual(d, coll.get_lasterror_options())
177
self.assertEqual(d, coll.write_concern)
179
self.assertTrue(cursor._Cursor__slave_okay)
180
cursor = coll.find(slave_okay=False)
181
self.assertFalse(cursor._Cursor__slave_okay)
183
c.unset_lasterror_options()
184
self.assertTrue(c.slave_okay)
185
self.assertTrue(c.safe)
187
self.assertFalse(c.safe)
189
self.assertFalse(c.slave_okay)
190
self.assertEqual({}, c.get_lasterror_options())
191
self.assertEqual({}, c.write_concern)
193
self.assertFalse(db.slave_okay)
194
self.assertFalse(db.safe)
195
self.assertEqual({}, db.get_lasterror_options())
196
self.assertEqual({}, db.write_concern)
198
self.assertFalse(coll.slave_okay)
199
self.assertFalse(coll.safe)
200
self.assertEqual({}, coll.get_lasterror_options())
201
self.assertEqual({}, coll.write_concern)
203
self.assertFalse(cursor._Cursor__slave_okay)
204
cursor = coll.find(slave_okay=True)
205
self.assertTrue(cursor._Cursor__slave_okay)
207
coll.set_lasterror_options(fsync=True)
208
self.assertEqual({'fsync': True}, coll.get_lasterror_options())
209
self.assertEqual({'fsync': True}, coll.write_concern)
210
self.assertEqual({}, db.get_lasterror_options())
211
self.assertEqual({}, db.write_concern)
212
self.assertFalse(db.safe)
213
self.assertEqual({}, c.get_lasterror_options())
214
self.assertEqual({}, c.write_concern)
215
self.assertFalse(c.safe)
217
db.set_lasterror_options(w='majority')
218
self.assertEqual({'fsync': True}, coll.get_lasterror_options())
219
self.assertEqual({'fsync': True}, coll.write_concern)
220
self.assertEqual({'w': 'majority'}, db.get_lasterror_options())
221
self.assertEqual({'w': 'majority'}, db.write_concern)
222
self.assertEqual({}, c.get_lasterror_options())
223
self.assertEqual({}, c.write_concern)
224
self.assertFalse(c.safe)
226
self.assertTrue(db.slave_okay)
227
self.assertFalse(c.slave_okay)
228
self.assertFalse(coll.slave_okay)
230
self.assertFalse(cursor._Cursor__slave_okay)
231
cursor = db.coll2.find()
232
self.assertTrue(cursor._Cursor__slave_okay)
233
cursor = db.coll2.find(slave_okay=False)
234
self.assertFalse(cursor._Cursor__slave_okay)
236
self.assertRaises(ConfigurationError, coll.set_lasterror_options, foo=20)
237
self.assertRaises(TypeError, coll._BaseObject__set_slave_okay, 20)
238
self.assertRaises(TypeError, coll._BaseObject__set_safe, 20)
241
self.assertEqual(None, coll.find_one(slave_okay=True))
242
coll.unset_lasterror_options()
243
coll.set_lasterror_options(w=4, wtimeout=10)
244
# Fails if we don't have 4 active nodes or we don't have replication...
245
self.assertRaises(OperationFailure, coll.insert, {'foo': 'bar'})
246
# Succeeds since we override the lasterror settings per query.
247
self.assertTrue(coll.insert({'foo': 'bar'}, fsync=True))
252
def test_uuid_subtype(self):
254
raise SkipTest("No uuid module")
256
self.client = MongoClient(pair)
257
self.db = self.client.pymongo_test
258
coll = self.client.pymongo_test.uuid
27
from pymongo.errors import OperationFailure
28
from pymongo.write_concern import WriteConcern
29
from test import client_context, pair, unittest, IntegrationTest
30
from test.utils import connected, rs_or_single_client, single_client
33
@client_context.require_connection
38
class TestCommon(IntegrationTest):
40
def test_uuid_representation(self):
261
def change_subtype(collection, subtype):
262
collection.uuid_subtype = subtype
265
self.assertEqual(OLD_UUID_SUBTYPE, coll.uuid_subtype)
266
self.assertRaises(ConfigurationError, change_subtype, coll, 7)
267
self.assertRaises(ConfigurationError, change_subtype, coll, 2)
45
self.assertEqual(PYTHON_LEGACY,
46
coll.codec_options.uuid_representation)
269
48
# Test basic query
271
50
# Insert as binary subtype 3
272
coll.insert({'uu': uu})
51
coll.insert_one({'uu': uu})
273
52
self.assertEqual(uu, coll.find_one({'uu': uu})['uu'])
274
coll.uuid_subtype = UUID_SUBTYPE
275
self.assertEqual(UUID_SUBTYPE, coll.uuid_subtype)
53
coll = self.db.get_collection(
54
"uuid", CodecOptions(uuid_representation=STANDARD))
55
self.assertEqual(STANDARD, coll.codec_options.uuid_representation)
276
56
self.assertEqual(None, coll.find_one({'uu': uu}))
277
57
self.assertEqual(uu, coll.find_one({'uu': UUIDLegacy(uu)})['uu'])
279
59
# Test Cursor.count
280
60
self.assertEqual(0, coll.find({'uu': uu}).count())
281
coll.uuid_subtype = OLD_UUID_SUBTYPE
61
coll = self.db.get_collection(
62
"uuid", CodecOptions(uuid_representation=PYTHON_LEGACY))
282
63
self.assertEqual(1, coll.find({'uu': uu}).count())
285
coll.uuid_subtype = UUID_SUBTYPE
286
coll.remove({'uu': uu})
66
coll = self.db.get_collection(
67
"uuid", CodecOptions(uuid_representation=STANDARD))
68
coll.delete_one({'uu': uu})
287
69
self.assertEqual(1, coll.count())
288
coll.uuid_subtype = OLD_UUID_SUBTYPE
289
coll.remove({'uu': uu})
70
coll = self.db.get_collection(
71
"uuid", CodecOptions(uuid_representation=PYTHON_LEGACY))
72
coll.delete_one({'uu': uu})
290
73
self.assertEqual(0, coll.count())
293
coll.insert({'_id': uu, 'i': 0})
294
self.assertEqual(1, coll.count())
295
self.assertEqual(1, coll.find({'_id': uu}).count())
296
self.assertEqual(0, coll.find_one({'_id': uu})['i'])
297
doc = coll.find_one({'_id': uu})
300
self.assertEqual(1, coll.find_one({'_id': uu})['i'])
303
coll.uuid_subtype = UUID_SUBTYPE
304
coll.update({'_id': uu}, {'$set': {'i': 2}})
305
coll.uuid_subtype = OLD_UUID_SUBTYPE
306
self.assertEqual(1, coll.find_one({'_id': uu})['i'])
307
coll.update({'_id': uu}, {'$set': {'i': 2}})
76
coll.insert_one({'_id': uu, 'i': 1})
77
coll = self.db.get_collection(
78
"uuid", CodecOptions(uuid_representation=STANDARD))
79
coll.update_one({'_id': uu}, {'$set': {'i': 2}})
80
coll = self.db.get_collection(
81
"uuid", CodecOptions(uuid_representation=PYTHON_LEGACY))
82
self.assertEqual(1, coll.find_one({'_id': uu})['i'])
83
coll.update_one({'_id': uu}, {'$set': {'i': 2}})
308
84
self.assertEqual(2, coll.find_one({'_id': uu})['i'])
310
86
# Test Cursor.distinct
311
87
self.assertEqual([2], coll.find({'_id': uu}).distinct('i'))
312
coll.uuid_subtype = UUID_SUBTYPE
88
coll = self.db.get_collection(
89
"uuid", CodecOptions(uuid_representation=STANDARD))
313
90
self.assertEqual([], coll.find({'_id': uu}).distinct('i'))
315
# Test find_and_modify
316
self.assertEqual(None, coll.find_and_modify({'_id': uu},
318
coll.uuid_subtype = OLD_UUID_SUBTYPE
319
self.assertEqual(2, coll.find_and_modify({'_id': uu},
320
{'$set': {'i': 5}})['i'])
93
self.assertEqual(None, coll.find_one_and_update({'_id': uu},
95
coll = self.db.get_collection(
96
"uuid", CodecOptions(uuid_representation=PYTHON_LEGACY))
97
self.assertEqual(2, coll.find_one_and_update({'_id': uu},
98
{'$set': {'i': 5}})['i'])
321
99
self.assertEqual(5, coll.find_one({'_id': uu})['i'])
324
db = self.client.pymongo_test
325
no_obj_error = "No matching object found"
326
result = db.command('findAndModify', 'uuid',
327
allowable_errors=[no_obj_error],
328
uuid_subtype=UUID_SUBTYPE,
330
update={'$set': {'i': 6}})
331
self.assertEqual(None, result.get('value'))
332
self.assertEqual(5, db.command('findAndModify', 'uuid',
333
update={'$set': {'i': 6}},
334
query={'_id': uu})['value']['i'])
335
self.assertEqual(6, db.command('findAndModify', 'uuid',
336
update={'$set': {'i': 7}},
337
query={'_id': UUIDLegacy(uu)}
102
self.assertEqual(5, self.db.command('findAndModify', 'uuid',
103
update={'$set': {'i': 6}},
104
query={'_id': uu})['value']['i'])
105
self.assertEqual(6, self.db.command(
106
'findAndModify', 'uuid',
107
update={'$set': {'i': 7}},
108
query={'_id': UUIDLegacy(uu)})['value']['i'])
340
110
# Test (inline)_map_reduce
342
coll.insert({"_id": uu, "x": 1, "tags": ["dog", "cat"]})
343
coll.insert({"_id": uuid.uuid4(), "x": 3,
344
"tags": ["mouse", "cat", "dog"]})
112
coll.insert_one({"_id": uu, "x": 1, "tags": ["dog", "cat"]})
113
coll.insert_one({"_id": uuid.uuid4(), "x": 3,
114
"tags": ["mouse", "cat", "dog"]})
346
116
map = Code("function () {"
347
117
" this.tags.forEach(function(z) {"
360
coll.uuid_subtype = UUID_SUBTYPE
362
if version.at_least(self.db.connection, (1, 7, 4)):
363
result = coll.inline_map_reduce(map, reduce, query=q)
364
self.assertEqual([], result)
366
result = coll.map_reduce(map, reduce, "results", query=q)
367
self.assertEqual(0, db.results.count())
369
coll.uuid_subtype = OLD_UUID_SUBTYPE
371
if version.at_least(self.db.connection, (1, 7, 4)):
372
result = coll.inline_map_reduce(map, reduce, query=q)
373
self.assertEqual(2, len(result))
375
result = coll.map_reduce(map, reduce, "results", query=q)
376
self.assertEqual(2, db.results.count())
378
db.drop_collection("result")
130
coll = self.db.get_collection(
131
"uuid", CodecOptions(uuid_representation=STANDARD))
133
result = coll.inline_map_reduce(map, reduce, query=q)
134
self.assertEqual([], result)
136
result = coll.map_reduce(map, reduce, "results", query=q)
137
self.assertEqual(0, self.db.results.count())
139
coll = self.db.get_collection(
140
"uuid", CodecOptions(uuid_representation=PYTHON_LEGACY))
142
result = coll.inline_map_reduce(map, reduce, query=q)
143
self.assertEqual(2, len(result))
145
result = coll.map_reduce(map, reduce, "results", query=q)
146
self.assertEqual(2, self.db.results.count())
148
self.db.drop_collection("result")
382
coll.insert({"_id": uu, "a": 2})
383
coll.insert({"_id": uuid.uuid4(), "a": 1})
152
coll.insert_one({"_id": uu, "a": 2})
153
coll.insert_one({"_id": uuid.uuid4(), "a": 1})
385
155
reduce = "function (obj, prev) { prev.count++; }"
386
coll.uuid_subtype = UUID_SUBTYPE
156
coll = self.db.get_collection(
157
"uuid", CodecOptions(uuid_representation=STANDARD))
387
158
self.assertEqual([],
388
159
coll.group([], {"_id": uu},
389
{"count": 0}, reduce))
390
coll.uuid_subtype = OLD_UUID_SUBTYPE
160
{"count": 0}, reduce))
161
coll = self.db.get_collection(
162
"uuid", CodecOptions(uuid_representation=PYTHON_LEGACY))
391
163
self.assertEqual([{"count": 1}],
392
164
coll.group([], {"_id": uu},
393
165
{"count": 0}, reduce))
395
167
def test_write_concern(self):
396
c = MongoClient(pair)
398
self.assertEqual({}, c.write_concern)
399
wc = {'w': 2, 'wtimeout': 1000}
401
self.assertEqual(wc, c.write_concern)
402
wc = {'w': 3, 'wtimeout': 1000}
403
c.write_concern['w'] = 3
404
self.assertEqual(wc, c.write_concern)
406
del c.write_concern['wtimeout']
407
self.assertEqual(wc, c.write_concern)
409
wc = {'w': 3, 'wtimeout': 1000}
410
c = MongoClient(pair, w=3, wtimeout=1000)
411
self.assertEqual(wc, c.write_concern)
412
wc = {'w': 2, 'wtimeout': 1000}
168
c = MongoClient(connect=False)
169
self.assertEqual(WriteConcern(), c.write_concern)
171
c = MongoClient(connect=False, w=2, wtimeout=1000)
172
wc = WriteConcern(w=2, wtimeout=1000)
414
173
self.assertEqual(wc, c.write_concern)
416
175
db = c.pymongo_test
417
176
self.assertEqual(wc, db.write_concern)
419
178
self.assertEqual(wc, coll.write_concern)
420
coll.write_concern = {'j': True}
421
self.assertEqual({'j': True}, coll.write_concern)
180
cwc = WriteConcern(j=True)
181
coll = db.get_collection('test', write_concern=cwc)
182
self.assertEqual(cwc, coll.write_concern)
422
183
self.assertEqual(wc, db.write_concern)
425
coll.write_concern = wc
426
self.assertEqual(wc.to_dict(), coll.write_concern)
429
c.write_concern = {'foo': 'bar'}
430
self.assertRaises(ConfigurationError, f)
433
c.write_concern['foo'] = 'bar'
434
self.assertRaises(ConfigurationError, f)
437
c.write_concern = [('foo', 'bar')]
438
self.assertRaises(ConfigurationError, f)
440
185
def test_mongo_client(self):
441
m = MongoClient(pair, w=0)
186
m = rs_or_single_client(w=0)
442
187
coll = m.pymongo_test.write_concern_test
445
ctx = catch_warnings()
447
warnings.simplefilter("ignore", DeprecationWarning)
448
doc = {"_id": ObjectId()}
450
self.assertTrue(coll.insert(doc, safe=False))
451
self.assertTrue(coll.insert(doc, w=0))
452
self.assertTrue(coll.insert(doc))
453
self.assertRaises(OperationFailure, coll.insert, doc, safe=True)
454
self.assertRaises(OperationFailure, coll.insert, doc, w=1)
456
m = MongoClient(pair)
457
coll = m.pymongo_test.write_concern_test
458
self.assertTrue(coll.insert(doc, safe=False))
459
self.assertTrue(coll.insert(doc, w=0))
460
self.assertRaises(OperationFailure, coll.insert, doc)
461
self.assertRaises(OperationFailure, coll.insert, doc, safe=True)
462
self.assertRaises(OperationFailure, coll.insert, doc, w=1)
464
m = MongoClient("mongodb://%s/" % (pair,))
465
self.assertTrue(m.safe)
466
coll = m.pymongo_test.write_concern_test
467
self.assertRaises(OperationFailure, coll.insert, doc)
468
m = MongoClient("mongodb://%s/?w=0" % (pair,))
469
self.assertFalse(m.safe)
470
coll = m.pymongo_test.write_concern_test
471
self.assertTrue(coll.insert(doc))
189
doc = {"_id": ObjectId()}
191
self.assertTrue(coll.insert_one(doc))
192
coll = coll.with_options(write_concern=WriteConcern(w=1))
193
self.assertRaises(OperationFailure, coll.insert_one, doc)
195
m = rs_or_single_client()
196
coll = m.pymongo_test.write_concern_test
197
new_coll = coll.with_options(write_concern=WriteConcern(w=0))
198
self.assertTrue(new_coll.insert_one(doc))
199
self.assertRaises(OperationFailure, coll.insert_one, doc)
201
m = MongoClient("mongodb://%s/" % (pair,),
202
replicaSet=client_context.replica_set_name)
204
coll = m.pymongo_test.write_concern_test
205
self.assertRaises(OperationFailure, coll.insert_one, doc)
206
m = MongoClient("mongodb://%s/?w=0" % (pair,),
207
replicaSet=client_context.replica_set_name)
209
coll = m.pymongo_test.write_concern_test
476
self.assertEqual(m, MongoClient("mongodb://%s/?w=0" % (pair,)))
477
self.assertFalse(m != MongoClient("mongodb://%s/?w=0" % (pair,)))
479
def test_mongo_replica_set_client(self):
480
c = MongoClient(pair)
481
ismaster = c.admin.command('ismaster')
482
if 'setName' in ismaster:
483
setname = str(ismaster.get('setName'))
485
raise SkipTest("Not connected to a replica set.")
486
m = MongoReplicaSetClient(pair, replicaSet=setname, w=0)
487
coll = m.pymongo_test.write_concern_test
490
ctx = catch_warnings()
492
warnings.simplefilter("ignore", DeprecationWarning)
493
doc = {"_id": ObjectId()}
495
self.assertTrue(coll.insert(doc, safe=False))
496
self.assertTrue(coll.insert(doc, w=0))
497
self.assertTrue(coll.insert(doc))
498
self.assertRaises(OperationFailure, coll.insert, doc, safe=True)
499
self.assertRaises(OperationFailure, coll.insert, doc, w=1)
501
m = MongoReplicaSetClient(pair, replicaSet=setname)
502
coll = m.pymongo_test.write_concern_test
503
self.assertTrue(coll.insert(doc, safe=False))
504
self.assertTrue(coll.insert(doc, w=0))
505
self.assertRaises(OperationFailure, coll.insert, doc)
506
self.assertRaises(OperationFailure, coll.insert, doc, safe=True)
507
self.assertRaises(OperationFailure, coll.insert, doc, w=1)
509
m = MongoReplicaSetClient("mongodb://%s/?replicaSet=%s" % (pair, setname))
510
self.assertTrue(m.safe)
511
coll = m.pymongo_test.write_concern_test
512
self.assertRaises(OperationFailure, coll.insert, doc)
513
m = MongoReplicaSetClient("mongodb://%s/?replicaSet=%s;w=0" % (pair, setname))
514
self.assertFalse(m.safe)
515
coll = m.pymongo_test.write_concern_test
516
self.assertTrue(coll.insert(doc))
213
direct = connected(single_client(w=0))
214
self.assertEqual(direct,
215
connected(MongoClient("mongodb://%s/?w=0" % (pair,))))
217
self.assertFalse(direct !=
218
connected(MongoClient("mongodb://%s/?w=0" % (pair,))))
521
221
if __name__ == "__main__":