1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234
|
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation
# files (the "Software"), to deal in the Software without
# restriction, including without limitation the rights to use,
# copy, modify, merge, publish, distribute, sublicense, and/or
# sell copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following
# conditions:
#
# This permission notice shall be included in all copies or
# substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
# PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHOR(S) BE
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
# OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
# DEALINGS IN THE SOFTWARE.
# Piglit core
from __future__ import print_function, absolute_import
import errno
import os
import re
import subprocess
import sys
import ConfigParser
from framework import exceptions
__all__ = [
'PIGLIT_CONFIG',
'PLATFORMS',
'PiglitConfig',
'Options',
'collect_system_info',
'parse_listfile',
]
PLATFORMS = ["glx", "x11_egl", "wayland", "gbm", "mixed_glx_egl"]
class PiglitConfig(ConfigParser.SafeConfigParser):
"""Custom Config parser that provides a few extra helpers."""
def __init__(self, *args, **kwargs):
# In Python2 the ConfigParser classes are old style, you can't use
# super() on them. sigh
ConfigParser.SafeConfigParser.__init__(self, *args, **kwargs)
self.filename = None
def readfp(self, fp, filename=None):
# In Python2 the ConfigParser classes are old style, you can't use
# super() on them. sigh
ConfigParser.SafeConfigParser.readfp(self, fp, filename)
self.filename = os.path.abspath(filename or fp.name)
def safe_get(self, *args, **kwargs):
"""A version of self.get that doesn't raise NoSectionError or
NoOptionError.
This is equivalent to passing if the option isn't found. It will return
None if an error is caught
"""
try:
return self.get(*args, **kwargs)
except (ConfigParser.NoOptionError, ConfigParser.NoSectionError):
return None
def required_get(self, section, option, **kwargs):
"""A version fo self.get that raises PiglitFatalError.
If self.get returns NoSectionError or NoOptionError then this will
raise a PiglitFatalException, aborting the program.
"""
try:
return self.get(section, option, **kwargs)
except ConfigParser.NoSectionError:
raise exceptions.PiglitFatalError(
'No Section "{}" in file "{}".\n'
'This section is required.'.format(
section, self.filename))
except ConfigParser.NoOptionError:
raise exceptions.PiglitFatalError(
'No option "{}" from section "{}" in file "{}".\n'
'This option is required.'.format(
option, section, self.filename))
PIGLIT_CONFIG = PiglitConfig(allow_no_value=True)
def get_config(arg=None):
if arg:
PIGLIT_CONFIG.readfp(arg)
else:
# Load the piglit.conf. First try looking in the current directory,
# then trying the XDG_CONFIG_HOME, then $HOME/.config/, finally try the
# piglit root dir
for d in ['.',
os.environ.get('XDG_CONFIG_HOME',
os.path.expandvars('$HOME/.config')),
os.path.join(os.path.dirname(__file__), '..')]:
try:
with open(os.path.join(d, 'piglit.conf'), 'r') as f:
PIGLIT_CONFIG.readfp(f)
break
except IOError:
pass
# Ensure the given directory exists
def checkDir(dirname, failifexists):
exists = True
try:
os.stat(dirname)
except OSError as e:
if e.errno == errno.ENOENT or e.errno == errno.ENOTDIR:
exists = False
if exists and failifexists:
print("%(dirname)s exists already.\nUse --overwrite if "
"you want to overwrite it.\n" % locals(), file=sys.stderr)
exit(1)
try:
os.makedirs(dirname)
except OSError as e:
if e.errno != errno.EEXIST:
raise
class Options(object):
""" Contains options for a piglit run
Options are as follows:
concurrent -- True if concurrency is to be used
execute -- False for dry run
filter -- list of compiled regex which include exclusively tests that match
exclude_filter -- list of compiled regex which exclude tests that match
valgrind -- True if valgrind is to be used
dmesg -- True if dmesg checking is desired. This forces concurrency off
env -- environment variables set for each test before run
"""
def __init__(self, concurrent=True, execute=True, include_filter=None,
exclude_filter=None, valgrind=False, dmesg=False, sync=False):
self.concurrent = concurrent
self.execute = execute
self.filter = \
[re.compile(x, re.IGNORECASE) for x in include_filter or []]
self.exclude_filter = \
[re.compile(x, re.IGNORECASE) for x in exclude_filter or []]
self.exclude_tests = set()
self.valgrind = valgrind
self.dmesg = dmesg
self.sync = sync
# env is used to set some base environment variables that are not going
# to change across runs, without sending them to os.environ which is
# fickle and easy to break
self.env = {
'PIGLIT_SOURCE_DIR':
os.environ.get(
'PIGLIT_SOURCE_DIR',
os.path.abspath(os.path.join(os.path.dirname(__file__),
'..')))
}
def __iter__(self):
for key, values in self.__dict__.iteritems():
# If the values are regex compiled then yield their pattern
# attribute, which is the original plaintext they were compiled
# from, otherwise yield them normally.
if key in ['filter', 'exclude_filter']:
yield (key, [x.pattern for x in values])
else:
yield (key, values)
def collect_system_info():
""" Get relavent information about the system running piglit
This method runs through a list of tuples, where element 1 is the name of
the program being run, and elemnt 2 is a command to run (in a form accepted
by subprocess.Popen)
"""
progs = [('wglinfo', ['wglinfo']),
('glxinfo', ['glxinfo']),
('uname', ['uname', '-a']),
('lspci', ['lspci'])]
result = {}
for name, command in progs:
try:
result[name] = subprocess.check_output(command,
stderr=subprocess.STDOUT)
except OSError as e:
# If we get the 'no file or directory' error then pass, that means
# that the binary isn't installed or isn't relavent to the system.
# If it's any other OSError, then raise
if e.errno != errno.ENOENT:
raise
except subprocess.CalledProcessError:
# If the binary is installed by doesn't work on the window system
# (glxinfo) it will raise this error. go on
pass
return result
def parse_listfile(filename):
"""
Parses a newline-seperated list in a text file and returns a python list
object. It will expand tildes on Unix-like system to the users home
directory.
ex file.txt:
~/tests1
~/tests2/main
/tmp/test3
returns:
['/home/user/tests1', '/home/users/tests2/main', '/tmp/test3']
"""
with open(filename, 'r') as file:
return [os.path.expanduser(i.strip()) for i in file.readlines()]
|