tests,python: Upgrading testlib to function with Python2

Change-Id: I9926b1507e9069ae8564c31bdd377b2b916462a2
Issue-on: https://gem5.atlassian.net/browse/GEM5-395
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/29088
Reviewed-by: Bobby R. Bruce <bbruce@ucdavis.edu>
Maintainer: Bobby R. Bruce <bbruce@ucdavis.edu>
Tested-by: kokoro <noreply+kokoro@google.com>
This commit is contained in:
Bobby R. Bruce
2020-04-16 11:55:17 -07:00
parent 80a2636983
commit 7ffd684334
31 changed files with 190 additions and 164 deletions

View File

@@ -29,12 +29,12 @@
from .state import *
from .runner import *
from .test import *
from .test_util import *
from .suite import *
from .loader import *
from .fixture import *
from .config import *
from main import main
from .configuration import *
from .main import main
#TODO Remove this awkward bootstrap
#FIXME

View File

@@ -83,10 +83,11 @@ import copy
import os
import re
from ConfigParser import ConfigParser
from six import add_metaclass
from six.moves import configparser as ConfigParser
from pickle import HIGHEST_PROTOCOL as highest_pickle_protocol
from helper import absdirpath, AttrDict, FrozenAttrDict
from testlib.helper import absdirpath, AttrDict, FrozenAttrDict
class UninitialzedAttributeException(Exception):
'''
@@ -598,9 +599,8 @@ def define_common_args(config):
# one in the list will be saved.
common_args = AttrDict({arg.name:arg for arg in common_args})
@add_metaclass(abc.ABCMeta)
class ArgParser(object):
__metaclass__ = abc.ABCMeta
def __init__(self, parser):
# Copy public methods of the parser.

View File

@@ -29,8 +29,8 @@
import copy
import traceback
import helper
import log
import testlib.helper as helper
import testlib.log as log
class SkipException(Exception):
def __init__(self, fixture, testitem):
@@ -61,7 +61,7 @@ class Fixture(object):
collector = helper.InstanceCollector()
def __new__(klass, *args, **kwargs):
obj = super(Fixture, klass).__new__(klass, *args, **kwargs)
obj = super(Fixture, klass).__new__(klass)
Fixture.collector.collect(obj)
return obj

View File

@@ -35,20 +35,20 @@ from __future__ import print_function
import multiprocessing
import os
import Queue
import sys
import threading
import time
import traceback
import helper
import log
import result
import state
import test
import terminal
import testlib.helper as helper
import testlib.log as log
import testlib.result as result
import testlib.state as state
import testlib.test_util as test
import testlib.terminal as terminal
from config import config, constants
from six.moves import queue as Queue
from testlib.configuration import config, constants
class _TestStreamManager(object):

View File

@@ -34,7 +34,6 @@ from collections import MutableSet, OrderedDict
import difflib
import errno
import os
import Queue
import re
import shutil
import stat
@@ -44,6 +43,8 @@ import threading
import time
import traceback
from six.moves import queue as Queue
#TODO Tear out duplicate logic from the sandbox IOManager
def log_call(logger, command, *popenargs, **kwargs):
'''
@@ -80,7 +81,8 @@ def log_call(logger, command, *popenargs, **kwargs):
def log_output(log_callback, pipe, redirects=tuple()):
# Read iteractively, don't allow input to fill the pipe.
for line in iter(pipe.readline, ''):
for line in iter(pipe.readline, b''):
line = line.decode("utf-8")
for r in redirects:
r.write(line)
log_callback(line.rstrip())

View File

