Exemple #1
0
def init(context, path, template, force, **kwargs):
    """
    Initialize a new tmt tree.

    By default tree is created in the current directory.
    Provide a PATH to create it in a different location.

    \b
    A tree can be optionally populated with example metadata:
    * 'mini' template contains a minimal plan and no tests,
    * 'base' template contains a plan and a beakerlib test,
    * 'full' template contains a 'full' story, an 'full' plan and a shell test.
    """

    # Check for existing tree
    path = os.path.realpath(path)
    try:
        tree = tmt.Tree(path)
        # Are we creating a new tree under the existing one?
        if path == tree.root:
            echo("Tree '{}' already exists.".format(tree.root))
        else:
            tree = None
    except tmt.utils.GeneralError:
        tree = None
    # Create a new tree
    if tree is None:
        try:
            fmf.Tree.init(path)
            tree = tmt.Tree(path)
        except fmf.utils.GeneralError as error:
            raise tmt.utils.GeneralError(
                "Failed to initialize tree in '{}': {}".format(
                    path, error))
        echo("Tree '{}' initialized.".format(tree.root))

    # Populate the tree with example objects if requested
    if template == 'empty':
        non_empty_choices = [c for c in _init_template_choices if c != 'empty']
        echo("To populate it with example content, use --template with "
             "{}.".format(listed(non_empty_choices, join='or')))
    else:
        echo("Applying template '{}'.".format(template, _init_templates))
    if template == 'mini':
        tmt.Plan.create('/plans/example', 'mini', tree, force)
    elif template == 'base':
        tmt.Test.create('/tests/example', 'beakerlib', tree, force)
        tmt.Plan.create('/plans/example', 'base', tree, force)
    elif template == 'full':
        tmt.Test.create('/tests/example', 'shell', tree, force)
        tmt.Plan.create('/plans/example', 'full', tree, force)
        tmt.Story.create('/stories/example', 'full', tree, force)
Exemple #2
0
def main(click_contex, root, context, **kwargs):
    """ Test Management Tool """
    # Show current tmt version and exit
    if kwargs.get('version'):
        print(f"tmt version: {tmt.__version__}")
        raise SystemExit(0)

    # Disable coloring if NO_COLOR is set
    if 'NO_COLOR' in os.environ:
        click_contex.color = False

    # Save click context and fmf context for future use
    tmt.utils.Common._save_context(click_contex)
    click_contex.obj = tmt.utils.Common()
    click_contex.obj.fmf_context = tmt.utils.context_to_dict(context)

    # Initialize metadata tree (from given path or current directory)
    tree = tmt.Tree(root or os.curdir)
    click_contex.obj.tree = tree

    # List of enabled steps
    click_contex.obj.steps = set()

    # Show overview of available tests, plans and stories
    if click_contex.invoked_subcommand is None:
        tmt.Test.overview(tree)
        tmt.Plan.overview(tree)
        tmt.Story.overview(tree)
Exemple #3
0
 def go(self):
     """ Discover available tests """
     super(DiscoverFmf, self).go()
     testdir = os.path.join(self.workdir, 'tests')
     # Clone provided git repository
     if self.repository:
         self.info('repository', self.repository, 'green')
         self.debug(f"Clone '{self.repository}' to '{testdir}'.")
         self.run(f'git clone {self.repository} {testdir}')
     # Copy current directory to workdir
     else:
         directory = self.step.plan.run.tree.root
         self.info('directory', directory, 'green')
         self.debug("Copy '{}' to '{}'.".format(directory, testdir))
         shutil.copytree(directory, testdir)
     # Checkout revision if requested
     if self.revision:
         self.info('revision', self.revision, 'green')
         self.debug(f"Checkout revision '{self.revision}'.")
         self.run(f"git checkout -f {self.revision}", cwd=testdir)
     # Initialize the metadata tree
     self.debug(f"Check metadata tree in '{testdir}'.")
     if self.opt('dry'):
         return
     self.tests_tree = tmt.Tree(testdir)
