Add tests for /compose API
Because you cannot share data between test methods these have to all be in one big function. This adds one series to test the failed compose results, and a 2nd function to test for the successful compose.
This commit is contained in:
		
							parent
							
								
									daa5ed2aaf
								
							
						
					
					
						commit
						fdecf13299
					
				| @ -15,14 +15,17 @@ | |||||||
| # along with this program.  If not, see <http://www.gnu.org/licenses/>. | # along with this program.  If not, see <http://www.gnu.org/licenses/>. | ||||||
| # | # | ||||||
| import os | import os | ||||||
|  | from glob import glob | ||||||
| import shutil | import shutil | ||||||
| import tempfile | import tempfile | ||||||
|  | import time | ||||||
| from threading import Lock | from threading import Lock | ||||||
| import unittest | import unittest | ||||||
| 
 | 
 | ||||||
| from flask import json | from flask import json | ||||||
| import pytoml as toml | import pytoml as toml | ||||||
| from pylorax.api.config import configure, make_yum_dirs | from pylorax.api.config import configure, make_yum_dirs, make_queue_dirs | ||||||
|  | from pylorax.api.queue import start_queue_monitor | ||||||
| from pylorax.api.recipes import open_or_create_repo, commit_recipe_directory | from pylorax.api.recipes import open_or_create_repo, commit_recipe_directory | ||||||
| from pylorax.api.server import server, GitLock, YumLock | from pylorax.api.server import server, GitLock, YumLock | ||||||
| from pylorax.api.yumbase import get_base_object | from pylorax.api.yumbase import get_base_object | ||||||
| @ -38,6 +41,11 @@ class ServerTestCase(unittest.TestCase): | |||||||
|         server.config["GITLOCK"] = GitLock(repo=repo, lock=Lock(), dir=repo_dir) |         server.config["GITLOCK"] = GitLock(repo=repo, lock=Lock(), dir=repo_dir) | ||||||
| 
 | 
 | ||||||
|         server.config["COMPOSER_CFG"] = configure(root_dir=repo_dir, test_config=True) |         server.config["COMPOSER_CFG"] = configure(root_dir=repo_dir, test_config=True) | ||||||
|  |         os.makedirs(joinpaths(server.config["COMPOSER_CFG"].get("composer", "share_dir"), "composer")) | ||||||
|  |         errors = make_queue_dirs(server.config["COMPOSER_CFG"], 0) | ||||||
|  |         if errors: | ||||||
|  |             raise RuntimeError("\n".join(errors)) | ||||||
|  | 
 | ||||||
|         make_yum_dirs(server.config["COMPOSER_CFG"]) |         make_yum_dirs(server.config["COMPOSER_CFG"]) | ||||||
|         yb = get_base_object(server.config["COMPOSER_CFG"]) |         yb = get_base_object(server.config["COMPOSER_CFG"]) | ||||||
|         server.config["YUMLOCK"] = YumLock(yb=yb, lock=Lock()) |         server.config["YUMLOCK"] = YumLock(yb=yb, lock=Lock()) | ||||||
| @ -47,9 +55,16 @@ class ServerTestCase(unittest.TestCase): | |||||||
| 
 | 
 | ||||||
|         self.examples_path = "./tests/pylorax/recipes/" |         self.examples_path = "./tests/pylorax/recipes/" | ||||||
| 
 | 
 | ||||||
|  |         # Copy the shared files over to the directory tree we are using | ||||||
|  |         share_path = "./share/composer/" | ||||||
|  |         for f in glob(joinpaths(share_path, "*")): | ||||||
|  |             shutil.copy(f, joinpaths(server.config["COMPOSER_CFG"].get("composer", "share_dir"), "composer")) | ||||||
|  | 
 | ||||||
|         # Import the example recipes |         # Import the example recipes | ||||||
|         commit_recipe_directory(server.config["GITLOCK"].repo, "master", self.examples_path) |         commit_recipe_directory(server.config["GITLOCK"].repo, "master", self.examples_path) | ||||||
| 
 | 
 | ||||||
|  |         start_queue_monitor(server.config["COMPOSER_CFG"], 0, 0) | ||||||
|  | 
 | ||||||
