Beispiel #1
0
 def ForMissing(cls, location):
   update_context = updates.Context({'expect_exit': collections.OrderedDict()},
                                    'expect_exit',
                                    cls.EventType().UpdateMode(),
                                    was_missing=True,
                                    location=location)
   return cls(update_context, 0, assertions.EqualsAssertion(None),
              assertions.EqualsAssertion(None))
Beispiel #2
0
 def ForMissing(cls, location):
     update_context = updates.Context(
         {'expect_file_written': OrderedDict()},
         'expect_file_written',
         cls.EventType().UpdateMode(),
         was_missing=True,
         location=location)
     return cls(update_context, assertions.EqualsAssertion(None),
                assertions.EqualsAssertion(None),
                assertions.EqualsAssertion(None),
                assertions.EqualsAssertion(False))
Beispiel #3
0
    def _ForCommon(cls, mode, http_data, uri_assertion, method_assertion,
                   extract_references):
        """Builder for the attributes applicable to both requests and responses."""
        header_assertion = assertions.DictAssertion()
        for header, value in six.iteritems(http_data.get('headers', {})):
            header_assertion.AddAssertion(
                header, assertions.Assertion.ForComplex(value))

        payload_json_assertion = None
        payload_text_assertion = None
        body_present = True
        body_data = http_data.get('body')
        if 'body' not in http_data or (not body_data
                                       and body_data is not None):
            # The body section is missing entirely or it is present and is an empty
            # dictionary. In these cases, the assertions are not present and will be
            # updated always.
            body_present = False
            payload_json_assertion = assertions.JsonAssertion().Matches(
                '', assertions.MISSING_VALUE)
            payload_text_assertion = assertions.EqualsAssertion(
                assertions.MISSING_VALUE)
            http_data['body'] = {'text': None, 'json': {}}
        elif body_data is None:
            # The body section is present and explicitly None. This implies assertions
            # that the body is actual None. If it is not, the assertions will fail.
            body_present = False
            payload_json_assertion = assertions.JsonAssertion().Matches(
                '', None)
            payload_text_assertion = assertions.EqualsAssertion(None)
        else:
            # The body is present, load the assertions that were provided.
            if 'text' in body_data:
                payload_text_assertion = assertions.Assertion.ForComplex(
                    body_data['text'])
            if 'json' in body_data:
                payload_json_assertion = assertions.JsonAssertion()
                json_data = body_data['json']
                if not json_data or json_data == assertions.MISSING_VALUE:
                    # If explicitly None, this asserts that the request is empty.
                    # If explicitly the empty dictionary, the assertion checks nothing.
                    payload_json_assertion.Matches('', json_data)
                else:
                    for field, struct in six.iteritems(json_data):
                        payload_json_assertion.Matches(field, struct)

        return cls(mode, uri_assertion, method_assertion, header_assertion,
                   payload_json_assertion, payload_text_assertion,
                   body_present, extract_references)
Beispiel #4
0
  def FromData(cls, mode, http_data):
    """Creates an HttpBodyAssertion for an HTTP request or response.

    Args:
      mode: string, 'expect_request' or 'expect_response' depending on if it is
          a request or response.
      http_data: dict, api_call.expect_request or api_call.expect_response.

    Returns:
      HttpBodyAssertion
    """
    payload_json_assertion = None
    payload_text_assertion = None
    body_present = True
    body_data = http_data.get('body')
    if 'body' not in http_data or (not body_data and body_data is not None):
      # The body section is missing entirely or it is present and is an empty
      # dictionary. In these cases, the assertions are not present and will be
      # updated always.
      body_present = False
      payload_json_assertion = assertions.JsonAssertion().Matches(
          '', assertions.MISSING_VALUE)
      payload_text_assertion = assertions.EqualsAssertion(
          assertions.MISSING_VALUE)
      http_data['body'] = {'text': None, 'json': {}}
    elif body_data is None:
      # The body section is present and explicitly None. This implies assertions
      # that the body is actual None. If it is not, the assertions will fail.
      body_present = False
      payload_json_assertion = assertions.JsonAssertion().Matches('', None)
      payload_text_assertion = assertions.EqualsAssertion(None)
    else:
      # The body is present, load the assertions that were provided.
      if 'text' in body_data:
        payload_text_assertion = assertions.Assertion.ForComplex(
            body_data['text'])
      if 'json' in body_data:
        payload_json_assertion = assertions.JsonAssertion()
        json_data = body_data['json']
        if not json_data or json_data == assertions.MISSING_VALUE:
          # If explicitly None, this asserts that the request is empty.
          # If explicitly the empty dictionary, the assertion checks nothing.
          payload_json_assertion.Matches('', json_data)
        else:
          for field, struct in six.iteritems(json_data):
            payload_json_assertion.Matches(field, struct)

    return cls(mode, body_present, payload_json_assertion,
               payload_text_assertion)
