Skip to content

Commit c9d2662

Browse files
author
Xin Dong
committed
Added delete tests into correctness
1 parent 17724c2 commit c9d2662

File tree

2 files changed

+108
-15
lines changed

2 files changed

+108
-15
lines changed

test/correctness/document-correctness.py

Lines changed: 83 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,62 @@ def test_update(collection1, collection2, verbose=False):
277277

278278
return (True, False)
279279

280+
def test_delete_many(collection1, collection2, verbose=False):
281+
for i in range(1, 10):
282+
exceptionOne = None
283+
exceptionTwo = None
284+
query = gen.random_query(gen.global_prng.random())
285+
286+
util.trace('debug', '\n========== Delete_many No.', i, '==========')
287+
util.trace('debug', 'Query:', query)
288+
util.trace('debug', 'Number results from collection: ', gen.count_query_results(
289+
collection1, query))
290+
for item in collection1.find(query):
291+
util.trace('debug', 'Find Result1:', item)
292+
for item in collection2.find(query):
293+
util.trace('debug', 'Find Result2:', item)
294+
295+
try:
296+
if verbose:
297+
all = [x for x in collection1.find(dict())]
298+
for item in collection1.find(query):
299+
print '[{}] Before delete doc:{}'.format(type(collection1), item)
300+
print 'Before delete collection1 size: ', len(all)
301+
collection1.delete_many(query)
302+
except pymongo.errors.OperationFailure as e:
303+
exceptionOne = e
304+
except MongoModelException as e:
305+
exceptionOne = e
306+
try:
307+
if verbose:
308+
all = [x for x in collection2.find(dict())]
309+
for item in collection2.find(query):
310+
print '[{}]Before delete doc:{}'.format(type(collection2), item)
311+
print 'Before delete collection2 size: ', len(all)
312+
collection2.delete_many(query)
313+
except pymongo.errors.OperationFailure as e:
314+
exceptionTwo = e
315+
except MongoModelException as e:
316+
exceptionTwo = e
317+
318+
if (exceptionOne is None and exceptionTwo is None):
319+
# happy case, proceed to consistency check
320+
pass
321+
elif exceptionOne is not None and exceptionTwo is not None and exceptionOne.code == exceptionTwo.code:
322+
# TODO re-enable consistency check when failure happened
323+
return (True, True)
324+
else:
325+
print 'Unmatched result: '
326+
print type(exceptionOne), ': ', str(exceptionOne)
327+
print type(exceptionTwo), ': ', str(exceptionTwo)
328+
ignored_exception_check(exceptionOne)
329+
ignored_exception_check(exceptionTwo)
330+
return (False, False)
331+
332+
if not check_query(dict(), collection1, collection2):
333+
return (False, False)
334+
335+
return (True, False)
280336

281337
class IgnoredException(Exception):
282338
def __init__(self, message):
@@ -289,10 +345,11 @@ def ignored_exception_check(e):
289345

290346

291347
def one_iteration(collection1, collection2, ns, seed):
292-
update_tests_enabled = ns['no_updates']
348+
update_tests_enabled = not ns['no_updates']
349+
delete_many_tests_enabled = not ns['no_delete_many']
293350
sorting_tests_enabled = gen.generator_options.allow_sorts
294-
indexes_enabled = ns['no_indexes']
295-
projections_enabled = ns['no_projections']
351+
indexes_enabled = not ns['no_indexes']
352+
projections_enabled = not ns['no_projections']
296353
verbose = ns['verbose']
297354
num_doc = ns['num_doc']
298355
fname = "unknown"
@@ -406,6 +463,15 @@ def _run_operation_(op1, op2):
406463
if not okay:
407464
return (okay, fname, None)
408465

466+
if delete_many_tests_enabled:
467+
okay, skip_current_iteration = test_delete_many(collection1, collection2, verbose)
468+
if skip_current_iteration:
469+
if verbose:
470+
print "Skipping current iteration due to the failure from update."
471+
return (True, fname, None)
472+
if not okay:
473+
return (okay, fname, None)
474+
409475
if update_tests_enabled:
410476
okay, skip_current_iteration = test_update(collection1, collection2, verbose)
411477
if skip_current_iteration:
@@ -507,10 +573,10 @@ def test_forever(ns):
507573

508574

