From afdb3202663e752b4c24b14baa42340098f905da Mon Sep 17 00:00:00 2001 From: "Brian C. Lane" Date: Sat, 21 Oct 2017 13:41:39 -0700 Subject: [PATCH] Add tests for the pylorax.api.recipes module --- Makefile | 5 +- tests/pylorax/recipes/atlas.toml | 10 ++ tests/pylorax/recipes/development.toml | 82 +++++++++ tests/pylorax/recipes/glusterfs.toml | 14 ++ tests/pylorax/recipes/http-server.toml | 35 ++++ tests/pylorax/recipes/jboss.toml | 14 ++ tests/pylorax/recipes/kubernetes.toml | 26 +++ tests/pylorax/results/full-recipe.dict | 1 + tests/pylorax/results/full-recipe.toml | 35 ++++ tests/pylorax/results/minimal.dict | 1 + tests/pylorax/results/minimal.toml | 3 + tests/pylorax/results/modules-only.dict | 1 + tests/pylorax/results/modules-only.toml | 23 +++ tests/pylorax/results/packages-only.dict | 1 + tests/pylorax/results/packages-only.toml | 15 ++ tests/pylorax/test_recipes.py | 206 +++++++++++++++++++++++ 16 files changed, 471 insertions(+), 1 deletion(-) create mode 100644 tests/pylorax/recipes/atlas.toml create mode 100644 tests/pylorax/recipes/development.toml create mode 100644 tests/pylorax/recipes/glusterfs.toml create mode 100644 tests/pylorax/recipes/http-server.toml create mode 100644 tests/pylorax/recipes/jboss.toml create mode 100644 tests/pylorax/recipes/kubernetes.toml create mode 100644 tests/pylorax/results/full-recipe.dict create mode 100644 tests/pylorax/results/full-recipe.toml create mode 100644 tests/pylorax/results/minimal.dict create mode 100644 tests/pylorax/results/minimal.toml create mode 100644 tests/pylorax/results/modules-only.dict create mode 100644 tests/pylorax/results/modules-only.toml create mode 100644 tests/pylorax/results/packages-only.dict create mode 100644 tests/pylorax/results/packages-only.toml create mode 100644 tests/pylorax/test_recipes.py diff --git a/Makefile b/Makefile index 84b93552..bdb596f8 100644 --- a/Makefile +++ b/Makefile @@ -28,7 +28,10 @@ check: test: @echo "*** Running tests ***" PYTHONPATH=$(PYTHONPATH):./src/ $(PYTHON) -m nose -v --with-coverage --cover-erase --cover-branches \ - --cover-package=pylorax --cover-package=bin --cover-package=sbin --cover-inclusive + --cover-package=pylorax --cover-inclusive \ + ./src/pylorax/ ./tests/pylorax/ + + coverage report -m [ -f "/usr/bin/coveralls" ] && [ -n "$(COVERALLS_REPO_TOKEN)" ] && coveralls || echo diff --git a/tests/pylorax/recipes/atlas.toml b/tests/pylorax/recipes/atlas.toml new file mode 100644 index 00000000..1cbb0c24 --- /dev/null +++ b/tests/pylorax/recipes/atlas.toml @@ -0,0 +1,10 @@ +name = "atlas" +description = "Automatically Tuned Linear Algebra Software" + +[[modules]] +name = "atlas" +version = "3.10.*" + +[[modules]] +name = "numpy" +version = "1.7.*" diff --git a/tests/pylorax/recipes/development.toml b/tests/pylorax/recipes/development.toml new file mode 100644 index 00000000..8eece1df --- /dev/null +++ b/tests/pylorax/recipes/development.toml @@ -0,0 +1,82 @@ +name = "development" +description = "A general purpose development image" + +[[packages]] +name = "cmake" +version = "*" + +[[packages]] +name = "curl" +version = "*" + +[[packages]] +name = "file" +version = "*" + +[[packages]] +name = "gcc" +version = "*" + +[[packages]] +name = "gcc-c++" +version = "*" + +[[packages]] +name = "gdb" +version = "*" + +[[packages]] +name = "git" +version = "*" + +[[packages]] +name = "glibc-devel" +version = "*" + +[[packages]] +name = "gnupg2" +version = "*" + +[[packages]] +name = "libcurl-devel" +version = "*" + +[[packages]] +name = "make" +version = "*" + +[[packages]] +name = "openssl-devel" +version = "*" + +[[packages]] +name = "openssl-devel" +version = "*" + +[[packages]] +name = "sqlite" +version = "*" + +[[packages]] +name = "sqlite-devel" +version = "*" + +[[packages]] +name = "sudo" +version = "*" + +[[packages]] +name = "tar" +version = "*" + +[[packages]] +name = "xz" +version = "*" + +[[packages]] +name = "xz-devel" +version = "*" + +[[packages]] +name = "zlib-devel" +version = "*" diff --git a/tests/pylorax/recipes/glusterfs.toml b/tests/pylorax/recipes/glusterfs.toml new file mode 100644 index 00000000..b64fd883 --- /dev/null +++ b/tests/pylorax/recipes/glusterfs.toml @@ -0,0 +1,14 @@ +name = "glusterfs" +description = "An example GlusterFS server with samba" + +[[modules]] +name = "glusterfs" +version = "3.7.*" + +[[modules]] +name = "glusterfs-cli" +version = "3.7.*" + +[[packages]] +name = "samba" +version = "4.2.*" diff --git a/tests/pylorax/recipes/http-server.toml b/tests/pylorax/recipes/http-server.toml new file mode 100644 index 00000000..c6d74b1c --- /dev/null +++ b/tests/pylorax/recipes/http-server.toml @@ -0,0 +1,35 @@ +name = "http-server" +description = "An example http server with PHP and MySQL support." +version = "0.0.1" + +[[modules]] +name = "httpd" +version = "2.4.*" + +[[modules]] +name = "mod_auth_kerb" +version = "5.4" + +[[modules]] +name = "mod_ssl" +version = "2.4.*" + +[[modules]] +name = "php" +version = "5.4.*" + +[[modules]] +name = "php-mysql" +version = "5.4.*" + +[[packages]] +name = "tmux" +version = "2.2" + +[[packages]] +name = "openssh-server" +version = "6.6.*" + +[[packages]] +name = "rsync" +version = "3.0.*" diff --git a/tests/pylorax/recipes/jboss.toml b/tests/pylorax/recipes/jboss.toml new file mode 100644 index 00000000..9c7090fb --- /dev/null +++ b/tests/pylorax/recipes/jboss.toml @@ -0,0 +1,14 @@ +name = "jboss" +description = "An example jboss server" + +[[modules]] +name = "jboss-servlet-3.0-api" +version = "1.0.*" + +[[modules]] +name = "jboss-interceptors-1.1-api" +version = "1.0.*" + +[[modules]] +name = "java-1.8.0-openjdk" +version = "1.8.0.*" diff --git a/tests/pylorax/recipes/kubernetes.toml b/tests/pylorax/recipes/kubernetes.toml new file mode 100644 index 00000000..08e20bb7 --- /dev/null +++ b/tests/pylorax/recipes/kubernetes.toml @@ -0,0 +1,26 @@ +name = "kubernetes" +description = "An example kubernetes master" + +[[modules]] +name = "kubernetes" +version = "1.2.*" + +[[modules]] +name = "docker" +version = "1.10.*" + +[[modules]] +name = "docker-lvm-plugin" +version = "1.10.*" + +[[modules]] +name = "etcd" +version = "2.3.*" + +[[modules]] +name = "flannel" +version = "0.5.*" + +[[packages]] +name = "oci-systemd-hook" +version = "0.1.*" diff --git a/tests/pylorax/results/full-recipe.dict b/tests/pylorax/results/full-recipe.dict new file mode 100644 index 00000000..082d6de4 --- /dev/null +++ b/tests/pylorax/results/full-recipe.dict @@ -0,0 +1 @@ +{'description': u'An example http server with PHP and MySQL support.', 'packages': [{'version': u'6.6.*', 'name': u'openssh-server'}, {'version': u'3.0.*', 'name': u'rsync'}, {'version': u'2.2', 'name': u'tmux'}], 'modules': [{'version': u'2.4.*', 'name': u'httpd'}, {'version': u'5.4', 'name': u'mod_auth_kerb'}, {'version': u'2.4.*', 'name': u'mod_ssl'}, {'version': u'5.4.*', 'name': u'php'}, {'version': u'5.4.*', 'name': u'php-mysql'}], 'version': u'0.0.1', 'name': u'http-server'} diff --git a/tests/pylorax/results/full-recipe.toml b/tests/pylorax/results/full-recipe.toml new file mode 100644 index 00000000..c6d74b1c --- /dev/null +++ b/tests/pylorax/results/full-recipe.toml @@ -0,0 +1,35 @@ +name = "http-server" +description = "An example http server with PHP and MySQL support." +version = "0.0.1" + +[[modules]] +name = "httpd" +version = "2.4.*" + +[[modules]] +name = "mod_auth_kerb" +version = "5.4" + +[[modules]] +name = "mod_ssl" +version = "2.4.*" + +[[modules]] +name = "php" +version = "5.4.*" + +[[modules]] +name = "php-mysql" +version = "5.4.*" + +[[packages]] +name = "tmux" +version = "2.2" + +[[packages]] +name = "openssh-server" +version = "6.6.*" + +[[packages]] +name = "rsync" +version = "3.0.*" diff --git a/tests/pylorax/results/minimal.dict b/tests/pylorax/results/minimal.dict new file mode 100644 index 00000000..743b10a0 --- /dev/null +++ b/tests/pylorax/results/minimal.dict @@ -0,0 +1 @@ +{'description': u'An example http server with PHP and MySQL support.', 'packages': None, 'modules': None, 'version': u'0.0.1', 'name': u'http-server'} diff --git a/tests/pylorax/results/minimal.toml b/tests/pylorax/results/minimal.toml new file mode 100644 index 00000000..bb71b650 --- /dev/null +++ b/tests/pylorax/results/minimal.toml @@ -0,0 +1,3 @@ +name = "http-server" +description = "An example http server with PHP and MySQL support." +version = "0.0.1" diff --git a/tests/pylorax/results/modules-only.dict b/tests/pylorax/results/modules-only.dict new file mode 100644 index 00000000..e86f43c9 --- /dev/null +++ b/tests/pylorax/results/modules-only.dict @@ -0,0 +1 @@ +{'description': u'An example http server with PHP and MySQL support.', 'packages': None, 'modules': [{'version': u'2.4.*', 'name': u'httpd'}, {'version': u'5.4', 'name': u'mod_auth_kerb'}, {'version': u'2.4.*', 'name': u'mod_ssl'}, {'version': u'5.4.*', 'name': u'php'}, {'version': u'5.4.*', 'name': u'php-mysql'}], 'version': u'0.0.1', 'name': u'http-server'} diff --git a/tests/pylorax/results/modules-only.toml b/tests/pylorax/results/modules-only.toml new file mode 100644 index 00000000..3457797d --- /dev/null +++ b/tests/pylorax/results/modules-only.toml @@ -0,0 +1,23 @@ +name = "http-server" +description = "An example http server with PHP and MySQL support." +version = "0.0.1" + +[[modules]] +name = "httpd" +version = "2.4.*" + +[[modules]] +name = "mod_auth_kerb" +version = "5.4" + +[[modules]] +name = "mod_ssl" +version = "2.4.*" + +[[modules]] +name = "php" +version = "5.4.*" + +[[modules]] +name = "php-mysql" +version = "5.4.*" diff --git a/tests/pylorax/results/packages-only.dict b/tests/pylorax/results/packages-only.dict new file mode 100644 index 00000000..2f5b2773 --- /dev/null +++ b/tests/pylorax/results/packages-only.dict @@ -0,0 +1 @@ +{'description': u'An example http server with PHP and MySQL support.', 'packages': [{'version': u'6.6.*', 'name': u'openssh-server'}, {'version': u'3.0.*', 'name': u'rsync'}, {'version': u'2.2', 'name': u'tmux'}], 'modules': None, 'version': u'0.0.1', 'name': u'http-server'} diff --git a/tests/pylorax/results/packages-only.toml b/tests/pylorax/results/packages-only.toml new file mode 100644 index 00000000..2aa507f3 --- /dev/null +++ b/tests/pylorax/results/packages-only.toml @@ -0,0 +1,15 @@ +name = "http-server" +description = "An example http server with PHP and MySQL support." +version = "0.0.1" + +[[packages]] +name = "tmux" +version = "2.2" + +[[packages]] +name = "openssh-server" +version = "6.6.*" + +[[packages]] +name = "rsync" +version = "3.0.*" diff --git a/tests/pylorax/test_recipes.py b/tests/pylorax/test_recipes.py new file mode 100644 index 00000000..cf1da3a2 --- /dev/null +++ b/tests/pylorax/test_recipes.py @@ -0,0 +1,206 @@ +# +# Copyright (C) 2017 Red Hat, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +from pytoml import TomlError +import shutil +import tempfile +import unittest + +import pylorax.api.recipes as recipes +from pylorax.sysutils import joinpaths + +class BasicRecipeTest(unittest.TestCase): + @classmethod + def setUpClass(self): + # Input toml is in .toml and python dict string is in .dict + input_recipes = [("full-recipe.toml", "full-recipe.dict"), + ("minimal.toml", "minimal.dict"), + ("modules-only.toml", "modules-only.dict"), + ("packages-only.toml", "packages-only.dict")] + results_path = "./tests/pylorax/results/" + self.input_toml = [] + for (recipe_toml, recipe_dict) in input_recipes: + with open(joinpaths(results_path, recipe_toml)) as f_toml: + with open(joinpaths(results_path, recipe_dict)) as f_dict: + # XXX Warning, can run arbitrary code + result_dict = eval(f_dict.read()) + self.input_toml.append((f_toml.read(), result_dict)) + + @classmethod + def tearDownClass(self): + pass + + def toml_to_recipe_test(self): + """Test converting the TOML string to a Recipe object""" + for (toml_str, recipe_dict) in self.input_toml: + result = recipes.recipe_from_toml(toml_str) + self.assertEqual(result, recipe_dict) + + def toml_to_recipe_fail_test(self): + """Test trying to convert a non-TOML string to a Recipe""" + with self.assertRaises(TomlError): + recipes.recipe_from_toml("This is not a TOML string\n") + + with self.assertRaises(recipes.RecipeTOMLError): + recipes.recipe_from_toml('name = "a failed toml string"\n') + + def recipe_to_toml_test(self): + """Test converting a Recipe object to a TOML string""" + # In order to avoid problems from matching strings we convert to TOML and + # then back so compare the Recipes. + for (toml_str, _recipe_dict) in self.input_toml: + # This is tested in toml_to_recipe + recipe_1 = recipes.recipe_from_toml(toml_str) + # Convert the Recipe to TOML and then back to a Recipe + toml_2 = recipe_1.toml() + recipe_2 = recipes.recipe_from_toml(toml_2) + self.assertEqual(recipe_1, recipe_2) + + def recipe_bump_version_test(self): + """Test the Recipe's version bump function""" + + # Neither have a version + recipe = recipes.Recipe("test-recipe", "A recipe used for testing", None, None, None) + new_version = recipe.bump_version(None) + self.assertEqual(new_version, "0.0.1") + + # Original has a version, new does not + recipe = recipes.Recipe("test-recipe", "A recipe used for testing", "0.0.1", None, None) + new_version = recipe.bump_version(None) + self.assertEqual(new_version, "0.0.2") + + # Original has no version, new does + recipe = recipes.Recipe("test-recipe", "A recipe used for testing", None, None, None) + new_version = recipe.bump_version("0.1.0") + self.assertEqual(new_version, "0.1.0") + + # New and Original are the same + recipe = recipes.Recipe("test-recipe", "A recipe used for testing", "0.0.1", None, None) + new_version = recipe.bump_version("0.0.1") + self.assertEqual(new_version, "0.0.2") + + # New is different from Original + recipe = recipes.Recipe("test-recipe", "A recipe used for testing", "0.0.1", None, None) + new_version = recipe.bump_version("0.1.1") + self.assertEqual(new_version, "0.1.1") + + +class GitRecipesTest(unittest.TestCase): + @classmethod + def setUpClass(self): + self.repo_dir = tempfile.mkdtemp(prefix="lorax.test.repo.") + self.repo = recipes.open_or_create_repo(self.repo_dir) + + self.results_path = "./tests/pylorax/results/" + + @classmethod + def tearDownClass(self): + if self.repo is not None: + del self.repo + shutil.rmtree(self.repo_dir) + + def test_01_repo_creation(self): + """Test that creating the repository succeeded""" + self.assertNotEqual(self.repo, None) + + def test_02_commit_recipe(self): + """Test committing a Recipe object""" + recipe = recipes.Recipe("test-recipe", "A recipe used for testing", None, None, None) + oid = recipes.commit_recipe(self.repo, "master", recipe, "0.1.0") + self.assertNotEqual(oid, None) + + def test_03_list_recipe(self): + """Test listing recipe commits""" + commits = recipes.list_commits(self.repo, "master", "test-recipe.toml") + self.assertEqual(len(commits), 1, "Wrong number of commits.") + self.assertEqual(commits[0].message, "Recipe test-recipe, version 0.1.0 saved.") + self.assertNotEqual(commits[0].timestamp, None, "Timestamp is None") + self.assertEqual(len(commits[0].commit), 40, "Commit hash isn't 40 characters") + self.assertEqual(commits[0].revision, None, "revision is not None") + + def test_04_commit_toml_file(self): + """Test committing a TOML file""" + recipe_path = joinpaths(self.results_path, "full-recipe.toml") + oid = recipes.commit_recipe_file(self.repo, "master", recipe_path) + self.assertNotEqual(oid, None) + + commits = recipes.list_commits(self.repo, "master", "http-server.toml") + self.assertEqual(len(commits), 1, "Wrong number of commits: %s" % commits) + + def test_05_commit_toml_dir(self): + """Test committing a directory of TOML files""" + # It worked if it doesn't raise errors + recipes.commit_recipe_directory(self.repo, "master", self.results_path) + + def test_06_read_recipe(self): + """Test reading a recipe from a commit""" + commits = recipes.list_commits(self.repo, "master", "http-server.toml") + self.assertEqual(len(commits), 1, "Wrong number of commits: %s" % commits) + + recipe = recipes.read_recipe_commit(self.repo, "master", "http-server.toml") + self.assertNotEqual(recipe, None) + self.assertEqual(recipe["name"], "http-server") + + # Read by commit id + recipe = recipes.read_recipe_commit(self.repo, "master", "http-server.toml", commits[0].commit) + self.assertNotEqual(recipe, None) + self.assertEqual(recipe["name"], "http-server") + + def test_07_tag_commit(self): + """Test tagging the most recent commit of a recipe""" + result = recipes.tag_file_commit(self.repo, "master", "not-a-file") + self.assertEqual(result, None) + + result = recipes.tag_file_commit(self.repo, "master", "http-server.toml") + self.assertNotEqual(result, None) + + commits = recipes.list_commits(self.repo, "master", "http-server.toml") + self.assertEqual(len(commits), 1, "Wrong number of commits: %s" % commits) + self.assertEqual(commits[0].revision, 1) + + def test_08_delete_recipe(self): + """Test deleting a file from a branch""" + oid = recipes.delete_file(self.repo, "master", "http-server.toml") + self.assertNotEqual(oid, None) + + master_files = recipes.list_branch_files(self.repo, "master") + self.assertEqual("http-server.toml" in master_files, False) + + def test_09_revert_commit(self): + """Test reverting a file on a branch""" + commits = recipes.list_commits(self.repo, "master", "http-server.toml") + revert_to = commits[0].commit + oid = recipes.revert_file(self.repo, "master", "http-server.toml", revert_to) + self.assertNotEqual(oid, None) + + commits = recipes.list_commits(self.repo, "master", "http-server.toml") + self.assertEqual(len(commits), 2, "Wrong number of commits: %s" % commits) + self.assertEqual(commits[1].message, "Recipe http-server.toml reverted to commit %s" % revert_to) + + def test_10_tag_new_commit(self): + """Test tagging a newer commit of a recipe""" + recipe = recipes.read_recipe_commit(self.repo, "master", "http-server.toml") + recipe["description"] = "A modified description" + oid = recipes.commit_recipe(self.repo, "master", recipe, "0.1.0") + self.assertNotEqual(oid, None) + + # Tag the new commit + result = recipes.tag_file_commit(self.repo, "master", "http-server.toml") + self.assertNotEqual(result, None) + + commits = recipes.list_commits(self.repo, "master", "http-server.toml") + self.assertEqual(len(commits), 3, "Wrong number of commits: %s" % commits) + self.assertEqual(commits[0].revision, 2)