Beispiel #5
0
  def ForMissing(cls):
    """Creates a RequestAssertion for a missing api_call."""
    uri_assertion = assertions.EqualsAssertion(assertions.MISSING_VALUE)
    method_assertion = assertions.EqualsAssertion(assertions.MISSING_VALUE)
    headers_assertion = assertions.DictAssertion()

    payload_json_assertion = (assertions.JsonAssertion()
                              .Matches('', assertions.MISSING_VALUE))
    payload_text_assertion = assertions.EqualsAssertion(
        assertions.MISSING_VALUE)
    body_assertion = HttpBodyAssertion('expect_request', False,
                                       payload_json_assertion,
                                       payload_text_assertion)
    return cls(uri_assertion, method_assertion, headers_assertion,
               body_assertion)
Beispiel #6
0
    def _GenerateOperationsExtras(self, resource_ref_resolver, response_body):
        """Generates extra data if this response looks like an operation.

    If the body has a kind attribute that indicates an operation, this will
    update the scenario spec to include a default extract_references block
    to pull out the operation id. This should only be called if an
    expect_response block is not already present. If this is a polling operation
    it will be marked as optional.

    Args:
      resource_ref_resolver: ResourceReferenceResolver, The resolver to track
        the extracted references.
      response_body: str, The body of the response from the server.

    Returns:
      [Failure], The failures to update the spec and inject the new block or [].
    """
        op = Operation.FromResponse(None,
                                    response_body,
                                    force_operation=self._poll_operation)
        if not op:
            # Not an operation response at all.
            return []
        if resource_ref_resolver.IsExtractedIdCurrent('operation', op.name):
            # This is an op, but the id has already been extracted in a previous
            # event. This means that this is not the call that generated the op, but
            # rather the polling of the op. No need to generate the ref extraction,
            # but we do want to mark polling steps as optional and repeated calls.
            self.MarkRepeated()
            failures = self.CheckRepeatable()
            if op.status:
                # In order for optional to work, we need to also generate an assertion
                # against the status in the response.
                failures = assertions.EqualsAssertion(self._is_optional).Check(
                    self._update_context.ForKey('optional'), True)
                failures.append(
                    assertions.Failure.ForGeneric(
                        self._update_context.ForKey('expect_response'),
                        'Adding operation response assertion for optional polling',
                        OrderedDict([('body', {
                            'json': {
                                'status': op.status
                            }
                        })])))
            return failures

        # This is a call that resulted in an operation being created. Extract its
        # id for future polling calls.
        resource_ref_resolver.SetExtractedId('operation', op.name)
        return [
            assertions.Failure.ForGeneric(
                self._update_context.ForKey('expect_response'),
                'Adding reference extraction for Operations response',
                OrderedDict([('extract_references', [
                    OrderedDict([('field', 'name'),
                                 ('reference', 'operation')])
                ]), ('body', {
                    'json': {}
                })]))
        ]
Beispiel #7
0
 def Handle(self, ux_event_data):
   failures = super(_PromptEvent, self).Handle(ux_event_data)
   if self._user_input is None:
     # Set the answer to 'y' if the entire assertion was missing.
     failures.extend(
         assertions.EqualsAssertion(None).Check(
             self._update_context.ForKey('user_input'), self.DefaultValue()))
   return failures