|     @classmethod |     @classmethod | ||||||
|     def tearDownClass(self): |     def tearDownClass(self): | ||||||
|         shutil.rmtree(server.config["REPO_DIR"]) |         shutil.rmtree(server.config["REPO_DIR"]) | ||||||
| @ -502,3 +517,204 @@ class ServerTestCase(unittest.TestCase): | |||||||
|         resp = self.server.get("/api/docs/modules.html") |         resp = self.server.get("/api/docs/modules.html") | ||||||
|         doc_str = open(os.path.abspath(joinpaths(os.path.dirname(__file__), "../../docs/html/modules.html"))).read() |         doc_str = open(os.path.abspath(joinpaths(os.path.dirname(__file__), "../../docs/html/modules.html"))).read() | ||||||
|         self.assertEqual(doc_str, resp.data) |         self.assertEqual(doc_str, resp.data) | ||||||
|  | 
 | ||||||
|  |     def wait_for_status(self, uuid, wait_status): | ||||||
|  |         """Helper function that waits for a status | ||||||
|  | 
 | ||||||
|  |         :param uuid: UUID of the build to check | ||||||
|  |         :type uuid: str | ||||||
|  |         :param wait_status: List of statuses to exit on | ||||||
|  |         :type wait_status: list of str | ||||||
|  |         :returns: True if status was found, False if it timed out | ||||||
|  |         :rtype: bool | ||||||
|  | 
 | ||||||
|  |         This will time out after 60 seconds | ||||||
|  |         """ | ||||||
|  |         start = time.time() | ||||||
|  |         while True: | ||||||
|  |             resp = self.server.get("/api/v0/compose/info/%s" % uuid) | ||||||
|  |             data = json.loads(resp.data) | ||||||
|  |             self.assertNotEqual(data, None) | ||||||
|  |             queue_status = data.get("queue_status") | ||||||
|  |             if queue_status in wait_status: | ||||||
|  |                 return True | ||||||
|  |             if time.time() > start + 60: | ||||||
|  |                 return False | ||||||
|  |             time.sleep(5) | ||||||
|  | 
 | ||||||
|  |     def test_compose_01_types(self): | ||||||
|  |         """Test the /api/v0/compose/types route""" | ||||||
|  |         resp = self.server.get("/api/v0/compose/types") | ||||||
|  |         data = json.loads(resp.data) | ||||||
|  |         self.assertNotEqual(data, None) | ||||||
|  |         self.assertEqual({"name": "tar", "enabled": True} in data["types"], True) | ||||||
|  | 
 | ||||||
|  |     def test_compose_02_create_failed(self): | ||||||
|  |         """Test the /api/v0/compose routes with a failed test compose""" | ||||||
|  |         test_compose = {"recipe_name": "glusterfs", | ||||||
|  |                         "compose_type": "tar", | ||||||
|  |                         "branch": "master"} | ||||||
|  | 
 | ||||||
|  |         resp = self.server.post("/api/v0/compose?test=1", | ||||||
|  |                                 data=json.dumps(test_compose), | ||||||
|  |                                 content_type="application/json") | ||||||
|  |         data = json.loads(resp.data) | ||||||
|  |         self.assertNotEqual(data, None) | ||||||
|  |         self.assertEqual(data["status"], True, "Failed to start test compose: %s" % data) | ||||||
|  | 
 | ||||||
|  |         build_id = data["build_id"] | ||||||
|  | 
 | ||||||
|  |         # Is it in the queue list (either new or run is fine, based on timing) | ||||||
|  |         resp = self.server.get("/api/v0/compose/queue") | ||||||
|  |         data = json.loads(resp.data) | ||||||
|  |         self.assertNotEqual(data, None) | ||||||
|  |         ids = [e["id"] for e in data["new"] + data["run"]] | ||||||
|  |         self.assertEqual(build_id in ids, True, "Failed to add build to the queue") | ||||||
|  | 
 | ||||||
|  |         # Wait for it to start | ||||||
|  |         self.assertEqual(self.wait_for_status(build_id, ["RUNNING"]), True, "Failed to start test compose") | ||||||
|  | 
 | ||||||
|  |         # Wait for it to finish | ||||||
|  |         self.assertEqual(self.wait_for_status(build_id, ["FAILED"]), True, "Failed to finish test compose") | ||||||
|  | 
 | ||||||
|  |         resp = self.server.get("/api/v0/compose/info/%s" % build_id) | ||||||
|  |         data = json.loads(resp.data) | ||||||
|  |         self.assertNotEqual(data, None) | ||||||
|  |         self.assertEqual(data["queue_status"], "FAILED", "Build not in FAILED state") | ||||||
|  | 
 | ||||||
|  |         # Test the /api/v0/compose/failed route | ||||||
|  |         resp = self.server.get("/api/v0/compose/failed") | ||||||
|  |         data = json.loads(resp.data) | ||||||
|  |         self.assertNotEqual(data, None) | ||||||
|  |         ids = [e["id"] for e in data["failed"]] | ||||||
|  |         self.assertEqual(build_id in ids, True, "Failed build not listed by /compose/failed") | ||||||
|  | 
 | ||||||