@@ -67,16 +67,17 @@ a :class:`TestSuite` named after the module.
import os
import re
import six
import sys
import traceback
import config
import log
import suite as suite_mod
import test as test_mod
import fixture as fixture_mod
import wrappers
import uid
import testlib.configuration as configuration
import testlib.log as log
import testlib.suite as suite_mod
import testlib.test_util as test_mod
import testlib.fixture as fixture_mod
import testlib.wrappers as wrappers
import testlib.uid as uid
class DuplicateTestItemException(Exception):
'''
@@ -112,7 +113,7 @@ def _assert_files_in_same_dir(files):
if files:
directory = os.path.dirname(files[0])
for f in files:
assert os.path.dirname(f) == directory
assert(os.path.dirname(f) == directory)
class Loader(object):
'''
@@ -186,6 +187,7 @@ class Loader(object):
self._loaded_a_file = True
for directory in self._discover_files(root):
directory = list(directory)
if directory:
_assert_files_in_same_dir(directory)
for f in directory:
@@ -193,6 +195,7 @@ class Loader(object):
def load_dir(self, directory):
for dir_ in self._discover_files(directory):
directory = list(directory)
_assert_files_in_same_dir(dir_)
for f in dir_:
self.load_file(f)
@@ -221,29 +224,27 @@ class Loader(object):
sys.path.insert(0, os.path.dirname(path))
cwd = os.getcwd()
os.chdir(os.path.dirname(path))
config.config.file_under_load = path
configuration.config.file_under_load = path
new_tests = test_mod.TestCase.collector.create()
new_suites = suite_mod.TestSuite.collector.create()
new_fixtures = fixture_mod.Fixture.collector.create()
def cleanup():
config.config.file_under_load = None
sys.path[:] = old_path
os.chdir(cwd)
test_mod.TestCase.collector.remove(new_tests)
suite_mod.TestSuite.collector.remove(new_suites)
fixture_mod.Fixture.collector.remove(new_fixtures)
try:
execfile(path, newdict, newdict)
exec(open(path).read(), newdict, newdict)
except Exception as e:
log.test_log.debug(traceback.format_exc())
log.test_log.warn(
'Exception thrown while loading "%s"\n'
'Ignoring all tests in this file.'
% (path))
cleanup()
# Clean up
configuration.config.file_under_load = None
sys.path[:] = old_path
os.chdir(cwd)
test_mod.TestCase.collector.remove(new_tests)
suite_mod.TestSuite.collector.remove(new_suites)
fixture_mod.Fixture.collector.remove(new_fixtures)
return
# Create a module test suite for those not contained in a suite.
@@ -281,7 +282,13 @@ class Loader(object):
self.suites.extend(loaded_suites)
self.suite_uids.update({suite.uid: suite
for suite in loaded_suites})
cleanup()
# Clean up
configuration.config.file_under_load = None
sys.path[:] = old_path
os.chdir(cwd)
test_mod.TestCase.collector.remove(new_tests)
suite_mod.TestSuite.collector.remove(new_suites)
fixture_mod.Fixture.collector.remove(new_fixtures)
def _discover_files(self, root):
'''

View File

@@ -30,8 +30,9 @@
This module supplies the global `test_log` object which all testing
results and messages are reported through.
'''
import wrappers
import testlib.wrappers as wrappers
from six import add_metaclass
class LogLevel():
Fatal = 0
@@ -55,6 +56,7 @@ class RecordTypeCounterMetaclass(type):
RecordTypeCounterMetaclass.counter += 1
@add_metaclass(RecordTypeCounterMetaclass)
class Record(object):
'''
A generic object that is passed to the :class:`Log` and its handlers.
@@ -62,7 +64,6 @@ class Record(object):
..note: Although not statically enforced, all items in the record should be
be pickleable. This enables logging accross multiple processes.
'''
__metaclass__ = RecordTypeCounterMetaclass
def __init__(self, **data):
self.data = data

View File