Beispiel #8
0
  def FromData(cls, backing_data):
    file_data = backing_data['expect_file_written']
    update_context = updates.Context(backing_data, 'expect_file_written',
                                     cls.EventType().UpdateMode())

    path_assertion = assertions.EqualsAssertion(file_data.get('path'))
    contents_assertion = assertions.Assertion.ForComplex(
        file_data.get('contents'))
    binary_contents = file_data.get('binary_contents')
    if (binary_contents is not None and
        isinstance(binary_contents, six.text_type)):
      binary_contents = binary_contents.encode('utf-8')
    binary_contents_assertion = assertions.Assertion.ForComplex(binary_contents)
    is_private_assertion = assertions.EqualsAssertion(
        file_data.get('is_private') or False)

    return cls(update_context, path_assertion, contents_assertion,
               binary_contents_assertion, is_private_assertion)
Beispiel #9
0
 def FromData(cls, backing_data):
   exit_data = backing_data['expect_exit']
   code = exit_data.get('code')
   has_message = 'message' in exit_data
   message = exit_data.get('message')
   return cls(
       updates.Context(backing_data, 'expect_exit',
                       cls.EventType().UpdateMode()), code,
       assertions.EqualsAssertion(code),
       assertions.Assertion.ForComplex(message) if has_message else None)
Beispiel #10
0
 def FromCallData(cls, call_data):
   """Creates a RequestAssertion from an api_call dict."""
   http_data = call_data['expect_request']
   uri_assertion = assertions.Assertion.ForComplex(http_data.get('uri', ''))
   method_assertion = assertions.EqualsAssertion(
       http_data.get('method', 'GET'))
   headers_assertion = MakeHttpHeadersAssertion(http_data)
   body_assertion = HttpBodyAssertion.FromData('expect_request', http_data)
   return cls(uri_assertion, method_assertion, headers_assertion,
              body_assertion)
Beispiel #11
0
    def Execute(self, scenario_context):
        if scenario_context.execution_mode == session.ExecutionMode.LOCAL:
            # No need to wait for anything in local mode.
            return

        rrr = scenario_context.resource_ref_resolver
        command = rrr.Resolve(self._command)
        exit_code_assertion = (None if self._exit_code is None else
                               assertions.EqualsAssertion(self._exit_code))
        stdout_assertion = (None if self._stdout is None else
                            assertions.Assertion.ForComplex(
                                rrr.Resolve(self._stdout)))
        stderr_assertion = (None if self._stderr is None else
                            assertions.Assertion.ForComplex(
                                rrr.Resolve(self._stderr)))

        def _Run():
            """Executes the command for the retrier."""
            try:
                scenario_context.command_executor(command)
                exit_code = 0
            except Exception as e:  # pylint: disable=broad-except
                if isinstance(e, (KeyboardInterrupt, SystemExit)):
                    raise
                exit_code = getattr(e, 'exit_code', 1)
            stdout = scenario_context.stream_mocker.stdout_reader()
            stderr = scenario_context.stream_mocker.stderr_reader()
            result = (exit_code, stdout, stderr)
            if scenario_context.debug:
                sys.__stderr__.write('execute_command_until: Result: ' +
                                     six.text_type(result) + '\n')
            return result

        context = updates.Context.Empty()

        def _ShouldRetry(result, state):
            del state
            exit_code, stdout, stderr = result
            if exit_code_assertion and exit_code_assertion.Check(
                    context, exit_code):
                return True
            if stdout_assertion and stdout_assertion.Check(context, stdout):
                return True
            if stderr_assertion and stderr_assertion.Check(context, stderr):
                return True
            return False

        retrier = retry.Retryer(
            max_retrials=self._retries,
            max_wait_ms=self._timeout * 1000,
            exponential_sleep_multiplier=self._exponential_sleep_multiplier,
            wait_ceiling_ms=self._wait_ceiling_ms)
        retrier.RetryOnResult(_Run,
                              should_retry_if=_ShouldRetry,
                              sleep_ms=1000)
Beispiel #12
0
  def _GenerateOperationPolling(self, resource_ref_resolver, response):
    if not self._poll_operation and self._poll_operation is not None:
      # If explicitly disabled, don't treat this as an operation no matter what.
      return []

    op = Operation.FromResponse(response, force_operation=self._poll_operation)
    if not op or resource_ref_resolver.IsExtractedIdCurrent(
        'operation', op.name):
      # Not an operation response at all.
      if self._poll_operation is None:
        return []
      return assertions.EqualsAssertion(self._poll_operation).Check(
          self._update_context.ForKey('poll_operation'), False)

    # We've identified the response as an operation, make sure polling is turned
    # on.
    self._ExtractOperationPollingName(resource_ref_resolver, op)
    failures = assertions.EqualsAssertion(self._poll_operation).Check(
        self._update_context.ForKey('poll_operation'), True)
    return failures
