Beispiel #1
0
    def setUp(self):
        super(RouterMatcherTest, self).setUp()
        self.config_overrider = test_lib.ConfigOverrider(
            {"API.DefaultRouter": TestHttpApiRouter.__name__})
        self.config_overrider.Start()

        self.router_matcher = http_api.RouterMatcher()
Beispiel #2
0
    def setUp(self):
        super(RouterMatcherTest, self).setUp()
        self.config_overrider = test_lib.ConfigOverrider(
            {"API.DefaultRouter": TestHttpApiRouter.__name__})
        self.config_overrider.Start()
        # Make sure ApiAuthManager is initialized with this configuration setting.
        api_auth_manager.APIACLInit.InitApiAuthManager()

        self.router_matcher = http_api.RouterMatcher()
Beispiel #3
0
    def Check(self, method, url, payload=None, replace=None):
        """Records output of a given url accessed with a given method.

    Args:
      method: HTTP method. May be "GET" or "POST".
      url: String repesenting an url.
      payload: JSON-able payload that will be sent when "POST" method is used.
      replace: Dictionary of key->value pairs. In the recorded JSON output
               every "key" string will be replaced with its "value"
               counterpart. This way we can properly handle dynamically
               generated values (like hunts IDs) in the regression data.
    Raises:
      ValueError: if unsupported method argument is passed. Currently only
                  "GET", "POST", "DELETE" and "PATCH" are supported.
      RuntimeError: if request was handled by an unexpected API method (
                  every test is annotated with an "api_method" attribute
                  that points to the expected API method).
    """
        if self.use_api_v2:
            url = url.replace("/api/", "/api/v2/")

        parsed_url = urlparse.urlparse(url)
        request = utils.DataObject(method=method,
                                   scheme="http",
                                   path=parsed_url.path,
                                   environ={
                                       "SERVER_NAME": "foo.bar",
                                       "SERVER_PORT": 1234
                                   },
                                   user=self.token.username,
                                   body="")
        request.META = {"CONTENT_TYPE": "application/json"}

        if method == "GET":
            request.GET = dict(urlparse.parse_qsl(parsed_url.query))
        elif method in ["POST", "DELETE", "PATCH"]:
            # NOTE: this is a temporary trick. Payloads in regression tests
            # are using the API v1 (non-proto3) format. Here we're reparsing
            # them and serializing as proto3 JSON.
            # TODO(user): Make regression tests payload format-agnostic.
            # I.e. use protobuf and API client library to send requests.
            if self.use_api_v2 and payload:
                router_matcher = http_api.RouterMatcher()
                _, metadata, _ = router_matcher.MatchRouter(request)

                rdf_args = metadata.args_type()
                rdf_args.FromDict(payload)
                proto_args = metadata.args_type.protobuf()
                proto_args.ParseFromString(rdf_args.SerializeToString())

                request.body = json_format.MessageToJson(proto_args)
                payload = json.loads(request.body)
            else:
                request.body = json.dumps(payload or "")
        else:
            raise ValueError("Unsupported method: %s." % method)

        with self.NoAuthorizationChecks():
            http_response = http_api.RenderHttpResponse(request)

        api_method = http_response["X-API-Method"]
        if api_method != self.__class__.api_method:
            raise RuntimeError("Request was handled by an unexpected method. "
                               "Expected %s, got %s." %
                               (self.__class__.api_method, api_method))

        if hasattr(http_response, "streaming_content"):
            # We don't know the nature of response content, but we force it to be
            # unicode. It's a strategy that's good enough for testing purposes.
            content = utils.SmartUnicode("".join(
                http_response.streaming_content))
        else:
            content = http_response.content

        xssi_token = ")]}'\n"
        if content.startswith(xssi_token):
            content = content[len(xssi_token):]

        # replace the values of all tracebacks by <traceback content>
        regex = re.compile(r'"traceBack": "Traceback[^"\\]*(?:\\.[^"\\]*)*"',
                           re.DOTALL)
        content = regex.sub('"traceBack": "<traceback content>"', content)

        if replace:
            if hasattr(replace, "__call__"):
                replace = replace()

            # We reverse sort replacements by length to avoid cases when
            # replacements include each other and therefore order
            # of replacements affects the result.
            for substr in sorted(replace, key=len, reverse=True):
                repl = replace[substr]

                if hasattr(substr, "sub"):  # regex
                    content = substr.sub(repl, content)
                    url = substr.sub(repl, url)
                else:
                    content = content.replace(substr, repl)
                    url = url.replace(substr, repl)

        # We treat streaming content purely as strings and don't expect it to
        # contain JSON data.
        if hasattr(http_response, "streaming_content"):
            parsed_content = content
        else:
            parsed_content = json.loads(content)

        check_result = dict(api_method=api_method,
                            method=method,
                            url=url,
                            test_class=self.__class__.__name__,
                            response=parsed_content)

        if payload:
            check_result["request_payload"] = payload

        # Type stripping only makes sense for version 1 of the API.
        if not self.use_api_v2:
            stripped_content = api_value_renderers.StripTypeInfo(
                parsed_content)
            if parsed_content != stripped_content:
                check_result["type_stripped_response"] = stripped_content

        self.checks.append(check_result)