[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [21131] branches/soc-2009-jaguarandi/test: *changed from .xml files to .json files (xml.marshal.generic was kinda " ugly")

André Pinto andresusanopinto at gmail.com
Wed Jun 24 16:18:34 CEST 2009


Revision: 21131
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=21131
Author:   jaguarandi
Date:     2009-06-24 16:18:34 +0200 (Wed, 24 Jun 2009)

Log Message:
-----------
*changed from .xml files to .json files (xml.marshal.generic was kinda "ugly")
*renamed Test.py to test.py
*config.py no longer has side effects
*used optparse for argument parsing

all those were Martin Poirier (theeth) suggestions
Thanks for the code review :)

Modified Paths:
--------------
    branches/soc-2009-jaguarandi/test/blendertest.py
    branches/soc-2009-jaguarandi/test/config.py
    branches/soc-2009-jaguarandi/test/html.py
    branches/soc-2009-jaguarandi/test/persistent.py

Added Paths:
-----------
    branches/soc-2009-jaguarandi/test/case/sample/simple.json
    branches/soc-2009-jaguarandi/test/default_machine.json
    branches/soc-2009-jaguarandi/test/test.py

Removed Paths:
-------------
    branches/soc-2009-jaguarandi/test/Test.py
    branches/soc-2009-jaguarandi/test/case/sample/simple.xml
    branches/soc-2009-jaguarandi/test/default_machine.xml

Deleted: branches/soc-2009-jaguarandi/test/Test.py
===================================================================
--- branches/soc-2009-jaguarandi/test/Test.py	2009-06-24 14:16:56 UTC (rev 21130)
+++ branches/soc-2009-jaguarandi/test/Test.py	2009-06-24 14:18:34 UTC (rev 21131)
@@ -1,123 +0,0 @@
-import os
-import string
-import config
-import time
-import subprocess
-import persistent
-
-class Case(dict):
-	def __init__(self, arg = {}):
-		dict.__init__(self, arg)
-		
-	def run(self, res):
-		print self["name"]+":","test not implemented",self["type"]
-		return TestRun.RESULT_NONE
-		
-	def run_cmd(self, cmd, test):
-		dt = time.time()
-		proc = subprocess.Popen(cmd,stdout=subprocess.PIPE, stderr=subprocess.PIPE)
-		out, err = proc.communicate()
-		dt = time.time()-dt
-
-		test["cmdline"] = cmd
-		test["time"] = dt
-		test["stderr"] = err
-		test["stdout"] = out
-		test["exit_status"] = proc.returncode
-		
-		return proc.returncode
-
-
-class Render(Case):
-	__name__ = "render"
-	
-	def __init__(self, arg = {}):
-		Case.__init__(self, arg)
-		
-	def run(self, test):
-		#prepare cmdline
-		filename = os.path.join(test.path, self["filename"])
-		cmd = [ test["build"]["path"], "-b", self["scene"], "-o", filename, "-F", "PNG", "-x", "0", "-f", "%d"%self["frame"]]
-
-		if self.run_cmd(cmd, test) == 0:
-			test["result"] = TestRun.RESULT_OK
-		else:
-			test["result"] = TestRun.RESULT_FAIL
-
-
-################################
-class TestRun(dict):
-	RESULT_NONE = "none"
-	RESULT_OK	= "ok"
-	RESULT_FAIL	= "fail"
-
-	def __init__(self, machine, build, case):
-		self.path = os.path.join( config.run_path, machine["hash"], build["hash"], case["hash"] )
-		self.result_path = os.path.join( self.path, "result.xml" )
-		
-		if os.path.isfile(self.result_path):
-			dict.__init__(self, persistent.load(file(self.result_path, "r")))
-			if "result" not in self:
-				self["result"] = TestRun.RESULT_NONE
-		else:
-			self["machine"]	= machine
-			self["build"]	= build
-			self["case"]	= case
-			self["result"]	= TestRun.RESULT_NONE
-		
-	# Save results
-	def save_results(self):
-		dirname = os.path.dirname( self.result_path )
-		if not os.path.isdir(dirname):
-			os.makedirs(dirname)
-		persistent.dump( dict(self), file(self.result_path, "w") )
-
-
-	def getResult(self):
-		return self["result"]
-	
-	# get a path to an image generated by the test run
-	def getImageResult(self):
-		img  = os.path.join(self.path,'1.png')
-		if os.path.isfile( img ):
-			return img
-		return None
-
-
-	#Short run description:
-	# MM:SS.mmm <name> <result description>
-	def getResultDescription(self):
-		if self["result"] == TestRun.RESULT_NONE:
-			return self["case"]["name"] + " (not available)"
-		res = ""
-
-		if "time" in self:
-			time = self["time"]*1000
-			res += "%02d:%02d.%03d "%(time/60000, (time/1000)%60, time%1000)
-		res += self["case"]["name"]
-		
-		if "returncode" in self and self["returncode"] != 0:
-			res += " (non zero return)"
-		if "sdderr" in self and len(self["stderr"].splitlines()):
-			res += " (%d stderr lines)"%(len(self["stderr"].splitlines()))
-		return res
-
-	
-	# TODO should be atomic (if it crashs while saving result it can create a wrong xml file)
-	def run(self, force = False):
-		try:	
-			if self["result"] != TestRun.RESULT_NONE and force == False:
-				return
-		
-			if self["case"]["type"] == Render.__name__:
-				Render(self["case"]).run(self)
-
-			self.save_results()
-		except:
-			#TODO print exception
-			print "Failed to process test run:",self.result_path
-			os._exit(-1)
-	
-##########################################################################################
-def get(machine,build,case):
-	return TestRun(machine,build,case)

