Implement keycode text conversion functions for Ozone.
[chromium-blink-merge.git] / ppapi / generators / idl_namespace.py
blobb81411e68dd679b13e188d4cb7230f725e55fc36
1 #!/usr/bin/env python
2 # Copyright (c) 2012 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
6 """
7 IDLNamespace for PPAPI
9 This file defines the behavior of the AST namespace which allows for resolving
10 a symbol as one or more AST nodes given a release or range of releases.
11 """
13 import sys
15 from idl_option import GetOption, Option, ParseOptions
16 from idl_log import ErrOut, InfoOut, WarnOut
17 from idl_release import IDLRelease, IDLReleaseList
19 Option('label', 'Use the specifed label blocks.', default='Chrome')
20 Option('namespace_debug', 'Use the specified release')
24 # IDLNamespace
26 # IDLNamespace provides a mapping between a symbol name and an IDLReleaseList
27 # which contains IDLRelease objects. It provides an interface for fetching
28 # one or more IDLNodes based on a release or range of releases.
30 class IDLNamespace(object):
31 def __init__(self, parent):
32 self._name_to_releases = {}
33 self._parent = parent
35 def Dump(self):
36 for name in self._name_to_releases:
37 InfoOut.Log('NAME=%s' % name)
38 for cver in self._name_to_releases[name].GetReleases():
39 InfoOut.Log(' %s' % cver)
40 InfoOut.Log('')
42 def FindRelease(self, name, release):
43 verlist = self._name_to_releases.get(name, None)
44 if verlist == None:
45 if self._parent:
46 return self._parent.FindRelease(name, release)
47 else:
48 return None
49 return verlist.FindRelease(release)
51 def FindRange(self, name, rmin, rmax):
52 verlist = self._name_to_releases.get(name, None)
53 if verlist == None:
54 if self._parent:
55 return self._parent.FindRange(name, rmin, rmax)
56 else:
57 return []
58 return verlist.FindRange(rmin, rmax)
60 def FindList(self, name):
61 verlist = self._name_to_releases.get(name, None)
62 if verlist == None:
63 if self._parent:
64 return self._parent.FindList(name)
65 return verlist
67 def AddNode(self, node):
68 name = node.GetName()
69 verlist = self._name_to_releases.setdefault(name,IDLReleaseList())
70 if GetOption('namespace_debug'):
71 print "Adding to namespace: %s" % node
72 return verlist.AddNode(node)
76 # Testing Code
80 # MockNode
82 # Mocks the IDLNode to support error, warning handling, and string functions.
84 class MockNode(IDLRelease):
85 def __init__(self, name, rmin, rmax):
86 self.name = name
87 self.rmin = rmin
88 self.rmax = rmax
89 self.errors = []
90 self.warns = []
91 self.properties = {
92 'NAME': name,
93 'release': rmin,
94 'deprecate' : rmax
97 def __str__(self):
98 return '%s (%s : %s)' % (self.name, self.rmin, self.rmax)
100 def GetName(self):
101 return self.name
103 def Error(self, msg):
104 if GetOption('release_debug'): print 'Error: %s' % msg
105 self.errors.append(msg)
107 def Warn(self, msg):
108 if GetOption('release_debug'): print 'Warn: %s' % msg
109 self.warns.append(msg)
111 def GetProperty(self, name):
112 return self.properties.get(name, None)
114 errors = 0
116 # DumpFailure
118 # Dumps all the information relevant to an add failure.
119 def DumpFailure(namespace, node, msg):
120 global errors
121 print '\n******************************'
122 print 'Failure: %s %s' % (node, msg)
123 for warn in node.warns:
124 print ' WARN: %s' % warn
125 for err in node.errors:
126 print ' ERROR: %s' % err
127 print '\n'
128 namespace.Dump()
129 print '******************************\n'
130 errors += 1
132 # Add expecting no errors or warnings
133 def AddOkay(namespace, node):
134 okay = namespace.AddNode(node)
135 if not okay or node.errors or node.warns:
136 DumpFailure(namespace, node, 'Expected success')
138 # Add expecting a specific warning
139 def AddWarn(namespace, node, msg):
140 okay = namespace.AddNode(node)
141 if not okay or node.errors or not node.warns:
142 DumpFailure(namespace, node, 'Expected warnings')
143 if msg not in node.warns:
144 DumpFailure(namespace, node, 'Expected warning: %s' % msg)
146 # Add expecting a specific error any any number of warnings
147 def AddError(namespace, node, msg):
148 okay = namespace.AddNode(node)
149 if okay or not node.errors:
150 DumpFailure(namespace, node, 'Expected errors')
151 if msg not in node.errors:
152 DumpFailure(namespace, node, 'Expected error: %s' % msg)
153 print ">>%s<<\n>>%s<<\n" % (node.errors[0], msg)
155 # Verify that a FindRelease call on the namespace returns the expected node.
156 def VerifyFindOne(namespace, name, release, node):
157 global errors
158 if (namespace.FindRelease(name, release) != node):
159 print "Failed to find %s as release %f of %s" % (node, release, name)
160 namespace.Dump()
161 print "\n"
162 errors += 1
164 # Verify that a FindRage call on the namespace returns a set of expected nodes.
165 def VerifyFindAll(namespace, name, rmin, rmax, nodes):
166 global errors
167 out = namespace.FindRange(name, rmin, rmax)
168 if (out != nodes):
169 print "Found [%s] instead of[%s] for releases %f to %f of %s" % (
170 ' '.join([str(x) for x in out]),
171 ' '.join([str(x) for x in nodes]),
172 rmin,
173 rmax,
174 name)
175 namespace.Dump()
176 print "\n"
177 errors += 1
179 def Main(args):
180 global errors
181 ParseOptions(args)
183 InfoOut.SetConsole(True)
185 namespace = IDLNamespace(None)
187 FooXX = MockNode('foo', None, None)
188 Foo1X = MockNode('foo', 1.0, None)
189 Foo2X = MockNode('foo', 2.0, None)
190 Foo3X = MockNode('foo', 3.0, None)
192 # Verify we succeed with undeprecated adds
193 AddOkay(namespace, FooXX)
194 AddOkay(namespace, Foo1X)
195 AddOkay(namespace, Foo3X)
196 # Verify we fail to add a node between undeprecated releases
197 AddError(namespace, Foo2X,
198 'Overlap in releases: 3.0 vs 2.0 when adding foo (2.0 : None)')
200 BarXX = MockNode('bar', None, None)
201 Bar12 = MockNode('bar', 1.0, 2.0)
202 Bar23 = MockNode('bar', 2.0, 3.0)
203 Bar34 = MockNode('bar', 3.0, 4.0)
206 # Verify we succeed with fully qualified releases
207 namespace = IDLNamespace(namespace)
208 AddOkay(namespace, BarXX)
209 AddOkay(namespace, Bar12)
210 # Verify we warn when detecting a gap
211 AddWarn(namespace, Bar34, 'Gap in release numbers.')
212 # Verify we fail when inserting into this gap
213 # (NOTE: while this could be legal, it is sloppy so we disallow it)
214 AddError(namespace, Bar23, 'Declarations out of order.')
216 # Verify local namespace
217 VerifyFindOne(namespace, 'bar', 0.0, BarXX)
218 VerifyFindAll(namespace, 'bar', 0.5, 1.5, [BarXX, Bar12])
220 # Verify the correct release of the object is found recursively
221 VerifyFindOne(namespace, 'foo', 0.0, FooXX)
222 VerifyFindOne(namespace, 'foo', 0.5, FooXX)
223 VerifyFindOne(namespace, 'foo', 1.0, Foo1X)
224 VerifyFindOne(namespace, 'foo', 1.5, Foo1X)
225 VerifyFindOne(namespace, 'foo', 3.0, Foo3X)
226 VerifyFindOne(namespace, 'foo', 100.0, Foo3X)
228 # Verify the correct range of objects is found
229 VerifyFindAll(namespace, 'foo', 0.0, 1.0, [FooXX])
230 VerifyFindAll(namespace, 'foo', 0.5, 1.0, [FooXX])
231 VerifyFindAll(namespace, 'foo', 1.0, 1.1, [Foo1X])
232 VerifyFindAll(namespace, 'foo', 0.5, 1.5, [FooXX, Foo1X])
233 VerifyFindAll(namespace, 'foo', 0.0, 3.0, [FooXX, Foo1X])
234 VerifyFindAll(namespace, 'foo', 3.0, 100.0, [Foo3X])
236 FooBar = MockNode('foobar', 1.0, 2.0)
237 namespace = IDLNamespace(namespace)
238 AddOkay(namespace, FooBar)
240 if errors:
241 print 'Test failed with %d errors.' % errors
242 else:
243 print 'Passed.'
244 return errors
247 if __name__ == '__main__':
248 sys.exit(Main(sys.argv[1:]))