3 # Permission is hereby granted, free of charge, to any person
4 # obtaining a copy of this software and associated documentation
5 # files (the "Software"), to deal in the Software without
6 # restriction, including without limitation the rights to use,
7 # copy, modify, merge, publish, distribute, sublicense, and/or
8 # sell copies of the Software, and to permit persons to whom the
9 # Software is furnished to do so, subject to the following
12 # This permission notice shall be included in all copies or
13 # substantial portions of the Software.
15 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
16 # KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
17 # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
18 # PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHOR(S) BE
19 # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
20 # AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
21 # OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 # DEALINGS IN THE SOFTWARE.
49 #############################################################################
50 ##### Helper functions
51 #############################################################################
53 # Ensure the given directory exists
54 def checkDir(dirname
, failifexists
):
59 if e
.errno
== errno
.ENOENT
or e
.errno
== errno
.ENOTDIR
:
62 if exists
and failifexists
:
63 print >>sys
.stderr
, "%(dirname)s exists already.\nUse --overwrite if you want to overwrite it.\n" % locals()
69 if e
.errno
!= errno
.EEXIST
:
74 return text
.encode("string_escape")
77 return text
.decode("string_escape")
79 testBinDir
= os
.path
.dirname(__file__
) + '/../bin/'
82 #############################################################################
84 #############################################################################
86 class TestResult(dict):
87 def __init__(self
, *args
):
90 assert(len(args
) == 0 or len(args
) == 2)
94 self
.__setattr
__(k
, args
[0][k
])
99 attrnames
= set(dir(self
)) - set(dir(self
.__class
__()))
100 return '%(class)s(%(dir)s,%(dict)s)' % {
101 'class': self
.__class
__.__name
__,
102 'dir': dict([(k
, self
.__getattribute
__(k
)) for k
in attrnames
]),
103 'dict': dict.__repr
__(self
)
106 def allTestResults(self
, name
):
109 def write(self
, file, path
):
110 print >>file, "@test: " + encode(path
)
114 print >>file, k
+ "!"
116 print >>file, " " + encode(str(s
))
119 print >>file, k
+ ": " + encode(str(v
))
123 class GroupResult(dict):
124 def __init__(self
, *args
):
127 assert(len(args
) == 0 or len(args
) == 2)
131 self
.__setattr
__(k
, args
[0][k
])
136 attrnames
= set(dir(self
)) - set(dir(self
.__class
__()))
137 return '%(class)s(%(dir)s,%(dict)s)' % {
138 'class': self
.__class
__.__name
__,
139 'dir': dict([(k
, self
.__getattribute
__(k
)) for k
in attrnames
]),
140 'dict': dict.__repr
__(self
)
143 def allTestResults(self
, groupName
):
145 for name
, sub
in self
.items():
147 if len(groupName
) > 0:
148 subfullname
= groupName
+ '/' + subfullname
149 collection
.update(sub
.allTestResults(subfullname
))
152 def write(self
, file, groupName
):
153 for name
, sub
in self
.items():
155 if len(groupName
) > 0:
156 subfullname
= groupName
+ '/' + subfullname
157 sub
.write(file, subfullname
)
161 def __init__(self
, *args
):
163 self
.globalkeys
= ['name', 'href', 'glxinfo', 'lspci', 'time']
164 self
.results
= GroupResult()
166 def allTestResults(self
):
167 '''Return a dictionary containing (name: TestResult) mappings.
168 Note that writing to this dictionary has no effect.'''
169 return self
.results
.allTestResults('')
171 def write(self
, file):
172 for key
in self
.globalkeys
:
173 if key
in self
.__dict
__:
174 print >>file, "%s: %s" % (key
, encode(self
.__dict
__[key
]))
176 self
.results
.write(file,'')
178 def parseFile(self
, file):
193 colon
= line
.find(':')
195 excl
= line
.find('!')
197 raise Exception("Line %(linenr)d: Bad format" % locals())
201 stack
.append(arrayparser(d
[key
]))
205 value
= decode(line
[colon
+2:])
210 colon
= line
.find(':')
212 raise Exception("Line %(linenr)d: Bad format" % locals())
215 value
= decode(line
[colon
+2:])
216 if key
in self
.globalkeys
:
217 self
.__dict
__[key
] = value
219 comp
= value
.split('/')
221 for name
in comp
[:-1]:
222 if name
not in group
:
223 group
[name
] = GroupResult()
226 result
= TestResult()
227 group
[comp
[-1]] = result
229 stack
.append(dictparser(result
))
231 raise Exception("Line %d: Unknown key %s" % (linenr
, key
))
237 stack
[-1](line
[0:-1])
240 def parseDir(self
, path
, PreferSummary
):
242 filelist
= [path
+ '/main', path
+ '/summary']
244 filelist
[:0] = [path
+ '/summary']
245 for filename
in filelist
:
247 main
= open(filename
, 'U')
252 raise Exception("Failed to open %(path)s" % locals())
257 #############################################################################
258 ##### Generic Test classes
259 #############################################################################
263 self
.file = sys
.stdout
266 self
.exclude_filter
= []
268 def run(self
, command
):
270 p
= subprocess
.Popen(
271 command
, stdout
=subprocess
.PIPE
, stderr
=subprocess
.PIPE
)
272 (stdout
, stderr
) = p
.communicate()
274 return "Failed to run " + command
277 def collectData(self
):
278 if platform
.system() != 'Windows':
279 print >>self
.file, "glxinfo:", '@@@' + encode(self
.run('glxinfo'))
280 if platform
.system() == 'Linux':
281 print >>self
.file, "lspci:", '@@@' + encode(self
.run('lspci'))
292 raise NotImplementedError
294 def doRun(self
, env
, path
):
295 # Exclude tests that don't match the filter regexp
296 if len(env
.filter) > 0:
297 if not True in map(lambda f
: f
.search(path
) != None, env
.filter):
300 # And exclude tests that do match the exclude_filter regexp
301 if len(env
.exclude_filter
) > 0:
302 if True in map(lambda f
: f
.search(path
) != None, env
.exclude_filter
):
307 print "Test: %(path)s" % locals()
308 time_start
= time
.time()
310 time_end
= time
.time()
311 if 'time' not in result
:
312 result
['time'] = time_end
- time_start
313 if 'result' not in result
:
314 result
['result'] = 'fail'
315 if not isinstance(result
, TestResult
):
316 result
= TestResult({}, result
)
317 result
['result'] = 'warn'
318 result
['note'] = 'Result not returned as an instance of TestResult'
320 result
= TestResult()
321 result
['result'] = 'fail'
322 result
['exception'] = str(sys
.exc_info()[0]) + str(sys
.exc_info()[1])
323 result
['traceback'] = '@@@' + "".join(traceback
.format_tb(sys
.exc_info()[2]))
325 if result
['result'] != 'pass':
326 print " result: %(result)s" % { 'result': result
['result'] }
328 result
.write(env
.file, path
)
330 time
.sleep(Test
.sleep
)
332 print "Dry-run: %(path)s" % locals()
334 # Returns True iff the given error message should be ignored
335 def isIgnored(self
, error
):
336 for pattern
in Test
.ignoreErrors
:
337 if pattern
.search(error
):
342 # Default handling for stderr messages
343 def handleErr(self
, results
, err
):
344 errors
= filter(lambda s
: len(s
) > 0, map(lambda s
: s
.strip(), err
.split('\n')))
346 ignored
= [s
for s
in errors
if self
.isIgnored(s
)]
347 errors
= [s
for s
in errors
if s
not in ignored
]
350 results
['errors'] = errors
352 if results
['result'] == 'pass':
353 results
['result'] = 'warn'
356 results
['errors_ignored'] = ignored
360 def doRun(self
, env
, path
):
361 for sub
in sorted(self
):
364 spath
= path
+ '/' + spath
365 self
[sub
].doRun(env
, spath
)
374 time_start
= time
.time()
375 self
.tests
.doRun(env
, '')
376 time_end
= time
.time()
377 print >>env
.file, "time:",(time_end
-time_start
)
379 #############################################################################
381 #############################################################################
383 def loadTestProfile(filename
):
388 execfile(filename
, ns
)
391 traceback
.print_exc()
392 raise Exception('Could not read tests profile')
394 def loadTestResults(path
, PreferSummary
=False):
396 mode
= os
.stat(path
)[stat
.ST_MODE
]
397 testrun
= TestrunResult()
398 if stat
.S_ISDIR(mode
):
399 testrun
.parseDir(path
, PreferSummary
)
401 file = open(path
, 'r')
402 testrun
.parseFile(file)
405 if len(testrun
.name
) == 0:
407 testrun
.name
= os
.path
.basename(path
[0:-1])
409 testrun
.name
= os
.path
.basename(path
)
413 traceback
.print_exc()
414 raise Exception('Could not read tests results')