Exemple #4
0
def finito(*args, **kwargs):
    tree = tmt.Tree(tree_path)
    click.echo(
        click.style('Found {0}.'.format(
            fmf.utils.listed(tree.testsets, 'testset')),
                    fg='magenta'))
    for testset in tree.testsets:
        click.echo(click.style('\nTestset: {0}'.format(testset), fg='green'))
        testset.go()
Exemple #5
0
def main(context, path):
    """ Test Management Tool """
    # Initialize metadata tree
    global tree
    tree = tmt.Tree(path)

    # Show overview of available tests, plans and stories
    if context.invoked_subcommand is None:
        tmt.Test.overview()
        tmt.Plan.overview()
        tmt.Story.overview()

    return 'tmt'
Exemple #6
0
def main(context, root, **kwargs):
    """ Test Management Tool """
    # Initialize metadata tree
    tree = tmt.Tree(root)
    tree._context = context
    context.obj = tmt.utils.Common()
    context.obj.tree = tree

    # Show overview of available tests, plans and stories
    if context.invoked_subcommand is None:
        tmt.Test.overview(tree)
        tmt.Plan.overview(tree)
        tmt.Story.overview(tree)
Exemple #7
0
def init(context, path, mini, full, force, **kwargs):
    """
    Initialize a new tmt tree.

    By default tree is created in the current directory.
    Provide a PATH to create it in a different location.
    """

    # Check for existing tree
    path = os.path.realpath(path)
    try:
        tree = tmt.Tree(path)
        # Are we creating a new tree under the existing one?
        if path == tree.root:
            echo("Tree '{}' already exists.".format(tree.root))
        else:
            tree = None
    except tmt.utils.GeneralError:
        tree = None
    # Create a new tree
    if tree is None:
        try:
            fmf.Tree.init(path)
            tree = tmt.Tree(path)
        except fmf.utils.GeneralError as error:
            raise tmt.utils.GeneralError(
                "Failed to initialize tree in '{}': {}".format(
                    path, error))
        echo("Tree '{}' initialized.".format(tree.root))

    # Populate the tree with example objects if requested
    if mini:
        tmt.Test.create('/tests/example', 'shell', tree, force)
        tmt.Plan.create('/plans/example', 'mini', tree, force)
        tmt.Story.create('/stories/example', 'mini', tree, force)
    if full:
        tmt.Test.create('/tests/example', 'shell', tree, force)
        tmt.Plan.create('/plans/example', 'full', tree, force)
        tmt.Story.create('/stories/example', 'full', tree, force)
Exemple #8
0
    def go(self):
        """
        Go and perform the plugin task

        Discover available tests in this case.
        """
        super().go()
        print("go() called")

        # Prepare test environment
        print("Code should prepare environment for tests.")

        # Use a tmt.Tree to apply possible command line filters
        tests = tmt.Tree(tree=tests).tests()
        self._tests = tests
Exemple #9
0
Fichier : cli.py Projet : happz/tmt
def main(context, root, **kwargs):
    """ Test Management Tool """
    # Initialize metadata tree
    root = root or os.curdir
    tree = tmt.Tree(root)
    tree._save_context(context)
    context.obj = tmt.utils.Common()
    context.obj.tree = tree
    # List of enabled steps
    context.obj.steps = set()

    # Show overview of available tests, plans and stories
    if context.invoked_subcommand is None:
        tmt.Test.overview(tree)
        tmt.Plan.overview(tree)
        tmt.Story.overview(tree)
