diff options
author | Milo Casagrande <milo.casagrande@linaro.org> | 2015-03-06 16:41:18 +0100 |
---|---|---|
committer | Milo Casagrande <milo.casagrande@linaro.org> | 2015-03-06 16:41:18 +0100 |
commit | 7e5d4a29da65b9bda84ec249db82a8053547ba02 (patch) | |
tree | c74c662af634de287922c58eb11af91f97cbf52f | |
parent | 02cca3c56a9e7d4d84f9be190efe499587ee843b (diff) |
Complete test suite handler.
* More work is still necessary to implement the test sets and
test cases import logic.
* Add tests.
-rw-r--r-- | app/handlers/common.py | 14 | ||||
-rw-r--r-- | app/handlers/test_suite.py | 139 | ||||
-rw-r--r-- | app/handlers/tests/test_test_suite_handler.py | 300 |
3 files changed, 440 insertions, 13 deletions
diff --git a/app/handlers/common.py b/app/handlers/common.py index 05f6834..c5972ed 100644 --- a/app/handlers/common.py +++ b/app/handlers/common.py @@ -363,6 +363,20 @@ TEST_SUITE_VALID_KEYS = { models.VERSION_KEY ] }, + "PUT": [ + models.ARCHITECTURE_KEY, + models.BOARD_INSTANCE_KEY, + models.BOARD_KEY, + models.BOOT_ID_KEY, + models.DEFCONFIG_FULL_KEY, + models.DEFCONFIG_ID_KEY, + models.DEFCONFIG_KEY, + models.JOB_ID_KEY, + models.JOB_KEY, + models.KERNEL_KEY, + models.METADATA_KEY, + models.NAME_KEY + ], "GET": [ models.ARCHITECTURE_KEY, models.BOARD_INSTANCE_KEY, diff --git a/app/handlers/test_suite.py b/app/handlers/test_suite.py index c7ce574..1813c96 100644 --- a/app/handlers/test_suite.py +++ b/app/handlers/test_suite.py @@ -13,6 +13,11 @@ """The RequestHandler for /test/suite URLs.""" +try: + import simplejson as json +except ImportError: + import json + import bson import datetime import types @@ -23,9 +28,12 @@ import handlers.response as hresponse import models import models.test_suite as mtsuite import utils.db +import utils.validator as validator +# pylint: disable=too-many-public-methods class TestSuiteHandler(hbase.BaseHandler): + """The test suite request handler.""" def __init__(self, application, request, **kwargs): super(TestSuiteHandler, self).__init__(application, request, **kwargs) @@ -71,17 +79,144 @@ class TestSuiteHandler(hbase.BaseHandler): response.messages = ( "Associated test sets will be parsed and imported") # TODO: import async the test sets. - pass if all([test_case, isinstance(test_case, types.ListType)]): response.status_code = 202 response.messages = ( "Associated test cases will be parsed and imported") # TODO: import async the test cases. - pass else: response.status_code = 500 response.reason = ( "Error saving test set '%s'" % test_suite.name) return response + + def execute_put(self, *args, **kwargs): + """Execute the PUT pre-operations.""" + response = None + + if self.validate_req_token("PUT"): + if kwargs and kwargs.get("id", None): + valid_request = self._valid_post_request() + + if valid_request == 200: + try: + json_obj = json.loads(self.request.body.decode("utf8")) + + valid_json, j_reason = validator.is_valid_json( + json_obj, self._valid_keys("PUT") + ) + if valid_json: + kwargs["json_obj"] = json_obj + kwargs["db_options"] = self.settings["dboptions"] + kwargs["reason"] = j_reason + response = self._put(*args, **kwargs) + else: + response = hresponse.HandlerResponse(400) + if j_reason: + response.reason = ( + "Provided JSON is not valid: %s" % j_reason + ) + else: + response.reason = "Provided JSON is not valid" + response.result = None + except ValueError, ex: + self.log.exception(ex) + error = "No JSON data found in the PUT request" + self.log.error(error) + response = hresponse.HandlerResponse(422) + response.reason = error + response.result = None + else: + response = hresponse.HandlerResponse(valid_request) + response.reason = ( + "%s: %s" % + ( + self._get_status_message(valid_request), + "Use %s as the content type" % self.content_type + ) + ) + response.result = None + else: + response = hresponse.HandlerResponse(400) + response.reason = "No ID specified" + else: + response = hresponse.HandlerResponse(403) + response.reason = hcommon.NOT_VALID_TOKEN + + return response + + def _put(self, *args, **kwargs): + response = hresponse.HandlerResponse() + update_doc = kwargs.get("json_obj") + doc_id = kwargs.get("id") + + try: + suite_id = bson.objectid.ObjectId(doc_id) + if utils.db.find_one2(self.collection, suite_id): + update_val = utils.db.update( + self.collection, suite_id, update_doc) + + if update_val == 200: + response.reason = "Resource '%s' updated" % doc_id + else: + response.status_code = update_val + response.reason = "Error updating resource '%s'" % doc_id + else: + response.status_code = 404 + response.reason = self._get_status_message(404) + except bson.errors.InvalidId, ex: + self.log.exception(ex) + self.log.error("Invalid ID specified: %s", doc_id) + response.status_code = 400 + response.reason = "Wrong ID specified" + return response + + def _delete(self, doc_id): + response = hresponse.HandlerResponse() + response.result = None + + try: + suite_id = bson.objectid.ObjectId(doc_id) + if utils.db.find_one2(self.collection, suite_id): + response.status_code = utils.db.delete( + self.collection, suite_id) + + if response.status_code == 200: + response.reason = "Resource '%s' deleted" % doc_id + + test_set_canc = utils.db.delete( + self.db[models.TEST_SET_COLLECTION], + {models.TEST_SUITE_ID_KEY: {"$in": [suite_id]}} + ) + + test_case_canc = utils.db.delete( + self.db[models.TEST_CASE_COLLECTION], + {models.TEST_SUITE_ID_KEY: {"$in": [suite_id]}} + ) + + if test_case_canc != 200: + response.errors = ( + "Error deleting test cases with " + "test_suite_id '%s'" % + doc_id + ) + if test_set_canc != 200: + response.errors = ( + "Error deleting test sets with " + "test_suite_id '%s'" % + doc_id + ) + else: + response.reason = "Error deleting resource '%s'" % doc_id + else: + response.status_code = 404 + response.reason = self._get_status_message(404) + except bson.errors.InvalidId, ex: + self.log.exception(ex) + self.log.error("Invalid ID specified: %s", doc_id) + response.status_code = 400 + response.reason = "Wrong ID specified" + + return response diff --git a/app/handlers/tests/test_test_suite_handler.py b/app/handlers/tests/test_test_suite_handler.py index b26da19..0117d55 100644 --- a/app/handlers/tests/test_test_suite_handler.py +++ b/app/handlers/tests/test_test_suite_handler.py @@ -138,8 +138,7 @@ class TestTestSuiteHandler( headers = {"Authorization": "foo", "Content-Type": "application/json"} response = self.fetch( - "/test/suite", method="POST", body="", headers=headers - ) + "/test/suite", method="POST", body="", headers=headers) self.assertEqual(response.code, 422) self.assertEqual( @@ -149,8 +148,7 @@ class TestTestSuiteHandler( headers = {"Authorization": "foo"} response = self.fetch( - "/test/suite", method="POST", body="", headers=headers - ) + "/test/suite", method="POST", body="", headers=headers) self.assertEqual(response.code, 415) self.assertEqual( @@ -162,8 +160,7 @@ class TestTestSuiteHandler( body = json.dumps(dict(foo="foo", bar="bar")) response = self.fetch( - "/test/suite", method="POST", body=body, headers=headers - ) + "/test/suite", method="POST", body=body, headers=headers) self.assertEqual(response.code, 400) self.assertEqual( @@ -172,10 +169,77 @@ class TestTestSuiteHandler( @mock.patch("utils.db.save") def test_post_correct(self, mock_save): mock_save.return_value = (201, "test-suite-id") - headers = { - "Authorization": "foo", - "Content-Type": "application/json", - } + headers = {"Authorization": "foo", "Content-Type": "application/json"} + + body = json.dumps( + dict( + name="test", + lab_name="lab_name", version="1.0", defconfig_id="defconfig") + ) + + response = self.fetch( + "/test/suite", method="POST", headers=headers, body=body + ) + + self.assertEqual(response.code, 201) + self.assertEqual( + response.headers["Content-Type"], DEFAULT_CONTENT_TYPE) + + def test_post_correct_with_id(self): + headers = {"Authorization": "foo", "Content-Type": "application/json"} + body = json.dumps( + dict( + name="suite", + version="1.0", lab_name="lab", defconfig_id="defconfig") + ) + + response = self.fetch( + "/test/suite/fake-id", method="POST", headers=headers, body=body) + + self.assertEqual(response.code, 400) + self.assertEqual( + response.headers["Content-Type"], DEFAULT_CONTENT_TYPE) + + def test_post_correct_with_test_set(self): + headers = {"Authorization": "foo", "Content-Type": "application/json"} + body = json.dumps( + dict( + name="suite", + version="1.0", + lab_name="lab", + defconfig_id="defconfig", test_set=[{"foo": "bar"}] + ) + ) + + response = self.fetch( + "/test/suite", method="POST", headers=headers, body=body) + + self.assertEqual(response.code, 202) + self.assertEqual( + response.headers["Content-Type"], DEFAULT_CONTENT_TYPE) + + def test_post_correct_with_test_case(self): + headers = {"Authorization": "foo", "Content-Type": "application/json"} + body = json.dumps( + dict( + name="suite", + version="1.0", + lab_name="lab", + defconfig_id="defconfig", test_case=[{"foo": "bar"}] + ) + ) + + response = self.fetch( + "/test/suite", method="POST", headers=headers, body=body) + + self.assertEqual(response.code, 202) + self.assertEqual( + response.headers["Content-Type"], DEFAULT_CONTENT_TYPE) + + @mock.patch("utils.db.save") + def test_post_correct_with_error(self, mock_save): + mock_save.return_value = (500, None) + headers = {"Authorization": "foo", "Content-Type": "application/json"} body = json.dumps( dict( @@ -187,6 +251,220 @@ class TestTestSuiteHandler( "/test/suite", method="POST", headers=headers, body=body ) - self.assertEqual(response.code, 201) + self.assertEqual(response.code, 500) + self.assertEqual( + response.headers["Content-Type"], DEFAULT_CONTENT_TYPE) + + def test_put_no_token(self): + response = self.fetch("/test/suite/id", method="PUT", body="") + + self.assertEqual(response.code, 403) + self.assertEqual( + response.headers["Content-Type"], DEFAULT_CONTENT_TYPE) + + def test_put_wrong_token(self): + headers = {"Authorization": "foo", "Content-Type": "application/json"} + self.validate_token.return_value = False + + response = self.fetch( + "/test/suite/id", method="PUT", headers=headers, body="" + ) + + self.assertEqual(response.code, 403) + self.assertEqual( + response.headers["Content-Type"], DEFAULT_CONTENT_TYPE) + + def test_put_wrong_content_type(self): + headers = {"Authorization": "foo"} + + response = self.fetch( + "/test/suite/id", method="PUT", body="", headers=headers) + + self.assertEqual(response.code, 415) + self.assertEqual( + response.headers["Content-Type"], DEFAULT_CONTENT_TYPE) + + def test_put_no_id(self): + headers = {"Authorization": "foo", "Content-Type": "application/json"} + + response = self.fetch( + "/test/suite/", method="PUT", headers=headers, body="" + ) + + self.assertEqual(response.code, 400) + self.assertEqual( + response.headers["Content-Type"], DEFAULT_CONTENT_TYPE) + + def test_put_no_valid_json(self): + headers = {"Authorization": "foo", "Content-Type": "application/json"} + + body = json.dumps(dict(foo="foo", bar="bar")) + + response = self.fetch( + "/test/suite/id", method="PUT", body=body, headers=headers + ) + + self.assertEqual(response.code, 400) + self.assertEqual( + response.headers["Content-Type"], DEFAULT_CONTENT_TYPE) + + def test_put_no_json_data(self): + headers = {"Authorization": "foo", "Content-Type": "application/json"} + + response = self.fetch( + "/test/suite/id", method="PUT", body="", headers=headers + ) + + self.assertEqual(response.code, 422) + self.assertEqual( + response.headers["Content-Type"], DEFAULT_CONTENT_TYPE) + + def test_put_no_valid_id(self): + headers = {"Authorization": "foo", "Content-Type": "application/json"} + + body = json.dumps(dict(job="job", kernel="kernel")) + + response = self.fetch( + "/test/suite/wrong-id", method="PUT", body=body, headers=headers + ) + + self.assertEqual(response.code, 400) + self.assertEqual( + response.headers["Content-Type"], DEFAULT_CONTENT_TYPE) + + @mock.patch("utils.db.find_one2") + @mock.patch("bson.objectid.ObjectId") + def test_put_id_not_found(self, mock_id, mock_find): + mock_id.return_value = "fake-id" + mock_find.return_value = None + headers = {"Authorization": "foo", "Content-Type": "application/json"} + + body = json.dumps(dict(job="job", kernel="kernel")) + + response = self.fetch( + "/test/suite/wrong-id", method="PUT", body=body, headers=headers + ) + + self.assertEqual(response.code, 404) + self.assertEqual( + response.headers["Content-Type"], DEFAULT_CONTENT_TYPE) + + @mock.patch("utils.db.update") + @mock.patch("utils.db.find_one2") + @mock.patch("bson.objectid.ObjectId") + def test_put_valid_no_error(self, mock_id, mock_find, mock_update): + mock_id.return_value = "fake-id" + mock_find.return_value = {"_id": "fake-id", "job": "bar"} + mock_update.return_value = 200 + headers = {"Authorization": "foo", "Content-Type": "application/json"} + + body = json.dumps(dict(job="job", kernel="kernel")) + + response = self.fetch( + "/test/suite/fake-id", method="PUT", body=body, headers=headers) + + self.assertEqual(response.code, 200) + self.assertEqual( + response.headers["Content-Type"], DEFAULT_CONTENT_TYPE) + + @mock.patch("utils.db.update") + @mock.patch("utils.db.find_one2") + @mock.patch("bson.objectid.ObjectId") + def test_put_valid_with_error(self, mock_id, mock_find, mock_update): + mock_id.return_value = "fake-id" + mock_find.return_value = {"_id": "fake-id", "job": "bar"} + mock_update.return_value = 500 + headers = {"Authorization": "foo", "Content-Type": "application/json"} + + body = json.dumps(dict(job="job", kernel="kernel")) + + response = self.fetch( + "/test/suite/fake-id", method="PUT", body=body, headers=headers) + + self.assertEqual(response.code, 500) + self.assertEqual( + response.headers["Content-Type"], DEFAULT_CONTENT_TYPE) + + def test_delete_no_token(self): + response = self.fetch("/test/suite/id", method="DELETE") + + self.assertEqual(response.code, 403) + self.assertEqual( + response.headers["Content-Type"], DEFAULT_CONTENT_TYPE) + + def test_delete_wrong_token(self): + headers = {"Authorization": "foo"} + self.validate_token.return_value = False + + response = self.fetch( + "/test/suite/id", method="DELETE", headers=headers) + + self.assertEqual(response.code, 403) + self.assertEqual( + response.headers["Content-Type"], DEFAULT_CONTENT_TYPE) + + def test_delete_no_id(self): + headers = {"Authorization": "foo"} + + response = self.fetch( + "/test/suite/", method="DELETE", headers=headers) + + self.assertEqual(response.code, 400) + self.assertEqual( + response.headers["Content-Type"], DEFAULT_CONTENT_TYPE) + + def test_delete_wrong_id(self): + headers = {"Authorization": "foo"} + + response = self.fetch( + "/test/suite/wrong-id", method="DELETE", headers=headers) + + self.assertEqual(response.code, 400) + self.assertEqual( + response.headers["Content-Type"], DEFAULT_CONTENT_TYPE) + + @mock.patch("utils.db.find_one2") + @mock.patch("bson.objectid.ObjectId") + def test_delete_correct_not_found(self, mock_id, mock_find): + mock_id.return_value = "fake-id" + mock_find.return_value = None + headers = {"Authorization": "foo"} + + response = self.fetch( + "/test/suite/fake-id", method="DELETE", headers=headers) + + self.assertEqual(response.code, 404) + self.assertEqual( + response.headers["Content-Type"], DEFAULT_CONTENT_TYPE) + + @mock.patch("utils.db.delete") + @mock.patch("utils.db.find_one2") + @mock.patch("bson.objectid.ObjectId") + def test_delete_correct_with_error(self, mock_id, mock_find, mock_delete): + mock_id.return_value = "fake-id" + mock_find.return_value = {"_id": "fake-id"} + mock_delete.return_value = 500 + headers = {"Authorization": "foo"} + + response = self.fetch( + "/test/suite/fake-id", method="DELETE", headers=headers) + + self.assertEqual(response.code, 500) + self.assertEqual( + response.headers["Content-Type"], DEFAULT_CONTENT_TYPE) + + @mock.patch("utils.db.delete") + @mock.patch("utils.db.find_one2") + @mock.patch("bson.objectid.ObjectId") + def test_delete_correct(self, mock_id, mock_find, mock_delete): + mock_id.return_value = "fake-id" + mock_find.return_value = {"_id": "fake-id"} + mock_delete.side_effect = [200, 500, 500] + headers = {"Authorization": "foo"} + + response = self.fetch( + "/test/suite/fake-id", method="DELETE", headers=headers) + + self.assertEqual(response.code, 200) self.assertEqual( response.headers["Content-Type"], DEFAULT_CONTENT_TYPE) |