- add sources.
[platform/framework/web/crosswalk.git] / src / tools / generate_stubs / generate_stubs_unittest.py
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.
5
6 """Unittest for the generate_stubs.py.
7
8 Since generate_stubs.py is a code generator, it is hard to do a very good
9 test.  Instead of creating a golden-file test, which might be flakey, this
10 test elects instead to verify that various components "exist" within the
11 generated file as a sanity check.  In particular, there is a simple hit
12 test to make sure that umbrella functions, etc., do try and include every
13 function they are responsible for invoking.  Missing an invocation is quite
14 easily missed.
15
16 There is no attempt to verify ordering of different components, or whether
17 or not those components are going to parse incorrectly because of prior
18 errors or positioning.  Most of that should be caught really fast anyways
19 during any attempt to use a badly behaving script.
20 """
21
22 import generate_stubs as gs
23 import re
24 import StringIO
25 import sys
26 import unittest
27
28
29 def _MakeSignature(return_type, name, params):
30   return {'return_type': return_type,
31           'name': name,
32           'params': params}
33
34
35 SIMPLE_SIGNATURES = [
36     ('int foo(int a)', _MakeSignature('int', 'foo', ['int a'])),
37     ('int bar(int a, double b)', _MakeSignature('int', 'bar',
38                                                 ['int a', 'double b'])),
39     ('int baz(void)', _MakeSignature('int', 'baz', ['void'])),
40     ('void quux(void)', _MakeSignature('void', 'quux', ['void'])),
41     ('void waldo(void);', _MakeSignature('void', 'waldo', ['void'])),
42     ('int corge(void);', _MakeSignature('int', 'corge', ['void'])),
43     ]
44
45 TRICKY_SIGNATURES = [
46     ('const struct name *foo(int a, struct Test* b);  ',
47      _MakeSignature('const struct name *',
48                     'foo',
49                     ['int a', 'struct Test* b'])),
50     ('const struct name &foo(int a, struct Test* b);',
51      _MakeSignature('const struct name &',
52                     'foo',
53                     ['int a', 'struct Test* b'])),
54     ('const struct name &_foo(int a, struct Test* b);',
55      _MakeSignature('const struct name &',
56                     '_foo',
57                     ['int a', 'struct Test* b'])),
58     ('struct name const * const _foo(int a, struct Test* b) '
59      '__attribute__((inline));',
60      _MakeSignature('struct name const * const',
61                     '_foo',
62                     ['int a', 'struct Test* b']))
63     ]
64
65 INVALID_SIGNATURES = ['I am bad', 'Seriously bad(', ';;;']
66
67
68 class GenerateStubModuleFunctionsUnittest(unittest.TestCase):
69   def testExtractModuleName(self):
70     self.assertEqual('somefile-2', gs.ExtractModuleName('somefile-2.ext'))
71
72   def testParseSignatures_EmptyFile(self):
73     # Empty file just generates empty signatures.
74     infile = StringIO.StringIO()
75     signatures = gs.ParseSignatures(infile)
76     self.assertEqual(0, len(signatures))
77
78   def testParseSignatures_SimpleSignatures(self):
79     file_contents = '\n'.join([x[0] for x in SIMPLE_SIGNATURES])
80     infile = StringIO.StringIO(file_contents)
81     signatures = gs.ParseSignatures(infile)
82     self.assertEqual(len(SIMPLE_SIGNATURES), len(signatures))
83
84     # We assume signatures are in order.
85     for i in xrange(len(SIMPLE_SIGNATURES)):
86       self.assertEqual(SIMPLE_SIGNATURES[i][1], signatures[i],
87                        msg='Expected %s\nActual %s\nFor %s' %
88                        (SIMPLE_SIGNATURES[i][1],
89                         signatures[i],
90                         SIMPLE_SIGNATURES[i][0]))
91
92   def testParseSignatures_TrickySignatures(self):
93     file_contents = '\n'.join([x[0] for x in TRICKY_SIGNATURES])
94     infile = StringIO.StringIO(file_contents)
95     signatures = gs.ParseSignatures(infile)
96     self.assertEqual(len(TRICKY_SIGNATURES), len(signatures))
97
98     # We assume signatures are in order.
99     for i in xrange(len(TRICKY_SIGNATURES)):
100       self.assertEqual(TRICKY_SIGNATURES[i][1], signatures[i],
101                        msg='Expected %s\nActual %s\nFor %s' %
102                        (TRICKY_SIGNATURES[i][1],
103                         signatures[i],
104                         TRICKY_SIGNATURES[i][0]))
105
106   def testParseSignatures_InvalidSignatures(self):
107     for i in INVALID_SIGNATURES:
108       infile = StringIO.StringIO(i)
109       self.assertRaises(gs.BadSignatureError, gs.ParseSignatures, infile)
110
111   def testParseSignatures_CommentsIgnored(self):
112     my_sigs = []
113     my_sigs.append('# a comment')
114     my_sigs.append(SIMPLE_SIGNATURES[0][0])
115     my_sigs.append('# another comment')
116     my_sigs.append(SIMPLE_SIGNATURES[0][0])
117     my_sigs.append('# a third comment')
118     my_sigs.append(SIMPLE_SIGNATURES[0][0])
119
120     file_contents = '\n'.join(my_sigs)
121     infile = StringIO.StringIO(file_contents)
122     signatures = gs.ParseSignatures(infile)
123     self.assertEqual(3, len(signatures))
124
125
126 class WindowsLibUnittest(unittest.TestCase):
127   def testWriteWindowsDefFile(self):
128     module_name = 'my_module-1'
129     signatures = [sig[1] for sig in SIMPLE_SIGNATURES]
130     outfile = StringIO.StringIO()
131     gs.WriteWindowsDefFile(module_name, signatures, outfile)
132     contents = outfile.getvalue()
133
134     # Check that the file header is correct.
135     self.assertTrue(contents.startswith("""LIBRARY %s
136 EXPORTS
137 """ % module_name))
138
139     # Check that the signatures were exported.
140     for sig in signatures:
141       pattern = '\n  %s\n' % sig['name']
142       self.assertTrue(re.search(pattern, contents),
143                       msg='Expected match of "%s" in %s' % (pattern, contents))
144
145   def testQuietRun(self):
146     output = StringIO.StringIO()
147     gs.QuietRun([sys.executable,
148                  '-c', 'print "line 1 and suffix\\nline 2"'],
149                 write_to=output)
150     self.assertEqual('line 1 and suffix\nline 2\n', output.getvalue())
151
152     output = StringIO.StringIO()
153     gs.QuietRun([sys.executable,
154                  '-c', 'print "line 1 and suffix\\nline 2"'],
155                  filter='line 1', write_to=output)
156     self.assertEqual('line 2\n', output.getvalue())
157
158
159 class PosixStubWriterUnittest(unittest.TestCase):
160   def setUp(self):
161     self.module_name = 'my_module-1'
162     self.signatures = [sig[1] for sig in SIMPLE_SIGNATURES]
163     self.out_dir = 'out_dir'
164     self.writer = gs.PosixStubWriter(self.module_name, self.signatures)
165
166   def testEnumName(self):
167     self.assertEqual('kModuleMy_module1',
168                      gs.PosixStubWriter.EnumName(self.module_name))
169
170   def testIsInitializedName(self):
171     self.assertEqual('IsMy_module1Initialized',
172                      gs.PosixStubWriter.IsInitializedName(self.module_name))
173
174   def testInitializeModuleName(self):
175     self.assertEqual(
176         'InitializeMy_module1',
177         gs.PosixStubWriter.InitializeModuleName(self.module_name))
178
179   def testUninitializeModuleName(self):
180     self.assertEqual(
181         'UninitializeMy_module1',
182         gs.PosixStubWriter.UninitializeModuleName(self.module_name))
183
184   def testStubFunctionPointer(self):
185     self.assertEqual(
186         'static int (*foo_ptr)(int a) = NULL;',
187         gs.PosixStubWriter.StubFunctionPointer(SIMPLE_SIGNATURES[0][1]))
188
189   def testStubFunction(self):
190     # Test for a signature with a return value and a parameter.
191     self.assertEqual("""extern int foo(int a) __attribute__((weak));
192 int foo(int a) {
193   return foo_ptr(a);
194 }""", gs.PosixStubWriter.StubFunction(SIMPLE_SIGNATURES[0][1]))
195
196     # Test for a signature with a void return value and no parameters.
197     self.assertEqual("""extern void waldo(void) __attribute__((weak));
198 void waldo(void) {
199   waldo_ptr();
200 }""", gs.PosixStubWriter.StubFunction(SIMPLE_SIGNATURES[4][1]))
201
202   def testWriteImplemenationContents(self):
203     outfile = StringIO.StringIO()
204     self.writer.WriteImplementationContents('my_namespace', outfile)
205     contents = outfile.getvalue()
206
207     # Verify namespace exists somewhere.
208     self.assertTrue(contents.find('namespace my_namespace {') != -1)
209
210     # Verify that each signature has an _ptr and a function call in the file.
211     # Check that the signatures were exported.
212     for sig in self.signatures:
213       decl = gs.PosixStubWriter.StubFunctionPointer(sig)
214       self.assertTrue(contents.find(decl) != -1,
215                       msg='Expected "%s" in %s' % (decl, contents))
216
217     # Verify that each signature has an stub function generated for it.
218     for sig in self.signatures:
219       decl = gs.PosixStubWriter.StubFunction(sig)
220       self.assertTrue(contents.find(decl) != -1,
221                       msg='Expected "%s" in %s' % (decl, contents))
222
223     # Find module initializer functions.  Make sure all 3 exist.
224     decl = gs.PosixStubWriter.InitializeModuleName(self.module_name)
225     self.assertTrue(contents.find(decl) != -1,
226                     msg='Expected "%s" in %s' % (decl, contents))
227     decl = gs.PosixStubWriter.UninitializeModuleName(self.module_name)
228     self.assertTrue(contents.find(decl) != -1,
229                     msg='Expected "%s" in %s' % (decl, contents))
230     decl = gs.PosixStubWriter.IsInitializedName(self.module_name)
231     self.assertTrue(contents.find(decl) != -1,
232                     msg='Expected "%s" in %s' % (decl, contents))
233
234   def testWriteHeaderContents(self):
235     # Data for header generation.
236     module_names = ['oneModule', 'twoModule']
237
238     # Make the header.
239     outfile = StringIO.StringIO()
240     self.writer.WriteHeaderContents(module_names, 'my_namespace', 'GUARD_',
241                                     outfile)
242     contents = outfile.getvalue()
243
244     # Check for namespace and header guard.
245     self.assertTrue(contents.find('namespace my_namespace {') != -1)
246     self.assertTrue(contents.find('#ifndef GUARD_') != -1)
247
248     # Check for umbrella initializer.
249     self.assertTrue(contents.find('InitializeStubs(') != -1)
250
251     # Check per-module declarations.
252     for name in module_names:
253       # Check for enums.
254       decl = gs.PosixStubWriter.EnumName(name)
255       self.assertTrue(contents.find(decl) != -1,
256                       msg='Expected "%s" in %s' % (decl, contents))
257
258       # Check for module initializer functions.
259       decl = gs.PosixStubWriter.IsInitializedName(name)
260       self.assertTrue(contents.find(decl) != -1,
261                       msg='Expected "%s" in %s' % (decl, contents))
262       decl = gs.PosixStubWriter.InitializeModuleName(name)
263       self.assertTrue(contents.find(decl) != -1,
264                       msg='Expected "%s" in %s' % (decl, contents))
265       decl = gs.PosixStubWriter.UninitializeModuleName(name)
266       self.assertTrue(contents.find(decl) != -1,
267                       msg='Expected "%s" in %s' % (decl, contents))
268
269   def testWriteUmbrellaInitializer(self):
270     # Data for header generation.
271     module_names = ['oneModule', 'twoModule']
272
273     # Make the header.
274     outfile = StringIO.StringIO()
275     self.writer.WriteUmbrellaInitializer(module_names, 'my_namespace', outfile)
276     contents = outfile.getvalue()
277
278     # Check for umbrella initializer declaration.
279     self.assertTrue(contents.find('bool InitializeStubs(') != -1)
280
281     # If the umbrella initializer is correctly written, each module will have
282     # its initializer called, checked, and uninitialized on failure.  Sanity
283     # check that here.
284     for name in module_names:
285       # Check for module initializer functions.
286       decl = gs.PosixStubWriter.IsInitializedName(name)
287       self.assertTrue(contents.find(decl) != -1,
288                       msg='Expected "%s" in %s' % (decl, contents))
289       decl = gs.PosixStubWriter.InitializeModuleName(name)
290       self.assertTrue(contents.find(decl) != -1,
291                       msg='Expected "%s" in %s' % (decl, contents))
292       decl = gs.PosixStubWriter.UninitializeModuleName(name)
293       self.assertTrue(contents.find(decl) != -1,
294                       msg='Expected "%s" in %s' % (decl, contents))
295
296 if __name__ == '__main__':
297   unittest.main()