forked from mirrors/gecko-dev
249 lines
7.2 KiB
Python
Executable file
249 lines
7.2 KiB
Python
Executable file
#!/usr/bin/env python
|
|
# Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
|
# Use of this source code is governed by a BSD-style license that can be
|
|
# found in the LICENSE file.
|
|
|
|
"""
|
|
IDLNamespace for PPAPI
|
|
|
|
This file defines the behavior of the AST namespace which allows for resolving
|
|
a symbol as one or more AST nodes given a release or range of releases.
|
|
"""
|
|
|
|
import sys
|
|
|
|
from idl_option import GetOption, Option, ParseOptions
|
|
from idl_log import ErrOut, InfoOut, WarnOut
|
|
from idl_release import IDLRelease, IDLReleaseList
|
|
|
|
Option('label', 'Use the specifed label blocks.', default='Chrome')
|
|
Option('namespace_debug', 'Use the specified release')
|
|
|
|
|
|
#
|
|
# IDLNamespace
|
|
#
|
|
# IDLNamespace provides a mapping between a symbol name and an IDLReleaseList
|
|
# which contains IDLRelease objects. It provides an interface for fetching
|
|
# one or more IDLNodes based on a release or range of releases.
|
|
#
|
|
class IDLNamespace(object):
|
|
def __init__(self, parent):
|
|
self._name_to_releases = {}
|
|
self._parent = parent
|
|
|
|
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 FindRelease(self, name, release):
|
|
verlist = self._name_to_releases.get(name, None)
|
|
if verlist == None:
|
|
if self._parent:
|
|
return self._parent.FindRelease(name, release)
|
|
else:
|
|
return None
|
|
return verlist.FindRelease(release)
|
|
|
|
def FindRange(self, name, rmin, rmax):
|
|
verlist = self._name_to_releases.get(name, None)
|
|
if verlist == None:
|
|
if self._parent:
|
|
return self._parent.FindRange(name, rmin, rmax)
|
|
else:
|
|
return []
|
|
return verlist.FindRange(rmin, rmax)
|
|
|
|
def FindList(self, name):
|
|
verlist = self._name_to_releases.get(name, None)
|
|
if verlist == None:
|
|
if self._parent:
|
|
return self._parent.FindList(name)
|
|
return verlist
|
|
|
|
def AddNode(self, node):
|
|
name = node.GetName()
|
|
verlist = self._name_to_releases.setdefault(name,IDLReleaseList())
|
|
if GetOption('namespace_debug'):
|
|
print "Adding to namespace: %s" % node
|
|
return verlist.AddNode(node)
|
|
|
|
|
|
#
|
|
# Testing Code
|
|
#
|
|
|
|
#
|
|
# MockNode
|
|
#
|
|
# Mocks the IDLNode to support error, warning handling, and string functions.
|
|
#
|
|
class MockNode(IDLRelease):
|
|
def __init__(self, name, rmin, rmax):
|
|
self.name = name
|
|
self.rmin = rmin
|
|
self.rmax = rmax
|
|
self.errors = []
|
|
self.warns = []
|
|
self.properties = {
|
|
'NAME': name,
|
|
'release': rmin,
|
|
'deprecate' : rmax
|
|
}
|
|
|
|
def __str__(self):
|
|
return '%s (%s : %s)' % (self.name, self.rmin, self.rmax)
|
|
|
|
def GetName(self):
|
|
return self.name
|
|
|
|
def Error(self, msg):
|
|
if GetOption('release_debug'): print 'Error: %s' % msg
|
|
self.errors.append(msg)
|
|
|
|
def Warn(self, msg):
|
|
if GetOption('release_debug'): print 'Warn: %s' % msg
|
|
self.warns.append(msg)
|
|
|
|
def GetProperty(self, name):
|
|
return self.properties.get(name, None)
|
|
|
|
errors = 0
|
|
#
|
|
# DumpFailure
|
|
#
|
|
# Dumps all the information relevant to an add failure.
|
|
def DumpFailure(namespace, node, msg):
|
|
global errors
|
|
print '\n******************************'
|
|
print 'Failure: %s %s' % (node, msg)
|
|
for warn in node.warns:
|
|
print ' WARN: %s' % warn
|
|
for err in node.errors:
|
|
print ' ERROR: %s' % err
|
|
print '\n'
|
|
namespace.Dump()
|
|
print '******************************\n'
|
|
errors += 1
|
|
|
|
# Add expecting no errors or warnings
|
|
def AddOkay(namespace, node):
|
|
okay = namespace.AddNode(node)
|
|
if not okay or node.errors or node.warns:
|
|
DumpFailure(namespace, node, 'Expected success')
|
|
|
|
# Add expecting a specific warning
|
|
def AddWarn(namespace, node, msg):
|
|
okay = namespace.AddNode(node)
|
|
if not okay or node.errors or not node.warns:
|
|
DumpFailure(namespace, node, 'Expected warnings')
|
|
if msg not in node.warns:
|
|
DumpFailure(namespace, node, 'Expected warning: %s' % msg)
|
|
|
|
# Add expecting a specific error any any number of warnings
|
|
def AddError(namespace, node, msg):
|
|
okay = namespace.AddNode(node)
|
|
if okay or not node.errors:
|
|
DumpFailure(namespace, node, 'Expected errors')
|
|
if msg not in node.errors:
|
|
DumpFailure(namespace, node, 'Expected error: %s' % msg)
|
|
print ">>%s<<\n>>%s<<\n" % (node.errors[0], msg)
|
|
|
|
# Verify that a FindRelease call on the namespace returns the expected node.
|
|
def VerifyFindOne(namespace, name, release, node):
|
|
global errors
|
|
if (namespace.FindRelease(name, release) != node):
|
|
print "Failed to find %s as release %f of %s" % (node, release, name)
|
|
namespace.Dump()
|
|
print "\n"
|
|
errors += 1
|
|
|
|
# Verify that a FindRage call on the namespace returns a set of expected nodes.
|
|
def VerifyFindAll(namespace, name, rmin, rmax, nodes):
|
|
global errors
|
|
out = namespace.FindRange(name, rmin, rmax)
|
|
if (out != nodes):
|
|
print "Found [%s] instead of[%s] for releases %f to %f of %s" % (
|
|
' '.join([str(x) for x in out]),
|
|
' '.join([str(x) for x in nodes]),
|
|
rmin,
|
|
rmax,
|
|
name)
|
|
namespace.Dump()
|
|
print "\n"
|
|
errors += 1
|
|
|
|
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
|
|
|
|
|
|
if __name__ == '__main__':
|
|
sys.exit(Main(sys.argv[1:]))
|
|
|