|  |         # Test the /api/v0/compose/finished route | ||||||
|  |         resp = self.server.get("/api/v0/compose/finished") | ||||||
|  |         data = json.loads(resp.data) | ||||||
|  |         self.assertNotEqual(data, None) | ||||||
|  |         self.assertEqual(data["finished"], [], "Finished build not listed by /compose/finished") | ||||||
|  | 
 | ||||||
|  |         # Test the /api/v0/compose/status/<uuid> route | ||||||
|  |         resp = self.server.get("/api/v0/compose/status/%s" % build_id) | ||||||
|  |         data = json.loads(resp.data) | ||||||
|  |         self.assertNotEqual(data, None) | ||||||
|  |         ids = [(e["id"], e["queue_status"]) for e in data["uuids"]] | ||||||
|  |         self.assertEqual((build_id, "FAILED") in ids, True, "Failed build not listed by /compose/status") | ||||||
|  | 
 | ||||||
|  |         # Test the /api/v0/compose/cancel/<uuid> route | ||||||
|  |         resp = self.server.post("/api/v0/compose?test=1", | ||||||
|  |                                 data=json.dumps(test_compose), | ||||||
|  |                                 content_type="application/json") | ||||||
|  |         data = json.loads(resp.data) | ||||||
|  |         self.assertNotEqual(data, None) | ||||||
|  |         self.assertEqual(data["status"], True, "Failed to start test compose: %s" % data) | ||||||
|  | 
 | ||||||
|  |         cancel_id = data["build_id"] | ||||||
|  | 
 | ||||||
|  |         # Wait for it to start | ||||||
|  |         self.assertEqual(self.wait_for_status(cancel_id, ["RUNNING"]), True, "Failed to start test compose") | ||||||
|  | 
 | ||||||
|  |         # Cancel the build | ||||||
|  |         resp = self.server.delete("/api/v0/compose/cancel/%s" % cancel_id) | ||||||
|  |         data = json.loads(resp.data) | ||||||
|  |         self.assertNotEqual(data, None) | ||||||
|  |         self.assertEqual(data["status"], True, "Failed to cancel test compose: %s" % data) | ||||||
|  | 
 | ||||||
|  |         # Delete the failed build | ||||||
|  |         # Test the /api/v0/compose/delete/<uuid> route | ||||||
|  |         resp = self.server.delete("/api/v0/compose/delete/%s" % build_id) | ||||||
|  |         data = json.loads(resp.data) | ||||||
|  |         self.assertNotEqual(data, None) | ||||||
|  |         ids = [(e["uuid"], e["status"]) for e in data["uuids"]] | ||||||
|  |         self.assertEqual((build_id, True) in ids, True, "Failed to delete test compose: %s" % data) | ||||||
|  | 
 | ||||||
|  |         # Make sure the failed list is empty | ||||||
|  |         resp = self.server.get("/api/v0/compose/failed") | ||||||
|  |         data = json.loads(resp.data) | ||||||
|  |         self.assertNotEqual(data, None) | ||||||
|  |         self.assertEqual(data["failed"], [], "Failed to delete the failed build: %s" % data) | ||||||
|  | 
 | ||||||
|  |     def test_compose_03_create_finished(self): | ||||||
|  |         """Test the /api/v0/compose routes with a finished test compose""" | ||||||
|  |         test_compose = {"recipe_name": "glusterfs", | ||||||
|  |                         "compose_type": "tar", | ||||||
|  |                         "branch": "master"} | ||||||
|  | 
 | ||||||
|  |         resp = self.server.post("/api/v0/compose?test=2", | ||||||
|  |                                 data=json.dumps(test_compose), | ||||||
|  |                                 content_type="application/json") | ||||||
|  |         data = json.loads(resp.data) | ||||||
|  |         self.assertNotEqual(data, None) | ||||||
|  |         self.assertEqual(data["status"], True, "Failed to start test compose: %s" % data) | ||||||
|  | 
 | ||||||
|  |         build_id = data["build_id"] | ||||||
|  | 
 | ||||||
|  |         # Is it in the queue list (either new or run is fine, based on timing) | ||||||
|  |         resp = self.server.get("/api/v0/compose/queue") | ||||||
|  |         data = json.loads(resp.data) | ||||||
|  |         self.assertNotEqual(data, None) | ||||||
|  |         ids = [e["id"] for e in data["new"] + data["run"]] | ||||||
|  |         self.assertEqual(build_id in ids, True, "Failed to add build to the queue") | ||||||
|  | 
 | ||||||
