def TestNamespaceFiles(filter): idldir = os.path.split(sys.argv[0])[0] idldir = os.path.join(idldir, 'test_namespace', '*.idl') filenames = glob.glob(idldir) testnames = [] for filename in filenames: if filter and filename not in filter: continue testnames.append(filename) # If we have no files to test, then skip this test if not testnames: InfoOut.Log('No files to test for namespace.') return 0 InfoOut.SetConsole(False) ast = ParseFiles(testnames) InfoOut.SetConsole(True) errs = ast.GetProperty('ERRORS') if errs: ErrOut.Log("Failed namespace test.") else: InfoOut.Log("Passed namespace test.") return errs
def DetermineInterfaces(self, ast, releases): """Get a list of interfaces along with whatever metadata we need. """ iface_releases = [] for filenode in ast.GetListOf('File'): # If this file has errors, skip it if filenode in self.skip_list: if GetOption('verbose'): InfoOut.Log('WrapperGen: Skipping %s due to errors\n' % filenode.GetName()) continue file_name = self.GetHeaderName(filenode.GetName()) ifaces = filenode.GetListOf('Interface') for iface in ifaces: releases_for_iface = iface.GetUniqueReleases(releases) for release in releases_for_iface: version = iface.GetVersion(release) struct_name = self.cgen.GetStructName(iface, release, include_version=True) needs_wrap = self.InterfaceVersionNeedsWrapping( iface, version) if not needs_wrap: if GetOption('verbose'): InfoOut.Log( 'Interface %s ver %s does not need wrapping' % (struct_name, version)) iface_releases.append( Interface(iface, release, version, struct_name, needs_wrap, file_name)) return iface_releases
def Generate(self, ast, options): self.errors = 0 rangestr = GetOption('range') releasestr = GetOption('release') print "Found releases: %s" % ast.releases # Generate list of files to ignore due to errors for filenode in ast.GetListOf('File'): # If this file has errors, skip it if filenode.GetProperty('ERRORS') > 0: self.skip_list.append(filenode) continue # Check for a range option which over-rides a release option if not releasestr and rangestr: range_list = rangestr.split(',') if len(range_list) != 2: self.Error('Failed to generate for %s, incorrect range: "%s"' % (self.name, rangestr)) else: vmin = range_list[0] vmax = range_list[1] # Generate 'start' and 'end' represent first and last found. if vmin == 'start': vmin = ast.releases[0] if vmax == 'end': vmax = ast.releases[-1] vmin = ast.releases.index(vmin) vmax = ast.releases.index(vmax) + 1 releases = ast.releases[vmin:vmax] InfoOut.Log('Generate range %s of %s.' % (rangestr, self.name)) ret = self.GenerateRange(ast, releases, options) if ret < 0: self.Error('Failed to generate range %s : %s.' %(vmin, vmax)) else: InfoOut.Log('%s wrote %d files.' % (self.name, ret)) # Otherwise this should be a single release generation else: if releasestr == 'start': releasestr = ast.releases[0] if releasestr == 'end': releasestr = ast.releases[-1] if releasestr: InfoOut.Log('Generate release %s of %s.' % (releasestr, self.name)) ret = self.GenerateRelease(ast, releasestr, options) if ret < 0: self.Error('Failed to generate release %s.' % releasestr) else: InfoOut.Log('%s wrote %d files.' % (self.name, ret)) else: self.Error('No range or release specified for %s.' % releasestr) return self.errors
def DumpReduction(cls, p): if p[0] is None: InfoOut.Log("OBJ: %s(%d) - None\n" % (cls, len(p))) InfoOut.Log(" [%s]\n" % [str(x) for x in p[1:]]) else: out = "" for index in range(len(p) - 1): out += " >%s< " % str(p[index + 1]) InfoOut.Log("OBJ: %s(%d) - %s : %s\n" % (cls, len(p), str(p[0]), out))
def token(self): tok = self.lexobj.token() if tok: self.last = tok if self.token_debug: InfoOut.Log("TOKEN %s(%s)" % (tok.type, tok.value)) return tok
def ChildTest(): errors = 0 child = IDLNode('child', 'no file', 1, 0) parent = IDLNode('parent', 'no file', 1, 0, [child]) if child.parent != parent: ErrOut.Log('Failed to connect parent.') errors += 1 if [child] != parent.GetChildren(): ErrOut.Log('Failed GetChildren.') errors += 1 if child != parent.GetOneOf('child'): ErrOut.Log('Failed GetOneOf(child)') errors += 1 if parent.GetOneOf('bogus'): ErrOut.Log('Failed GetOneOf(bogus)') errors += 1 if not parent.IsA('parent'): ErrOut.Log('Expecting parent type') errors += 1 parent = IDLNode('parent', 'no file', 1, 0, [child, child]) if [child, child] != parent.GetChildren(): ErrOut.Log('Failed GetChildren2.') errors += 1 if not errors: InfoOut.Log('Passed ChildTest') return errors
def IsRelease(self, release): if self.rmax and self.rmax <= release: return False if self.rmin and self.rmin > release: return False if GetOption('release_debug'): InfoOut.Log('%f is in %s' % (release, self)) return True
def DumpOption(option): if len(option.name) > 1: out = ' --%-15.15s\t%s' % (option.name, option.desc) else: out = ' -%-15.15s\t%s' % (option.name, option.desc) if option.default: out = '%s\n\t\t\t(Default: %s)\n' % (out, option.default) InfoOut.Log(out)
def Close(self): filename = os.path.realpath(self.filename) self.open = False outtext = ''.join(self.outlist) oldtext = '' if not self.always_write: if os.path.isfile(filename): oldtext = open(filename, 'rb').read() if self.IsEquivalent_(oldtext): if GetOption('verbose'): InfoOut.Log('Output %s unchanged.' % self.filename) return False if GetOption('diff'): for line in difflib.unified_diff(oldtext.split('\n'), outtext.split('\n'), 'OLD ' + self.filename, 'NEW ' + self.filename, n=1, lineterm=''): ErrOut.Log(line) try: # If the directory does not exit, try to create it, if we fail, we # still get the exception when the file is openned. basepath, leafname = os.path.split(filename) if basepath and not os.path.isdir(basepath) and self.create_dir: InfoOut.Log('Creating directory: %s\n' % basepath) os.makedirs(basepath) if not GetOption('test'): outfile = open(filename, 'wb') outfile.write(outtext) outfile.close() InfoOut.Log('Output %s written.' % self.filename) return True except IOError as e: ErrOut.Log("I/O error(%d): %s" % (e.errno, e.strerror)) except: ErrOut.Log("Unexpected error: %s" % sys.exc_info()[0]) raise return False
def BuildProduction(self, cls, p, index, childlist=None): if not childlist: childlist = [] filename = self.lexobj.filename lineno = p.lineno(index) pos = p.lexpos(index) out = IDLNode(cls, filename, lineno, pos, childlist) if self.build_debug: InfoOut.Log("Building %s" % out) return out
def AddNode(self, node): if GetOption('release_debug'): InfoOut.Log('\nAdding %s %s' % (node.Location(), node)) last = None # Check current releases in that namespace for cver in self.nodes: if GetOption('release_debug'): InfoOut.Log(' Checking %s' % cver) # We should only be missing a 'release' tag for the first item. if not node.rmin: node.Error('Missing release on overload of previous %s.' % cver.Location()) return False # If the node has no max, then set it to this one if not cver.rmax: cver.rmax = node.rmin if GetOption('release_debug'): InfoOut.Log(' Update %s' % cver) # if the max and min overlap, than's an error if cver.rmax > node.rmin: if node.rmax and cver.rmin >= node.rmax: node.Error('Declarations out of order.') else: node.Error('Overlap in releases: %s vs %s when adding %s' % (cver.rmax, node.rmin, node)) return False last = cver # Otherwise, the previous max and current min should match # unless this is the unlikely case of something being only # temporarily deprecated. if last and last.rmax != node.rmin: node.Warn('Gap in release numbers.') # If we made it here, this new node must be the 'newest' # and does not overlap with anything previously added, so # we can add it to the end of the list. if GetOption('release_debug'): InfoOut.Log('Done %s' % node) self.nodes.append(node) return True
def Generate(self, ast, options): self.errors = 0 rangestr = GetOption('range') releasestr = GetOption('release') # Check for a range option which over-rides a release option if not releasestr and rangestr: range_list = rangestr.split(',') if len(range_list) != 2: self.Error('Failed to generate for %s, incorrect range: "%s"' % (self.name, rangestr)) else: vmin = range_list[0] vmax = range_list[1] vmin = ast.releases.index(vmin) vmax = ast.releases.index(vmax) + 1 range = ast.releases[vmin:vmax] InfoOut.Log('Generate range %s of %s.' % (range, self.name)) ret = self.GenerateRange(ast, range, options) if ret < 0: self.Error('Failed to generate range %s : %s.' % (vmin, vmax)) else: InfoOut.Log('%s wrote %d files.' % (self.name, ret)) # Otherwise this should be a single release generation else: if releasestr: InfoOut.Log('Generate release %s of %s.' % (releasestr, self.name)) ret = self.GenerateRelease(ast, releasestr, options) if ret < 0: self.Error('Failed to generate release %s.' % releasestr) else: InfoOut.Log('%s wrote %d files.' % (self.name, ret)) else: self.Error('No range or release specified for %s.' % releasestr) return self.errors
def TestFiles(filenames, test_releases): ast = ParseFiles(filenames) iface_releases = pnaclgen.DetermineInterfaces(ast, test_releases) new_output = CleanString( pnaclgen.GenerateWrapperForMethods(iface_releases, comments=False)) old_output = GetOldTestOutput(ast) if new_output != old_output: PrintErrorDiff(old_output, new_output) ErrOut.Log('Failed pnacl generator test.') return 1 else: InfoOut.Log('Passed pnacl generator test.') return 0
def TestVersionFiles(filter): idldir = os.path.split(sys.argv[0])[0] idldir = os.path.join(idldir, 'test_version', '*.idl') filenames = glob.glob(idldir) testnames = [] for filename in filenames: if filter and filename not in filter: continue testnames.append(filename) # If we have no files to test, then skip this test if not testnames: InfoOut.Log('No files to test for version.') return 0 ast = ParseFiles(testnames) errs = FindVersionError(ast.releases, ast) if errs: ErrOut.Log("Failed version test.") else: InfoOut.Log("Passed version test.") return errs
def InRange(self, rmin, rmax): assert (rmin == None) or rmin < rmax # An min of None always passes a min bound test # An max of None always passes a max bound test if rmin is not None and self.rmax is not None: if self.rmax <= rmin: return False if rmax is not None and self.rmin is not None: if self.rmin >= rmax: return False if GetOption('release_debug'): InfoOut.Log('%f to %f is in %s' % (rmin, rmax, self)) return True
def GenerateRange(self, ast, releases, options): """Generate shim code for a range of releases. """ # Remember to set the output filename before running this. out_filename = self.output_file if out_filename is None: ErrOut.Log('Did not set filename for writing out wrapper\n') return 1 InfoOut.Log("Generating %s for %s" % (out_filename, self.wrapper_prefix)) out = IDLOutFile(out_filename) # Get a list of all the interfaces along with metadata. iface_releases = self.DetermineInterfaces(ast, releases) # Generate the includes. self.GenerateIncludes(iface_releases, out) out.Write(self.GetGuardStart()) # Write out static helper functions (mystrcmp). self.GenerateHelperFunctions(out) # Declare list of WrapperInfo before actual wrapper methods, since # they reference each other. self.DeclareWrapperInfos(iface_releases, out) # Generate wrapper functions for each wrapped method in the interfaces. result = self.GenerateWrapperForMethods(iface_releases) out.Write(result) # Collect all the wrapper functions into interface structs. self.GenerateWrapperInterfaces(iface_releases, out) # Generate a table of the wrapped interface structs that can be looked up. self.GenerateWrapperInfoAndCollection(iface_releases, out) # Write out the IDL-invariant functions. self.GenerateFixedFunctions(out) out.Write(self.GetGuardEnd()) out.Close() return 0
def ReplaceTest(): errors = 0 left = BuildNode('Left', ['Left=Left']) right = BuildNode('Right', ['Right=Right']) top = BuildNode('Top', ['Left=Top', 'Right=Top'], [left, right]) errors += ExpectText(top, '$Left$', 'Top') errors += ExpectText(top, '$Right$', 'Top') errors += ExpectText(left, '$Left$', 'Left') errors += ExpectText(left, '$Right$', 'Top') errors += ExpectText(right, '$Left$', 'Top') errors += ExpectText(right, '$Right$', 'Right') if not errors: InfoOut.Log('Passed ReplaceTest') return errors
def PropertyTest(): errors = 0 left = BuildNode('Left', ['Left=Left']) right = BuildNode('Right', ['Right=Right']) top = BuildNode('Top', ['Left=Top', 'Right=Top'], [left, right]) errors += ExpectProp(top, 'Left', 'Top') errors += ExpectProp(top, 'Right', 'Top') errors += ExpectProp(left, 'Left', 'Left') errors += ExpectProp(left, 'Right', 'Top') errors += ExpectProp(right, 'Left', 'Top') errors += ExpectProp(right, 'Right', 'Right') if not errors: InfoOut.Log('Passed PropertyTest') return errors
def MultiParentTest(): errors = 0 parent1 = BuildNode('parent1', ['PARENT1=parent1', 'TOPMOST=$TOP$']) parent2 = BuildNode('parent2', ['PARENT1=parent2', 'PARENT2=parent2']) child = BuildNode('child', ['CHILD=child'], parents=[parent1, parent2]) BuildNode('top', ['TOP=top'], children=[parent1]) errors += ExpectText(child, '$CHILD$', 'child') errors += ExpectText(child, '$PARENT1$', 'parent1') errors += ExpectText(child, '$PARENT2$', 'parent2') # Verify recursive resolution errors += ExpectText(child, '$TOPMOST$', 'top') if not errors: InfoOut.Log('Passed MultiParentTest') return errors
def StringTest(): errors = 0 name_str = 'MyName' text_str = 'MyNode(%s)' % name_str name_node = IDLAttribute('NAME', name_str) node = IDLNode('MyNode', 'no file', 1, 0, [name_node]) if node.GetName() != name_str: ErrOut.Log('GetName returned >%s< not >%s<' % (node.GetName(), name_str)) errors += 1 if node.GetProperty('NAME') != name_str: ErrOut.Log('Failed to get name property.') errors += 1 if str(node) != text_str: ErrOut.Log('str() returned >%s< not >%s<' % (str(node), text_str)) errors += 1 if not errors: InfoOut.Log('Passed StringTest') return errors
def main(): errors = 0 stringlist = ['Test', 'Testing\n', 'Test'] filename = 'outtest.txt' # Test forcibly writing a file errors += TestFile(filename, stringlist, force=True, update=True) # Test conditionally writing the file skipping errors += TestFile(filename, stringlist, force=False, update=False) # Test conditionally writing the file updating errors += TestFile(filename, stringlist + ['X'], force=False, update=True) # Clean up file os.remove(filename) if not errors: InfoOut.Log('All tests pass.') return errors
def TestErrorFiles(filter): idldir = os.path.split(sys.argv[0])[0] idldir = os.path.join(idldir, 'test_parser', '*.idl') filenames = glob.glob(idldir) parser = IDLParser() total_errs = 0 for filename in filenames: if filter and filename not in filter: continue errs = TestFile(parser, filename) if errs: ErrOut.Log("%s test failed with %d error(s)." % (filename, errs)) total_errs += errs if total_errs: ErrOut.Log("Failed parsing test.") else: InfoOut.Log("Passed parsing test.") return total_errs
def Main(args): filenames = ParseOptions(args) # If testing... if GetOption('test'): errs = TestErrorFiles(filenames) errs = TestNamespaceFiles(filenames) if errs: ErrOut.Log("Parser failed with %d errors." % errs) return -1 return 0 # Otherwise, build the AST ast = ParseFiles(filenames) errs = ast.GetProperty('ERRORS') if errs: ErrOut.Log('Found %d error(s).' % errs) InfoOut.Log("%d files processed." % len(filenames)) return errs
def ParseFile(self, filename): date = time.ctime(os.path.getmtime(filename)) data = open(filename).read() if self.verbose: InfoOut.Log("Parsing %s" % filename) try: out = self.ParseData(data, filename) # If we have a src root specified, remove it from the path srcroot = GetOption('srcroot') if srcroot and filename.find(srcroot) == 0: filename = filename[len(srcroot) + 1:] filenode = IDLFile(filename, out, self.parse_errors + self.lex_errors) filenode.SetProperty('DATETIME', date) return filenode except Exception as e: ErrOut.LogLine(filename, self.last.lineno, self.last.lexpos, 'Internal parsing error - %s.' % str(e)) raise
def TestFiles(filenames): if not filenames: idldir = os.path.split(sys.argv[0])[0] idldir = os.path.join(idldir, 'test_cgen', '*.idl') filenames = glob.glob(idldir) filenames = sorted(filenames) ast = ParseFiles(filenames) total_errs = 0 for filenode in ast.GetListOf('File'): errs = TestFile(filenode) if errs: ErrOut.Log('%s test failed with %d error(s).' % (filenode.GetName(), errs)) total_errs += errs if total_errs: ErrOut.Log('Failed generator test.') else: InfoOut.Log('Passed generator test.') return total_errs
def DumpHelp(option=None): InfoOut.Log('Usage:') for opt in sorted(OptionMap.keys()): DumpOption(OptionMap[opt]) sys.exit(0)
def Dump(self): for name in self._name_to_releases: InfoOut.Log('NAME=%s' % name) for cver in self._name_to_releases[name].GetReleases(): InfoOut.Log(' %s' % cver) InfoOut.Log('')
def TestErrors(filename, filenode): nodelist = filenode.GetChildren() lexer = IDLLexer() data = open(filename).read() lexer.SetData(filename, data) pass_comments = [] fail_comments = [] while True: tok = lexer.lexobj.token() if tok == None: break if tok.type == 'COMMENT': args = tok.value[3:-3].split() if args[0] == 'OK': pass_comments.append((tok.lineno, ' '.join(args[1:]))) else: if args[0] == 'FAIL': fail_comments.append((tok.lineno, ' '.join(args[1:]))) obj_list = [] for node in nodelist: obj_list.extend(FlattenTree(node)) errors = 0 # # Check for expected successes # obj_cnt = len(obj_list) pass_cnt = len(pass_comments) if obj_cnt != pass_cnt: InfoOut.Log("Mismatched pass (%d) vs. nodes built (%d)." % (pass_cnt, obj_cnt)) InfoOut.Log("PASS: %s" % [x[1] for x in pass_comments]) InfoOut.Log("OBJS: %s" % obj_list) errors += 1 if pass_cnt > obj_cnt: pass_cnt = obj_cnt for i in range(pass_cnt): line, comment = pass_comments[i] if obj_list[i] != comment: ErrOut.LogLine(filename, line, None, "OBJ %s : EXPECTED %s\n" % (obj_list[i], comment)) errors += 1 # # Check for expected errors # err_list = ErrOut.DrainLog() err_cnt = len(err_list) fail_cnt = len(fail_comments) if err_cnt != fail_cnt: InfoOut.Log("Mismatched fail (%d) vs. errors seen (%d)." % (fail_cnt, err_cnt)) InfoOut.Log("FAIL: %s" % [x[1] for x in fail_comments]) InfoOut.Log("ERRS: %s" % err_list) errors += 1 if fail_cnt > err_cnt: fail_cnt = err_cnt for i in range(fail_cnt): line, comment = fail_comments[i] err = err_list[i].strip() if err_list[i] != comment: ErrOut.Log("%s(%d) Error\n\tERROR : %s\n\tEXPECT: %s" % (filename, line, err_list[i], comment)) errors += 1 # Clear the error list for the next run err_list = [] return errors
def Dump(self): for name in self.namespace: InfoOut.Log('NAME=%s' % name) for cver in self.namespace[name].nodes: InfoOut.Log(' %s' % cver) InfoOut.Log('')
def Main(args): global errors ParseOptions(args) InfoOut.SetConsole(True) namespace = IDLNamespace(None) FooXX = MockNode('foo', None, None) Foo1X = MockNode('foo', 1.0, None) Foo2X = MockNode('foo', 2.0, None) Foo3X = MockNode('foo', 3.0, None) # Verify we succeed with undeprecated adds AddOkay(namespace, FooXX) AddOkay(namespace, Foo1X) AddOkay(namespace, Foo3X) # Verify we fail to add a node between undeprecated releases AddError(namespace, Foo2X, 'Overlap in releases: 3.0 vs 2.0 when adding foo (2.0 : None)') BarXX = MockNode('bar', None, None) Bar12 = MockNode('bar', 1.0, 2.0) Bar23 = MockNode('bar', 2.0, 3.0) Bar34 = MockNode('bar', 3.0, 4.0) # Verify we succeed with fully qualified releases namespace = IDLNamespace(namespace) AddOkay(namespace, BarXX) AddOkay(namespace, Bar12) # Verify we warn when detecting a gap AddWarn(namespace, Bar34, 'Gap in release numbers.') # Verify we fail when inserting into this gap # (NOTE: while this could be legal, it is sloppy so we disallow it) AddError(namespace, Bar23, 'Declarations out of order.') # Verify local namespace VerifyFindOne(namespace, 'bar', 0.0, BarXX) VerifyFindAll(namespace, 'bar', 0.5, 1.5, [BarXX, Bar12]) # Verify the correct release of the object is found recursively VerifyFindOne(namespace, 'foo', 0.0, FooXX) VerifyFindOne(namespace, 'foo', 0.5, FooXX) VerifyFindOne(namespace, 'foo', 1.0, Foo1X) VerifyFindOne(namespace, 'foo', 1.5, Foo1X) VerifyFindOne(namespace, 'foo', 3.0, Foo3X) VerifyFindOne(namespace, 'foo', 100.0, Foo3X) # Verify the correct range of objects is found VerifyFindAll(namespace, 'foo', 0.0, 1.0, [FooXX]) VerifyFindAll(namespace, 'foo', 0.5, 1.0, [FooXX]) VerifyFindAll(namespace, 'foo', 1.0, 1.1, [Foo1X]) VerifyFindAll(namespace, 'foo', 0.5, 1.5, [FooXX, Foo1X]) VerifyFindAll(namespace, 'foo', 0.0, 3.0, [FooXX, Foo1X]) VerifyFindAll(namespace, 'foo', 3.0, 100.0, [Foo3X]) FooBar = MockNode('foobar', 1.0, 2.0) namespace = IDLNamespace(namespace) AddOkay(namespace, FooBar) if errors: print 'Test failed with %d errors.' % errors else: print 'Passed.' return errors