Exemple #10
0
    def go(self):
        """ Discover available tests """
        super(DiscoverShell, self).go()
        tests = fmf.Tree(dict(summary='tests'))

        # Check and process each defined shell test
        for data in self.data['tests']:
            # Create data copy (we want to keep original data for save()
            data = copy.deepcopy(data)
            # Extract name, make sure it is present
            try:
                name = data.pop('name')
            except KeyError:
                raise tmt.utils.SpecificationError(
                    f"Missing test name in '{self.step.plan.name}'.")
            # Make sure that the test script is defined
            if 'test' not in data:
                raise tmt.utils.SpecificationError(
                    f"Missing test script in '{self.step.plan.name}'.")
            # Prepare path to the test working directory (tree root by default)
            try:
                data['path'] = f"/tests{data['path']}"
            except KeyError:
                data['path'] = f"/tests"
            # Apply default test duration unless provided
            if 'duration' not in data:
                data['duration'] = tmt.base.DEFAULT_TEST_DURATION_L2

            # Create a simple fmf node, adjust its name
            tests.child(name, data)

        # Copy directory tree (if defined) to the workdir
        directory = self.step.plan.my_run.tree.root
        testdir = os.path.join(self.workdir, 'tests')
        if directory:
            self.info('directory', directory, 'green')
            self.debug("Copy '{}' to '{}'.".format(directory, testdir))
            shutil.copytree(directory, testdir, symlinks=True)
        else:
            os.makedirs(testdir)

        # Use a tmt.Tree to apply possible command line filters
        tests = tmt.Tree(tree=tests).tests(conditions=["manual is False"])
        self._tests = tests
Exemple #11
0
def main(click_contex, root, context, **kwargs):
    """ Test Management Tool """
    # Save click context and fmf context for future use
    tmt.utils.Common._save_context(click_contex)
    click_contex.obj = tmt.utils.Common()
    click_contex.obj.fmf_context = tmt.utils.context_to_dict(context)

    # Initialize metadata tree (from given path or current directory)
    tree = tmt.Tree(root or os.curdir)
    click_contex.obj.tree = tree

    # List of enabled steps
    click_contex.obj.steps = set()

    # Show overview of available tests, plans and stories
    if click_contex.invoked_subcommand is None:
        tmt.Test.overview(tree)
        tmt.Plan.overview(tree)
        tmt.Story.overview(tree)
Exemple #12
0
    def go(self):
        """ Discover available tests """
        super(DiscoverShell, self).go()
        tests = fmf.Tree(dict(summary='tests'))

        # Check and process each defined shell test
        for data in self.data['tests']:
            # Create data copy (we want to keep original data for save()
            data = copy.deepcopy(data)
            # Extract name, make sure it is present
            try:
                name = data.pop('name')
            except KeyError:
                raise tmt.utils.SpecificationError(
                    f"Missing test name in '{self.step.plan.name}'.")
            # Make sure that the test script is defined
            if 'test' not in data:
                raise tmt.utils.SpecificationError(
                    f"Missing test script in '{self.step.plan.name}'.")
            # Prepare path to the test working directory (tree root by default)
            try:
                data['path'] = f"/tests{data['path']}"
            except KeyError:
                data['path'] = f"/tests"
            # Apply default test duration unless provided
            if 'duration' not in data:
                data['duration'] = tmt.base.DEFAULT_TEST_DURATION_L2

            # Create a simple fmf node, adjust its name
            tests.child(name, data)

        # Symlink tests directory to the plan work tree
        testdir = os.path.join(self.workdir, "tests")
        relative_path = os.path.relpath(self.step.plan.worktree, self.workdir)
        os.symlink(relative_path, testdir)

        # Use a tmt.Tree to apply possible command line filters
        tests = tmt.Tree(tree=tests).tests(conditions=["manual is False"])
        self._tests = tests
Exemple #13
0
 def go(self):
     """ Discover available tests """
     super(DiscoverShell, self).go()
     tests = fmf.Tree(dict(summary='tests'))
     path = False
     for data in self.data['tests']:
         # Extract name, make sure it is present
         try:
             name = data.pop('name')
         except KeyError:
             raise tmt.utils.SpecificationError(
                 f"Missing test name in '{self.step.plan.name}'.")
         # Make sure that the test script is defined
         if 'test' not in data:
             raise tmt.utils.SpecificationError(
                 f"Missing test script in '{self.step.plan.name}'.")
         # Adjust path if necessary (defaults to '.')
         try:
             data['path'] = f"/{self.name}/tests{data['path']}"
             path = True
         except KeyError:
             data['path'] = '.'
         # Create a simple fmf node, adjust its name
         tests.child(name, data)
     # Copy current directory to workdir only if any path specified
     if path:
         directory = self.step.plan.run.tree.root
         testdir = os.path.join(self.workdir, 'tests')
         self.info('directory', directory, 'green')
         self.debug("Copy '{}' to '{}'.".format(directory, testdir))
         shutil.copytree(directory, testdir)
     # Use a tmt.Tree to apply possible command line filters
     tests = tmt.Tree(tree=tests).tests()
     # Summary of selected tests, test list in verbose mode
     summary = fmf.utils.listed(len(tests), 'test') + ' selected'
     self.info('tests', summary, 'green')
     for test in tests:
         self.verbose(test.name, color='red', shift=1)
     self._tests = tests
