You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@buildstream.apache.org by no...@apache.org on 2020/12/29 12:35:40 UTC

[buildstream] 08/15: sourcetests: Create a new SourceTests class

This is an automated email from the ASF dual-hosted git repository.

not-in-ldap pushed a commit to branch bschubert/standardize-source-tests
in repository https://gitbox.apache.org/repos/asf/buildstream.git

commit ad99234e3a853ad8a64dca18193ac6eaa776222c
Author: Benjamin Schubert <co...@benschubert.me>
AuthorDate: Sat Aug 22 13:34:56 2020 +0000

    sourcetests: Create a new SourceTests class
    
    This adds a new 'SourceTests' class that will contain all
    standardised tests that authors of sources would want to pass.
    
    This lets the users only inherit this class and then implement the
    missing parts and all the tests would be able to run explicitely
---
 src/buildstream/testing/__init__.py              |  8 ++
 src/buildstream/testing/_sourcetests/__init__.py | 28 +++++++
 src/buildstream/testing/_sourcetests/base.py     | 36 +++++++++
 src/buildstream/testing/_sourcetests/fetch.py    | 98 +++++++++++-------------
 src/buildstream/testing/_sourcetests/generic.py  | 25 ++++++
 tests/testutils/repo/bzr.py                      |  2 +-
 tests/testutils/repo/git.py                      |  2 +-
 7 files changed, 142 insertions(+), 57 deletions(-)

