~le-chi-thu/lava-test/add-verbose-argument

« back to all changes in this revision

Viewing changes to lava_test/core/tests.py

  • Committer: Paul Larson
  • Date: 2011-09-22 17:58:01 UTC
  • mfrom: (92.1.4 using-lava-tool-2)
  • Revision ID: paul.larson@canonical.com-20110922175801-l99rky1xxsr6k3fn
Big refactoring branch to make lava-test use lava-tool.  Thanks to
Zygmunt and ChiThu!

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Copyright (c) 2010, 2011 Linaro
 
2
#
 
3
# This program is free software: you can redistribute it and/or modify
 
4
# it under the terms of the GNU General Public License as published by
 
5
# the Free Software Foundation, either version 3 of the License, or
 
6
# (at your option) any later version.
 
7
#
 
8
# This program is distributed in the hope that it will be useful,
 
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
11
# GNU General Public License for more details.
 
12
#
 
13
# You should have received a copy of the GNU General Public License
 
14
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
15
 
 
16
from __future__ import absolute_import
 
17
 
 
18
import json
 
19
import logging
 
20
import os
 
21
import shutil
 
22
 
 
23
from lava_test.api.core import ITest
 
24
from lava_test.core.artifacts import TestArtifacts
 
25
from lava_test.core.config import get_config
 
26
from lava_test.core.installers import TestInstaller
 
27
from lava_test.core.parsers import TestParser, NativeTestParser
 
28
from lava_test.core.runners import TestRunner
 
29
from lava_test.utils import changed_directory
 
30
 
 
31
 
 
32
class Test(ITest):
 
33
    """
 
34
    Reusable class for defining tests.
 
35
 
 
36
    This class uses composition instead of inheritance. You should be able to
 
37
    customize the parts you care about by providing delegate objects. This
 
38
    class can be used by test definition files to create an object that
 
39
    contains the building blocks for installing tests, running them, and
 
40
    parsing the results.
 
41
 
 
42
    :ivar test_id:
 
43
        Name of the test or test suite
 
44
    :ivar test_version:
 
45
        Version of the test or test suite
 
46
    :ivar installer:
 
47
        ITestInstaller instance to use
 
48
    :ivar runner:
 
49
        ITestRunner instance to use
 
50
    :ivar parser:
 
51
        ITestParser instance to use
 
52
    """
 
53
 
 
54
    def __init__(self, test_id, test_version=None,
 
55
                 installer=None, runner=None, parser=None):
 
56
        self._test_id = test_id
 
57
        self._test_version = test_version
 
58
        # Delegate objects
 
59
        self.installer = installer
 
60
        self.runner = runner
 
61
        self.parser = parser
 
62
        # Config instance
 
63
        self._config = get_config()
 
64
 
 
65
    def __repr__(self):
 
66
        return ("<%s test_id=%r test_version=%r installer=%r runner=%r"
 
67
                " parser=%r>") % (
 
68
                    self.__class__.__name__, self.test_id, self.test_version,
 
69
                    self.installer, self.runner, self.parser)
 
70
 
 
71
    @property
 
72
    def test_id(self):
 
73
        """
 
74
        Return the ID of the test.
 
75
        """
 
76
        return self._test_id
 
77
 
 
78
    @property
 
79
    def test_version(self):
 
80
        """
 
81
        Return the version of the test
 
82
        """
 
83
        return self._test_version
 
84
 
 
85
    @property
 
86
    def install_dir(self):
 
87
        """
 
88
        Pathname of a directory with binary and data files installed by the
 
89
        test.
 
90
 
 
91
        .. versionadded:: 0.2
 
92
        """
 
93
        return os.path.join(self._config.installdir, self.test_id)
 
94
 
 
95
    @property
 
96
    def is_installed(self):
 
97
        return os.path.exists(self.install_dir)
 
98
 
 
99
    def install(self, observer=None):
 
100
        if self.is_installed:
 
101
            raise RuntimeError(
 
102
                "%s is already installed" % self.test_id)
 
103
        if not self.installer:
 
104
            raise RuntimeError(
 
105
                "no installer defined for '%s'" % self.test_id)
 
106
        with changed_directory(self.install_dir):
 
107
            try:
 
108
                logging.debug(
 
109
                    "Invoking %r.install(...)", self.installer)
 
110
                self.installer.install(observer)
 
111
            except:
 
112
                self.uninstall()
 
113
                raise
 
114
 
 
115
    def uninstall(self):
 
116
        logging.debug("Removing test %r", self.test_id)
 
117
        if os.path.exists(self.install_dir):
 
118
            shutil.rmtree(self.install_dir)
 
119
 
 
120
    def run(self, observer=None):
 
121
        if not self.runner:
 
122
            raise RuntimeError(
 
123
                "no test runner defined for '%s'" % self.test_id)
 
124
        artifacts = TestArtifacts.allocate(self.test_id, self._config)
 
125
        with changed_directory(self.install_dir):
 
126
            logging.debug(
 
127
                "Invoking %r.run_and_store_artifacts(...)",
 
128
                self.runner, observer)
 
129
            self.runner.run(artifacts, observer)
 
130
        return artifacts
 
131
 
 
132
    def parse(self, artifacts):
 
133
        if self.parser:
 
134
            logging.debug("Invoking %r.parse()", self.parser)
 
135
            with changed_directory(artifacts.results_dir, False):
 
136
                self.parser.parse(artifacts)
 
137
            return self.parser.results
 
138
 
 
139
 
 
140
class DeclarativeTest(Test):
 
141
    """
 
142
    Declaretive ITest implementation.
 
143
 
 
144
    Declarative test is like :class:`lava_test.core.tests.Test` but cannot
 
145
    contain any python code and is completely encapsulated in a .json file.
 
146
 
 
147
    The idea is to write .json files that assemble a Test instance using
 
148
    readily-available TestInstaller, TestRunner and TestParser subclasses.
 
149
    """
 
150
 
 
151
    def __init__(self, about):
 
152
        self.about = about
 
153
        super(DeclarativeTest, self).__init__(self.about.get('test_id'))
 
154
        self.installer = TestInstaller(**self.about.get('install', {}))
 
155
        self.runner = TestRunner(**self.about.get('run', {}))
 
156
        if self.about.get('parse', {}).get('native', False) is True:
 
157
            self.parser = NativeTestParser(self)
 
158
        else:
 
159
            self.parser = TestParser(**self.about.get('parse', {}))
 
160
 
 
161
    @classmethod
 
162
    def load_from_stream(cls, stream):
 
163
        return cls(json.load(stream))
 
164
 
 
165
    def save_to_stream(self, stream):
 
166
        json.dumps(self.about, stream, indent="2")