@@ -29,16 +29,16 @@
import os
import itertools
import config
import fixture as fixture_mod
import handlers
import loader as loader_mod
import log
import query
import result
import runner
import terminal
import uid
import testlib.configuration as configuration
import testlib.fixture as fixture_mod
import testlib.handlers as handlers
import testlib.loader as loader_mod
import testlib.log as log
import testlib.query as query
import testlib.result as result
import testlib.runner as runner
import testlib.terminal as terminal
import testlib.uid as uid
def entry_message():
log.test_log.message("Running the new gem5 testing script.")
@@ -50,7 +50,7 @@ def entry_message():
class RunLogHandler():
def __init__(self):
term_handler = handlers.TerminalHandler(
verbosity=config.config.verbose+log.LogLevel.Info
verbosity=configuration.config.verbose+log.LogLevel.Info
)
summary_handler = handlers.SummaryHandler()
self.mp_handler = handlers.MultiprocessingHandlerWrapper(
@@ -62,7 +62,7 @@ class RunLogHandler():
def schedule_finalized(self, test_schedule):
# Create the result handler object.
self.result_handler = handlers.ResultHandler(
test_schedule, config.config.result_path)
test_schedule, configuration.config.result_path)
self.mp_handler.add_handler(self.result_handler)
def finish_testing(self):
@@ -87,27 +87,27 @@ class RunLogHandler():
return self.result_handler.unsuccessful()
def get_config_tags():
return getattr(config.config,
config.StorePositionalTagsAction.position_kword)
return getattr(configuration.config,
configuration.StorePositionalTagsAction.position_kword)
def filter_with_config_tags(loaded_library):
tags = get_config_tags()
final_tags = []
regex_fmt = '^%s$'
cfg = config.config
cfg = configuration.config
def _append_inc_tag_filter(name):
if hasattr(cfg, name):
tag_opts = getattr(cfg, name)
for tag in tag_opts:
final_tags.append(config.TagRegex(True, regex_fmt % tag))
final_tags.append(configuration.TagRegex(True, regex_fmt % tag))
def _append_rem_tag_filter(name):
if hasattr(cfg, name):
tag_opts = getattr(cfg, name)
for tag in cfg.constants.supported_tags[name]:
if tag not in tag_opts:
final_tags.append(config.TagRegex(False, regex_fmt % tag))
final_tags.append(configuration.TagRegex(False, regex_fmt % tag))
# Append additional tags for the isa, length, and variant options.
# They apply last (they take priority)
@@ -206,13 +206,13 @@ def load_tests():
testloader = loader_mod.Loader()
log.test_log.message(terminal.separator())
log.test_log.message('Loading Tests', bold=True)
testloader.load_root(config.config.directory)
testloader.load_root(configuration.config.directory)
return testloader
def do_list():
term_handler = handlers.TerminalHandler(
verbosity=config.config.verbose+log.LogLevel.Info,
machine_only=config.config.quiet
verbosity=configuration.config.verbose+log.LogLevel.Info,
machine_only=configuration.config.quiet
)
log.test_log.log_obj.add_handler(term_handler)
@@ -223,11 +223,11 @@ def do_list():
qrunner = query.QueryRunner(test_schedule)
if config.config.suites:
if configuration.config.suites:
qrunner.list_suites()
elif config.config.tests:
elif configuration.config.tests:
qrunner.list_tests()
elif config.config.all_tags:
elif configuration.config.all_tags:
qrunner.list_tags()
else:
qrunner.list_suites()
@@ -259,13 +259,13 @@ def run_schedule(test_schedule, log_handler):
log.test_log.message('Running Tests from {} suites'
.format(len(test_schedule.suites)), bold=True)
log.test_log.message("Results will be stored in {}".format(
config.config.result_path))
configuration.config.result_path))
log.test_log.message(terminal.separator())
# Build global fixtures and exectute scheduled test suites.
if config.config.test_threads > 1:
if configuration.config.test_threads > 1:
library_runner = runner.LibraryParallelRunner(test_schedule)
library_runner.set_threads(config.config.test_threads)
library_runner.set_threads(configuration.config.test_threads)
else:
library_runner = runner.LibraryRunner(test_schedule)
library_runner.run()
@@ -279,8 +279,8 @@ def run_schedule(test_schedule, log_handler):
def do_run():
# Initialize early parts of the log.
with RunLogHandler() as log_handler:
if config.config.uid:
uid_ = uid.UID.from_uid(config.config.uid)
if configuration.config.uid:
uid_ = uid.UID.from_uid(configuration.config.uid)
if isinstance(uid_, uid.TestUID):
log.test_log.error('Unable to run a standalone test.\n'
'Gem5 expects test suites to be the smallest unit '
@@ -305,8 +305,8 @@ def do_rerun():
with RunLogHandler() as log_handler:
# Load previous results
results = result.InternalSavedResults.load(
os.path.join(config.config.result_path,
config.constants.pickle_filename))
os.path.join(configuration.config.result_path,
configuration.constants.pickle_filename))
rerun_suites = (suite.uid for suite in results if suite.unsuccessful)
@@ -323,10 +323,10 @@ def main():
Returns 0 on success and 1 otherwise so it can be used as a return code
for scripts.
'''
config.initialize_config()
configuration.initialize_config()
# 'do' the given command.
result = globals()['do_'+config.config.command]()
result = globals()['do_'+configuration.config.command]()
log.test_log.close()
return result

View File

@@ -26,8 +26,8 @@
#
# Authors: Sean Wilson
import terminal
import log
import testlib.terminal as terminal
import testlib.log as log
# TODO Refactor print logic out of this so the objects
# created are separate from print logic.

View File

@@ -30,10 +30,10 @@ import os
import pickle
import xml.sax.saxutils
from config import config
import helper
import state
import log
from testlib.configuration import config
import testlib.helper as helper
import testlib.state as state
import testlib.log as log
def _create_uid_index(iterable):
index = {}
@@ -62,7 +62,7 @@ class _CommonMetadataMixin:
return self._metadata.result.value != state.Result.Passed
class InternalTestResult(object, _CommonMetadataMixin):
class InternalTestResult(_CommonMetadataMixin):
def __init__(self, obj, suite, directory):
self._metadata = obj.metadata
self.suite = suite
@@ -77,7 +77,7 @@ class InternalTestResult(object, _CommonMetadataMixin):
)
class InternalSuiteResult(object, _CommonMetadataMixin):
class InternalSuiteResult(_CommonMetadataMixin):
def __init__(self, obj, directory):
self._metadata = obj.metadata
self.directory = directory
@@ -104,7 +104,7 @@ class InternalSuiteResult(object, _CommonMetadataMixin):
return results
class InternalLibraryResults(object, _CommonMetadataMixin):
class InternalLibraryResults(_CommonMetadataMixin):
def __init__(self, obj, directory):
self.directory = directory
self._metadata = obj.metadata
@@ -159,12 +159,12 @@ class InternalSavedResults:
if exc.errno != errno.EEXIST:
raise
with open(path, 'w') as f:
with open(path, 'wb') as f:
pickle.dump(results, f, protocol)
@staticmethod
def load(path):
with open(path, 'r') as f:
with open(path, 'rb') as f:
return pickle.load(f)

View File

@@ -30,13 +30,13 @@ import multiprocessing.dummy
import threading
import traceback
import helper
import state
import log
import sandbox
import testlib.helper as helper
import testlib.state as state
import testlib.log as log
import testlib.sandbox as sandbox
from state import Status, Result
from fixture import SkipException
from testlib.state import Status, Result
from testlib.fixture import SkipException
def compute_aggregate_result(iterable):
'''

