#!/usr/bin/env python # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # # # Convert rules to tests # import sys, re, os.path from getopt import getopt, GetoptError from string import capitalize from xml import dom from xml.dom.minidom import parse def camelcase(s): """Convert 'string like this' to 'StringLikeThis'""" return "".join([capitalize(w) for w in re.split(re.compile("\W*"), s)]) def uncapitalize(s): return s[0].lower()+s[1:] def ancestors(node): "Return iterator of ancestors from top-level element to node" def generator(node): while node and node.parentNode: yield node node = node.parentNode return reversed(list(generator(node))) def tagAndName(element): nameAttr = element.getAttribute("name"); if (nameAttr) : return camelcase(nameAttr) + camelcase(element.tagName) else: return camelcase(element.tagName) def nodeText(n): """Recursively collect text from all text nodes under n""" if n.nodeType == dom.Node.TEXT_NODE: return n.data if n.childNodes: return reduce(lambda t, c: t + nodeText(c), n.childNodes, "") return "" def cleanup(docString, level=8): unindent = re.sub("\n[ \t]*", "\n", docString.strip()) emptyLines = re.sub("\n\n\n", "\n\n", unindent) indented = re.sub("\n", "\n"+level*" ", emptyLines) return level*" " + indented def printTest(test, docstring): print "class %s(TestBase):" % test print ' """' print docstring print ' """' print print def printTests(doc, module): """Returns dictionary { classname : [ (methodname, docstring)* ] * }""" tests = {} rules = doc.getElementsByTagName("rule") for r in rules: path = list(ancestors(r)) if module == path[1].getAttribute("name").lower(): test = "".join(map(tagAndName, path[2:])) + "Tests" docstring = cleanup(nodeText(r), 4) printTest(test, docstring) def usage(message=None): if message: print >>sys.stderr, message print >>sys.stderr, """ rule2test [options] Print test classes for each rule for the amqpclass in amqp.xml. Options: -?/-h/--help : this message -s/--spec : file containing amqp XML spec """ return 1 def main(argv): try: opts, args = getopt(argv[1:], "h?s:", ["help", "spec="]) except GetoptError, e: return usage(e) spec = "../specs/amqp.xml" # Default for opt, val in opts: if (opt in ("-h", "-?", "--help")): return usage() if (opt in ("-s", "--spec")): spec = val doc = parse(spec) if len(args) == 0: return usage() printTests(doc, args[0]) return 0 if (__name__ == "__main__"): sys.exit(main(sys.argv))