import helper
import log
-global_fixtures = []
-
class SkipException(Exception):
def __init__(self, fixture, testitem):
self.fixture = fixture
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
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
'''
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
+# 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.
#
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( **{
'''
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)
)
@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):
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
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
: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'
]
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):