View File

@@ -33,7 +33,7 @@ import sys
import threading
import traceback
import log
import testlib.log as log
pdb._Pdb = pdb.Pdb
class ForkedPdb(pdb._Pdb):
@@ -81,18 +81,18 @@ class IoManager(object):
self.old_stdout = os.dup(sys.stdout.fileno())
os.dup2(self.stderr_wp, sys.stderr.fileno())
sys.stderr = os.fdopen(self.stderr_wp, 'w', 0)
sys.stderr = os.fdopen(self.stderr_wp, 'w')
os.dup2(self.stdout_wp, sys.stdout.fileno())
sys.stdout = os.fdopen(self.stdout_wp, 'w', 0)
sys.stdout = os.fdopen(self.stdout_wp, 'w')
def restore_pipes(self):
self.stderr_wp = os.dup(sys.stderr.fileno())
self.stdout_wp = os.dup(sys.stdout.fileno())
os.dup2(self.old_stderr, sys.stderr.fileno())
sys.stderr = os.fdopen(self.old_stderr, 'w', 0)
sys.stderr = open(self.old_stderr, 'w')
os.dup2(self.old_stdout, sys.stdout.fileno())
sys.stdout = os.fdopen(self.old_stdout, 'w', 0)
sys.stdout = open(self.old_stdout, 'w')
def start_loggers(self):
self.log_ouput()

View File

