]> git.ipfire.org Git - thirdparty/patchwork.git/commitdiff
tests: Provide a way to disable API schema
authorStephen Finucane <stephen@that.guru>
Sat, 30 Nov 2019 18:48:35 +0000 (18:48 +0000)
committerStephen Finucane <stephen@that.guru>
Tue, 24 Dec 2019 11:15:21 +0000 (11:15 +0000)
The API schema validation is strict, in that it will error out with
invalid keys in either the request or response. Unfortunately the API
itself is not. We're hopefully going to fix this in a distant v2.0, but
for now we need a way to ensure that the API does what it's supposed to,
namely not set fields that don't exist or that the user isn't allowed to
set, even if proper error codes aren't raised.

This isn't actually used yet. That will come later.

Signed-off-by: Stephen Finucane <stephen@that.guru>
patchwork/tests/api/utils.py
patchwork/tests/api/validator.py

index 0c232d04b5da21359ebb63e6a5de699b7ffe7c8d..c405f737bf63ae14798d2c776eaf24b1fff4fcdb 100644 (file)
@@ -112,44 +112,68 @@ class APIClient(BaseAPIClient):
         self.factory = APIRequestFactory()
 
     def get(self, path, data=None, follow=False, **extra):
+        validate_request = extra.pop('validate_request', True)
+        validate_response = extra.pop('validate_response', True)
+
         request = self.factory.get(
             path, data=data, SERVER_NAME='example.com', **extra)
         response = super(APIClient, self).get(
             path, data=data, follow=follow, SERVER_NAME='example.com', **extra)
-        validator.validate_data(path, request, response)
+
+        validator.validate_data(path, request, response, validate_request,
+                                validate_response)
+
         return response
 
     def post(self, path, data=None, format=None, content_type=None,
              follow=False, **extra):
+        validate_request = extra.pop('validate_request', True)
+        validate_response = extra.pop('validate_response', True)
+
         request = self.factory.post(
             path, data=data, format='json', content_type=content_type,
             SERVER_NAME='example.com', **extra)
         response = super(APIClient, self).post(
             path, data=data, format='json', content_type=content_type,
             follow=follow, SERVER_NAME='example.com', **extra)
-        validator.validate_data(path, request, response)
+
+        validator.validate_data(path, request, response, validate_request,
+                                validate_response)
+
         return response
 
     def put(self, path, data=None, format=None, content_type=None,
             follow=False, **extra):
+        validate_request = extra.pop('validate_request', True)
+        validate_response = extra.pop('validate_response', True)
+
         request = self.factory.put(
             path, data=data, format='json', content_type=content_type,
             SERVER_NAME='example.com', **extra)
         response = super(APIClient, self).put(
             path, data=data, format='json', content_type=content_type,
             follow=follow, SERVER_NAME='example.com', **extra)
-        validator.validate_data(path, request, response)
+
+        validator.validate_data(path, request, response, validate_request,
+                                validate_response)
+
         return response
 
     def patch(self, path, data=None, format=None, content_type=None,
               follow=False, **extra):
+        validate_request = extra.pop('validate_request', True)
+        validate_response = extra.pop('validate_response', True)
+
         request = self.factory.patch(
             path, data=data, format='json', content_type=content_type,
             SERVER_NAME='example.com', **extra)
         response = super(APIClient, self).patch(
             path, data=data, format='json', content_type=content_type,
             follow=follow, SERVER_NAME='example.com', **extra)
-        validator.validate_data(path, request, response)
+
+        validator.validate_data(path, request, response, validate_request,
+                                validate_response)
+
         return response
 
 
index ad4d7f156cbe222149287d75d8aed966c46243da..9cead2923f44f892985520cd8e20282d9f03f0de 100644 (file)
@@ -291,7 +291,8 @@ class DRFOpenAPIResponse(BaseOpenAPIResponse):
         return 'application/json'
 
 
-def validate_data(path, request, response):
+def validate_data(path, request, response, validate_request,
+                  validate_response):
     if response.status_code == status.HTTP_405_METHOD_NOT_ALLOWED:
         return
 
@@ -300,18 +301,23 @@ def validate_data(path, request, response):
     response = DRFOpenAPIResponse(response)
 
     # request
-    validator = RequestValidator(spec, custom_formatters=CUSTOM_FORMATTERS)
-    result = validator.validate(request)
-    try:
-        result.raise_for_errors()
-    except OpenAPIMediaTypeError:
-        assert response.status_code == status.HTTP_400_BAD_REQUEST
-    except OpenAPIParameterError:
-        # TODO(stephenfin): In API v2.0, this should be an error. As things
-        # stand, we silently ignore these issues.
-        assert response.status_code == status.HTTP_200_OK
+    if validate_request:
+        validator = RequestValidator(
+            spec, custom_formatters=CUSTOM_FORMATTERS)
+        result = validator.validate(request)
+        try:
+            result.raise_for_errors()
+        except OpenAPIMediaTypeError:
+            if response.status_code != status.HTTP_400_BAD_REQUEST:
+                raise
+        except OpenAPIParameterError:
+            # TODO(stephenfin): In API v2.0, this should be an error. As things
+            # stand, we silently ignore these issues.
+            assert response.status_code == status.HTTP_200_OK
 
     # response
-    validator = ResponseValidator(spec, custom_formatters=CUSTOM_FORMATTERS)
-    result = validator.validate(request, response)
-    result.raise_for_errors()
+    if validate_response:
+        validator = ResponseValidator(
+            spec, custom_formatters=CUSTOM_FORMATTERS)
+        result = validator.validate(request, response)
+        result.raise_for_errors()