509575
def start_forever_test(ns):
510-
gen.generator_options.test_nulls = ns['no_nulls']
511-
gen.generator_options.upserts_enabled = ns['no_upserts']
512-
gen.generator_options.numeric_fieldnames = ns['no_numeric_fieldnames']
513-
gen.generator_options.allow_sorts = ns['no_sort']
576+
gen.generator_options.test_nulls = not ns['no_nulls']
577+
gen.generator_options.upserts_enabled = not ns['no_upserts']
578+
gen.generator_options.numeric_fieldnames = not ns['no_numeric_fieldnames']
579+
gen.generator_options.allow_sorts = not ns['no_sort']
514580

515581
util.weaken_tests(ns)
516582

@@ -540,6 +606,7 @@ def tester_thread(c1, c2):
540606
collection2=c2,
541607
seed=random.random(),
542608
update_tests_enabled=True,
609+
delete_many_tests_enabled=True,
543610
sorting_tests_enabled=True,
544611
indexes_enabled=False,
545612
projections_enabled=True,
@@ -598,22 +665,23 @@ def tester_thread(c1, c2):
598665
parser_forever.add_argument('2', choices=['mongo', 'mm', 'doclayer'], help='second tester')
599666
parser_forever.add_argument(
600667
'-s', '--seed', type=int, default=random.randint(0, sys.maxint), help='random seed to use')
601-
parser_forever.add_argument('--no-updates', default=True, action='store_false', help='disable update tests')
668+
parser_forever.add_argument('--no-updates', default=False, action='store_true', help='disable update tests')
669+
parser_forever.add_argument('--no-delete-many', default=False, action='store_true', help='disable delete_many tests')
602670
parser_forever.add_argument(
603-
'--no-sort', default=True, action='store_false', help='disable non-deterministic sort tests')
671+
'--no-sort', default=False, action='store_true', help='disable non-deterministic sort tests')
604672
parser_forever.add_argument(
605673
'--no-numeric-fieldnames',
606-
default=True,
607-
action='store_false',
674+
default=False,
675+
action='store_true',
608676
help='disable use of numeric fieldnames in subobjects')
609677
parser_forever.add_argument(
610-
'--no-nulls', default=True, action='store_false', help='disable generation of null values')
678+
'--no-nulls', default=False, action='store_true', help='disable generation of null values')
611679
parser_forever.add_argument(
612-
'--no-upserts', default=True, action='store_false', help='disable operator-operator upserts in update tests')
680+
'--no-upserts', default=False, action='store_true', help='disable operator-operator upserts in update tests')
613681
parser_forever.add_argument(
614-
'--no-indexes', default=True, action='store_false', help='disable generation of random indexes')
682+
'--no-indexes', default=False, action='store_true', help='disable generation of random indexes')
615683
parser_forever.add_argument(
616-
'--no-projections', default=True, action='store_false', help='disable generation of random query projections')
684+
'--no-projections', default=False, action='store_true', help='disable generation of random query projections')
617685
parser_forever.add_argument('--num-doc', type=int, default=300, help='number of documents in the collection')
618686
parser_forever.add_argument('--buggify', default=False, action='store_true', help='enable buggification')
619687
parser_forever.add_argument('--num-iter', type=int, default=0, help='number of iterations of this type of test')

test/correctness/mongo_model.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1112,6 +1112,31 @@ def transform_operator_query_to_upsert(self, selector):
11121112
raise MongoModelException("bad query!")
11131113
return selector
11141114

1115+
def delete_one(self, query):
1116+
"""Delete one document that matches the query. Notice when comparing the result of this with the result from
1117+
document layer, user may see difference because MongoModel does not use indexes when doing query, while
1118+
document layer does and thus document layer might delete a different doc here.
1119+
"""
1120+
if len(query) == 0:
1121+
for k in self.data.keys():
1122+
del self.data[k]
1123+
return
1124+
queryKey = query.keys()[0]
1125+
for k, item in self.data.iteritems():
1126+
if evaluate(queryKey, query[queryKey], item, self.options):
1127+
del self.data[k]
1128+
return
1129+
1130+
def delete_many(self, query):
1131+
if len(query) == 0:
1132+
self.data = SortedDict()
1133+
return
1134+
queryKey = query.keys()[0]
1135+
for k, item in self.data.iteritems():
1136+
if evaluate(queryKey, query[queryKey], item, self.options):
1137+
del self.data[k]
1138+
1139+
11151140
def update(self, query, update, upsert, multi):
11161141
isOperatorUpdate = self.has_operator_expressions(update)
11171142
if not isOperatorUpdate and multi:

0 commit comments

Comments
 (0)