@@ -27,8 +27,8 @@
# Authors: Sean Wilson
import helper
import runner as runner_mod
import testlib.helper as helper
import testlib.runner as runner_mod
class TestSuite(object):
'''
@@ -52,7 +52,7 @@ class TestSuite(object):
tags = set()
def __new__(klass, *args, **kwargs):
obj = super(TestSuite, klass).__new__(klass, *args, **kwargs)
obj = super(TestSuite, klass).__new__(klass)
TestSuite.collector.collect(obj)
return obj

View File

@@ -28,6 +28,7 @@ import sys
import fcntl
import termios
import struct
import six
# Intended usage example:
#
@@ -74,7 +75,7 @@ try:
def cap_string(s, *args):
cap = curses.tigetstr(s)
if cap:
return curses.tparm(cap, *args)
return curses.tparm(cap, *args).decode("utf-8")
else:
return ''
except:
@@ -84,7 +85,7 @@ class ColorStrings(object):
def __init__(self, cap_string):
for i, c in enumerate(color_names):
setattr(self, c, cap_string('setaf', i))
for name, cap in capability_map.iteritems():
for name, cap in six.iteritems(capability_map):
setattr(self, name, cap_string(cap))
termcap = ColorStrings(cap_string)
@@ -137,7 +138,7 @@ def insert_separator(inside, char=default_separator,
.. seealso:: :func:`separator`
'''
# Use a bytearray so it's efficient to manipulate
string = bytearray(separator(char, color=color))
string = bytearray(separator(char, color=color), 'utf-8')
# Check if we can fit inside with at least min_barrier.
gap = (len(string) - len(inside)) - min_barrier * 2
@@ -145,27 +146,27 @@ def insert_separator(inside, char=default_separator,
# We'll need to expand the string to fit us.
string.extend([ char for _ in range(-gap)])
# Emplace inside
middle = ((len(string)-1)/2)
start_idx = middle - len(inside)/2
string[start_idx:len(inside)+start_idx] = inside
return str(string)
middle = (len(string)-1)//2
start_idx = middle - len(inside)//2
string[start_idx:len(inside)+start_idx] = str.encode(inside)
return str(string.decode("utf-8"))
if __name__ == '__main__':
def test_termcap(obj):
for c_name in color_names:
c_str = getattr(obj, c_name)
print c_str + c_name + obj.Normal
print(c_str + c_name + obj.Normal)
for attr_name in capability_names:
if attr_name == 'Normal':
continue
attr_str = getattr(obj, attr_name)
print attr_str + c_str + attr_name + " " + c_name + obj.Normal
print obj.Bold + obj.Underline + \
c_name + "Bold Underline " + c_str + obj.Normal
print(attr_str + c_str + attr_name + " " + c_name + obj.Normal)
print(obj.Bold + obj.Underline + \
c_name + "Bold Underline " + c_str + obj.Normal)
print "=== termcap enabled ==="
print("=== termcap enabled ===")
test_termcap(termcap)
print termcap.Normal
print "=== termcap disabled ==="
print(termcap.Normal)
print("=== termcap disabled ===")
test_termcap(no_termcap)

View File

@@ -28,8 +28,8 @@
import functools
import helper
import runner as runner_mod
import testlib.helper as helper
import testlib.runner as runner_mod
class TestingException(Exception):
'''Common ancestor for manual Testing Exceptions.'''
@@ -62,7 +62,7 @@ class TestCase(object):
collector = helper.InstanceCollector()
def __new__(cls, *args, **kwargs):
obj = super(TestCase, cls).__new__(cls, *args, **kwargs)
obj = super(TestCase, cls).__new__(cls)
TestCase.collector.collect(obj)
return obj

View File

@@ -29,7 +29,7 @@
import os
import itertools
import config
import testlib.configuration as configuration
class UID(object):
sep = ':'
@@ -42,12 +42,12 @@ class UID(object):
@staticmethod
def _shorten_path(path):
return os.path.relpath(path,
os.path.commonprefix((config.constants.testing_base,
os.path.commonprefix((configuration.constants.testing_base,
path)))
@staticmethod
def _full_path(short_path):
return os.path.join(config.constants.testing_base, short_path)
return os.path.join(configuration.constants.testing_base, short_path)
@classmethod
def uid_to_path(cls, uid):

View File

@@ -44,9 +44,8 @@ loaded by the testlib :class:`testlib.loader.Loader`.
'''
import itertools
import log
import uid
from state import Status, Result
import testlib.uid as uid
from testlib.state import Status, Result
class TestCaseMetadata():
def __init__(self, name, uid, path, result, status, suite_uid):
@@ -127,9 +126,11 @@ class LoadedTestable(object):
# TODO Change log to provide status_update, result_update for all types.
def log_status(self, status):
import testlib.log as log
log.test_log.status_update(self, status)
def log_result(self, result):
import testlib.log as log
log.test_log.result_update(self, result)
def __iter__(self):