# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#
-# Authors: Sean Wilson
import os
import tempfile
import shutil
+import sys
+import socket
import threading
+from six.moves import urllib
+
from testlib.fixture import Fixture
-from testlib.config import config, constants
+from testlib.configuration import config, constants
from testlib.helper import log_call, cacheresult, joinpath, absdirpath
import testlib.log as log
+from testlib.state import Result
class VariableFixture(Fixture):
def setup(self, testitem):
self.path = tempfile.mkdtemp(prefix='gem5out')
+ def post_test_procedure(self, testitem):
+ suiteUID = testitem.metadata.uid.suite
+ testUID = testitem.metadata.name
+ testing_result_folder = os.path.join(config.result_path,
+ "SuiteUID:" + suiteUID,
+ "TestUID:" + testUID)
+
+ # Copy the output files of the run from /tmp to testing-results
+ # We want to wipe the entire result folder for this test first. Why?
+ # If the result folder exists (probably from the previous run), if
+ # this run emits fewer files, there'll be files from the previous
+ # run in this folder, which would cause confusion if one does not
+ # check the timestamp of the file.
+ if os.path.exists(testing_result_folder):
+ shutil.rmtree(testing_result_folder)
+ shutil.copytree(self.path, testing_result_folder)
+
def teardown(self, testitem):
- if self.path is not None:
+ if testitem.result == Result.Passed:
shutil.rmtree(self.path)
- def skip_cleanup(self):
- # Set path to none so it's not deleted
- self.path = None
-
class UniqueFixture(Fixture):
'''
Base class for fixtures that generate a target in the
command.extend(self.targets)
if self.options:
command.extend(self.options)
- log_call(log.test_log, command)
+ log_call(log.test_log, command, stderr=sys.stderr)
class Gem5Fixture(SConsFixture):
def __new__(cls, isa, variant, protocol=None):
targets = set(self.required_by)
command = ['make', '-C', self.directory]
command.extend([target.target for target in targets])
- log_call(command)
+ log_call(log.test_log, command, stderr=sys.stderr)
class MakeTarget(Fixture):
class TestProgram(MakeTarget):
def __init__(self, program, isa, os, recompile=False):
- make_dir = joinpath('test-progs', program)
+ make_dir = joinpath(config.bin_dir, program)
make_fixture = MakeFixture(make_dir)
target = joinpath('bin', isa, os, program)
super(TestProgram, self).__init__(target, make_fixture)
elif not os.path.exists(self.path):
super(MakeTarget, self).setup()
-class DownloadedProgram(Fixture):
+class DownloadedProgram(UniqueFixture):
""" Like TestProgram, but checks the version in the gem5 binary repository
and downloads an updated version if it is needed.
"""
- urlbase = "http://gem5.org/dist/current/"
- def __init__(self, path, program, **kwargs):
+ def __new__(cls, url, path, filename):
+ target = joinpath(path, filename)
+ return super(DownloadedProgram, cls).__new__(cls, target)
+
+ def _init(self, url, path, filename, **kwargs):
"""
+ url: string
+ The url of the archive
path: string
- The path to the directory containing the binary relative to
- $GEM5_BASE/tests
- program: string
- The name of the binary file
+ The absolute path of the directory containing the archive
+ filename: string
+ The name of the archive
"""
- super(DownloadedProgram, self).__init__("download-" + program,
- build_once=True, **kwargs)
- self.program_dir = path
- relative_path = joinpath(self.program_dir, program)
- self.url = self.urlbase + relative_path
- self.path = os.path.realpath(
- joinpath(absdirpath(__file__), '../', relative_path)
- )
+ self.url = url
+ self.path = path
+ self.filename = joinpath(path, filename)
+ self.name = "Downloaded:" + self.filename
def _download(self):
- import urllib
import errno
log.test_log.debug("Downloading " + self.url + " to " + self.path)
- if not os.path.exists(self.program_dir):
+ if not os.path.exists(self.path):
try:
- os.makedirs(self.program_dir)
+ os.makedirs(self.path)
except OSError as e:
if e.errno != errno.EEXIST:
raise
- urllib.urlretrieve(self.url, self.path)
+ urllib.request.urlretrieve(self.url, self.filename)
def _getremotetime(self):
- import urllib2, datetime, time
+ import datetime, time
import _strptime # Needed for python threading bug
- u = urllib2.urlopen(self.url)
+ u = urllib.request.urlopen(self.url, timeout=10)
+
return time.mktime(datetime.datetime.strptime( \
- u.info().getheaders("Last-Modified")[0],
+ u.info()["Last-Modified"],
"%a, %d %b %Y %X GMT").timetuple())
- def setup(self, testitem):
- import urllib2
+ def _setup(self, testitem):
# Check to see if there is a file downloaded
- if not os.path.exists(self.path):
+ if not os.path.exists(self.filename):
+ self._download()
+ else:
+ try:
+ t = self._getremotetime()
+ except (urllib.error.URLError, socket.timeout):
+ # Problem checking the server, use the old files.
+ log.test_log.debug("Could not contact server. Binaries may be old.")
+ return
+ # If the server version is more recent, download it
+ if t > os.path.getmtime(self.filename):
+ self._download()
+
+class DownloadedArchive(DownloadedProgram):
+ """ Like TestProgram, but checks the version in the gem5 binary repository
+ and downloads an updated version if it is needed.
+ """
+
+ def _extract(self):
+ import tarfile
+ with tarfile.open(self.filename) as tf:
+ tf.extractall(self.path)
+
+ def _setup(self, testitem):
+ # Check to see if there is a file downloaded
+ if not os.path.exists(self.filename):
self._download()
+ self._extract()
else:
try:
t = self._getremotetime()
- except urllib2.URLError:
+ except (urllib.error.URLError, socket.timeout):
# Problem checking the server, use the old files.
- log.debug("Could not contact server. Binaries may be old.")
+ log.test_log.debug("Could not contact server. "
+ "Binaries may be old.")
return
# If the server version is more recent, download it
- if t > os.path.getmtime(self.path):
+ if t > os.path.getmtime(self.filename):
self._download()
+ self._extract()