|  |         # Wait for it to start | ||||||
|  |         self.assertEqual(self.wait_for_status(build_id, ["RUNNING"]), True, "Failed to start test compose") | ||||||
|  | 
 | ||||||
|  |         # Wait for it to finish | ||||||
|  |         self.assertEqual(self.wait_for_status(build_id, ["FINISHED"]), True, "Failed to finish test compose") | ||||||
|  | 
 | ||||||
|  |         resp = self.server.get("/api/v0/compose/info/%s" % build_id) | ||||||
|  |         data = json.loads(resp.data) | ||||||
|  |         self.assertNotEqual(data, None) | ||||||
|  |         self.assertEqual(data["queue_status"], "FINISHED", "Build not in FINISHED state") | ||||||
|  | 
 | ||||||
|  |         # Test the /api/v0/compose/finished route | ||||||
|  |         resp = self.server.get("/api/v0/compose/finished") | ||||||
|  |         data = json.loads(resp.data) | ||||||
|  |         self.assertNotEqual(data, None) | ||||||
|  |         ids = [e["id"] for e in data["finished"]] | ||||||
|  |         self.assertEqual(build_id in ids, True, "Finished build not listed by /compose/finished") | ||||||
|  | 
 | ||||||
|  |         # Test the /api/v0/compose/failed route | ||||||
|  |         resp = self.server.get("/api/v0/compose/failed") | ||||||
|  |         data = json.loads(resp.data) | ||||||
|  |         self.assertNotEqual(data, None) | ||||||
|  |         self.assertEqual(data["failed"], [], "Failed build not listed by /compose/failed") | ||||||
|  | 
 | ||||||
|  |         # Test the /api/v0/compose/status/<uuid> route | ||||||
|  |         resp = self.server.get("/api/v0/compose/status/%s" % build_id) | ||||||
|  |         data = json.loads(resp.data) | ||||||
|  |         self.assertNotEqual(data, None) | ||||||
|  |         ids = [(e["id"], e["queue_status"]) for e in data["uuids"]] | ||||||
|  |         self.assertEqual((build_id, "FINISHED") in ids, True, "Finished build not listed by /compose/status") | ||||||
|  | 
 | ||||||
|  |         # Test the /api/v0/compose/metadata/<uuid> route | ||||||
|  |         resp = self.server.get("/api/v0/compose/metadata/%s" % build_id) | ||||||
|  |         self.assertEqual(resp.status_code, 200) | ||||||
|  |         self.assertEqual(len(resp.data) > 1024, True) | ||||||
|  | 
 | ||||||
|  |         # Test the /api/v0/compose/results/<uuid> route | ||||||
|  |         resp = self.server.get("/api/v0/compose/results/%s" % build_id) | ||||||
|  |         self.assertEqual(resp.status_code, 200) | ||||||
|  |         self.assertEqual(len(resp.data) > 1024, True) | ||||||
|  | 
 | ||||||
|  |         # Test the /api/v0/compose/image/<uuid> route | ||||||
|  |         resp = self.server.get("/api/v0/compose/image/%s" % build_id) | ||||||
|  |         self.assertEqual(resp.status_code, 200) | ||||||
|  |         self.assertEqual(len(resp.data) > 0, True) | ||||||
|  |         self.assertEqual(resp.data, "TEST IMAGE") | ||||||
|  | 
 | ||||||
|  |         # Delete the finished build | ||||||
|  |         # Test the /api/v0/compose/delete/<uuid> route | ||||||
|  |         resp = self.server.delete("/api/v0/compose/delete/%s" % build_id) | ||||||
|  |         data = json.loads(resp.data) | ||||||
|  |         self.assertNotEqual(data, None) | ||||||
|  |         ids = [(e["uuid"], e["status"]) for e in data["uuids"]] | ||||||
|  |         self.assertEqual((build_id, True) in ids, True, "Failed to delete test compose: %s" % data) | ||||||
|  | 
 | ||||||
|  |         # Make sure the finished list is empty | ||||||
|  |         resp = self.server.get("/api/v0/compose/finished") | ||||||
|  |         data = json.loads(resp.data) | ||||||
|  |         self.assertNotEqual(data, None) | ||||||
|  |         self.assertEqual(data["finished"], [], "Failed to delete the failed build: %s" % data) | ||||||
|  | >>>>>>> Add tests for /compose API | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user