diff options
-rw-r--r-- | ext/testlib/fixture.py | 28 | ||||
-rw-r--r-- | ext/testlib/loader.py | 5 | ||||
-rw-r--r-- | ext/testlib/main.py | 14 | ||||
-rw-r--r-- | ext/testlib/wrappers.py | 29 | ||||
-rw-r--r-- | tests/gem5/fixture.py | 94 |
5 files changed, 50 insertions, 120 deletions
diff --git a/ext/testlib/fixture.py b/ext/testlib/fixture.py index be8924474..7af6cb289 100644 --- a/ext/testlib/fixture.py +++ b/ext/testlib/fixture.py @@ -32,8 +32,6 @@ import traceback import helper import log -global_fixtures = [] - class SkipException(Exception): def __init__(self, fixture, testitem): self.fixture = fixture @@ -71,21 +69,11 @@ class Fixture(object): if name is None: name = self.__class__.__name__ self.name = name + self._is_global = False def skip(self, testitem): raise SkipException(self.name, testitem.metadata) - def schedule_finalized(self, schedule): - ''' - This method is called once the schedule of for tests is known. - To enable tests to use the same fixture defintion for each execution - fixtures must return a copy of themselves in this method. - - :returns: a copy of this fixture which will be setup/torndown - when the test item this object is tied to is about to execute. - ''' - return self.copy() - def init(self, *args, **kwargs): pass @@ -95,9 +83,6 @@ class Fixture(object): def teardown(self, testitem): pass - def copy(self): - return copy.deepcopy(self) - def skip_cleanup(self): ''' If this method is called, then we should make sure that nothing is @@ -105,11 +90,8 @@ class Fixture(object): ''' pass + def set_global(self): + self._is_global = True -def globalfixture(fixture): - ''' - Store the given fixture as a global fixture. Its setup() method - will be called before the first test is executed. - ''' - global_fixtures.append(fixture) - return fixture + def is_global(self): + return self._is_global diff --git a/ext/testlib/loader.py b/ext/testlib/loader.py index e788c33a9..8f8f60e70 100644 --- a/ext/testlib/loader.py +++ b/ext/testlib/loader.py @@ -147,7 +147,7 @@ class Loader(object): @property def schedule(self): - return wrappers.LoadedLibrary(self.suites, fixture_mod.global_fixtures) + return wrappers.LoadedLibrary(self.suites) def load_schedule_for_suites(self, *uids): files = {uid.UID.uid_to_path(id_) for id_ in uids} @@ -155,8 +155,7 @@ class Loader(object): self.load_file(file_) return wrappers.LoadedLibrary( - [self.suite_uids[id_] for id_ in uids], - fixture_mod.global_fixtures) + [self.suite_uids[id_] for id_ in uids]) def _verify_no_duplicate_suites(self, new_suites): new_suite_uids = self.suite_uids.copy() diff --git a/ext/testlib/main.py b/ext/testlib/main.py index ac795473d..cbba0005f 100644 --- a/ext/testlib/main.py +++ b/ext/testlib/main.py @@ -254,20 +254,6 @@ def run_schedule(test_schedule, log_handler): log_handler.schedule_finalized(test_schedule) - # Iterate through all fixtures notifying them of the test schedule. - for suite in test_schedule: - copied_fixtures = [] - for fixture in suite.fixtures: - copied_fixtures.append(fixture.schedule_finalized(test_schedule)) - suite.fixtures = copied_fixtures - - for test in suite: - copied_fixtures = [] - for fixture in test.fixtures: - copied_fixtures.append(fixture.schedule_finalized( - test_schedule)) - test.fixtures = copied_fixtures - log.test_log.message(terminal.separator()) log.test_log.message('Running Tests from {} suites' .format(len(test_schedule.suites)), bold=True) diff --git a/ext/testlib/wrappers.py b/ext/testlib/wrappers.py index 4e96f3629..4bd22a468 100644 --- a/ext/testlib/wrappers.py +++ b/ext/testlib/wrappers.py @@ -1,3 +1,15 @@ +# Copyright (c) 2019 ARM Limited +# All rights reserved +# +# The license below extends only to copyright in the software and shall +# not be construed as granting a license to any other intellectual +# property including but not limited to intellectual property relating +# to a hardware implementation of the functionality of the software +# licensed hereunder. You may use the software subject to the license +# terms below provided that you ensure that this notice is replicated +# unmodified and in its entirety in all distributions of the software, +# modified or unmodified, in source code or in binary form. +# # Copyright (c) 2017 Mark D. Hill and David A. Wood # All rights reserved. # @@ -179,9 +191,8 @@ class LoadedLibrary(LoadedTestable): Wraps a collection of all loaded test suites and provides utility functions for accessing fixtures. ''' - def __init__(self, suites, global_fixtures): + def __init__(self, suites): LoadedTestable.__init__(self, suites) - self.global_fixtures = global_fixtures def _generate_metadata(self): return LibraryMetadata( **{ @@ -196,19 +207,13 @@ class LoadedLibrary(LoadedTestable): ''' return iter(self.obj) - def all_fixture_tuples(self): - return itertools.chain( - self.global_fixtures, - *(suite.fixtures for suite in self.obj)) - def all_fixtures(self): ''' :returns: an interator overall all global, suite, and test fixtures ''' return itertools.chain(itertools.chain( - self.global_fixtures, - *(suite.fixtures for suite in self.obj)), + *(suite.fixtures for suite in self.obj)), *(self.test_fixtures(suite) for suite in self.obj) ) @@ -221,7 +226,11 @@ class LoadedLibrary(LoadedTestable): @property def fixtures(self): - return self.global_fixtures + global_fixtures = [] + for fixture in self.all_fixtures(): + if fixture.is_global(): + global_fixtures.append(fixture) + return global_fixtures @property def uid(self): diff --git a/tests/gem5/fixture.py b/tests/gem5/fixture.py index b04a334b0..e84b89f69 100644 --- a/tests/gem5/fixture.py +++ b/tests/gem5/fixture.py @@ -43,7 +43,7 @@ import tempfile import shutil import threading -from testlib.fixture import Fixture, globalfixture +from testlib.fixture import Fixture from testlib.config import config, constants from testlib.helper import log_call, cacheresult, joinpath, absdirpath import testlib.log as log @@ -112,7 +112,7 @@ class UniqueFixture(Fixture): self._setup(testitem) -class SConsFixture(Fixture): +class SConsFixture(UniqueFixture): ''' Fixture will wait until all SCons targets are collected and tests are about to be ran, then will invocate a single instance of SCons for all @@ -121,21 +121,18 @@ class SConsFixture(Fixture): :param directory: The directory which scons will -C (cd) into before executing. If None is provided, will choose the config base_dir. ''' - def __init__(self, directory=None, target_class=None, options=[]): - self.directory = directory if directory else config.base_dir - self.target_class = target_class if target_class else SConsTarget - self.threads = config.threads - self.targets = set() - self.options = options - super(SConsFixture, self).__init__() - def setup(self, testitem): + def __new__(cls, target): + obj = super(SConsFixture, cls).__new__(cls, target) + return obj + + def _setup(self, testitem): if config.skip_build: return command = [ 'scons', '-C', self.directory, - '-j', str(self.threads), + '-j', str(config.threads), '--ignore-style' ] @@ -159,70 +156,27 @@ class SConsFixture(Fixture): command.extend(self.options) log_call(log.test_log, command) - -class SConsTarget(Fixture): - # The singleton scons fixture we'll use for all targets. - default_scons_invocation = None - - def __init__(self, target, build_dir=None, invocation=None): - ''' - Represents a target to be built by an 'invocation' of scons. - - :param target: The target known to scons. - - :param build_dir: The 'build' directory path which will be prepended - to the target name. - - :param invocation: Represents an invocation of scons which we will - automatically attach this target to. If None provided, uses the - main 'scons' invocation. - ''' - - if build_dir is None: - build_dir = config.build_dir - self.target = os.path.join(build_dir, target) - super(SConsTarget, self).__init__(name=target) - - if invocation is None: - if self.default_scons_invocation is None: - SConsTarget.default_scons_invocation = SConsFixture() - globalfixture(SConsTarget.default_scons_invocation) - - invocation = self.default_scons_invocation - self.invocation = invocation - - def schedule_finalized(self, schedule): - self.invocation.targets.add(self.target) - return Fixture.schedule_finalized(self, schedule) - -class Gem5Fixture(SConsTarget): - other_invocations = {} # stores scons invocations other than the default - - def __init__(self, isa, variant, protocol=None): +class Gem5Fixture(SConsFixture): + def __new__(cls, isa, variant, protocol=None): + target_dir = joinpath(config.build_dir, isa.upper()) if protocol: - # When specifying an non-default protocol, we have to make a - # separate scons invocation with specific parameters. However, if - # more than one tests needs the same target, we need to make sure - # that we don't call scons too many times. - target_dir = isa.upper()+'-'+protocol - target = joinpath(target_dir, 'gem5.%s' % variant) - if target_dir in self.other_invocations.keys(): - invocation = self.other_invocations[target_dir] - else: - options = ['PROTOCOL='+protocol, '--default='+isa.upper()] - invocation = SConsFixture(options=options) - globalfixture(invocation) - Gem5Fixture.other_invocations[target_dir] = invocation - else: - target = joinpath(isa.upper(), 'gem5.%s' % variant) - invocation = None # use default - super(Gem5Fixture, self).__init__(target, invocation=invocation) + target_dir += '_' + protocol + target = joinpath(target_dir, 'gem5.%s' % variant) + obj = super(Gem5Fixture, cls).__new__(cls, target) + return obj + def _init(self, isa, variant, protocol=None): self.name = constants.gem5_binary_fixture_name + + self.targets = [self.target] self.path = self.target - self.isa = isa - self.variant = variant + self.directory = config.base_dir + self.options = [] + if protocol: + self.options = [ '--default=' + isa.upper(), + 'PROTOCOL=' + protocol ] + self.set_global() class MakeFixture(Fixture): def __init__(self, directory, *args, **kwargs): |