Exemple #14
0
 def go(self):
     """ Discover available tests """
     super(DiscoverFmf, self).go()
     testdir = os.path.join(self.workdir, 'tests')
     # Clone provided git repository
     if self.repository:
         self.info('repository', self.repository, 'green')
         self.debug(f"Clone '{self.repository}' to '{testdir}'.")
         self.run(f'git clone {self.repository} {testdir}')
     # Copy current directory to workdir
     else:
         directory = self.step.plan.run.tree.root
         self.info('directory', directory, 'green')
         self.debug("Copy '{}' to '{}'.".format(directory, testdir))
         shutil.copytree(directory, testdir)
     # Checkout revision if requested
     if self.revision:
         self.info('revision', self.revision, 'green')
         self.debug(f"Checkout revision '{self.revision}'.")
         self.run(f"git checkout -f {self.revision}", cwd=testdir)
     # Show filters if provided
     if self.filters:
         for filter_ in self.filters:
             self.info('filter', filter_, 'green')
     # Initialize the metadata tree
     self.debug(f"Check metadata tree in '{testdir}'.")
     # Nothing more to do here when in dry mode
     if self.opt('dry'):
         return []
     tests = tmt.Tree(testdir).tests(filters=self.filters)
     # Modify test names and paths to make them unique
     for test in tests:
         test.name = f"/{self.name}{test.name}"
         test.path = f"/{self.name}/tests{test.path}"
     # Summary of selected tests, test list in verbose mode
     self.info('tests', listed(len(tests), 'test') + ' selected', 'green')
     for test in tests:
         self.verbose(test.name, color='red', shift=1)
     self._tests = tests