diff --git a/src/buildstream/testing/__init__.py b/src/buildstream/testing/__init__.py
index 7e9f009..09606c3 100644
--- a/src/buildstream/testing/__init__.py
+++ b/src/buildstream/testing/__init__.py
@@ -30,6 +30,7 @@ from .integration import integration_cache
 from ._cachekeys import check_cache_key_stability
 
 __all__ = [
+    "SourceTests",
     "check_cache_key_stability",
     "create_repo",
     "register_repo_kind",
@@ -133,3 +134,10 @@ def sourcetests_collection_hook(session):
     # automatically collect templated tests.
     if should_collect_tests(session.config):
         session.config.args.append(source_test_path)
+
+
+# XXX: this needs to be imported last, as it depends on things from
+#      this module. We should move that back up once we've finished the
+#      refactor of the source tests
+# pylint: disable=wrong-import-position
+from ._sourcetests import SourceTests
diff --git a/src/buildstream/testing/_sourcetests/__init__.py b/src/buildstream/testing/_sourcetests/__init__.py
index e69de29..3a8a506 100644
--- a/src/buildstream/testing/_sourcetests/__init__.py
+++ b/src/buildstream/testing/_sourcetests/__init__.py
@@ -0,0 +1,28 @@
+#
+#  Copyright (C) 2020 Bloomberg Finance LP
+#
+#  This program is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU Lesser General Public
+#  License as published by the Free Software Foundation; either
+#  version 2 of the License, or (at your option) any later version.
+#
+#  This library 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
+#  Lesser General Public License for more details.
+#
+#  You should have received a copy of the GNU Lesser General Public
+#  License along with this library. If not, see <http://www.gnu.org/licenses/>.
+#
+
+# XXX: we should reorganize those modules after the source tests have
+#      been refactored
+# pylint: disable=cyclic-import
+
+from .fetch import FetchSourceTests
+
+__all__ = ["SourceTests"]
+
+
+class SourceTests(FetchSourceTests):
+    """Definition of standardized tests that each source should pass."""
diff --git a/src/buildstream/testing/_sourcetests/base.py b/src/buildstream/testing/_sourcetests/base.py
new file mode 100644
index 0000000..6ee361d
--- /dev/null
+++ b/src/buildstream/testing/_sourcetests/base.py
@@ -0,0 +1,36 @@
+#
+#  Copyright (C) 2020 Bloomberg Finance LP
+#
+#  This program is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU Lesser General Public
+#  License as published by the Free Software Foundation; either
+#  version 2 of the License, or (at your option) any later version.
+#
+#  This library 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
+#  Lesser General Public License for more details.
+#
+#  You should have received a copy of the GNU Lesser General Public
+#  License along with this library. If not, see <http://www.gnu.org/licenses/>.
+#
+
+import os
+from abc import ABC, abstractmethod
+from typing import Type
+
+from ..repo import Repo
+
+
+class BaseSourceTests(ABC):
+    @property
+    @classmethod
+    @abstractmethod
+    def KIND(cls) -> str:
+        """Human readable name of the source currently being tested."""
+
+    @property
+    @classmethod
+    @abstractmethod
+    def REPO(cls) -> Type[Repo]:
+        """Get the repo implementation for the currently tested source."""
diff --git a/src/buildstream/testing/_sourcetests/fetch.py b/src/buildstream/testing/_sourcetests/fetch.py
index 05b43d7..62bbd31 100644
--- a/src/buildstream/testing/_sourcetests/fetch.py
+++ b/src/buildstream/testing/_sourcetests/fetch.py
@@ -1,6 +1,6 @@
 #
 #  Copyright (C) 2018 Codethink Limited
-#  Copyright (C) 2019 Bloomberg Finance LP
+#  Copyright (C) 2020 Bloomberg Finance LP
 #
 #  This program is free software; you can redistribute it and/or
 #  modify it under the terms of the GNU Lesser General Public
@@ -16,79 +16,67 @@
 #  License along with this library. If not, see <http://www.gnu.org/licenses/>.
 #
 
-# Pylint doesn't play well with fixtures and dependency injection from pytest
-# pylint: disable=redefined-outer-name
-
 import os
 import pytest
 
 from buildstream import _yaml
 from .._utils import generate_junction
-from .. import create_repo
-from .. import cli  # pylint: disable=unused-import
 from .utils import update_project_configuration
-from .utils import kind  # pylint: disable=unused-import
-
-
-# Project directory
-TOP_DIR = os.path.dirname(os.path.realpath(__file__))
-DATA_DIR = os.path.join(TOP_DIR, "project")
+from .base import BaseSourceTests
 
 
-@pytest.mark.datafiles(DATA_DIR)
-def test_fetch(cli, tmpdir, datafiles, kind):
-    project = str(datafiles)
-    bin_files_path = os.path.join(project, "files", "bin-files")
-    element_path = os.path.join(project, "elements")
-    element_name = "fetch-test-{}.bst".format(kind)
+class FetchSourceTests(BaseSourceTests):
+    def test_fetch(self, cli, tmpdir, datafiles):
+        project = str(datafiles)
+        bin_files_path = os.path.join(project, "files", "bin-files")
+        element_path = os.path.join(project, "elements")
+        element_name = "fetch-test-{}.bst".format(self.KIND)
 
-    # Create our repo object of the given source type with
-    # the bin files, and then collect the initial ref.
-    #
-    repo = create_repo(kind, str(tmpdir))
-    ref = repo.create(bin_files_path)
+        # Create our repo object of the given source type with
+        # the bin files, and then collect the initial ref.
+        #
+        repo = self.REPO(str(tmpdir))
+        ref = repo.create(bin_files_path)
 
-    # Write out our test target
-    element = {"kind": "import", "sources": [repo.source_config(ref=ref)]}
-    _yaml.roundtrip_dump(element, os.path.join(element_path, element_name))
+        # Write out our test target
+        element = {"kind": "import", "sources": [repo.source_config(ref=ref)]}
+        _yaml.roundtrip_dump(element, os.path.join(element_path, element_name))
 
-    # Assert that a fetch is needed
-    assert cli.get_element_state(project, element_name) == "fetch needed"
+        # Assert that a fetch is needed
+        assert cli.get_element_state(project, element_name) == "fetch needed"
 
-    # Now try to fetch it
-    result = cli.run(project=project, args=["source", "fetch", element_name])
-    result.assert_success()
+        # Now try to fetch it
+        result = cli.run(project=project, args=["source", "fetch", element_name])
+        result.assert_success()
 
-    # Assert that we are now buildable because the source is
-    # now cached.
-    assert cli.get_element_state(project, element_name) == "buildable"
+        # Assert that we are now buildable because the source is
+        # now cached.
+        assert cli.get_element_state(project, element_name) == "buildable"
 
+    @pytest.mark.parametrize("ref_storage", ["inline", "project.refs"])
+    def test_fetch_cross_junction(self, cli, tmpdir, datafiles, ref_storage):
+        project = str(datafiles)
+        subproject_path = os.path.join(project, "files", "sub-project")
+        junction_path = os.path.join(project, "elements", "junction.bst")
 
-@pytest.mark.datafiles(DATA_DIR)
-@pytest.mark.parametrize("ref_storage", ["inline", "project.refs"])
-def test_fetch_cross_junction(cli, tmpdir, datafiles, ref_storage, kind):
-    project = str(datafiles)
-    subproject_path = os.path.join(project, "files", "sub-project")
-    junction_path = os.path.join(project, "elements", "junction.bst")
+        import_etc_path = os.path.join(subproject_path, "elements", "import-etc-repo.bst")
+        etc_files_path = os.path.join(subproject_path, "files", "etc-files")
 
-    import_etc_path = os.path.join(subproject_path, "elements", "import-etc-repo.bst")
-    etc_files_path = os.path.join(subproject_path, "files", "etc-files")
+        repo = self.REPO(str(tmpdir.join("import-etc")))
+        ref = repo.create(etc_files_path)
 
-    repo = create_repo(kind, str(tmpdir.join("import-etc")))
-    ref = repo.create(etc_files_path)
+        element = {"kind": "import", "sources": [repo.source_config(ref=(ref if ref_storage == "inline" else None))]}
+        _yaml.roundtrip_dump(element, import_etc_path)
 
-    element = {"kind": "import", "sources": [repo.source_config(ref=(ref if ref_storage == "inline" else None))]}
-    _yaml.roundtrip_dump(element, import_etc_path)
+        update_project_configuration(project, {"ref-storage": ref_storage})
 
-    update_project_configuration(project, {"ref-storage": ref_storage})
+        generate_junction(tmpdir, subproject_path, junction_path, store_ref=(ref_storage == "inline"))
 
-    generate_junction(tmpdir, subproject_path, junction_path, store_ref=(ref_storage == "inline"))
+        if ref_storage == "project.refs":
+            result = cli.run(project=project, args=["source", "track", "junction.bst"])
+            result.assert_success()
+            result = cli.run(project=project, args=["source", "track", "junction.bst:import-etc.bst"])
+            result.assert_success()
 
-    if ref_storage == "project.refs":
-        result = cli.run(project=project, args=["source", "track", "junction.bst"])
-        result.assert_success()
-        result = cli.run(project=project, args=["source", "track", "junction.bst:import-etc.bst"])
+        result = cli.run(project=project, args=["source", "fetch", "junction.bst:import-etc.bst"])
         result.assert_success()
-
-    result = cli.run(project=project, args=["source", "fetch", "junction.bst:import-etc.bst"])
-    result.assert_success()
diff --git a/src/buildstream/testing/_sourcetests/generic.py b/src/buildstream/testing/_sourcetests/generic.py
new file mode 100644
index 0000000..9308e6e
--- /dev/null
+++ b/src/buildstream/testing/_sourcetests/generic.py
@@ -0,0 +1,25 @@
+#
+#  Copyright (C) 2020 Bloomberg Finance LP
+#
+#  This program is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU Lesser General Public
+#  License as published by the Free Software Foundation; either
+#  version 2 of the License, or (at your option) any later version.
+#
+#  This library 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
+#  Lesser General Public License for more details.
+#
+#  You should have received a copy of the GNU Lesser General Public
+#  License along with this library. If not, see <http://www.gnu.org/licenses/>.
+#
+
+
+from . import SourceTests
+from .. import ALL_REPO_KINDS
+
+
+for kind, (repo_cls, _) in ALL_REPO_KINDS.items():
+    cls_name = "Test{}Source".format(kind.upper())
+    globals()[cls_name] = type(cls_name, (SourceTests,), {"KIND": cls_name, "REPO": repo_cls})
diff --git a/tests/testutils/repo/bzr.py b/tests/testutils/repo/bzr.py
index b698341..7421be8 100644
--- a/tests/testutils/repo/bzr.py
+++ b/tests/testutils/repo/bzr.py
@@ -7,7 +7,7 @@ from buildstream.testing._utils.site import BZR, BZR_ENV, HAVE_BZR
 
 
 class Bzr(Repo):
-    def __init__(self, directory, subdir):
+    def __init__(self, directory, subdir="repo"):
         if not HAVE_BZR:
             pytest.skip("bzr is not available")
         super().__init__(directory, subdir)
diff --git a/tests/testutils/repo/git.py b/tests/testutils/repo/git.py
index 1deca3f..02fe878 100644
--- a/tests/testutils/repo/git.py
+++ b/tests/testutils/repo/git.py
@@ -9,7 +9,7 @@ from buildstream.testing._utils.site import GIT, GIT_ENV, HAVE_GIT
 
 
 class Git(Repo):
-    def __init__(self, directory, subdir):
+    def __init__(self, directory, subdir="repo"):
         if not HAVE_GIT:
             pytest.skip("git is not available")