From b4ddcfbe481a761a79a29a6ae0e64b537d2ad3f1 Mon Sep 17 00:00:00 2001 From: Sam Robertson Date: Tue, 8 Nov 2011 17:11:44 -0800 Subject: [PATCH] Cleaning up stuff, reorganizing parser into a class to make it more manageable --- tools/testClient/translator.py | 210 +++++++++++++++++++-------------- 1 file changed, 121 insertions(+), 89 deletions(-) diff --git a/tools/testClient/translator.py b/tools/testClient/translator.py index fe5beee0c5e..8547342eb9a 100644 --- a/tools/testClient/translator.py +++ b/tools/testClient/translator.py @@ -5,61 +5,36 @@ import random import os import sys +# Constants INDENT = " " INDENT2 = INDENT + INDENT -INDENT3 = INDENT2 + INDENT -outFile = None +class xml_to_python(object): + def __init__(self, debug): + ''' + constructor + ''' + self.debug = debug + self._output = False + self.out_buffer = [] -def getText(nodelist): - if nodelist[0].childNodes is not None: - return nodelist[0].childNodes[0].nodeValue - else: - return "" + self.cmd_name = None + self.cmd_name_var = None + self.cmd_name_resp = None -def get_doc(name): - return xml.dom.minidom.parse(name) + self.glos = [] -def parse_xmlFile(dom, outf, glos): - testName = dom.documentElement.nodeName + def _write(self, output_string): + ''' + internal print function + ''' + self.out_buffer.append("%s\n" % output_string) - if outf is not None: - outFile.write("# Generated by translator.py\n# from %s\n" % options.xmlfile) - outFile.write("# on %s\n\n" % str(now)) - outFile.write("from cloudstackTestCase import *\n") - outFile.write("import cloudstackException\n") - outFile.write("import cloudstackTestClient\n") - outFile.write("import time\n\n") - outFile.write("# These are global variables used in the script below\n") - for key in glos: - outFile.write("%s = None\n" % key) - outFile.write("# End of globals\n\n") - outFile.write("if __name__ == \"__main__\":\n\n") - outFile.write("%s# Possible initialization parameters:\n" % INDENT) - outFile.write("%s# cloudstackTestClient(mgtSvr=None, port=8096, apiKey = None, securityKey = None, asyncTimeout=3600, defaultWorkerThreads=10, logging=None)\n" % INDENT) - outFile.write("%stestClient = cloudstackTestClient.cloudstackTestClient(\"localhost\")\n\n" % INDENT) - outFile.write("%sapiclient = testClient.getApiClient()\n" % INDENT) - else: - glos = [] - - ## eventually, this should all be put in a class so we can isolate context better... - # outFile.write("class %s(cloudstackTestCase):\n\n" % testName) - # outFile.write("%sdef test_%s(self):\n" % (INDENT, testName)) - # outFile.write("%sapiClient = self.testClient.getApiClient()\n" % INDENT2) - - for cmd in dom.getElementsByTagName("command"): - cmd_name = cmd.getElementsByTagName("name")[0].childNodes[0].nodeValue.strip() - cmd_name_var = "_%s" % cmd_name - cmd_name_resp = "resp_%s" % cmd_name - - testCaseName = cmd.getElementsByTagName("testcase")[0].childNodes[0].nodeValue.strip() - if outf is not None: - outFile.write("\n%s# %s\n" % (INDENT, testCaseName)) - - if outf is not None: - outFile.write("%s%s = %s.%sCmd()\n" % (INDENT, cmd_name_var, cmd_name, cmd_name)) - - for param in cmd.getElementsByTagName("parameters"): + def parse_parameters(self, dom): + ''' + process parameters of command + ''' + for param in dom.getElementsByTagName("parameters"): for item in param.getElementsByTagName("item"): itemName = item.getElementsByTagName("name")[0].childNodes[0].nodeValue.strip() itemParam = None @@ -77,33 +52,28 @@ def parse_xmlFile(dom, outf, glos): # handle getparam and setparam and random attributes here... if item.getAttribute("getparam") == "true" and itemParam is not None: - if outf is not None: - outFile.write("%s%s.%s = %s\n" % (INDENT, cmd_name_var, itemName, itemParam)) - else: - glos.append(itemParam) + self._write("%s%s.%s = %s" % (INDENT, self.cmd_name_var, itemName, itemParam)) + self.glos.append(itemParam) elif item.getAttribute("random") == "true" or item.getAttribute("randomnumber") == "true": # we should do this in the resulting python file. randValue = int(random.random() * 10000000) - if outf is not None: - outFile.write("%s%s.%s = '%s-randomName'\n" % (INDENT, cmd_name_var, itemName, str(randValue))) + self._write("%s%s.%s = '%s-randomName'" % (INDENT, self.cmd_name_var, itemName, str(randValue))) if item.getAttribute("setparam") == "true" and itemParam is not None: - if outf is not None: - outFile.write("%s%s = '%s-randomName'\n" % (INDENT, itemName, str(randValue))) - else: - glos.append(itemParam) + self._write("%s%s = '%s-randomName'" % (INDENT, itemName, str(randValue))) + self.glos.append(itemParam) else: try: val = int(itemValue) except Exception: val = "'%s'" % itemValue - if outf is not None: - outFile.write("%s%s.%s = %s\n" % (INDENT, cmd_name_var, itemName, val)) + self._write("%s%s.%s = %s" % (INDENT, self.cmd_name_var, itemName, val)) - # now we execute command - if outf is not None: - outFile.write("%s%s = apiClient.%s(%s)\n" % (INDENT, cmd_name_resp, cmd_name, cmd_name_var)) - for return_val in cmd.getElementsByTagName("returnvalue"): + def parse_returnvalue(self, dom): + ''' + process returnvalue section of command + ''' + for return_val in dom.getElementsByTagName("returnvalue"): for item in return_val.getElementsByTagName("item"): #if item.getAttribute("list") == "true": @@ -111,47 +81,109 @@ def parse_xmlFile(dom, outf, glos): itemParam = item.getElementsByTagName("param")[0].childNodes[0].nodeValue.strip() if item.getAttribute("setparam") == "true": - if outf is not None: - outFile.write("%s%s = %s.%s\n" % (INDENT, itemParam, cmd_name_resp, itemName)) + self._write("%s%s = %s.%s" % (INDENT, itemParam, self.cmd_name_resp, itemName)) else: - if outf is not None: - outFile.write("%sif %s != %s.%s:\n" % (INDENT, itemParam, cmd_name_resp, itemName)) - outFile.write("%sprint %s.%s + \" does not match \" + %s\n" % (INDENT2, cmd_name_resp, itemName, itemValue)) - return set(glos) + self._write("%sif %s != %s.%s:" % (INDENT, itemParam, self.cmd_name_resp, itemName)) + self._write("%sprint %s.%s + \" does not match \" + %s" % ( + INDENT2, self.cmd_name_resp, itemName, itemParam)) + + + def parse_command(self, dom): + ''' + process command elements and their children + ''' + for cmd in dom.getElementsByTagName("command"): + self.cmd_name = cmd.getElementsByTagName("name")[0].childNodes[0].nodeValue.strip() + self.cmd_name_var = "_%s" % self.cmd_name + self.cmd_name_resp = "resp_%s" % self.cmd_name + + testCaseName = cmd.getElementsByTagName("testcase")[0].childNodes[0].nodeValue.strip() + self._write("\n%s# %s" % (INDENT, testCaseName)) + + self._write("%s%s = %s.%sCmd()" % (INDENT, self.cmd_name_var, self.cmd_name, self.cmd_name)) + + self.parse_parameters(cmd) + # now we execute command + self._write("%s%s = apiClient.%s(%s)" % (INDENT, self.cmd_name_resp, self.cmd_name, self.cmd_name_var)) + + self.parse_returnvalue(cmd) + + def generate_python_header(self, outfile): + ''' + generates python file header + + the basic stuff to bootstrap the script + ''' + now = datetime.datetime.now() + + outfile.write("# Generated by translator.py\n") + outfile.write("# from %s\n" % options.xmlfile) + outfile.write("# on %s\n\n" % str(now)) + outfile.write("from cloudstackTestCase import *\n") + outfile.write("import cloudstackTestClient\n") + outfile.write("import time\n\n") + outfile.write("# These are global variables used in the script below\n") + for key in set(self.glos): + outfile.write("%s = None\n" % key) + outfile.write("# End of globals\n\n") + outfile.write("if __name__ == \"__main__\":\n") + outfile.write("%s# Possible initialization parameters:\n" % INDENT) + outfile.write( + "%s# cloudstackTestClient(mgtSvr=None, port=8096, apiKey = None, securityKey = None, asyncTimeout=3600, defaultWorkerThreads=10, logging=None)\n" % INDENT) + outfile.write("%stestClient = cloudstackTestClient.cloudstackTestClient(\"localhost\")\n" % INDENT) + outfile.write("%sapiClient = testClient.getApiClient()\n" % INDENT) + + def output_python(self, outfile): + self.generate_python_header(outfile) + for line in self.out_buffer: + outfile.write(line) + outfile.close() + + + def parse_xmlFile(self, xmlFile, outfile): + ''' + parse_xmlFile, this is the main function of the translator + ''' + dom = xml.dom.minidom.parse(xmlFile) + + self.parse_command(dom) + self.output_python(outfile) if __name__ == "__main__": - parser = OptionParser() - - parser.add_option("-i", "--inputfile", dest="xmlfile", help="The path to the XML file containing tests.", default="../../test/metadata/func/portforwarding.xml") - parser.add_option("-o", "--output_file_path", dest="outfile", help="The path to the resulting python script file.") - parser.add_option("-d", action="store_true", dest="debug", help="Don't create output file, but send output to stdout", default=False) + opts = OptionParser() - (options, args) = parser.parse_args() + opts.add_option("-i", "--inputfile", dest="xmlfile", help="The XML file and it's path containing tests.", + default="../../test/metadata/func/portforwarding.xml") + opts.add_option("-o", "--output_file_path", dest="outpath", help="The path where we create the python file.") + opts.add_option("-d", action="store_true", dest="debug", + help="Don't create output file, but send output to stderr", default=False) + + (options, args) = opts.parse_args() if options.xmlfile is None or not os.path.exists(options.xmlfile): print "The input file MUST be specified and exist: %s" % options.xmlfile exit(1) - now = datetime.datetime.now() - - if options.debug == False: - if options.outfile is None: - options.outfile = "%s.py" % (os.path.basename(options.xmlfile)) + if options.outpath is None: + options.outpath = "%s.py" % (os.path.basename(options.xmlfile)) else: - options.outfile = "%s%s.py" % (options.outfile, os.path.basename(options.xmlfile)) + if options.outpath.endswith('/'): + options.outpath = "%s%s.py" % (options.outpath, os.path.basename(options.xmlfile)) + else: + options.outpath = "%s/%s.py" % (options.outpath, os.path.basename(options.xmlfile)) - if os.path.exists(options.outfile): - print "The output file already exists: %s" % options.outfile + if os.path.exists(options.outpath): + print "The output file already exists: %s" % options.outpath exit(1) - outFile = open(options.outfile, "w") + outFile = open(options.outpath, "w") else: outFile = sys.stderr - print "# Processing: %s Output: %s" % (options.xmlfile, outFile.name) - dom = get_doc(options.xmlfile) + print("<>" % (options.xmlfile, outFile.name)) - glos = parse_xmlFile(dom, None, None) - parse_xmlFile(dom, outFile, glos) \ No newline at end of file + processor = xml_to_python(options.debug) + + processor.parse_xmlFile(options.xmlfile, outFile) \ No newline at end of file