Modified: branches/soc-2009-jaguarandi/test/blendertest.py
===================================================================
--- branches/soc-2009-jaguarandi/test/blendertest.py	2009-06-24 14:16:56 UTC (rev 21130)
+++ branches/soc-2009-jaguarandi/test/blendertest.py	2009-06-24 14:18:34 UTC (rev 21131)
@@ -4,19 +4,24 @@
 	case/<path>.blend
 	build/<path>.bin
 	
-	run/<machine-hash>/<build_hash>/<case_hash>/result.xml
+	run/<machine-hash>/<build_hash>/<case_hash>/result.json
 	run/<machine-hash>/<build_hash>/<case_hash>/1.png
 """
 import sys
 import os
 import re
+from optparse import OptionParser
+
 import config
-
-import Test
+import test
 import persistent
 import html
 import util
 
+
+
+
+
 OK = "\033[92m"
 WARNING = "\033[93m"
 FAIL = "\033[91m"
@@ -29,7 +34,7 @@
 	return _valid_build.match( arg )
 	
 def load_build(path):
-	#TODO test the existence of a .xml file with information about this build
+	#TODO test the existence of a .json file with information about this build
 	conf = dict(config.default_build_config)
 
 	conf["path"] = path
@@ -52,10 +57,10 @@
 	conf["name"] = os.path.splitext(os.path.basename(path))[0]
 	conf["hash"] = util.get_hash(open(path, 'rb'))
 		
-	xml_conf = util.change_extension(path, ".xml")
-	if os.path.isfile(xml_conf):
-		conf["path"] = xml_conf
-		conf.update( persistent.load( open(xml_conf, "r" ) ) )
+	conf_path = util.change_extension(path, ".json")
+	if os.path.isfile(conf_path):
+		conf["path"] = conf_path
+		conf.update( persistent.load( open(conf_path, "r" ) ) )
 	else:
 		conf.update( config.default_case_config )
 	
@@ -72,96 +77,112 @@
 		return result_color[trun["result"]]
 	return WARNING
 
-def update_test_runs( builds, cases ):
+def do_update( builds, cases ):
 	tot = len(cases)
 	for build in builds:
 		i = 1
 		print INFO+"=== "+build["path"]+" ==="+ENDC
 		for case in cases:
-			res = Test.get( config.machine, build, case )
+			res = test.get( config.machine, build, case )
 			res.run()
 			print get_color(res)+"[%2d/%d] %s" % (i,tot,res.getResultDescription())+ENDC
 			i += 1
 				
 				
 #############################################
-def gen_html( builds, cases ):
+def do_html( builds, cases ):
 	return html.generate( [config.machine], builds, cases)
 	
 	
 #############################################
-def do_help():
-	print """Usage:
-blender_test.py [action] [<paths for test cases or builds>]
+def do_info(builds, cases):
+	print INFO," Machine   : ",config.machine,ENDC
+	print INFO," test-cases: ",len(cases),ENDC
+	print INFO," builds    : ",len(builds),ENDC
 
-actions:
-	--update	runs tests cases between the given builds and cases
-				test results are saved under:
-					<config.run_path>/<machine-hash>/<build-hash>/<case-hash>/
+def main():
+	builds = []
+	cases = []
 