Beispiel #13
0
 def ForRequest(cls, http_data):
     uri_assertion = assertions.Assertion.ForComplex(
         http_data.get('uri', ''))
     method_assertion = assertions.EqualsAssertion(
         http_data.get('method', 'GET'))
     extract_references = [
         ReferenceExtraction.FromData(d)
         for d in http_data.get('extract_references', [])
     ]
     return cls._ForCommon('expect_request', http_data, uri_assertion,
                           method_assertion, extract_references)
Beispiel #14
0
 def HandleReturnCode(self, return_code, message=None):
     failures = []
     failures.extend(
         self._code_assertion.Check(self._update_context.ForKey('code'),
                                    return_code))
     if self._message_assertion or (failures and message):
         msg_assertion = self._message_assertion or assertions.EqualsAssertion(
             '')
         failures.extend(
             msg_assertion.Check(self._update_context.ForKey('message'),
                                 message))
     return failures
Beispiel #15
0
    def ForMissing(cls, location):
        backing_data = {
            'api_call':
            OrderedDict([('expect_request',
                          OrderedDict([('uri', ''), ('method', ''),
                                       ('headers', {}),
                                       ('body', {
                                           'text': None,
                                           'json': {}
                                       })])),
                         ('return_response',
                          OrderedDict([('headers', {
                              'status': '200'
                          }), ('body', None)]))])
        }
        update_context = updates.Context(backing_data,
                                         'api_call',
                                         cls.EventType().UpdateMode(),
                                         was_missing=True,
                                         location=location)
        response = backing_data['api_call']['return_response']

        return cls(
            update_context, None, None, False,
            HTTPAssertion(
                'expect_request',
                assertions.EqualsAssertion(assertions.MISSING_VALUE),
                assertions.EqualsAssertion(assertions.MISSING_VALUE),
                assertions.DictAssertion(),
                assertions.JsonAssertion().Matches('',
                                                   assertions.MISSING_VALUE),
                assertions.EqualsAssertion(assertions.MISSING_VALUE), False,
                {}), None,
            HTTPResponsePayload(headers=response['headers'],
                                payload=response['body'],
                                omit_fields=None))
Beispiel #16
0
    def _Build(cls, backing_data, field, was_missing=False, location=None):
        ux_event_data = backing_data.setdefault(field, OrderedDict())
        update_context = updates.Context(backing_data,
                                         field,
                                         cls.EventType().UpdateMode(),
                                         was_missing=was_missing,
                                         location=location)

        attr_assertions = OrderedDict()
        for a in cls.EventType().UXElementAttributes():
            if was_missing or a in ux_event_data:
                # Only create assertions for things that were specified, or if the event
                # was missing, assert everything so it all gets filled in.
                attr_assertions[a] = assertions.EqualsAssertion(
                    ux_event_data.get(a, None))

        return cls(update_context, attr_assertions, ux_event_data)
Beispiel #17
0
  def FromCallData(cls, call_data):
    """Creates a ResponseAssertion from an api_call dict."""
    if 'expect_response' not in call_data:
      return None

    http_data = call_data['expect_response']
    status = http_data.get('status')
    if not status:
      status = int(http_data.get('headers', {}).get('status', httplib.OK))
    status_assertion = assertions.EqualsAssertion(status)
    headers_assertion = MakeHttpHeadersAssertion(http_data, for_response=True)
    body_assertion = HttpBodyAssertion.FromData('expect_response', http_data)
    extract_references = [
        ReferenceExtraction.FromData(d)
        for d in http_data.get('extract_references', [])
    ]
    return cls(status_assertion, headers_assertion, body_assertion,
               extract_references)
