|
26 | 26 | import os.path |
27 | 27 | import random |
28 | 28 | import sys |
| 29 | +import pprint |
29 | 30 |
|
30 | 31 | import pymongo |
31 | 32 |
|
32 | 33 | import gen |
33 | 34 | import util |
34 | 35 | from mongo_model import MongoCollection |
35 | 36 | from mongo_model import MongoModel |
| 37 | +from mongo_model import SortedDict |
| 38 | +from gen import HashableOrderedDict |
36 | 39 | from util import MongoModelException |
37 | 40 |
|
38 | 41 |
|
@@ -152,6 +155,7 @@ def diff_results(cA, rA, cB, rB): |
152 | 155 |
|
153 | 156 | def check_query(query, collection1, collection2, projection=None, sort=None, limit=0, skip=0): |
154 | 157 | util.trace('debug', '\n==================================================') |
| 158 | + util.trace('debug', 'checking consistency bettwen the two collections...') |
155 | 159 | util.trace('debug', 'query:', query) |
156 | 160 | util.trace('debug', 'sort:', sort) |
157 | 161 | util.trace('debug', 'limit:', limit) |
@@ -213,60 +217,65 @@ def check_query(query, collection1, collection2, projection=None, sort=None, lim |
213 | 217 | return False |
214 | 218 |
|
215 | 219 |
|
216 | | -def test_update(collections, verbose=False): |
217 | | - okay = True |
| 220 | +def test_update(collection1, collection2, verbose=False): |
218 | 221 | for i in range(1, 10): |
219 | | - update = gen.random_update(collections[0]) |
| 222 | + exceptionOne = None |
| 223 | + exceptionTwo = None |
| 224 | + update = gen.random_update(collection1) |
220 | 225 |
|
221 | 226 | util.trace('debug', '\n========== Update No.', i, '==========') |
222 | 227 | util.trace('debug', 'Query:', update['query']) |
223 | 228 | util.trace('debug', 'Update:', str(update['update'])) |
224 | 229 | util.trace('debug', 'Number results from collection: ', gen.count_query_results( |
225 | | - collections[0], update['query'])) |
226 | | - for item in collections[0].find(update['query']): |
227 | | - util.trace('debug', 'Find Result0:', item) |
228 | | - |
229 | | - exception = [] |
230 | | - exception_msg = [] |
231 | | - for coll in collections: |
232 | | - try: |
233 | | - if verbose: |
234 | | - all = [x for x in coll.find(dict())] |
235 | | - for item in coll.find(update['query']): |
236 | | - print 'Before update doc:', item |
237 | | - print 'Before update coll size: ', len(all) |
| 230 | + collection1, update['query'])) |
| 231 | + for item in collection1.find(update['query']): |
| 232 | + util.trace('debug', 'Find Result1:', item) |
| 233 | + for item in collection2.find(update['query']): |
| 234 | + util.trace('debug', 'Find Result2:', item) |
| 235 | + |
| 236 | + try: |
| 237 | + if verbose: |
| 238 | + all = [x for x in collection1.find(dict())] |
| 239 | + for item in collection1.find(update['query']): |
| 240 | + print '[{}] Before update doc:{}'.format(type(collection1), item) |
| 241 | + print 'Before update collection1 size: ', len(all) |
| 242 | + collection1.update(update['query'], update['update'], upsert=update['upsert'], multi=update['multi']) |
| 243 | + except pymongo.errors.OperationFailure as e: |
| 244 | + exceptionOne = e |
| 245 | + except MongoModelException as e: |
| 246 | + exceptionOne = e |
| 247 | + try: |
| 248 | + if verbose: |
| 249 | + all = [x for x in collection2.find(dict())] |
| 250 | + for item in collection2.find(update['query']): |
| 251 | + print '[{}]Before update doc:{}'.format(type(collection2), item) |
| 252 | + print 'Before update collection2 size: ', len(all) |
| 253 | + collection2.update(update['query'], update['update'], upsert=update['upsert'], multi=update['multi']) |
| 254 | + except pymongo.errors.OperationFailure as e: |
| 255 | + exceptionTwo = e |
| 256 | + except MongoModelException as e: |
| 257 | + exceptionTwo = e |
238 | 258 |
|
239 | | - coll.update(update['query'], update['update'], upsert=update['upsert'], multi=update['multi']) |
| 259 | + if (exceptionOne is None and exceptionTwo is None): |
| 260 | + # happy case, proceed to consistency check |
| 261 | + pass |
| 262 | + elif exceptionOne is not None and exceptionTwo is not None: |
| 263 | + # or (exceptionOne is not None and exceptionTwo is not None and exceptionOne.code == exceptionTwo.code)): |
| 264 | + # TODO re-enable the exact error check. |
| 265 | + # TODO re-enable consistency check when failure happened |
| 266 | + return (True, True) |
| 267 | + else: |
| 268 | + print 'Unmatched result: ' |
| 269 | + print type(exceptionOne), ': ', str(exceptionOne) |
| 270 | + print type(exceptionTwo), ': ', str(exceptionTwo) |
| 271 | + ignored_exception_check(exceptionOne) |
| 272 | + ignored_exception_check(exceptionTwo) |
| 273 | + return (False, False) |
240 | 274 |
|
241 | | - if verbose: |
242 | | - all = [x for x in coll.find(dict())] |
243 | | - for item in coll.find(update['query']): |
244 | | - print 'After update doc:', item |
245 | | - print 'After update coll size: ', len(all) |
246 | | - |
247 | | - except pymongo.errors.OperationFailure as e: |
248 | | - exception.append(e) |
249 | | - exception_msg.append( |
250 | | - util.join_n('Caught PyMongo error while attempting update: %s' % e[0], |
251 | | - 'Query: %s' % update['query'], 'Update: %s' % update['update'], |
252 | | - 'Upsert: {0}, Multi: {1}'.format(update['upsert'], update['multi']))) |
253 | | - except MongoModelException as e: |
254 | | - exception.append(e) |
255 | | - exception_msg.append( |
256 | | - util.join_n('Caught MongoModel error. Offending update(', str(update['query']), |
257 | | - str(update['update']), str(update['upsert']), str(update['multi']), ')')) |
258 | | - |
259 | | - if len(exception_msg) == 1: |
260 | | - print 'Update: ' + str(update['update']) |
261 | | - print '\033[91m', exception[0], '\033[0m' |
262 | | - print '\033[91m', exception_msg[0], '\033[0m' |
263 | | - return False |
264 | | - |
265 | | - if not check_query(dict(), collections[0], collections[1]): |
266 | | - print 'Update: ' + str(update['update']) |
267 | | - return False |
| 275 | + if not check_query(dict(), collection1, collection2): |
| 276 | + return (False, False) |
268 | 277 |
|
269 | | - return okay |
| 278 | + return (True, False) |
270 | 279 |
|
271 | 280 |
|
272 | 281 | class IgnoredException(Exception): |
@@ -297,18 +306,22 @@ def _run_operation_(op1, op2): |
297 | 306 | try: |
298 | 307 | func1(*args1, **kwargs1) |
299 | 308 | except pymongo.errors.OperationFailure as e: |
300 | | - print "Failed func1 with " + str(e) |
| 309 | + if verbose: |
| 310 | + print "Failed func1 with " + str(e) |
301 | 311 | exceptionOne = e |
302 | 312 | except MongoModelException as e: |
303 | | - print "Failed func1 with " + str(e) |
| 313 | + if verbose: |
| 314 | + print "Failed func1 with " + str(e) |
304 | 315 | exceptionOne = e |
305 | 316 | try: |
306 | 317 | func2(*args2, **kwargs2) |
307 | 318 | except pymongo.errors.OperationFailure as e: |
308 | | - print "Failed func2 with " + str(e) |
| 319 | + if verbose: |
| 320 | + print "Failed func2 with " + str(e) |
309 | 321 | exceptionTwo = e |
310 | 322 | except MongoModelException as e: |
311 | | - print "Failed func2 with " + str(e) |
| 323 | + if verbose: |
| 324 | + print "Failed func2 with " + str(e) |
312 | 325 | exceptionTwo = e |
313 | 326 |
|
314 | 327 | if ((exceptionOne is None and exceptionTwo is None) |
@@ -394,8 +407,12 @@ def _run_operation_(op1, op2): |
394 | 407 | return (okay, fname, None) |
395 | 408 |
|
396 | 409 | if update_tests_enabled: |
397 | | - if not test_update([collection1, collection2], verbose): |
398 | | - okay = False |
| 410 | + okay, skip_current_iteration = test_update(collection1, collection2, verbose) |
| 411 | + if skip_current_iteration: |
| 412 | + if verbose: |
| 413 | + print "Skipping current iteration due to the failure from update." |
| 414 | + return (True, fname, None) |
| 415 | + if not okay: |
399 | 416 | return (okay, fname, None) |
400 | 417 |
|
401 | 418 | for ii in range(1, 30): |
|
0 commit comments