progs/gallium/python: New home for python statetracker scripts.
This commit is contained in:
344
progs/gallium/python/tests/base.py
Executable file
344
progs/gallium/python/tests/base.py
Executable file
@@ -0,0 +1,344 @@
|
||||
#!/usr/bin/env python
|
||||
##########################################################################
|
||||
#
|
||||
# Copyright 2009 VMware, Inc.
|
||||
# Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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, sub license, 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:
|
||||
#
|
||||
# The above copyright notice and this permission notice (including the
|
||||
# next paragraph) 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 NON-INFRINGEMENT.
|
||||
# IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS 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.
|
||||
#
|
||||
##########################################################################
|
||||
|
||||
|
||||
"""Base classes for tests.
|
||||
|
||||
Loosely inspired on Python's unittest module.
|
||||
"""
|
||||
|
||||
|
||||
import os.path
|
||||
import sys
|
||||
|
||||
from gallium import *
|
||||
|
||||
|
||||
# Enumerate all pixel formats
|
||||
formats = {}
|
||||
for name, value in globals().items():
|
||||
if name.startswith("PIPE_FORMAT_") and isinstance(value, int):
|
||||
formats[value] = name
|
||||
|
||||
def is_depth_stencil_format(format):
|
||||
# FIXME: make and use binding to util_format_is_depth_or_stencil
|
||||
return format in (
|
||||
PIPE_FORMAT_Z32_UNORM,
|
||||
PIPE_FORMAT_Z24S8_UNORM,
|
||||
PIPE_FORMAT_Z24X8_UNORM,
|
||||
PIPE_FORMAT_Z16_UNORM,
|
||||
)
|
||||
|
||||
def make_image(width, height, rgba):
|
||||
import Image
|
||||
outimage = Image.new(
|
||||
mode='RGB',
|
||||
size=(width, height),
|
||||
color=(0,0,0))
|
||||
outpixels = outimage.load()
|
||||
for y in range(0, height):
|
||||
for x in range(0, width):
|
||||
offset = (y*width + x)*4
|
||||
r, g, b, a = [int(min(max(rgba[offset + ch], 0.0), 1.0)*255) for ch in range(4)]
|
||||
outpixels[x, y] = r, g, b
|
||||
return outimage
|
||||
|
||||
def save_image(width, height, rgba, filename):
|
||||
outimage = make_image(width, height, rgba)
|
||||
outimage.save(filename, "PNG")
|
||||
|
||||
def show_image(width, height, **rgbas):
|
||||
import Tkinter as tk
|
||||
from PIL import Image, ImageTk
|
||||
|
||||
root = tk.Tk()
|
||||
|
||||
x = 64
|
||||
y = 64
|
||||
|
||||
labels = rgbas.keys()
|
||||
labels.sort()
|
||||
for i in range(len(labels)):
|
||||
label = labels[i]
|
||||
outimage = make_image(width, height, rgbas[label])
|
||||
|
||||
if i:
|
||||
window = tk.Toplevel(root)
|
||||
else:
|
||||
window = root
|
||||
window.title(label)
|
||||
image1 = ImageTk.PhotoImage(outimage)
|
||||
w = image1.width()
|
||||
h = image1.height()
|
||||
window.geometry("%dx%d+%d+%d" % (w, h, x, y))
|
||||
panel1 = tk.Label(window, image=image1)
|
||||
panel1.pack(side='top', fill='both', expand='yes')
|
||||
panel1.image = image1
|
||||
x += w + 2
|
||||
|
||||
root.mainloop()
|
||||
|
||||
|
||||
class TestFailure(Exception):
|
||||
|
||||
pass
|
||||
|
||||
class TestSkip(Exception):
|
||||
|
||||
pass
|
||||
|
||||
|
||||
class Test:
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def _run(self, result):
|
||||
raise NotImplementedError
|
||||
|
||||
def run(self):
|
||||
result = TestResult()
|
||||
self._run(result)
|
||||
result.summary()
|
||||
|
||||
def assert_rgba(self, surface, x, y, w, h, expected_rgba, pixel_tol=4.0/256, surface_tol=0.85):
|
||||
total = h*w
|
||||
different = surface.compare_tile_rgba(x, y, w, h, expected_rgba, tol=pixel_tol)
|
||||
if different:
|
||||
sys.stderr.write("%u out of %u pixels differ\n" % (different, total))
|
||||
|
||||
if float(total - different)/float(total) < surface_tol:
|
||||
if 0:
|
||||
rgba = FloatArray(h*w*4)
|
||||
surface.get_tile_rgba(x, y, w, h, rgba)
|
||||
show_image(w, h, Result=rgba, Expected=expected_rgba)
|
||||
save_image(w, h, rgba, "result.png")
|
||||
save_image(w, h, expected_rgba, "expected.png")
|
||||
#sys.exit(0)
|
||||
|
||||
raise TestFailure
|
||||
|
||||
|
||||
class TestCase(Test):
|
||||
|
||||
tags = ()
|
||||
|
||||
def __init__(self, dev, **kargs):
|
||||
Test.__init__(self)
|
||||
self.dev = dev
|
||||
self.__dict__.update(kargs)
|
||||
|
||||
def description(self):
|
||||
descriptions = []
|
||||
for tag in self.tags:
|
||||
value = self.get(tag)
|
||||
if value is not None and value != '':
|
||||
descriptions.append(tag + '=' + str(value))
|
||||
return ' '.join(descriptions)
|
||||
|
||||
def get(self, tag):
|
||||
try:
|
||||
method = getattr(self, '_get_' + tag)
|
||||
except AttributeError:
|
||||
return getattr(self, tag, None)
|
||||
else:
|
||||
return method()
|
||||
|
||||
def _get_target(self):
|
||||
return {
|
||||
PIPE_TEXTURE_1D: "1d",
|
||||
PIPE_TEXTURE_2D: "2d",
|
||||
PIPE_TEXTURE_3D: "3d",
|
||||
PIPE_TEXTURE_CUBE: "cube",
|
||||
}[self.target]
|
||||
|
||||
def _get_format(self):
|
||||
name = formats[self.format]
|
||||
if name.startswith('PIPE_FORMAT_'):
|
||||
name = name[12:]
|
||||
name = name.lower()
|
||||
return name
|
||||
|
||||
def _get_face(self):
|
||||
if self.target == PIPE_TEXTURE_CUBE:
|
||||
return {
|
||||
PIPE_TEX_FACE_POS_X: "+x",
|
||||
PIPE_TEX_FACE_NEG_X: "-x",
|
||||
PIPE_TEX_FACE_POS_Y: "+y",
|
||||
PIPE_TEX_FACE_NEG_Y: "-y",
|
||||
PIPE_TEX_FACE_POS_Z: "+z",
|
||||
PIPE_TEX_FACE_NEG_Z: "-z",
|
||||
}[self.face]
|
||||
else:
|
||||
return ''
|
||||
|
||||
def test(self):
|
||||
raise NotImplementedError
|
||||
|
||||
def _run(self, result):
|
||||
result.test_start(self)
|
||||
try:
|
||||
self.test()
|
||||
except KeyboardInterrupt:
|
||||
raise
|
||||
except TestSkip:
|
||||
result.test_skipped(self)
|
||||
except TestFailure:
|
||||
result.test_failed(self)
|
||||
else:
|
||||
result.test_passed(self)
|
||||
|
||||
|
||||
class TestSuite(Test):
|
||||
|
||||
def __init__(self, tests = None):
|
||||
Test.__init__(self)
|
||||
if tests is None:
|
||||
self.tests = []
|
||||
else:
|
||||
self.tests = tests
|
||||
|
||||
def add_test(self, test):
|
||||
self.tests.append(test)
|
||||
|
||||
def _run(self, result):
|
||||
for test in self.tests:
|
||||
test._run(result)
|
||||
|
||||
|
||||
class TestResult:
|
||||
|
||||
def __init__(self):
|
||||
self.tests = 0
|
||||
self.passed = 0
|
||||
self.skipped = 0
|
||||
self.failed = 0
|
||||
|
||||
self.names = ['result']
|
||||
self.types = ['pass skip fail']
|
||||
self.rows = []
|
||||
|
||||
def test_start(self, test):
|
||||
sys.stdout.write("Running %s...\n" % test.description())
|
||||
sys.stdout.flush()
|
||||
self.tests += 1
|
||||
|
||||
def test_passed(self, test):
|
||||
sys.stdout.write("PASS\n")
|
||||
sys.stdout.flush()
|
||||
self.passed += 1
|
||||
self.log_result(test, 'pass')
|
||||
|
||||
def test_skipped(self, test):
|
||||
sys.stdout.write("SKIP\n")
|
||||
sys.stdout.flush()
|
||||
self.skipped += 1
|
||||
#self.log_result(test, 'skip')
|
||||
|
||||
def test_failed(self, test):
|
||||
sys.stdout.write("FAIL\n")
|
||||
sys.stdout.flush()
|
||||
self.failed += 1
|
||||
self.log_result(test, 'fail')
|
||||
|
||||
def log_result(self, test, result):
|
||||
row = ['']*len(self.names)
|
||||
|
||||
# add result
|
||||
assert self.names[0] == 'result'
|
||||
assert result in ('pass', 'skip', 'fail')
|
||||
row[0] = result
|
||||
|
||||
# add tags
|
||||
for tag in test.tags:
|
||||
value = test.get(tag)
|
||||
|
||||
# infer type
|
||||
if value is None:
|
||||
continue
|
||||
elif isinstance(value, (int, float)):
|
||||
value = str(value)
|
||||
type = 'c' # continous
|
||||
elif isinstance(value, basestring):
|
||||
type = 'd' # discrete
|
||||
else:
|
||||
assert False
|
||||
value = str(value)
|
||||
type = 'd' # discrete
|
||||
|
||||
# insert value
|
||||
try:
|
||||
col = self.names.index(tag, 1)
|
||||
except ValueError:
|
||||
self.names.append(tag)
|
||||
self.types.append(type)
|
||||
row.append(value)
|
||||
else:
|
||||
row[col] = value
|
||||
assert self.types[col] == type
|
||||
|
||||
self.rows.append(row)
|
||||
|
||||
def summary(self):
|
||||
sys.stdout.write("%u tests, %u passed, %u skipped, %u failed\n\n" % (self.tests, self.passed, self.skipped, self.failed))
|
||||
sys.stdout.flush()
|
||||
|
||||
name, ext = os.path.splitext(os.path.basename(sys.argv[0]))
|
||||
filename = name + '.tsv'
|
||||
stream = file(filename, 'wt')
|
||||
|
||||
# header
|
||||
stream.write('\t'.join(self.names) + '\n')
|
||||
stream.write('\t'.join(self.types) + '\n')
|
||||
stream.write('class\n')
|
||||
|
||||
# rows
|
||||
for row in self.rows:
|
||||
row += ['']*(len(self.names) - len(row))
|
||||
stream.write('\t'.join(row) + '\n')
|
||||
|
||||
stream.close()
|
||||
|
||||
# See http://www.ailab.si/orange/doc/ofb/c_otherclass.htm
|
||||
try:
|
||||
import orange
|
||||
import orngTree
|
||||
except ImportError:
|
||||
sys.stderr.write('Install Orange from http://www.ailab.si/orange/ for a classification tree.\n')
|
||||
return
|
||||
|
||||
data = orange.ExampleTable(filename)
|
||||
|
||||
tree = orngTree.TreeLearner(data, sameMajorityPruning=1, mForPruning=2)
|
||||
|
||||
orngTree.printTxt(tree, maxDepth=4)
|
||||
|
||||
file(name+'.txt', 'wt').write(orngTree.dumpTree(tree))
|
||||
|
||||
orngTree.printDot(tree, fileName=name+'.dot', nodeShape='ellipse', leafShape='box')
|
Reference in New Issue
Block a user