Beispiel #18
0
class AssertionTests(test_case.TestCase, parameterized.TestCase):
  @parameterized.parameters([
      (assertions.EqualsAssertion(''), '', True),
      (assertions.EqualsAssertion(''), 'asdf', False),
      (assertions.EqualsAssertion('asdf'), 'asdf', True),
      (assertions.EqualsAssertion('asdf'), 'qwer', False),

      (assertions.MatchesAssertion('asdf'), 'asdf', True),
      (assertions.MatchesAssertion('a.*'), 'asdf', True),
      (assertions.MatchesAssertion('b.*'), 'asdf', False),
      (assertions.MatchesAssertion(''), 'asdf', False),
      (assertions.MatchesAssertion('.*'), 'asdf', True),
      (assertions.MatchesAssertion('.*'), b'asdf', True),

      (assertions.IsNoneAssertion(True), None, True),
      (assertions.IsNoneAssertion(True), 'asdf', False),
      (assertions.IsNoneAssertion(True), True, False),
      (assertions.IsNoneAssertion(True), False, False),
      (assertions.IsNoneAssertion(True), 1, False),
      (assertions.IsNoneAssertion(False), None, False),
      (assertions.IsNoneAssertion(False), 'asdf', True),
      (assertions.IsNoneAssertion(False), True, True),
      (assertions.IsNoneAssertion(False), False, True),
      (assertions.IsNoneAssertion(False), 1, True),

      (assertions.InAssertion({1, 2, 3}), 1, True),
      (assertions.InAssertion({1, 2, 3}), 4, False),
      (assertions.InAssertion({1, 2, 3}), 'a', False),
      (assertions.InAssertion({1, 2, 3}), None, False),
      (assertions.InAssertion({'a', 'b', 'c'}), 'a', True),
      (assertions.InAssertion({'a', 'b', 'c'}), 'd', False),
      (assertions.InAssertion({'a', 'b', 'c'}), 1, False),
      (assertions.InAssertion({'a', 'b', 'c'}), None, False),

      (assertions.DictAssertion(), {}, True),
      (assertions.DictAssertion().Equals('a', 'b'), {}, False),
      (assertions.DictAssertion().Equals('a', 'b'), {'a': 'b'}, True),
      (assertions.DictAssertion().Equals('a', 'b'), {'a': 'c'}, False),

      (assertions.DictAssertion().Matches('a', 'b'), {}, False),
      (assertions.DictAssertion().Matches('a', 'b'), {'a': 'b'}, True),
      (assertions.DictAssertion().Matches('a', 'b'), {'a': 'c'}, False),
      (assertions.DictAssertion().Matches('a', '.*'), {'a': 'c'}, True),
      (assertions.DictAssertion().Matches(
          'a', 'as.*df'), {'a': 'asqwerdf'}, True),

      (assertions.DictAssertion().IsNone('a'), {}, True),
      (assertions.DictAssertion().IsNone('a'), {'a': 'b'}, False),

      (assertions.DictAssertion().In('a', ['1', '2', '3']), {}, False),
      (assertions.DictAssertion().In('a', ['1', '2', '3']), {'a': 'b'}, False),
      (assertions.DictAssertion().In('a', ['1', '2', '3']), {'a': '1'}, True),
  ])
  def testAssertion(self, assertion, actual, matches):
    if matches:
      with assertions.FailureCollector([]) as f:
        f.AddAll(assertion.Check(updates.Context.Empty(), actual))
    else:
      with self.assertRaises(assertions.Error):
        with assertions.FailureCollector([]) as f:
          f.AddAll(assertion.Check(updates.Context.Empty(), actual))

  @parameterized.parameters([
      (assertions.JsonAssertion().Matches('', {}), True),
      (assertions.JsonAssertion().Matches('', {'a': {}}), True),
      (assertions.JsonAssertion().Matches('', {'a': {'b': 'c'}}), True),
      (assertions.JsonAssertion().Matches('', {'a': {'b': 'c', 'f': 1}}), True),
      (assertions.JsonAssertion().Matches('', {'a': {'b': 'd'}}), False),
      (assertions.JsonAssertion().Matches('a.f', 1), True),
      (assertions.JsonAssertion().Matches('a.f', 2), False),
      (assertions.JsonAssertion().Matches('a.g', True), True),
      (assertions.JsonAssertion().Matches('a.g', False), False),
      (assertions.JsonAssertion().Matches('h.o.p', 'q'), True),
      (assertions.JsonAssertion().Matches('h.o.p', 'z'), False),
      (assertions.JsonAssertion().Matches('h.o', {'p': 'q'}), True),
      (assertions.JsonAssertion().Matches('list', {}), False),
      (assertions.JsonAssertion().Matches('list', []), False),
      (assertions.JsonAssertion().Matches('list', [1, 2]), False),
      (assertions.JsonAssertion().Matches('list', [{}, {}]), True),
      (assertions.JsonAssertion().Matches('list',
                                          [{'s': 't'}, {'y': 'z'}]), True),
      (assertions.JsonAssertion().Matches('list',
                                          [{'s': 't'}, {'y': 'x'}]), False),
      (assertions.JsonAssertion().Matches('list',
                                          [{'s': 't'}, {'z': 'asdf'}]), False),
      (assertions.JsonAssertion().Matches('list',
                                          [{'s': 't'}, {'y': 'z'},
                                           {'asdf', 'asdf'}]), False),
      (assertions.JsonAssertion().Matches('a.f', 1).Matches('a.b', 'c'), True),
      (assertions.JsonAssertion().Matches('a.f', 1).IsAbsent('a.x'), True),
      (assertions.JsonAssertion().Matches('a.f', 1).IsAbsent('a.d'), False),
      (assertions.JsonAssertion().Matches('n_l.l.a', [1, 3, 5]), True),
      (assertions.JsonAssertion().Matches('n_l.l.b', [2, 3]), False),
      (assertions.JsonAssertion().Matches('n_l.l.c', [0, 0]), False),
      (assertions.JsonAssertion().Matches('n_l.l', [{'a': 1, 'b': 2},
                                                    {'a': 3, 'b': 4},
                                                    {'a': 5, 'b': 6}]), True),
  ])
  def testCheckJsonContent(self, assertion, matches):
    actual = {
        'a': {'b': 'c', 'd': 'e', 'f': 1, 'g': True},
        'h': {
            'i': {'j': 'k', 'l': 'm'},
            'o': {'p': 'q', 'r': 'r'},
        },
        'list': [
            {'s': 't', 'u': 'v'},
            {'w': 'x', 'y': 'z'},
        ],
        'n_l': {'l': [
            {'a': 1, 'b': 2}, {'a': 3, 'b': 4}, {'a': 5, 'b': 6}
        ]}
    }
    if matches:
      with assertions.FailureCollector([]) as f:
        f.AddAll(assertion.Check(updates.Context.Empty(), actual))
    else:
      with self.assertRaises(assertions.Error):
        with assertions.FailureCollector([]) as f:
          f.AddAll(assertion.Check(updates.Context.Empty(), actual))

  def testJsonUpdate(self):
    actual = {
        'foo': 'bar',
        'a': {'b': 'c', 'd': 'e'},
        'h': {
            'i': {'j': 'k', 'l': 'm'},
        },
        'scalar_list': ['s', 't', 'u'],
        'dict_list': [
            {'s': 't', 'u': 'v'},
            {'w': 'x', 'y': 'z'},
        ],
        'diff_len_lists': [{'a': 'b'}, 'b', 'c'],
    }
    assertion_data = {
        'foo': 'X',
        'a': {'b': 'X'},
        'h': {'i': {'j': 'X'}},
        'scalar_list': ['s', 'X', 'u'],
        'dict_list': [{'s': 'X', 'u': 'v'}, {'w': 'x', 'y': 'X'},],
        'diff_len_lists': ['X'],
    }
    assertion = assertions.JsonAssertion()
    for field, struct in assertion_data.items():
      assertion.Matches(field, struct)

    context = updates.Context(
        {'data': assertion_data}, 'data', updates.Mode.RESULT)
    failures = assertion.Check(context, actual)
    self.assertEqual(7, len(failures))

    for f in failures:
      f.Update([updates.Mode.RESULT])
    self.assertEqual('bar', assertion_data['foo'])
    self.assertEqual('c', assertion_data['a']['b'])
    self.assertEqual('k', assertion_data['h']['i']['j'])
    self.assertEqual('t', assertion_data['scalar_list'][1])
    self.assertEqual('t', assertion_data['dict_list'][0]['s'])
    self.assertEqual('z', assertion_data['dict_list'][1]['y'])
    self.assertEqual([{'a': 'b'}, 'b', 'c'], assertion_data['diff_len_lists'])
Beispiel #19
0
 def CheckRepeatable(self):
   return assertions.EqualsAssertion(self._is_repeatable).Check(
       self._update_context.ForKey('repeatable'), self._was_repeated)