Exemple #15
0
Fichier : fmf.py Projet : thrix/tmt
    def go(self):
        """ Discover available tests """
        super(DiscoverFmf, self).go()

        # Check url and path, prepare test directory
        url = self.get('url')
        path = self.get('path')
        testdir = os.path.join(self.workdir, 'tests')

        # Clone provided git repository (if url given) with disabled
        # prompt to ignore possibly missing or private repositories
        if url:
            self.info('url', url, 'green')
            self.debug(f"Clone '{url}' to '{testdir}'.")
            self.run(['git', 'clone', url, testdir],
                     shell=False,
                     env={"GIT_ASKPASS": "******"})
        # Copy git repository root to workdir
        else:
            if path and not os.path.isdir(path):
                raise tmt.utils.DiscoverError(
                    f"Provided path '{path}' is not a directory.")
            fmf_root = path or self.step.plan.my_run.tree.root
            # Check git repository root (use fmf root if not found)
            try:
                output = self.run('git rev-parse --show-toplevel',
                                  cwd=fmf_root,
                                  dry=True)
                git_root = output[0].strip('\n')
            except tmt.utils.RunError:
                self.debug(f"Git root not found, using '{fmf_root}.'")
                git_root = fmf_root
            # Set path to relative path from the git root to fmf root
            path = os.path.relpath(fmf_root, git_root)
            self.info('directory', git_root, 'green')
            self.debug(f"Copy '{git_root}' to '{testdir}'.")
            if not self.opt('dry'):
                shutil.copytree(git_root, testdir, symlinks=True)

        # Checkout revision if requested
        ref = self.get('ref')
        if ref:
            self.info('ref', ref, 'green')
            self.debug(f"Checkout ref '{ref}'.")
            self.run(['git', 'checkout', '-f', ref], cwd=testdir, shell=False)

        # Show current commit hash if inside a git repository
        try:
            hash_, _ = self.run('git rev-parse --short HEAD', cwd=testdir)
            self.verbose('hash', hash_.strip(), 'green')
        except (tmt.utils.RunError, AttributeError):
            pass

        # Adjust path and optionally show
        if path is None or path == '.':
            path = ''
        else:
            self.info('path', path, 'green')

        # Prepare the whole tree path and test path prefix
        tree_path = os.path.join(testdir, path.lstrip('/'))
        if not os.path.isdir(tree_path) and not self.opt('dry'):
            raise tmt.utils.DiscoverError(
                f"Metadata tree path '{path}' not found.")
        prefix_path = os.path.join('/tests', path.lstrip('/'))

        # Show filters and test names if provided
        # Check the 'test --filter' option first, then from discover
        filters = list(tmt.base.Test._opt('filters') or self.get('filter', []))
        for filter_ in filters:
            self.info('filter', filter_, 'green')
        # Check the 'test --name' option first, then 'test' from discover
        names = list(tmt.base.Test._opt('names') or self.get('test', []))
        if names:
            self.info('names', fmf.utils.listed(names), 'green')

        # Filter only modified tests if requested
        modified_only = self.get('modified-only')
        modified_url = self.get('modified-url')
        if modified_url:
            self.info('modified-url', modified_url, 'green')
            self.debug(f"Fetch also '{modified_url}' as 'reference'.")
            self.run(['git', 'remote', 'add', 'reference', modified_url],
                     cwd=testdir,
                     shell=False)
            self.run(['git', 'fetch', 'reference'], cwd=testdir, shell=False)
        if modified_only:
            modified_ref = self.get('modified-ref',
                                    tmt.utils.default_branch(testdir))
            self.info('modified-ref', modified_ref, 'green')
            output = self.run([
                'git', 'log', '--format=', '--stat', '--name-only',
                f"{modified_ref}..HEAD"
            ],
                              cwd=testdir,
                              shell=False)[0]
            modified = set(f"^/{re.escape(name)}"
                           for name in map(os.path.dirname, output.split('\n'))
                           if name)
            self.debug(f"Limit to modified test dirs: {modified}", level=3)
            names.extend(modified)

        # Initialize the metadata tree, search for available tests
        self.debug(f"Check metadata tree in '{tree_path}'.")
        if self.opt('dry'):
            self._tests = []
            return
        tree = tmt.Tree(path=tree_path, context=self.step.plan._fmf_context())
        self._tests = tree.tests(filters=filters, names=names)

        # Prefix tests and handle library requires
        for test in self._tests:
            # Prefix test path with 'tests' and possible 'path' prefix
            test.path = os.path.join(prefix_path, test.path.lstrip('/'))
            # Check for possible required beakerlib libraries
            if test.require or test.recommend:
                test.require, test.recommend, _ = tmt.beakerlib.dependencies(
                    test.require, test.recommend, parent=self)
Exemple #16
0
from mock import Mock as MagicMock


class Mock(MagicMock):
    @classmethod
    def __getattr__(cls, name):
        return Mock()


MOCK_MODULES = ['testcloud', 'testcloud.image', 'testcloud.instance']
sys.modules.update((mod_name, Mock()) for mod_name in MOCK_MODULES)

# Generate stories
import tmt

tree = tmt.Tree('.')

areas = {
    '/stories/docs': 'Documentation',
    '/stories/cli': 'Command Line',
    '/stories/install': 'Installation',
    '/stories/coverage': 'Coverage',
    '/spec/core': 'Core',
    '/spec/tests': 'Tests',
    '/spec/plans': 'Plans',
    '/spec/steps': 'Steps',
    '/spec/stories': 'Stories',
    '/spec/context': 'Context',
}

os.makedirs('stories', exist_ok=True)
Exemple #17
0
import tmt

tree = tmt.Tree('data')


def test_root():
    root = tree.tests(names=['/root'])[0]
    assert root.summary == 'Test in the root directory'
    assert root.path == '/'


def test_simple():
    simple = tree.tests(names=['/simple'])[0]
    assert simple.summary == 'Simple test in a separate directory'
    assert simple.path == '/simple'


def test_virtual():
    for virtual in tree.tests(names=['/virtual']):
        assert 'Virtual test' in virtual.summary
        assert virtual.path == '/virtual'
