|
18 | 18 | """
|
19 | 19 |
|
20 | 20 | import copy
|
21 |
| -import functools |
22 | 21 | import os
|
23 | 22 | import sys
|
24 | 23 | import types
|
25 | 24 |
|
26 | 25 | from bson import json_util, SON
|
27 | 26 | from bson.py3compat import abc, iteritems, text_type
|
28 | 27 |
|
29 |
| -from pymongo import operations, ASCENDING, MongoClient |
| 28 | +from pymongo import ASCENDING, MongoClient |
30 | 29 | from pymongo.cursor import Cursor
|
31 | 30 | from pymongo.database import Database
|
32 | 31 | from pymongo.monitoring import (
|
|
38 | 37 |
|
39 | 38 | from test import client_context, unittest, IntegrationTest
|
40 | 39 | from test.utils import (
|
41 |
| - camel_to_snake, camel_to_snake_args, rs_or_single_client, |
| 40 | + camel_to_snake, rs_or_single_client, |
42 | 41 | snake_to_camel, ScenarioDict)
|
43 | 42 |
|
44 | 43 | from test.version import Version
|
45 |
| -from test.utils import (camel_to_upper_camel, |
46 |
| - parse_spec_options, |
47 |
| - prepare_spec_arguments) |
| 44 | +from test.utils import parse_spec_options, prepare_spec_arguments |
48 | 45 |
|
49 | 46 |
|
50 | 47 | JSON_OPTS = json_util.JSONOptions(tz_aware=False)
|
@@ -157,8 +154,6 @@ def _create_entity(self, entity_spec):
|
157 | 154 | # Add logic to respect the following fields
|
158 | 155 | # - uriOptions
|
159 | 156 | # - useMultipleMongoses
|
160 |
| - # - observeEvents |
161 |
| - # - ignoreCommandMonitoringEvents |
162 | 157 | observe_events = spec.get('observeEvents')
|
163 | 158 | ignore_commands = spec.get('ignoreCommandMonitoringEvents', [])
|
164 | 159 | if observe_events:
|
@@ -226,16 +221,41 @@ class MatchEvaluatorUtil(object):
|
226 | 221 | def __init__(self, test_class):
|
227 | 222 | self._test_class = test_class
|
228 | 223 |
|
229 |
| - def _evaluate_special_operation(self, operation, expectation, actual): |
230 |
| - pass |
| 224 | + def _operation_exists(self, spec, actual): |
| 225 | + raise NotImplementedError |
| 226 | + |
| 227 | + def _operation_type(self, spec, actual): |
| 228 | + raise NotImplementedError |
| 229 | + |
| 230 | + def _operation_matchesEntity(self, spec, actual): |
| 231 | + raise NotImplementedError |
| 232 | + |
| 233 | + def _operation_matchesHexBytes(self, spec, actual): |
| 234 | + raise NotImplementedError |
| 235 | + |
| 236 | + def _operation_unsetOrMatches(self, spec, actual): |
| 237 | + raise NotImplementedError |
| 238 | + |
| 239 | + def _operation_sessionLsid(self, spec, actual): |
| 240 | + raise NotImplementedError |
| 241 | + |
| 242 | + def _evaluate_special_operation(self, opname, spec, actual): |
| 243 | + method_name = '_operation_%s' % (opname.strip('$'),) |
| 244 | + try: |
| 245 | + method = getattr(self, method_name) |
| 246 | + except AttributeError: |
| 247 | + self._test_class.fail( |
| 248 | + 'Unsupported special matching operator %s' % (opname,)) |
| 249 | + else: |
| 250 | + method(spec, actual) |
231 | 251 |
|
232 | 252 | def _evaluate_if_special_operation(self, expectation, actual):
|
233 | 253 | if isinstance(expectation, abc.Mapping) and len(expectation) == 1:
|
234 | 254 | key, value = next(iteritems(expectation))
|
235 | 255 | if key.startswith('$$'):
|
236 | 256 | self._evaluate_special_operation(
|
237 |
| - operation=key, |
238 |
| - expectation=value, |
| 257 | + opname=key, |
| 258 | + spec=value, |
239 | 259 | actual=actual)
|
240 | 260 | return True
|
241 | 261 | return False
|
@@ -374,28 +394,64 @@ def setUp(self):
|
374 | 394 | # initialize internals
|
375 | 395 | self.match_evaluator = MatchEvaluatorUtil(self)
|
376 | 396 |
|
| 397 | + def process_error(self, exception, spec): |
| 398 | + is_error = spec.get('isError') |
| 399 | + is_client_error = spec.get('isClientError') |
| 400 | + error_contains = spec.get('errorContains') |
| 401 | + error_code = spec.get('errorCode') |
| 402 | + error_code_name = spec.get('errorCodeName') |
| 403 | + error_labels_contain = spec.get('errorLabelsContain') |
| 404 | + error_labels_omit = spec.get('errorLabelsOmit') |
| 405 | + expect_result = spec.get('expectResult') |
| 406 | + # TODO: process expectedError object |
| 407 | + # See L420-446 of utils_spec_runner.py |
| 408 | + |
| 409 | + if is_error: |
| 410 | + self.assertIsInstance(exception, Exception) |
| 411 | + |
| 412 | + if is_client_error: |
| 413 | + raise NotImplementedError |
| 414 | + |
| 415 | + if error_contains: |
| 416 | + raise RuntimeError |
| 417 | + |
| 418 | + if error_code: |
| 419 | + raise NotImplementedError |
| 420 | + |
| 421 | + if error_code_name: |
| 422 | + raise NotImplementedError |
| 423 | + |
| 424 | + if error_labels_contain: |
| 425 | + raise NotImplementedError |
| 426 | + |
| 427 | + if error_labels_omit: |
| 428 | + raise NotImplementedError |
| 429 | + |
| 430 | + if expect_result: |
| 431 | + raise NotImplementedError |
| 432 | + |
377 | 433 | def run_entity_operation(self, spec):
|
378 | 434 | target = self.entity_map[spec['object']]
|
379 | 435 | opname = camel_to_snake(spec['name'])
|
380 | 436 | opargs = spec.get('arguments')
|
381 | 437 | expect_error = spec.get('expectError')
|
382 |
| - if expect_error: |
383 |
| - # TODO: process expectedError object |
384 |
| - # See L420-446 of utils_spec_runner.py |
385 |
| - return |
386 |
| - |
387 |
| - # Operation expected to succeed |
388 | 438 | arguments = parse_spec_options(copy.deepcopy(opargs))
|
389 | 439 | cmd = getattr(target, opname)
|
390 | 440 | prepare_spec_arguments(spec, arguments, opname, self.entity_map,
|
391 | 441 | None)
|
392 |
| - result = cmd(**dict(arguments)) |
393 | 442 |
|
394 |
| - if isinstance(result, Cursor): |
395 |
| - result = list(result) |
| 443 | + try: |
| 444 | + result = cmd(**dict(arguments)) |
| 445 | + except Exception as exc: |
| 446 | + if expect_error: |
| 447 | + return self.process_error(exc, expect_error) |
| 448 | + raise |
| 449 | + else: |
| 450 | + if isinstance(result, Cursor): |
| 451 | + result = list(result) |
396 | 452 |
|
397 |
| - expected_result = spec.get('expectResult') |
398 |
| - self.match_evaluator.match_result(expected_result, result) |
| 453 | + expect_result = spec.get('expectResult') |
| 454 | + self.match_evaluator.match_result(expect_result, result) |
399 | 455 |
|
400 | 456 | save_as_entity = spec.get('saveResultAsEntity')
|
401 | 457 | if save_as_entity:
|
|
0 commit comments