diff options
| -rw-r--r-- | tests/CMakeLists.txt | 14 | ||||
| -rw-r--r-- | tests/OffscreenContext.mm | 9 | ||||
| -rw-r--r-- | tests/OffscreenContextGLX.cc (renamed from tests/OffscreenContext.cc) | 11 | ||||
| -rw-r--r-- | tests/OffscreenContextWGL.cc | 6 | ||||
| -rw-r--r-- | tests/OffscreenView.cc | 32 | ||||
| -rw-r--r-- | tests/csgtestcore.cc | 28 | ||||
| -rwxr-xr-x | tests/ctest_pretty_print.py | 254 | ||||
| -rwxr-xr-x | tests/test_cmdline_tool.py | 9 | ||||
| -rwxr-xr-x | tests/test_pretty_print.py | 266 | 
9 files changed, 330 insertions, 299 deletions
| diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 85c4f21..5315c01 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -265,7 +265,7 @@ if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")  	set(OFFSCREEN_CTX_SOURCE "OffscreenContext.mm" CACHE TYPE STRING)  elseif(UNIX)  	message(STATUS "Offscreen OpenGL Context - using Unix GLX") -	set(OFFSCREEN_CTX_SOURCE "OffscreenContext.cc" CACHE TYPE STRING) +	set(OFFSCREEN_CTX_SOURCE "OffscreenContextGLX.cc" CACHE TYPE STRING)  elseif(WIN32)  	message(STATUS "Offscreen OpenGL Context - using Microsoft WGL")  	set(OFFSCREEN_CTX_SOURCE "OffscreenContextWGL.cc" CACHE TYPE STRING) @@ -367,16 +367,20 @@ enable_testing()  # set up custom pretty printing of results  set(INFOCMD "execute_process(COMMAND ${CMAKE_CURRENT_BINARY_DIR}/opencsgtest --info OUTPUT_FILE sysinfo.txt)") -set(PRETTYCMD "\"${PYTHON_EXECUTABLE} ctest_pretty_print.py\"") +set(PRETTYCMD "\"${PYTHON_EXECUTABLE} test_pretty_print.py\"")  set(CTEST_CUSTOM_FILE ${CMAKE_CURRENT_BINARY_DIR}/CTestCustom.cmake)  set(CTEST_CUSTOM_TXT "\n    message(\"running 'opencsgtest --info' to generate sysinfo.txt\")\n    ${INFOCMD}\n -  set(CTEST_CUSTOM_POST_TEST ${PRETTYCMD})\n +  # set(CTEST_CUSTOM_POST_TEST ${PRETTYCMD})\n # doesn't work. log is written +  # after all tests run.  ")  file(WRITE ${CTEST_CUSTOM_FILE} ${CTEST_CUSTOM_TXT}) -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/ctest_pretty_print.py  -                 ${CMAKE_CURRENT_BINARY_DIR}/ctest_pretty_print.py COPYONLY) + +foreach(FILE test_pretty_print.py) +  configure_file(${CMAKE_CURRENT_SOURCE_DIR}/${FILE} +                 ${CMAKE_CURRENT_BINARY_DIR}/${FILE} COPYONLY) +endforeach()  # Find all scad files  file(GLOB MINIMAL_FILES ${CMAKE_SOURCE_DIR}/../testdata/scad/minimal/*.scad) diff --git a/tests/OffscreenContext.mm b/tests/OffscreenContext.mm index baa39e0..7d95481 100644 --- a/tests/OffscreenContext.mm +++ b/tests/OffscreenContext.mm @@ -18,10 +18,11 @@ struct OffscreenContext  string offscreen_context_getinfo(OffscreenContext *ctx)  { -  sstream result; -  result << "OS info: Mac OSX\n"; -  result << "Machine: Apple(TM) Mac(TM)\n"; -  return result.str(); +  stringstream out; +  out << "GL context creator: Cocoa / CGL\n" +      << "OS info: Mac OSX\n" +      << "Machine: Apple(TM) Mac(TM)\n"; +  return out.str();  }  OffscreenContext *create_offscreen_context(int w, int h) diff --git a/tests/OffscreenContext.cc b/tests/OffscreenContextGLX.cc index 994a74d..ed9ef46 100644 --- a/tests/OffscreenContext.cc +++ b/tests/OffscreenContextGLX.cc @@ -52,7 +52,7 @@ See Also  using namespace std;  struct OffscreenContext -	{ +{    GLXContext openGLContext;    Display *xdisplay;    Window xwindow; @@ -71,7 +71,7 @@ void offscreen_context_init(OffscreenContext &ctx, int width, int height)    ctx.fbo = NULL;  } -string get_unix_info() +string get_os_info()  {    struct utsname u;    stringstream out; @@ -99,10 +99,9 @@ string offscreen_context_getinfo(OffscreenContext *ctx)    glXQueryVersion(ctx->xdisplay, &major, &minor);    stringstream out; -  out << "GLX version: " << major << "." << minor << "\n"; -  out << glew_dump(false); - -  out << get_unix_info(); +  out << "GL context creator: GLX\n" +      << "GLX version: " << major << "." << minor << "\n" +      << get_os_info();    return out.str();  } diff --git a/tests/OffscreenContextWGL.cc b/tests/OffscreenContextWGL.cc index 3756a82..4deaf2a 100644 --- a/tests/OffscreenContextWGL.cc +++ b/tests/OffscreenContextWGL.cc @@ -48,7 +48,7 @@ void offscreen_context_init(OffscreenContext &ctx, int width, int height)    ctx.fbo = NULL;  } -string get_windows_info() +string get_os_info()  {    OSVERSIONINFO osvi; @@ -81,8 +81,8 @@ string get_windows_info()  string offscreen_context_getinfo(OffscreenContext *ctx)  {    stringstream out; -  out << glew_dump(false); -  out << get_windows_info(); +  out << "GL context creator: WGL\n" +      << get_windows_info();    return out.str();  } diff --git a/tests/OffscreenView.cc b/tests/OffscreenView.cc index 2a4a27e..9c8964c 100644 --- a/tests/OffscreenView.cc +++ b/tests/OffscreenView.cc @@ -1,11 +1,13 @@  #include <GL/glew.h>  #include "OffscreenView.h" +#include "system-gl.h"  #include <opencsg.h>  #include "renderer.h"  #include <math.h>  #include <stdio.h>  #include <string.h>  #include <cstdlib> +#include <sstream>  #define FAR_FAR_AWAY 100000.0 @@ -17,19 +19,6 @@ OffscreenView::OffscreenView(size_t width, size_t height)  	this->ctx = create_offscreen_context(width, height);  	if ( this->ctx == NULL ) throw -1; -#ifdef DEBUG -	GLint rbits, gbits, bbits, abits, dbits, sbits; -	glGetIntegerv(GL_RED_BITS, &rbits); -	glGetIntegerv(GL_GREEN_BITS, &gbits); -	glGetIntegerv(GL_BLUE_BITS, &bbits); -	glGetIntegerv(GL_ALPHA_BITS, &abits); -	glGetIntegerv(GL_DEPTH_BITS, &dbits); -	glGetIntegerv(GL_STENCIL_BITS, &sbits); - -	fprintf(stderr, "FBO: RGBA(%d%d%d%d), depth(%d), stencil(%d)\n",  -					rbits, gbits, bbits, abits, dbits, sbits); -#endif -  	initializeGL();  	resizeGL(width, height);  } @@ -251,7 +240,22 @@ bool OffscreenView::save(const char *filename)  std::string OffscreenView::getInfo()  { -	return offscreen_context_getinfo(this->ctx); +	std::stringstream out; +	GLint rbits, gbits, bbits, abits, dbits, sbits; +	glGetIntegerv(GL_RED_BITS, &rbits); +	glGetIntegerv(GL_GREEN_BITS, &gbits); +	glGetIntegerv(GL_BLUE_BITS, &bbits); +	glGetIntegerv(GL_ALPHA_BITS, &abits); +	glGetIntegerv(GL_DEPTH_BITS, &dbits); +	glGetIntegerv(GL_STENCIL_BITS, &sbits); + +	out << glew_dump(false) +	    << "FBO: RGBA(" << rbits << gbits << bbits << abits +	    << "), depth(" << dbits +	    << "), stencil(" << sbits << ")\n" +	    << offscreen_context_getinfo(this->ctx); + +	return out.str();  }  void OffscreenView::setCamera(const Eigen::Vector3d &pos, const Eigen::Vector3d ¢er) diff --git a/tests/csgtestcore.cc b/tests/csgtestcore.cc index 5866346..9511688 100644 --- a/tests/csgtestcore.cc +++ b/tests/csgtestcore.cc @@ -76,8 +76,8 @@ AbstractNode *find_root_tag(AbstractNode *n)  string info_dump(OffscreenView *glview)  { -#define STRINGIFY(x) #x -#define TOSTRING(x) STRINGIFY(x) +	assert(glview); +  #ifdef __GNUG__  #define compiler_info "GCC " << __VERSION__  #elif defined(_MSC_VER) @@ -85,18 +85,26 @@ string info_dump(OffscreenView *glview)  #else  #define compiler_info "unknown compiler"  #endif -	assert(glview); +  	std::stringstream out;  	out << "OpenSCAD info dump:" -	  << "\nOpenSCAD Year/Month/Day: " << int(OPENSCAD_YEAR) << "." -	  << int(OPENSCAD_MONTH) << "."  +	    << "\nOpenSCAD Year/Month/Day: " << int(OPENSCAD_YEAR) << "." +	    << int(OPENSCAD_MONTH) << "."  #ifdef OPENSCAD_DAY -	  << int(OPENSCAD_DAY) +	    << int(OPENSCAD_DAY);  #endif -	  << "\nOpenSCAD Version: " << TOSTRING(OPENSCAD_VERSION) -          << "\nCompiled with: " << compiler_info -	  << "\nGL Context info: \n" << glview->getInfo() -	  << "\n"; +#define STRINGIFY(x) #x +#define TOSTRING(x) STRINGIFY(x) +	    << "\nOpenSCAD Version: " << TOSTRING(OPENSCAD_VERSION) +            << "\nCompiled by: " << compiler_info +	    << "\nBoost version: " << BOOST_LIB_VERSION +	    << "\nEigen version: " << EIGEN_WORLD_VERSION << "." +	    << EIGEN_MAJOR_VERSION << "." << EIGEN_MINOR_VERSION +	    // << "\nCGAL version: " << CGAL_VERSION ??? +	    // << "\nOpenCSG" << ??? +	    << "\n" << glview->getInfo() +	    << "\n"; +  	return out.str();  } diff --git a/tests/ctest_pretty_print.py b/tests/ctest_pretty_print.py deleted file mode 100755 index 430f106..0000000 --- a/tests/ctest_pretty_print.py +++ /dev/null @@ -1,254 +0,0 @@ -#!/usr/bin/python -import string,platform,sys,re,os - -wiki_basepath = 'OpenSCAD' -logfilename = 'LastTest.log' -builddir = os.getcwd() -logpath = os.path.join(builddir,'Testing','Temporary',logfilename) -NO_END = False -if logfilename.endswith('.tmp'): NO_END = True - -def read_sysinfo(): -	try: -		f=open('sysinfo.txt') -	except: -		return '' -	data=f.read() -	machine_str, osplain_str, renderer_str = '','','' -	machine = re.search('Machine:(.*?)\n',data) -	osinfo = re.search('OS info:(.*?)\n',data) -	renderer = re.search('GL Renderer:(.*?)\n',data) -	if machine: machine_str = machine.group(1).strip().replace(' ','-').replace('/','-') -	if osinfo:  -		osplain_str = osinfo.group(1).strip().split(' ')[0].strip().replace('/','-') -		if 'windows' in osinfo.group(1).lower(): osplain_str = 'win' -	if renderer:  -		tmp = renderer.group(1).strip().split(' ') -		tmp = string.join(tmp[0:3],'-') -		if '/' in tmp: tmp = tmp.split('/')[0] -		renderer_str = tmp -	platform = osplain_str + '_' + machine_str + '_' + renderer_str -	platform = platform.lower() -	return data, platform - -def readlog(): -	try: -		print 'reading',logpath -		f = open(logpath) -	except: -		print 'couldnt open ',logpath -		return None - -	data = f.read() -	return data - -class Test: -	def __init__(self,fullname,time,passed,output,type,outputfile,expectedfile): -		self.fullname,self.time,self.passed,self.output = \ -			fullname, time, passed, output -		self.type = type -		self.outputfile = outputfile -		self.expectedfile = expectedfile - -	def __str__(self): -		x = 'fullname: ' + self.fullname -		x+= '\noutputfile: ' + self.outputfile -		x+= '\nexpectedfile: ' + self.expectedfile -		x+= '\ntesttime: ' + self.time -		x+= '\ntesttype: ' + self.type -		x+= '\npassfail: ' + self.passfail -		x+= '\noutput: \n' + self.output -		x+= '\n' -		return x - -def gettest_strings(data): -	chunks = data.split('----------------------------------------------------------') -	print 'read',len(chunks), 'chunks' -	if NO_END: -		enddate = 'n/a (cancelled)' -		chunks.pop() -	else: -		enddate = chunks.pop().replace('End testing: ','').strip() -	chunks.reverse() -	startdate = chunks.pop().replace('Start testing: ','').strip() -	chunks.reverse() -	tests=[] -	chunksize = 3 -	for i in range(0,len(chunks),chunksize): -		testchunks = chunks[i:i+chunksize] -		test = string.join(testchunks,'-----') -		tests += [test] -		#print '----------<<<<<<<<<<<<<<<<' -		#print test -		#print '----------<<<<<<<<<<<<<<<<' -		test = '' -	sysinfo, platform = read_sysinfo() -	return startdate, tests, enddate, sysinfo, platform - -def parsetest(teststring): -	s = teststring -	def regex(pat,str): -		x=re.search(pat,str,re.DOTALL|re.MULTILINE) -		if x:  -			if len(x.groups())>0:  -				return x.group(1).strip() -		return '' -	testfullname = regex("Test:(.*?)\n",s) -	testtime = regex("Test time =(.*?)\n",s).replace(' sec','') -	passfail = regex("Test time.*?Test (Passed)",s) -	command = regex("Command:(.*?)\n",s) -	tmp = command.split(' "') -	testtype = '' -	try: -		testtype = tmp[3].strip('"') -	except: -		print 'failed to parse log', teststring -	goodimg = regex("expected image:(.*?)\n",s) -	actualimg = regex("actual image:(.*?)\n",s) -	if passfail=='Passed': passed = True -	else: passed = False -	output = regex("Output:(.*?)<end of output>",s).replace('-----','') -	test = Test(testfullname, testtime, passed, output, testtype, actualimg, goodimg ) -	return test - -def parse(data): -	startdate, test_strs, enddate, sysinfo, platform = gettest_strings(data) -	print 'found', len(test_strs),'test results' -	tests = [] -	for i in range(len(test_strs)): -		test = parsetest(test_strs[i]) -		tests += [test] -	return startdate, tests, enddate, sysinfo, platform - -def towiki(startdate, tests, enddate, sysinfo, platform): -	def convert_path(fulltestname,platform,path): -		# convert system path name (image file) to wiki path name -		testprogram = fulltestname[0:fulltestname.rfind('_')] -		testprogram = testprogram.replace('test','') -		filename = os.path.basename(path) -		filename = filename.replace('-tests-actual.png','.png') -		filename = filename.replace('-tests-expected.png','.png') -		try: -			platform = platform[0].upper() + platform[1:] -		except: -			platform = 'error' -		newpath = testprogram + '_' + filename -		# must use _ not / b/c of wikinet.org weird name mangling -		newpath = wiki_basepath + '_' + platform + '_' + newpath -		return newpath -		 -	x=''' -<h3>OpenSCAD test run</h3> - -platform: PLATFORM - -detailed system info:  -<pre> -SYSINFO -</pre> - -start time: STARTDATE  -end time  : ENDDATE - -Failed tests - -{|TABLESTYLE -! Testname !! expected output !! actual output -|- -| FTESTNAME || [[File:EXPECTEDIMG|thumb|250px]] || [[File:ACTUALIMG|thumb|250px]] -|} - -Passed tests - -{|TABLESTYLE  -! Testname  -|- -| PTESTNAME -|} - -''' - -	repeat1=''' -|- -| FTESTNAME || [[File:EXPECTEDIMG|thumb|250px]] || [[File:ACTUALIMG|thumb|250px]] -''' - -	repeat2=''' -|- -| PTESTNAME -''' - -	x = x.replace('TABLESTYLE','border=1 cellspacing=0 cellpadding=1 align="center"') -	x = x.replace('STARTDATE',startdate) -	x = x.replace('ENDDATE',enddate) -	x = x.replace('SYSINFO',sysinfo) -	x = x.replace('PLATFORM',platform) - -	for t in tests: -		print t.type, t.fullname, t.expectedfile, t.outputfile -		if t.passed: -			tmp = str(repeat2) -			tmp = tmp.replace('PTESTNAME',t.fullname) -			x = x.replace(repeat2,tmp + repeat2) -		elif not t.passed and t.type=='png': -			tmp = str(repeat1) -			tmp = tmp.replace('FTESTNAME',t.fullname) - -			wiki_imgpath1 = convert_path(t.fullname,'expected',t.expectedfile) -			if t.type!='png': wiki_imgpath1 = '' -			if t.expectedfile=='': wiki_imgpath2 = '' -			tmp = tmp.replace('EXPECTEDIMG',wiki_imgpath1) - -			wiki_imgpath2 = convert_path(t.fullname,platform,t.outputfile) -			if t.type!='png': wiki_imgpath2 = '' -			if t.outputfile=='': wiki_imgpath2 = '' -			tmp = tmp.replace('ACTUALIMG',wiki_imgpath2) - -			x = x.replace(repeat1,tmp + repeat1) - -	x = x.replace(repeat1,'') -	x = x.replace(repeat2,'') -	return x - -def wikitohtml(data): -	# not pretty  -	data = data.replace('\n\n','\n<p>\n') -	data = re.sub('\{\|.*?\n','<table border=1>\n',data) -	data = re.sub('\n\! ','\n<tr>\n<td>',data) -	data = data.replace(' !! ','<td>') -	data = data.replace('|-','<tr>') -	data = re.sub('\n\| ','\n<td>',data) -	data = data.replace(' || ','<td>') -	data = data.replace('|}','\n</table>') -	data = re.sub('[[File:(.*?)|.*?]]','<img src="(\1)">',data) -	return data - -def testsort(tests): -	passed = [] -	failed = [] -	for t in tests: -		if t.passed: passed+=[t] -		else: failed +=[t] -	return failed+passed - -def save(data,filename): -	try: -		f=open(filename,'w') -	except: -		print 'couldnt open ',filename, 'for writing' -		return None -	print 'writing',len(data),'bytes to',filename -	f.write(data) -	f.close() - -def main(): -	data = readlog() -	startdate, tests, enddate, sysinfo, platform = parse(data) -	tests = testsort(tests) -	wikidata = towiki(startdate, tests, enddate, sysinfo, platform) -	htmldata = wikitohtml(wikidata)  -	save(wikidata, platform+'.wiki') -	save(htmldata, platform+'.html') - -main() - diff --git a/tests/test_cmdline_tool.py b/tests/test_cmdline_tool.py index 485a821..3e9f45a 100755 --- a/tests/test_cmdline_tool.py +++ b/tests/test_cmdline_tool.py @@ -64,17 +64,20 @@ def compare_text(expected, actual):      return get_normalized_text(expected) == get_normalized_text(actual)  def compare_default(resultfilename): +    print >> sys.stderr, 'diff text compare: ' +    print >> sys.stderr, ' expected textfile: ', expectedfilename +    print >> sys.stderr, ' actual textfile: ', resultfilename      if not compare_text(expectedfilename, resultfilename):           execute_and_redirect("diff", [expectedfilename, resultfilename], sys.stderr)          return False      return True  def compare_png(resultfilename): +    print >> sys.stderr, 'Yee image compare:' +    print >> sys.stderr, ' expected image: ', expectedfilename      if not resultfilename: -        print >> sys.stderr, "Error: OpenSCAD did not generate an image" +        print >> sys.stderr, "Error: OpenSCAD did not generate an image to test"          return False -    print >> sys.stderr, 'Yee image compare: ' -    print >> sys.stderr, ' expected image: ', expectedfilename      print >> sys.stderr, ' actual image: ', resultfilename      if execute_and_redirect("./yee_compare", [expectedfilename, resultfilename, "-downsample", "2", "-threshold", "300"], sys.stderr) != 0:          return False diff --git a/tests/test_pretty_print.py b/tests/test_pretty_print.py new file mode 100755 index 0000000..6bc3f54 --- /dev/null +++ b/tests/test_pretty_print.py @@ -0,0 +1,266 @@ +#!/usr/bin/python +# +# this program reads the ctest logfiles from builddir/Testing/Temporary +# and generates two 'pretty printed' outputs in that directory: +# +# 1. mediawiki format, for uploading to a wiki. +#    automated uploading is available by following these steps: +#  +#  download mwclient +#  python ctest_pretty_print.py --upload  +# +# 2. html format, for easy local viewing +# +# sysinfo.txt: +#   sysinfo.txt should have been created by ctest by the main test run.  +#   it is the output of opencsgtest --info  + + +# todo +# 1. add sysinfo about ... git branch +# 2. consolidate image flip +# 3. uploading, can it be done in one file +# 4. consolidate pretty print + +import string,sys,re,os,hashlib,subprocess + +def tryread(filename): +	data = None +	try: +		print 'reading', filename +		f = open(filename) +		data = f.read() +		f.close() +	except: +		print 'couldn\'t open ',filename +	return data + +def trysave(data,filename): +	try: +		f=open(filename,'w') +		print 'writing',len(data),'bytes to',filename +		f.write(data) +		f.close() +	except: +		print 'problem writing to',filename +		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.  +	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' +	return out + +def read_sysinfo(filename): +	data = tryread(filename) +	if not data: return 'sysinfo: unknown' + +	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 + +	hasher = hashlib.md5() +	hasher.update(data) +	hexhash = hasher.hexdigest()[-4:].upper() +	# make all letters for aesthetic reasons +	hash = '' +	for c in hexhash: hash += chr(ord(c)+97-48)  + +	sysid = osplain + '_' + machine + '_' + renderer + '_' + hash +	sysid = sysid.lower() +	 +	data += read_gitinfo() + +	return data, sysid + +class Test: +	def __init__(self,fullname,time,passed,output,type,actualfile,expectedfile,scadfile): +		self.fullname,self.time,self.passed,self.output = \ +			fullname, time, passed, output +		self.type, self.actualfile, self.expectedfile, self.scadfile = \ +			type, actualfile, expectedfile, scadfile + +	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)) +		x+= '\n' +		return x + +def parsetest(teststring): +	patterns = ["Test:(.*?)\n", # fullname +		"Test time =(.*?) sec\n", +		"Test time.*?Test (Passed)", +		"Output:(.*?)<end of output>", +		'Command:.*?-s" "(.*?)"', # type +		"actual .*?:(.*?)\n", +		"expected .*?:(.*?)\n", +		'Command:.*?(testdata.*?)"' # scadfile  +		] +	hits = map( lambda pattern: ezsearch(pattern,teststring), patterns ) +	test = Test(hits[0],hits[1],hits[2]=='Passed',hits[3],hits[4],hits[5],hits[6],hits[7]) +	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 ) +	print 'found', len(tests),'test results' +	return startdate, tests, enddate + +def wikify_filename(testname,filename,sysid): +	# translate from local system to wiki style filename. +	result = wiki_rootpath+'_'+testname+'_' +	expected = ezsearch('(expected....$)',filename) +	if expected!='': result += expected +	actual = ezsearch(os.sep+'.*?-output.*?(actual.*)',filename) +	if actual!='':  +		result += sysid+'_'+actual +	return result.replace('/','_') + + +def towiki(wiki_rootpath, startdate, tests, enddate, sysinfo, sysid, testlog): +	wiki_template = ''' +<h3>OpenSCAD test run</h3> + +sysid: SYSID + +detailed system info:  +<pre> +SYSINFO +</pre> + +start time: STARTDATE  +end time  : ENDDATE + +Failed image tests + +{|border=1 cellspacing=0 cellpadding=1 align="center" +! Testname !! expected output !! actual output +<REPEAT1> +|- +| FTESTNAME || [[File:EXPECTEDFILE|thumb|250px]] || ACTUALFILE_WIKI +</REPEAT1> +|} + +Failed text tests (see test log, below, for diff output) + +{|border=1 cellspacing=0 cellpadding=1 align="center" +<REPEAT2> +|- +| FTESTNAME +</REPEAT2> +|} + +Passed tests + +{|border=1 cellspacing=0 cellpadding=1 align="center" +! Testname  +<REPEAT3> +|- +| PTESTNAME +</REPEAT3> +|} + +LastTest.log + +<pre> +LASTTESTLOG +</pre> + +''' +	manifest = {} +	s = wiki_template +	repeat1 = ezsearch('(<REPEAT1>.*?</REPEAT1>)',s) +	repeat2 = ezsearch('(<REPEAT2>.*?</REPEAT2>)',s) +	repeat3 = ezsearch('(<REPEAT3>.*?</REPEAT3>)',s) +	dic = { 'STARTDATE': startdate, 'ENDDATE': enddate, +		'SYSINFO': sysinfo, 'SYSID':sysid, 'LASTTESTLOG':testlog } +	for key in dic.keys(): +		s = re.sub(key,dic[key],s) +	for t in tests: +		print t.passed, t.type, t.fullname, t.expectedfile, t.actualfile +		manifest[t.actualfile] = wikify_filename(t.fullname,t.actualfile,sysid) +		manifest[t.expectedfile] = wikify_filename(t.fullname,t.expectedfile,sysid) +		if t.passed: +			newchunk = re.sub('PTESTNAME',t.fullname,repeat3) +			s = s.replace(repeat3, newchunk+repeat3) +		elif not t.passed and t.type=='txt': +			newchunk = re.sub('FTEST_OUTPUTFILE',t.fullname,repeat2) +			newchunk = re.sub('FTESTNAME',t.fullname,repeat2) +			s = s.replace(repeat2, newchunk+repeat2) +		elif not t.passed and t.type=='png': +			if t.actualfile:  +				actualfile_wiki = '[[File:'+manifest[t.actualfile]+'|thumb|250px]]' +			else: +				actualfile_wiki = 'No file generated. See test output for more info' +			newchunk = re.sub('FTESTNAME',t.fullname,repeat1) +			newchunk = newchunk.replace('ACTUALFILE_WIKI',actualfile_wiki) +			newchunk = newchunk.replace('EXPECTEDFILE',manifest[t.expectedfile]) +			s = s.replace(repeat1, newchunk+repeat1) +	s = s.replace(repeat1,'') +	s = s.replace(repeat2,'') +	s = s.replace(repeat3,'') +	s = re.sub('<REPEAT.*?>\n','',s) +	s = re.sub('</REPEAT.*?>','',s) +	return manifest, s + +def wikitohtml(data): +	# not pretty  +	data = data.replace('\n\n','\n<p>\n') +	data = re.sub('\{\|.*?\n','<table border=1>\n',data) +	data = re.sub('\n\! ','\n<tr>\n<td>',data) +	data = data.replace(' !! ','<td>') +	data = data.replace('|-','<tr>') +	data = re.sub('\n\| ','\n<td>',data) +	data = data.replace(' || ','<td>') +	data = data.replace('|}','\n</table>') +	data = re.sub('[[File:(.*?)|.*?]]','<img src="(\1)">',data) +	return data + +wiki_rootpath = 'OpenSCAD' +builddir = os.getcwd() +logpath = os.path.join(builddir,'Testing','Temporary') +logfilename = os.path.join(logpath,'LastTest.log') + +def main(): +	testlog = tryread(logfilename) +	startdate, tests, enddate = parselog(testlog) +	tests = sorted(tests, key = lambda t:t.passed) +	sysinfo, sysid = read_sysinfo('sysinfo.txt') +	manifest, wikidata = towiki(wiki_rootpath, startdate, tests, enddate, sysinfo, sysid, testlog) +	htmldata = wikitohtml(wikidata)  +	#save(wikidata, os.path.join(logpath,sysid+'.wiki')) +	#save(htmldata, os.path.join(logpath,sysid+'.html')) +	trysave(wikidata, sysid+'.wiki') +	trysave(htmldata, sysid+'.html') + +main() + | 