Exemple #18
0
    def go(self):
        """ Discover available tests """
        super(DiscoverFmf, self).go()

        # Check url and path, prepare test directory
        url = self.get('url')
        path = self.get('path')
        testdir = os.path.join(self.workdir, 'tests')
        dist_git_source = self.get('dist-git-source', False)

        # Raise an exception if --fmf-id uses w/o url and git root
        # doesn't exist for discovered plan
        if self.opt('fmf_id'):

            def assert_git_url(plan_name=None):
                try:
                    subprocess.run('git rev-parse --show-toplevel'.split(),
                                   stdout=subprocess.PIPE,
                                   stderr=subprocess.DEVNULL,
                                   check=True)
                except subprocess.CalledProcessError:
                    raise tmt.utils.DiscoverError(
                        f"`tmt run discover --fmf-id` without `url` option in "
                        f"plan `{plan_name}` can be used only within"
                        f" git repo.")

            # It covers only one case, when there is:
            # 1) no --url on CLI
            # 2) plan w/o url exists in test run
            if not self.opt('url'):
                try:
                    fmf_tree = fmf.Tree(os.getcwd())
                except fmf.utils.RootError:
                    raise tmt.utils.DiscoverError(
                        f"No metadata found in the current directory. "
                        f"Use 'tmt init' to get started.")
                for i, attr in enumerate(fmf_tree.climb()):
                    try:
                        plan_url = attr.data.get('discover').get('url')
                        plan_name = attr.name
                        if not plan_url:
                            assert_git_url(plan_name)
                    except AttributeError:
                        pass
            # All other cases are covered by this condition
            if not url:
                assert_git_url(self.step.plan.name)

        # Clone provided git repository (if url given) with disabled
        # prompt to ignore possibly missing or private repositories
        if url:
            self.info('url', url, 'green')
            self.debug(f"Clone '{url}' to '{testdir}'.")
            self.run(['git', 'clone', url, testdir],
                     env={"GIT_ASKPASS": "******"})
        # Copy git repository root to workdir
        else:
            # Path for distgit sources cannot be checked until the
            # tarball is extracted
            if path and not os.path.isdir(path) and not dist_git_source:
                raise tmt.utils.DiscoverError(
                    f"Provided path '{path}' is not a directory.")
            if dist_git_source:
                git_root = self.step.plan.my_run.tree.root
            else:
                fmf_root = path or self.step.plan.my_run.tree.root
                if fmf_root is None:
                    raise tmt.utils.DiscoverError(
                        f"No metadata found in the current directory.")
                # Check git repository root (use fmf root if not found)
                try:
                    output = self.run(["git", "rev-parse", "--show-toplevel"],
                                      cwd=fmf_root,
                                      dry=True)
                    git_root = output[0].strip('\n')
                except tmt.utils.RunError:
                    self.debug(f"Git root not found, using '{fmf_root}.'")
                    git_root = fmf_root
                # Set path to relative path from the git root to fmf root
                path = os.path.relpath(fmf_root, git_root)
            self.info('directory', git_root, 'green')
            self.debug(f"Copy '{git_root}' to '{testdir}'.")
            if not self.opt('dry'):
                shutil.copytree(git_root, testdir, symlinks=True)

        # Checkout revision if requested
        ref = self.get('ref')
        if ref:
            self.info('ref', ref, 'green')
            self.debug(f"Checkout ref '{ref}'.")
            self.run(['git', 'checkout', '-f', str(ref)], cwd=testdir)

        # Show current commit hash if inside a git repository
        try:
            hash_, _ = self.run(["git", "rev-parse", "--short", "HEAD"],
                                cwd=testdir)
            self.verbose('hash', hash_.strip(), 'green')
        except (tmt.utils.RunError, AttributeError):
            pass

        # Fetch and extract distgit sources
        if dist_git_source:
            try:
                self.extract_distgit_source(testdir, testdir,
                                            self.get('dist-git-type'))
            except Exception as error:
                raise tmt.utils.DiscoverError(
                    f"Failed to process 'dist-git-source'.", original=error)

        # Adjust path and optionally show
        if path is None or path == '.':
            path = ''
        else:
            self.info('path', path, 'green')

        # Prepare the whole tree path and test path prefix
        tree_path = os.path.join(testdir, path.lstrip('/'))
        if not os.path.isdir(tree_path) and not self.opt('dry'):
            raise tmt.utils.DiscoverError(
                f"Metadata tree path '{path}' not found.")
        prefix_path = os.path.join('/tests', path.lstrip('/'))

        # Show filters and test names if provided
        # Check the 'test --filter' option first, then from discover
        filters = list(tmt.base.Test._opt('filters') or self.get('filter', []))
        for filter_ in filters:
            self.info('filter', filter_, 'green')
        # Names of tests selected by --test option
        names = self.get('test', [])
        if names:
            self.info('tests', fmf.utils.listed(names), 'green')
        # Check the 'test --link' option first, then from discover
        links = list(tmt.base.Test._opt('link') or self.get('link', []))
        for link_ in links:
            self.info('link', link_, 'green')

        excludes = list(
            tmt.base.Test._opt('exclude') or self.get('exclude', []))

        # Filter only modified tests if requested
        modified_only = self.get('modified-only')
        modified_url = self.get('modified-url')
        if modified_url:
            self.info('modified-url', modified_url, 'green')
            self.debug(f"Fetch also '{modified_url}' as 'reference'.")
            self.run(['git', 'remote', 'add', 'reference', modified_url],
                     cwd=testdir)
            self.run(['git', 'fetch', 'reference'], cwd=testdir)
        if modified_only:
            modified_ref = self.get('modified-ref',
                                    tmt.utils.default_branch(testdir))
            self.info('modified-ref', modified_ref, 'green')
            output = self.run([
                'git', 'log', '--format=', '--stat', '--name-only',
                f"{modified_ref}..HEAD"
            ],
                              cwd=testdir)[0]
            modified = set(f"^/{re.escape(name)}"
                           for name in map(os.path.dirname, output.split('\n'))
                           if name)
            self.debug(f"Limit to modified test dirs: {modified}", level=3)
            names.extend(modified)

        # Initialize the metadata tree, search for available tests
        self.debug(f"Check metadata tree in '{tree_path}'.")
        if self.opt('dry'):
            self._tests = []
            return
        tree = tmt.Tree(path=tree_path, context=self.step.plan._fmf_context())
        self._tests = tree.tests(filters=filters,
                                 names=names,
                                 conditions=["manual is False"],
                                 unique=False,
                                 links=links,
                                 excludes=excludes)

        # Prefix tests and handle library requires
        for test in self._tests:
            # Prefix test path with 'tests' and possible 'path' prefix
            test.path = os.path.join(prefix_path, test.path.lstrip('/'))
            # Check for possible required beakerlib libraries
            if test.require or test.recommend:
                test.require, test.recommend, _ = tmt.beakerlib.dependencies(
                    test.require, test.recommend, parent=self)
