2011-11-16 15:58:07 +04:00
|
|
|
#!/usr/bin/python
|
2011-12-01 08:24:14 +04:00
|
|
|
|
2012-12-03 11:59:57 +04:00
|
|
|
# test_pretty_print by don bright 2012. Copyright assigned to Marius Kintel and
|
|
|
|
# Clifford Wolf 2012. Released under the GPL 2, or later, as described in
|
|
|
|
# the file named 'COPYING' in OpenSCAD's project root.
|
2011-12-01 08:24:14 +04:00
|
|
|
|
2011-11-16 15:58:07 +04:00
|
|
|
#
|
2013-02-19 07:36:00 +04:00
|
|
|
# This program 'pretty prints' the ctest output, including
|
|
|
|
# - log files from builddir/Testing/Temporary/
|
|
|
|
# - .png and .txt files from testname-output/*
|
2011-12-07 08:20:17 +04:00
|
|
|
#
|
2013-02-19 07:36:00 +04:00
|
|
|
# The result is a single html report file with images data-uri encoded
|
|
|
|
# into the file. It can be uploaded as a single static file to a web server
|
|
|
|
# or the 'test_upload.py' script can be used.
|
2013-02-19 05:45:37 +04:00
|
|
|
|
2011-12-07 08:20:17 +04:00
|
|
|
|
2011-12-01 08:24:14 +04:00
|
|
|
# Design philosophy
|
|
|
|
#
|
|
|
|
# 1. parse the data (images, logs) into easy-to-use data structures
|
|
|
|
# 2. wikifiy the data
|
|
|
|
# 3. save the wikified data to disk
|
2013-02-19 07:36:00 +04:00
|
|
|
# 4. generate html, including base64 encoding of images
|
|
|
|
# 5. save html file
|
|
|
|
# 6. upload html to public site and share with others
|
2011-11-16 15:58:07 +04:00
|
|
|
|
|
|
|
# todo
|
2013-02-19 07:36:00 +04:00
|
|
|
#
|
|
|
|
# 1. Note: Wiki code is deprecated. All future development should move to
|
|
|
|
# create html output (or even xml output). Wiki design was based on the
|
|
|
|
# wrong assumption of easily accessible public wiki servers with
|
|
|
|
# auto-upload scripts available. wiki code should be removed and code
|
|
|
|
# simplified.
|
|
|
|
#
|
2013-02-25 07:20:11 +04:00
|
|
|
# to still use wiki, use args '--wiki' and/or '--wiki-upload'
|
|
|
|
#
|
2013-02-19 07:36:00 +04:00
|
|
|
# 2. why is hash differing
|
2011-11-30 06:57:44 +04:00
|
|
|
|
2011-12-15 01:02:55 +04:00
|
|
|
import string,sys,re,os,hashlib,subprocess,textwrap,time,platform
|
2011-11-16 15:58:07 +04:00
|
|
|
|
|
|
|
def tryread(filename):
|
|
|
|
data = None
|
|
|
|
try:
|
2011-11-30 06:41:28 +04:00
|
|
|
f = open(filename,'rb')
|
2011-11-16 15:58:07 +04:00
|
|
|
data = f.read()
|
|
|
|
f.close()
|
2013-02-19 07:36:00 +04:00
|
|
|
except Exception, e:
|
2011-11-16 15:58:07 +04:00
|
|
|
print 'couldn\'t open ',filename
|
2013-02-19 07:36:00 +04:00
|
|
|
print type(e), e
|
2011-11-16 15:58:07 +04:00
|
|
|
return data
|
|
|
|
|
2011-11-30 06:41:28 +04:00
|
|
|
def trysave(filename,data):
|
2013-02-19 07:36:00 +04:00
|
|
|
dir = os.path.dirname(filename)
|
2011-11-16 15:58:07 +04:00
|
|
|
try:
|
2013-02-19 07:36:00 +04:00
|
|
|
if not os.path.isdir(dir):
|
|
|
|
if not dir == '':
|
|
|
|
debug( 'creating' + dir)
|
|
|
|
os.mkdir(dir)
|
2011-11-30 06:41:28 +04:00
|
|
|
f=open(filename,'wb')
|
2011-11-16 15:58:07 +04:00
|
|
|
f.write(data)
|
|
|
|
f.close()
|
2013-02-19 07:36:00 +04:00
|
|
|
except Exception, e:
|
2011-11-16 15:58:07 +04:00
|
|
|
print 'problem writing to',filename
|
2013-02-19 07:36:00 +04:00
|
|
|
print type(e), e
|
2011-11-16 15:58:07 +04:00
|
|
|
return None
|
|
|
|
return True
|
|
|
|
|
|
|
|
def ezsearch(pattern,str):
|
|
|
|
x = re.search(pattern,str,re.DOTALL|re.MULTILINE)
|
|
|
|
if x and len(x.groups())>0: return x.group(1).strip()
|
|
|
|
return ''
|
|
|
|
|
|
|
|
def read_gitinfo():
|
|
|
|
# won't work if run from outside of branch.
|
2013-01-28 09:38:50 +04:00
|
|
|
try:
|
|
|
|
data = subprocess.Popen(['git','remote','-v'],stdout=subprocess.PIPE).stdout.read()
|
|
|
|
origin = ezsearch('^origin *?(.*?)\(fetch.*?$',data)
|
|
|
|
upstream = ezsearch('^upstream *?(.*?)\(fetch.*?$',data)
|
|
|
|
data = subprocess.Popen(['git','branch'],stdout=subprocess.PIPE).stdout.read()
|
|
|
|
branch = ezsearch('^\*(.*?)$',data)
|
|
|
|
out = 'Git branch: ' + branch + ' from origin ' + origin + '\n'
|
|
|
|
out += 'Git upstream: ' + upstream + '\n'
|
|
|
|
except:
|
|
|
|
out = 'Problem running git'
|
2011-11-16 15:58:07 +04:00
|
|
|
return out
|
|
|
|
|
|
|
|
def read_sysinfo(filename):
|
|
|
|
data = tryread(filename)
|
2011-12-15 01:02:55 +04:00
|
|
|
if not data:
|
|
|
|
sinfo = platform.sys.platform
|
|
|
|
sinfo += '\nsystem cannot create offscreen GL framebuffer object'
|
2013-02-20 05:43:25 +04:00
|
|
|
sinfo += '\nsystem cannot create GL based images'
|
|
|
|
sysid = platform.sys.platform+'_no_GL_renderer'
|
2011-12-15 01:02:55 +04:00
|
|
|
return sinfo, sysid
|
2011-11-16 15:58:07 +04:00
|
|
|
|
|
|
|
machine = ezsearch('Machine:(.*?)\n',data)
|
|
|
|
machine = machine.replace(' ','-').replace('/','-')
|
|
|
|
|
|
|
|
osinfo = ezsearch('OS info:(.*?)\n',data)
|
|
|
|
osplain = osinfo.split(' ')[0].strip().replace('/','-')
|
|
|
|
if 'windows' in osinfo.lower(): osplain = 'win'
|
|
|
|
|
|
|
|
renderer = ezsearch('GL Renderer:(.*?)\n',data)
|
|
|
|
tmp = renderer.split(' ')
|
|
|
|
tmp = string.join(tmp[0:3],'-')
|
|
|
|
tmp = tmp.split('/')[0]
|
|
|
|
renderer = tmp
|
|
|
|
|
2011-11-24 08:22:33 +04:00
|
|
|
data += read_gitinfo()
|
|
|
|
|
2011-11-26 21:11:55 +04:00
|
|
|
data += 'Image comparison: ImageMagick'
|
2011-11-24 08:22:33 +04:00
|
|
|
|
|
|
|
data = data.strip()
|
|
|
|
|
2011-11-24 08:27:11 +04:00
|
|
|
# create 4 letter hash and stick on end of sysid
|
2011-11-30 08:15:07 +04:00
|
|
|
nondate_data = re.sub("\n.*?ompile date.*?\n","\n",data).strip()
|
2011-11-17 07:36:58 +04:00
|
|
|
hexhash = hashlib.md5()
|
2011-11-24 08:27:11 +04:00
|
|
|
hexhash.update(nondate_data)
|
2011-11-17 07:36:58 +04:00
|
|
|
hexhash = hexhash.hexdigest()[-4:].upper()
|
2011-11-16 15:58:07 +04:00
|
|
|
hash = ''
|
|
|
|
for c in hexhash: hash += chr(ord(c)+97-48)
|
2011-11-30 06:57:44 +04:00
|
|
|
|
2011-11-16 15:58:07 +04:00
|
|
|
sysid = osplain + '_' + machine + '_' + renderer + '_' + hash
|
2013-02-20 05:43:25 +04:00
|
|
|
sysid = sysid.replace('(','_').replace(')','_')
|
2011-11-16 15:58:07 +04:00
|
|
|
sysid = sysid.lower()
|
|
|
|
|
|
|
|
return data, sysid
|
|
|
|
|
|
|
|
class Test:
|
2011-11-17 07:36:58 +04:00
|
|
|
def __init__(self,fullname,time,passed,output,type,actualfile,expectedfile,scadfile,log):
|
2011-11-16 15:58:07 +04:00
|
|
|
self.fullname,self.time,self.passed,self.output = \
|
|
|
|
fullname, time, passed, output
|
|
|
|
self.type, self.actualfile, self.expectedfile, self.scadfile = \
|
|
|
|
type, actualfile, expectedfile, scadfile
|
2011-11-17 07:36:58 +04:00
|
|
|
self.fulltestlog = log
|
2013-02-19 07:36:00 +04:00
|
|
|
|
2011-11-16 15:58:07 +04:00
|
|
|
def __str__(self):
|
|
|
|
x = 'fullname: ' + self.fullname
|
|
|
|
x+= '\nactualfile: ' + self.actualfile
|
|
|
|
x+= '\nexpectedfile: ' + self.expectedfile
|
|
|
|
x+= '\ntesttime: ' + self.time
|
|
|
|
x+= '\ntesttype: ' + self.type
|
|
|
|
x+= '\npassed: ' + str(self.passed)
|
|
|
|
x+= '\nscadfile: ' + self.scadfile
|
|
|
|
x+= '\noutput bytes: ' + str(len(self.output))
|
2011-11-17 07:36:58 +04:00
|
|
|
x+= '\ntestlog bytes: ' + str(len(self.fulltestlog))
|
2011-11-16 15:58:07 +04:00
|
|
|
x+= '\n'
|
|
|
|
return x
|
|
|
|
|
|
|
|
def parsetest(teststring):
|
|
|
|
patterns = ["Test:(.*?)\n", # fullname
|
|
|
|
"Test time =(.*?) sec\n",
|
2011-11-26 21:11:55 +04:00
|
|
|
"Test time.*?Test (Passed)", # pass/fail
|
2011-11-16 15:58:07 +04:00
|
|
|
"Output:(.*?)<end of output>",
|
|
|
|
'Command:.*?-s" "(.*?)"', # type
|
2011-12-21 20:42:11 +04:00
|
|
|
"^ actual .*?:(.*?)\n",
|
|
|
|
"^ expected .*?:(.*?)\n",
|
2011-11-16 15:58:07 +04:00
|
|
|
'Command:.*?(testdata.*?)"' # scadfile
|
|
|
|
]
|
|
|
|
hits = map( lambda pattern: ezsearch(pattern,teststring), patterns )
|
2011-11-17 07:36:58 +04:00
|
|
|
test = Test(hits[0],hits[1],hits[2]=='Passed',hits[3],hits[4],hits[5],hits[6],hits[7],teststring)
|
2011-12-21 20:42:11 +04:00
|
|
|
if len(test.actualfile) > 0: test.actualfile_data = tryread(test.actualfile)
|
2011-12-23 16:57:34 +04:00
|
|
|
if len(test.expectedfile) > 0: test.expectedfile_data = tryread(test.expectedfile)
|
2011-11-16 15:58:07 +04:00
|
|
|
return test
|
|
|
|
|
|
|
|
def parselog(data):
|
|
|
|
startdate = ezsearch('Start testing: (.*?)\n',data)
|
|
|
|
enddate = ezsearch('End testing: (.*?)\n',data)
|
|
|
|
pattern = '([0-9]*/[0-9]* Testing:.*?time elapsed.*?\n)'
|
|
|
|
test_chunks = re.findall(pattern,data,re.S)
|
|
|
|
tests = map( parsetest, test_chunks )
|
2011-11-30 06:41:28 +04:00
|
|
|
tests = sorted(tests, key = lambda t:t.passed)
|
2011-11-16 15:58:07 +04:00
|
|
|
return startdate, tests, enddate
|
|
|
|
|
2011-11-30 06:41:28 +04:00
|
|
|
def load_makefiles(builddir):
|
2011-11-30 08:15:07 +04:00
|
|
|
filelist = []
|
2011-11-30 06:41:28 +04:00
|
|
|
for root, dirs, files in os.walk(builddir):
|
2011-11-30 08:15:07 +04:00
|
|
|
for fname in files: filelist += [ os.path.join(root, fname) ]
|
|
|
|
files = filter(lambda x: 'build.make' in os.path.basename(x), filelist)
|
|
|
|
files += filter(lambda x: 'flags.make' in os.path.basename(x), filelist)
|
2011-11-30 06:41:28 +04:00
|
|
|
files = filter(lambda x: 'esting' not in x and 'emporary' not in x, files)
|
|
|
|
result = {}
|
2011-11-30 08:15:07 +04:00
|
|
|
for fname in files:
|
2011-11-30 06:41:28 +04:00
|
|
|
result[fname.replace(builddir,'')] = open(fname,'rb').read()
|
|
|
|
return result
|
|
|
|
|
|
|
|
def wikify_filename(fname, wiki_rootpath, sysid):
|
|
|
|
wikifname = fname.replace('/','_').replace('\\','_').strip('.')
|
|
|
|
return wiki_rootpath + '_' + sysid + '_' + wikifname
|
2011-11-16 15:58:07 +04:00
|
|
|
|
2011-11-30 06:41:28 +04:00
|
|
|
def towiki(wiki_rootpath, startdate, tests, enddate, sysinfo, sysid, makefiles):
|
2011-11-26 21:11:55 +04:00
|
|
|
|
2011-11-17 07:36:58 +04:00
|
|
|
wiki_template = """
|
|
|
|
<h3>[[WIKI_ROOTPATH]] test run report</h3>
|
2011-11-16 15:58:07 +04:00
|
|
|
|
2011-11-17 07:36:58 +04:00
|
|
|
'''Sysid''': SYSID
|
2011-11-16 15:58:07 +04:00
|
|
|
|
2011-11-17 07:36:58 +04:00
|
|
|
'''Result summary''': NUMPASSED / NUMTESTS tests passed ( PERCENTPASSED % ) <br>
|
|
|
|
|
|
|
|
'''System info''':
|
2011-11-16 15:58:07 +04:00
|
|
|
<pre>
|
|
|
|
SYSINFO
|
|
|
|
</pre>
|
|
|
|
|
2011-11-17 07:36:58 +04:00
|
|
|
start time: STARTDATE <br>
|
|
|
|
end time : ENDDATE <br>
|
2011-11-16 15:58:07 +04:00
|
|
|
|
2011-12-07 09:00:45 +04:00
|
|
|
'''Image tests'''
|
2011-11-16 15:58:07 +04:00
|
|
|
|
|
|
|
<REPEAT1>
|
2011-11-26 21:11:55 +04:00
|
|
|
{| border=1 cellspacing=0 cellpadding=1
|
2011-11-16 15:58:07 +04:00
|
|
|
|-
|
2011-11-26 21:11:55 +04:00
|
|
|
| colspan=2 | FTESTNAME
|
|
|
|
|-
|
|
|
|
| Expected image || Actual image
|
|
|
|
|-
|
|
|
|
| [[File:EXPECTEDFILE|250px]] || ACTUALFILE_WIKI
|
2011-11-16 15:58:07 +04:00
|
|
|
|}
|
|
|
|
|
2011-11-26 21:11:55 +04:00
|
|
|
<pre>
|
2011-11-26 22:17:54 +04:00
|
|
|
TESTLOG
|
2011-11-26 21:11:55 +04:00
|
|
|
</pre>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
</REPEAT1>
|
|
|
|
|
|
|
|
|
2011-12-07 09:00:45 +04:00
|
|
|
'''Text tests'''
|
2011-11-16 15:58:07 +04:00
|
|
|
|
|
|
|
<REPEAT2>
|
2011-12-01 08:24:14 +04:00
|
|
|
{|border=1 cellspacing=0 cellpadding=1
|
2011-11-16 15:58:07 +04:00
|
|
|
|-
|
|
|
|
| FTESTNAME
|
|
|
|
|}
|
|
|
|
|
2011-12-01 08:24:14 +04:00
|
|
|
<pre>
|
|
|
|
TESTLOG
|
|
|
|
</pre>
|
|
|
|
|
2011-12-07 09:10:44 +04:00
|
|
|
|
2011-12-01 08:24:14 +04:00
|
|
|
</REPEAT2>
|
|
|
|
|
2011-11-30 06:41:28 +04:00
|
|
|
'''build.make and flags.make'''
|
|
|
|
<REPEAT3>
|
|
|
|
*[[MAKEFILE_NAME]]
|
|
|
|
</REPEAT3>
|
2011-11-17 07:36:58 +04:00
|
|
|
"""
|
2011-11-30 06:41:28 +04:00
|
|
|
txtpages = {}
|
|
|
|
imgs = {}
|
2011-11-26 21:11:55 +04:00
|
|
|
passed_tests = filter(lambda x: x.passed, tests)
|
|
|
|
failed_tests = filter(lambda x: not x.passed, tests)
|
2011-12-09 21:31:18 +04:00
|
|
|
|
2011-12-18 04:17:13 +04:00
|
|
|
tests_to_report = failed_tests
|
|
|
|
if include_passed: tests_to_report = tests
|
2011-12-09 21:31:18 +04:00
|
|
|
|
2011-12-13 05:57:39 +04:00
|
|
|
try: percent = str(int(100.0*len(passed_tests) / len(tests)))
|
|
|
|
except ZeroDivisionError: percent = 'n/a'
|
2011-11-16 15:58:07 +04:00
|
|
|
s = wiki_template
|
|
|
|
repeat1 = ezsearch('(<REPEAT1>.*?</REPEAT1>)',s)
|
|
|
|
repeat2 = ezsearch('(<REPEAT2>.*?</REPEAT2>)',s)
|
2011-11-30 06:41:28 +04:00
|
|
|
repeat3 = ezsearch('(<REPEAT3>.*?</REPEAT3>)',s)
|
2011-11-24 07:47:33 +04:00
|
|
|
dic = { 'STARTDATE': startdate, 'ENDDATE': enddate, 'WIKI_ROOTPATH': wiki_rootpath,
|
2011-11-26 21:11:55 +04:00
|
|
|
'SYSINFO': sysinfo, 'SYSID':sysid,
|
|
|
|
'NUMTESTS':len(tests), 'NUMPASSED':len(passed_tests), 'PERCENTPASSED':percent }
|
2011-11-16 15:58:07 +04:00
|
|
|
for key in dic.keys():
|
2011-11-26 21:11:55 +04:00
|
|
|
s = s.replace(key,str(dic[key]))
|
2011-12-09 21:31:18 +04:00
|
|
|
|
|
|
|
for t in tests_to_report:
|
2013-06-24 22:16:13 +04:00
|
|
|
if t.type in ('txt', 'ast', 'csg'):
|
2011-11-26 21:11:55 +04:00
|
|
|
newchunk = re.sub('FTESTNAME',t.fullname,repeat2)
|
2011-12-01 08:24:14 +04:00
|
|
|
newchunk = newchunk.replace('TESTLOG',t.fulltestlog)
|
2011-11-26 21:11:55 +04:00
|
|
|
s = s.replace(repeat2, newchunk+repeat2)
|
|
|
|
elif t.type=='png':
|
2011-11-30 06:41:28 +04:00
|
|
|
tmp = t.actualfile.replace(builddir,'')
|
|
|
|
wikiname_a = wikify_filename(tmp,wiki_rootpath,sysid)
|
|
|
|
tmp = t.expectedfile.replace(os.path.dirname(builddir),'')
|
|
|
|
wikiname_e = wikify_filename(tmp,wiki_rootpath,sysid)
|
2011-12-21 20:42:11 +04:00
|
|
|
if hasattr(t, 'expectedfile_data'):
|
|
|
|
imgs[wikiname_e] = t.expectedfile_data
|
2011-11-26 21:11:55 +04:00
|
|
|
if t.actualfile:
|
2011-11-30 06:41:28 +04:00
|
|
|
actualfile_wiki = '[[File:'+wikiname_a+'|250px]]'
|
2011-12-21 20:42:11 +04:00
|
|
|
if hasattr(t, 'actualfile_data'):
|
|
|
|
imgs[wikiname_a] = t.actualfile_data
|
2011-11-26 21:11:55 +04:00
|
|
|
else:
|
|
|
|
actualfile_wiki = 'No image generated.'
|
|
|
|
newchunk = re.sub('FTESTNAME',t.fullname,repeat1)
|
|
|
|
newchunk = newchunk.replace('ACTUALFILE_WIKI',actualfile_wiki)
|
2011-11-30 06:41:28 +04:00
|
|
|
newchunk = newchunk.replace('EXPECTEDFILE',wikiname_e)
|
2011-11-26 21:11:55 +04:00
|
|
|
newchunk = newchunk.replace('TESTLOG',t.fulltestlog)
|
|
|
|
s = s.replace(repeat1, newchunk+repeat1)
|
2013-06-24 22:16:13 +04:00
|
|
|
else:
|
|
|
|
raise Exception("Unknown test type %r"%t.type)
|
2011-11-26 21:11:55 +04:00
|
|
|
|
2011-11-30 06:41:28 +04:00
|
|
|
makefiles_wikinames = {}
|
|
|
|
for mf in sorted(makefiles.keys()):
|
|
|
|
tmp = mf.replace('CMakeFiles','').replace('.dir','')
|
|
|
|
wikiname = wikify_filename(tmp,wiki_rootpath,sysid)
|
|
|
|
newchunk = re.sub('MAKEFILE_NAME',wikiname,repeat3)
|
|
|
|
s = s.replace(repeat3, newchunk+repeat3)
|
|
|
|
makefiles_wikinames[mf] = wikiname
|
|
|
|
|
2011-11-16 15:58:07 +04:00
|
|
|
s = s.replace(repeat1,'')
|
|
|
|
s = s.replace(repeat2,'')
|
2011-11-30 06:41:28 +04:00
|
|
|
s = s.replace(repeat3,'')
|
2011-11-16 15:58:07 +04:00
|
|
|
s = re.sub('<REPEAT.*?>\n','',s)
|
|
|
|
s = re.sub('</REPEAT.*?>','',s)
|
|
|
|
|
2011-11-30 06:41:28 +04:00
|
|
|
mainpage_wikiname = wiki_rootpath + '_' + sysid + '_test_report'
|
|
|
|
txtpages[ mainpage_wikiname ] = s
|
|
|
|
for mf in sorted(makefiles.keys()):
|
2011-11-30 06:57:44 +04:00
|
|
|
txtpages[ makefiles_wikinames[ mf ] ] = '\n*Subreport from [['+mainpage_wikiname+']]\n\n\n<pre>\n'+makefiles[mf]+'\n</pre>'
|
2011-11-30 06:41:28 +04:00
|
|
|
|
|
|
|
return imgs, txtpages
|
2011-11-16 15:58:07 +04:00
|
|
|
|
2013-02-19 07:36:00 +04:00
|
|
|
def png_encode64( fname, width=250 ):
|
|
|
|
# en.wikipedia.org/wiki/Data_URI_scheme
|
2013-03-09 19:42:53 +04:00
|
|
|
try:
|
|
|
|
f = open( fname, "rb" )
|
|
|
|
data = f.read()
|
|
|
|
except:
|
|
|
|
data = ''
|
2013-02-19 07:36:00 +04:00
|
|
|
data_uri = data.encode("base64").replace("\n","")
|
|
|
|
tag = '<img'
|
2013-03-09 19:58:54 +04:00
|
|
|
tag += ' style="border:1px solid gray"'
|
2013-02-19 07:36:00 +04:00
|
|
|
tag += ' src="data:image/png;base64,'
|
|
|
|
tag += data_uri + '"'
|
|
|
|
tag += ' width="'+str(width)+'"'
|
2013-03-09 19:58:54 +04:00
|
|
|
if data =='':
|
|
|
|
tag += ' alt="error: no image generated"'
|
|
|
|
else:
|
|
|
|
tag += ' alt="openscad_test_image"'
|
2013-02-19 07:36:00 +04:00
|
|
|
tag += ' />\n'
|
|
|
|
return tag
|
|
|
|
|
2011-12-07 08:53:58 +04:00
|
|
|
def tohtml(wiki_rootpath, startdate, tests, enddate, sysinfo, sysid, makefiles):
|
|
|
|
# kludge. assume wiki stuff has alreayd run and dumped files properly
|
2011-11-17 07:36:58 +04:00
|
|
|
head = '<html><head><title>'+wiki_rootpath+' test run for '+sysid +'</title></head><body>'
|
2011-12-07 08:53:58 +04:00
|
|
|
tail = '</body></html>'
|
|
|
|
|
|
|
|
passed_tests = filter(lambda x: x.passed, tests)
|
|
|
|
failed_tests = filter(lambda x: not x.passed, tests)
|
2011-12-13 05:57:39 +04:00
|
|
|
try: percent = str(int(100.0*len(passed_tests) / len(tests)))
|
|
|
|
except ZeroDivisionError: percent = 'n/a'
|
2011-12-07 08:53:58 +04:00
|
|
|
|
2011-12-18 04:17:13 +04:00
|
|
|
tests_to_report = failed_tests
|
|
|
|
if include_passed: tests_to_report = tests
|
2011-12-09 21:31:18 +04:00
|
|
|
|
2011-12-07 08:53:58 +04:00
|
|
|
s=''
|
|
|
|
|
2013-02-19 07:36:00 +04:00
|
|
|
s+= '\n<h3>'
|
|
|
|
s+= '\nSystem info\n'
|
|
|
|
s+= '\n</h3><p>'
|
|
|
|
s+= '<pre>'+sysinfo+'</pre>\n'
|
2011-12-07 08:53:58 +04:00
|
|
|
|
|
|
|
s+= '\n<pre>'
|
|
|
|
s+= '\nSTARTDATE: '+ startdate
|
|
|
|
s+= '\nENDDATE: '+ enddate
|
|
|
|
s+= '\nWIKI_ROOTPATH: '+ wiki_rootpath
|
|
|
|
s+= '\nSYSID: '+sysid
|
|
|
|
s+= '\nNUMTESTS: '+str(len(tests))
|
|
|
|
s+= '\nNUMPASSED: '+str(len(passed_tests))
|
|
|
|
s+= '\nPERCENTPASSED: '+ percent
|
|
|
|
s+= '\n</pre>'
|
|
|
|
|
2013-02-19 07:36:00 +04:00
|
|
|
if not include_passed:
|
|
|
|
s+= '<h3>Failed tests:</h3>\n'
|
|
|
|
|
2013-02-25 07:20:11 +04:00
|
|
|
if len(tests_to_report)==0:
|
|
|
|
s+= '<p>none</p>'
|
|
|
|
|
2011-12-09 21:31:18 +04:00
|
|
|
for t in tests_to_report:
|
2013-06-24 22:16:13 +04:00
|
|
|
if t.type in ('txt', 'ast', 'csg'):
|
2011-12-07 08:53:58 +04:00
|
|
|
s+='\n<pre>'+t.fullname+'</pre>\n'
|
|
|
|
s+='<p><pre>'+t.fulltestlog+'</pre>\n\n'
|
|
|
|
elif t.type=='png':
|
|
|
|
tmp = t.actualfile.replace(builddir,'')
|
|
|
|
wikiname_a = wikify_filename(tmp,wiki_rootpath,sysid)
|
|
|
|
tmp = t.expectedfile.replace(os.path.dirname(builddir),'')
|
|
|
|
wikiname_e = wikify_filename(tmp,wiki_rootpath,sysid)
|
2013-02-19 07:36:00 +04:00
|
|
|
# imgtag_e = <img src='+wikiname_e+' width=250/>'
|
|
|
|
# imatag_a = <img src='+wikiname_a+' width=250/>'
|
|
|
|
imgtag_e = png_encode64( t.expectedfile, 250 )
|
|
|
|
imgtag_a = png_encode64( t.actualfile, 250 )
|
2011-12-07 08:53:58 +04:00
|
|
|
s+='<table>'
|
|
|
|
s+='\n<tr><td colspan=2>'+t.fullname
|
|
|
|
s+='\n<tr><td>Expected<td>Actual'
|
2013-02-19 07:36:00 +04:00
|
|
|
s+='\n<tr><td>' + imgtag_e + '</td>'
|
|
|
|
s+='\n <td>' + imgtag_a + '</td>'
|
2011-12-07 08:53:58 +04:00
|
|
|
s+='\n</table>'
|
|
|
|
s+='\n<pre>'
|
|
|
|
s+=t.fulltestlog
|
|
|
|
s+='\n</pre>'
|
2013-06-24 22:16:13 +04:00
|
|
|
else:
|
|
|
|
raise Exception("Unknown test type %r"%t.type)
|
2011-12-07 08:53:58 +04:00
|
|
|
|
|
|
|
s+='\n\n<p>\n\n'
|
2013-02-19 07:36:00 +04:00
|
|
|
|
|
|
|
s+= '<h3> CMake .build files </h3>\n'
|
|
|
|
s+= '\n<pre>'
|
2011-12-07 08:53:58 +04:00
|
|
|
makefiles_wikinames = {}
|
|
|
|
for mf in sorted(makefiles.keys()):
|
2013-02-19 07:36:00 +04:00
|
|
|
mfname = mf.strip().lstrip(os.path.sep)
|
|
|
|
text = open(os.path.join(builddir,mfname)).read()
|
|
|
|
s+= '</pre><h4>'+mfname+'</h4><pre>'
|
|
|
|
s+= text
|
2011-12-07 08:53:58 +04:00
|
|
|
tmp = mf.replace('CMakeFiles','').replace('.dir','')
|
|
|
|
wikiname = wikify_filename(tmp,wiki_rootpath,sysid)
|
2013-02-19 07:36:00 +04:00
|
|
|
# s += '\n<a href='+wikiname+'>'+wikiname+'</a><br>'
|
|
|
|
s+= '\n</pre>'
|
2011-12-07 08:53:58 +04:00
|
|
|
s+='\n'
|
|
|
|
|
|
|
|
return head + s + tail
|
2011-11-17 07:36:58 +04:00
|
|
|
|
2011-12-07 07:48:19 +04:00
|
|
|
def wiki_login(wikiurl,api_php_path,botname,botpass):
|
|
|
|
site = mwclient.Site(wikiurl,api_php_path)
|
|
|
|
site.login(botname,botpass)
|
|
|
|
return site
|
|
|
|
|
|
|
|
def wiki_upload(wikiurl,api_php_path,botname,botpass,filedata,wikipgname):
|
|
|
|
counter = 0
|
|
|
|
done = False
|
|
|
|
descrip = 'test'
|
|
|
|
time.sleep(1)
|
|
|
|
while not done:
|
|
|
|
try:
|
|
|
|
print 'login',botname,'to',wikiurl
|
|
|
|
site = wiki_login(wikiurl,api_php_path,botname,botpass)
|
2011-12-07 08:31:59 +04:00
|
|
|
print 'uploading...',
|
2011-12-07 07:48:19 +04:00
|
|
|
if wikipgname.endswith('png'):
|
|
|
|
site.upload(filedata,wikipgname,descrip,ignore=True)
|
|
|
|
else:
|
|
|
|
page = site.Pages[wikipgname]
|
|
|
|
text = page.edit()
|
|
|
|
page.save(filedata)
|
|
|
|
done = True
|
2011-12-07 08:31:59 +04:00
|
|
|
print 'transfer ok'
|
2011-12-07 07:48:19 +04:00
|
|
|
except Exception, e:
|
|
|
|
print 'Error:', type(e),e
|
|
|
|
counter += 1
|
|
|
|
if counter>maxretry:
|
|
|
|
print 'giving up. please try a different wiki site'
|
|
|
|
done = True
|
|
|
|
else:
|
|
|
|
print 'wiki',wikiurl,'down. retrying in 15 seconds'
|
|
|
|
time.sleep(15)
|
|
|
|
|
2011-11-30 06:41:28 +04:00
|
|
|
def upload(wikiurl,api_php_path='/',wiki_rootpath='test', sysid='null', botname='cakebaby',botpass='anniew',wikidir='.',dryrun=True):
|
|
|
|
wetrun = not dryrun
|
2011-11-30 08:15:07 +04:00
|
|
|
if dryrun: print 'dry run'
|
2011-11-17 07:36:58 +04:00
|
|
|
try:
|
2011-12-07 07:48:19 +04:00
|
|
|
global mwclient
|
2011-11-17 07:36:58 +04:00
|
|
|
import mwclient
|
|
|
|
except:
|
2011-12-07 07:48:19 +04:00
|
|
|
print 'please download mwclient 0.6.5 and unpack here:', os.getcwd()
|
2011-11-30 06:41:28 +04:00
|
|
|
sys.exit()
|
2011-12-07 07:48:19 +04:00
|
|
|
|
|
|
|
if wetrun: site = wiki_login(wikiurl,api_php_path,botname,botpass)
|
2011-11-30 06:41:28 +04:00
|
|
|
|
|
|
|
wikifiles = os.listdir(wikidir)
|
|
|
|
testreport_page = filter( lambda x: 'test_report' in x, wikifiles )
|
|
|
|
if (len(testreport_page)>1):
|
|
|
|
print 'multiple test reports found, please clean dir',wikidir
|
|
|
|
sys.exit()
|
2011-12-07 07:48:19 +04:00
|
|
|
|
2011-11-30 06:41:28 +04:00
|
|
|
rootpage = testreport_page[0]
|
|
|
|
print 'add',rootpage,' to main report page ',wiki_rootpath
|
|
|
|
if wetrun:
|
2011-11-30 08:15:07 +04:00
|
|
|
page = site.Pages[wiki_rootpath]
|
|
|
|
text = page.edit()
|
|
|
|
if not '[['+rootpage+']]' in text:
|
|
|
|
page.save(text +'\n*[['+rootpage+']]\n')
|
2011-11-17 07:36:58 +04:00
|
|
|
|
2011-11-30 06:41:28 +04:00
|
|
|
wikifiles = os.listdir(wikidir)
|
2011-12-07 09:00:45 +04:00
|
|
|
wikifiles = filter(lambda x: not x.endswith('html'), wikifiles)
|
|
|
|
|
2011-11-30 06:41:28 +04:00
|
|
|
print 'upload wiki pages:'
|
|
|
|
for wikiname in wikifiles:
|
|
|
|
filename = os.path.join(wikidir,wikiname)
|
|
|
|
filedata = tryread(filename)
|
2011-12-07 08:31:59 +04:00
|
|
|
print 'upload',len(filedata),'bytes from',wikiname
|
2011-12-18 21:37:37 +04:00
|
|
|
if wetrun and len(filedata)>0:
|
2011-12-07 07:48:19 +04:00
|
|
|
wiki_upload(wikiurl,api_php_path,botname,botpass,filedata,wikiname)
|
2011-12-18 21:37:37 +04:00
|
|
|
if len(filedata)==0:
|
|
|
|
print 'cancelling empty upload'
|
2011-12-07 09:00:45 +04:00
|
|
|
|
2011-11-30 06:41:28 +04:00
|
|
|
def findlogfile(builddir):
|
|
|
|
logpath = os.path.join(builddir,'Testing','Temporary')
|
2011-12-01 08:24:14 +04:00
|
|
|
logfilename = os.path.join(logpath,'LastTest.log.tmp')
|
|
|
|
if not os.path.isfile(logfilename):
|
|
|
|
logfilename = os.path.join(logpath,'LastTest.log')
|
|
|
|
if not os.path.isfile(logfilename):
|
|
|
|
print 'cant find and/or open logfile',logfilename
|
|
|
|
sys.exit()
|
2011-11-30 06:41:28 +04:00
|
|
|
return logpath, logfilename
|
|
|
|
|
2013-02-19 07:36:00 +04:00
|
|
|
def debug(x):
|
|
|
|
if debug_test_pp: print 'test_pretty_print: '+x
|
|
|
|
|
|
|
|
debug_test_pp=False
|
|
|
|
builddir=os.getcwd()
|
|
|
|
|
2011-11-30 06:41:28 +04:00
|
|
|
def main():
|
2013-02-19 05:45:37 +04:00
|
|
|
#wikisite = 'cakebaby.referata.com'
|
|
|
|
#wiki_api_path = ''
|
2013-02-19 07:36:00 +04:00
|
|
|
global wikisite, wiki_api_path, wiki_rootpath, builddir, debug_test_pp
|
|
|
|
global maxretry, dry, include_passed
|
|
|
|
|
2013-02-19 05:45:37 +04:00
|
|
|
wikisite = 'cakebaby.wikia.com'
|
|
|
|
wiki_api_path = '/'
|
|
|
|
wiki_rootpath = 'OpenSCAD'
|
2013-02-19 07:36:00 +04:00
|
|
|
if '--debug' in string.join(sys.argv): debug_test_pp=True
|
2013-02-19 05:45:37 +04:00
|
|
|
maxretry = 10
|
|
|
|
|
|
|
|
if bool(os.getenv("TEST_GENERATE")): sys.exit(0)
|
|
|
|
|
|
|
|
include_passed = False
|
|
|
|
if '--include-passed' in sys.argv: include_passed = True
|
|
|
|
|
2011-11-30 06:41:28 +04:00
|
|
|
dry = False
|
2013-02-19 07:36:00 +04:00
|
|
|
debug( 'running test_pretty_print' )
|
2011-11-30 06:41:28 +04:00
|
|
|
if '--dryrun' in sys.argv: dry=True
|
2011-12-01 08:24:14 +04:00
|
|
|
suffix = ezsearch('--suffix=(.*?) ',string.join(sys.argv)+' ')
|
|
|
|
builddir = ezsearch('--builddir=(.*?) ',string.join(sys.argv)+' ')
|
|
|
|
if builddir=='': builddir=os.getcwd()
|
2013-02-19 07:36:00 +04:00
|
|
|
debug( 'build dir set to ' + builddir )
|
2011-11-30 06:41:28 +04:00
|
|
|
|
|
|
|
sysinfo, sysid = read_sysinfo(os.path.join(builddir,'sysinfo.txt'))
|
|
|
|
makefiles = load_makefiles(builddir)
|
|
|
|
logpath, logfilename = findlogfile(builddir)
|
|
|
|
testlog = tryread(logfilename)
|
|
|
|
startdate, tests, enddate = parselog(testlog)
|
2013-02-19 07:36:00 +04:00
|
|
|
if debug_test_pp:
|
2011-12-07 07:48:19 +04:00
|
|
|
print 'found sysinfo.txt,',
|
|
|
|
print 'found', len(makefiles),'makefiles,',
|
|
|
|
print 'found', len(tests),'test results'
|
2011-11-30 08:15:07 +04:00
|
|
|
|
2011-11-30 06:41:28 +04:00
|
|
|
imgs, txtpages = towiki(wiki_rootpath, startdate, tests, enddate, sysinfo, sysid, makefiles)
|
2011-11-30 08:15:07 +04:00
|
|
|
|
2011-12-07 07:48:19 +04:00
|
|
|
wikidir = os.path.join(logpath,sysid+'_report')
|
2013-02-19 07:36:00 +04:00
|
|
|
debug( 'erasing files in ' + wikidir )
|
2011-12-07 10:02:34 +04:00
|
|
|
try: map(lambda x:os.remove(os.path.join(wikidir,x)), os.listdir(wikidir))
|
|
|
|
except: pass
|
2013-02-19 07:36:00 +04:00
|
|
|
debug( 'output dir:\n' + wikidir.replace(os.getcwd(),'') )
|
|
|
|
debug( 'writing ' + str(len(imgs)) + ' images' )
|
|
|
|
debug( 'writing ' + str(len(txtpages)-1) + ' text pages' )
|
|
|
|
debug( 'writing index.html ' )
|
2013-02-25 07:20:11 +04:00
|
|
|
if '--wiki' in string.join(sys.argv):
|
|
|
|
print "wiki output is deprecated"
|
|
|
|
for pgname in sorted(imgs): trysave( os.path.join(wikidir,pgname), imgs[pgname])
|
|
|
|
for pgname in sorted(txtpages): trysave( os.path.join(wikidir,pgname), txtpages[pgname])
|
2011-12-07 08:53:58 +04:00
|
|
|
|
|
|
|
htmldata = tohtml(wiki_rootpath, startdate, tests, enddate, sysinfo, sysid, makefiles)
|
2013-02-19 07:36:00 +04:00
|
|
|
html_basename = sysid+'_report.html'
|
|
|
|
html_filename = os.path.join(builddir,'Testing','Temporary',html_basename)
|
|
|
|
debug('saving ' +html_filename + ' ' + str(len(htmldata)) + ' bytes')
|
|
|
|
trysave( html_filename, htmldata )
|
|
|
|
print "report saved:", html_filename.replace(os.getcwd()+os.path.sep,'')
|
2011-11-23 06:31:57 +04:00
|
|
|
|
2013-02-19 05:45:37 +04:00
|
|
|
if '--wiki-upload' in sys.argv:
|
2013-02-19 07:36:00 +04:00
|
|
|
print "wiki upload is deprecated."
|
2011-11-30 06:41:28 +04:00
|
|
|
upload(wikisite,wiki_api_path,wiki_rootpath,sysid,'openscadbot',
|
|
|
|
'tobdacsnepo',wikidir,dryrun=dry)
|
2011-12-07 08:31:59 +04:00
|
|
|
print 'upload attempt complete'
|
|
|
|
|
2013-02-19 07:36:00 +04:00
|
|
|
debug( 'test_pretty_print complete' )
|
2011-11-30 15:15:57 +04:00
|
|
|
|
2013-02-19 05:45:37 +04:00
|
|
|
if __name__=='__main__':
|
|
|
|
main()
|