-	--html		outputs html comparison table to standart output
-				test results are loaded from <config.run_path>
-				auxiliary html files are created under <config.html_path>
-	
-	if no action is given it will just print information on the cases
-	and builds found on the given paths
+	persistent.dump(config.machine,  open(config.machine_path, "w") )
 
-paths:
-	All given paths will be recursively searched for files matching:
-		*.blend to represent test scenes
-		*.bin to represent builds
-	
-	if no test case is given it will scan directory "case"
-	if no build is given it will scan directory "build"
-"""
+	def load_path(arg):
+		if os.path.isdir(arg):
+			for root, dirs, files in os.walk(arg):
+				 for file in files:
+				 	load_path(os.path.join(root, file))
+		else:
+			if is_valid_case(arg):
+				cases.append( load_case(arg) )		
+			elif is_valid_build(arg):
+				builds.append( load_build(arg) )
 
+	parser = OptionParser(usage="usage: %prog [options] <path> ...")
 
-builds = []
-cases = []
+	parser.add_option("--update",
+			action="store_true",
+			dest="update",
+			default=False,
+			help="runs tests cases between the given builds and cases, test results are saved under: <config.run_path>/<machine-hash>/<build-hash>/<case-hash>/"
+		)
 
-def load_path(arg):
-	if os.path.isdir(arg):
-		for root, dirs, files in os.walk(arg):
-			 for file in files:
-			 	load_path(os.path.join(root, file))
+	parser.add_option("--machine",
+			action="store",
+			dest="machine",
+			default=config.machine_path,
+			help="load machine configuration from the given argument (read the supplied default_machine.json for an example)"
+		)
+		
+	parser.add_option( "--html",
+			action="store_true",
+			dest="html",
+			default=False,
+			help="outputs html comparison table to standart output test results are loaded from <config.run_path>; auxiliary html files are created under <config.html_path>"
+		)
+		
+	(options, args) = parser.parse_args()
+	
+	if os.path.isfile(options.machine):
+		config.machine = persistent.load( open(options.machine, "r") )
+
+		if "hash" not in config.machine:
+			config.machine["hash"] = os.uname()[1]
+		if "hostname" not in config.machine:
+			config.machine["hostname"] = os.uname()[1]
 	else:
-		if is_valid_case(arg):
-			cases.append( load_case(arg) )		
-		elif is_valid_build(arg):
-			builds.append( load_build(arg) )
+		parser.error("No machine configuration found (use the --machine option) or configure "+config.machine_path)
 
+	
+	
+	for path in args:
+		load_path(path)
 
-do_update = False
-do_html = False
-do_info = True
+	if len(builds) == 0:
+		load_path( "build" )
+	
+	if len(cases) == 0:
+		load_path( "case" )
 
-if len(sys.argv) > 1:
+	if options.html == False:
+ 		do_info( builds, cases )
+		
+	if options.update:
+		if len(builds) == 0:
+			parser.error( "at least one build (blender;*.bin) must be supplied on paths" )
+		if len(cases) == 0:
+			parser.error( "at least one test case (*.blend) must be supplied on paths" )
 
-	for arg in sys.argv[1:]:
-		if arg == "--help":
-			do_help()
-			os._exit(-1)			
-		if arg == "--update":
-			do_update = True
-		if arg == "--html":
-			do_info = False
-			do_html = True
-		else:
-			load_path(arg)
-			
-if len(builds) == 0:
-	load_path( "build" )
+		do_update( builds, cases )
 
-if len(cases) == 0:
-	load_path( "case" )
+	if options.html:
+		if len(builds) == 0:
+			parser.error( "at least one build (blender;*.bin) must be supplied on paths" )
+		if len(cases) == 0:
+			parser.error( "at least one test case (*.blend) must be supplied on paths" )
+		
+		do_html( builds, cases )
+		
 
-if do_info:
-	print INFO," Machine   : ",config.machine,ENDC
-	print INFO," test-cases: ",len(cases),ENDC
-	print INFO," builds    : ",len(builds),ENDC
+if __name__ == "__main__":
+	main()
 
-if do_update:
-	update_test_runs( builds, cases )
-
-if do_html:
-	gen_html( builds, cases )		

Copied: branches/soc-2009-jaguarandi/test/case/sample/simple.json (from rev 21124, branches/soc-2009-jaguarandi/test/case/sample/simple.xml)
===================================================================

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list