Exemple #19
0
    def go(self):
        """ Discover available tests """
        super(DiscoverFmf, self).go()

        # Check url and path, prepare test directory
        url = self.get('url')
        path = self.get('path')
        testdir = os.path.join(self.workdir, 'tests')

        # Clone provided git repository (if url given)
        if url:
            self.info('url', url, 'green')
            self.debug(f"Clone '{url}' to '{testdir}'.")
            self.run(['git', 'clone', url, testdir], shell=False)
        # Copy git repository root to workdir
        else:
            if path and not os.path.isdir(path):
                raise tmt.utils.DiscoverError(
                    f"Provided path '{path}' is not a directory.")
            fmf_root = path or self.step.plan.run.tree.root
            # Check git repository root (use fmf root if not found)
            try:
                output = self.run(
                    'git rev-parse --show-toplevel', cwd=fmf_root, dry=True)
                git_root = output[0].strip('\n')
            except tmt.utils.RunError:
                self.debug(f"Git root not found, using '{fmf_root}.'")
                git_root = fmf_root
            # Set path to relative path from the git root to fmf root
            path = os.path.relpath(fmf_root, git_root)
            self.info('directory', git_root, 'green')
            self.debug(f"Copy '{git_root}' to '{testdir}'.")
            if not self.opt('dry'):
                shutil.copytree(git_root, testdir)

        # Checkout revision if requested
        ref = self.get('ref')
        if ref:
            self.info('ref', ref, 'green')
            self.debug(f"Checkout ref '{ref}'.")
            self.run(['git', 'checkout', '-f', ref], cwd=testdir, shell=False)

        # Adjust path and optionally show
        if path is None or path == '.':
            path = ''
        else:
            self.info('path', path, 'green')

        # Prepare the whole tree path and test path prefix
        tree_path = os.path.join(testdir, path.lstrip('/'))
        if not os.path.isdir(tree_path) and not self.opt('dry'):
            raise tmt.utils.DiscoverError(
                f"Metadata tree path '{path}' not found.")
        prefix_path = os.path.join('/tests', path.lstrip('/'))

        # Show filters and test names if provided
        filters = self.get('filter', [])
        for filter_ in filters:
            self.info('filter', filter_, 'green')
        names = self.get('test', [])
        if names:
            self.info('names', fmf.utils.listed(names), 'green')

        # Initialize the metadata tree, search for available tests
        self.debug(f"Check metadata tree in '{tree_path}'.")
        if self.opt('dry'):
            self._tests = []
            return
        self._tests = tmt.Tree(tree_path).tests(filters=filters, names=names)

        # Prefix tests and handle library requires
        for test in self._tests:
            # Prefix test path with 'tests' and possible 'path' prefix
            test.path = os.path.join(prefix_path, test.path.lstrip('/'))
            # Check for possible required beakerlib libraries
            if test.require:
                test.require, test.recommend, _ = tmt.beakerlib.dependencies(
                    test.require, test.recommend, parent=self)
Exemple #20
0
    def go(self):
        """ Discover available tests """
        super(DiscoverFmf, self).go()

        # Check url and path, prepare test directory
        url = self.get('url')
        path = self.get('path')
        testdir = os.path.join(self.workdir, 'tests')

        # Clone provided git repository (if url given)
        if url:
            self.info('url', url, 'green')
            self.debug(f"Clone '{url}' to '{testdir}'.")
            self.run(f'git clone {url} {testdir}')
        # Copy git repository root to workdir
        else:
            if path and not os.path.isdir(path):
                raise tmt.utils.GeneralError(
                    f"Provided path '{path}' is not a directory.")
            fmf_root = path or self.step.plan.run.tree.root
            output = self.run('git rev-parse --show-toplevel', cwd=fmf_root)
            git_root = output[0].strip('\n')
            # Set path to relative path from the git root to fmf root
            path = os.path.relpath(fmf_root, git_root)
            self.info('directory', git_root, 'green')
            self.debug(f"Copy '{git_root}' to '{testdir}'.")
            shutil.copytree(git_root, testdir)

        # Checkout revision if requested
        ref = self.get('ref')
        if ref:
            self.info('ref', ref, 'green')
            self.debug(f"Checkout ref '{ref}'.")
            self.run(f"git checkout -f {ref}", cwd=testdir)

        # Adjust path and optionally show
        if path is None or path == '.':
            path = ''
        else:
            self.info('path', path, 'green')

        # Prepare the whole tree path and test path prefix
        tree_path = os.path.join(testdir, path.lstrip('/'))
        if not os.path.isdir(tree_path):
            raise tmt.utils.GeneralError(
                f"Metadata tree path '{path}' not found.")
        prefix_path = os.path.join('/tests', path.lstrip('/'))

        # Show filters and test names if provided
        filters = self.get('filter', [])
        for filter_ in filters:
            self.info('filter', filter_, 'green')
        names = self.get('test', [])
        if names:
            self.info('names', fmf.utils.listed(names), 'green')

        # Initialize the metadata tree, search for available tests
        self.debug(f"Check metadata tree in '{tree_path}'.")
        if self.opt('dry'):
            return
        self._tests = tmt.Tree(tree_path).tests(filters=filters, names=names)

        # Prefix test path with 'tests' and possible 'path' prefix
        for test in self._tests:
            test.path = os.path.join(prefix_path, test.path.lstrip('/'))