summaryrefslogtreecommitdiffstats
path: root/chromium/tools/generate_stubs/generate_stubs_unittest.py
diff options
context:
space:
mode:
authorZeno Albisser <zeno.albisser@digia.com>2013-08-15 21:46:11 +0200
committerZeno Albisser <zeno.albisser@digia.com>2013-08-15 21:46:11 +0200
commit679147eead574d186ebf3069647b4c23e8ccace6 (patch)
treefc247a0ac8ff119f7c8550879ebb6d3dd8d1ff69 /chromium/tools/generate_stubs/generate_stubs_unittest.py
Initial import.
Diffstat (limited to 'chromium/tools/generate_stubs/generate_stubs_unittest.py')
-rwxr-xr-xchromium/tools/generate_stubs/generate_stubs_unittest.py297
1 files changed, 297 insertions, 0 deletions
diff --git a/chromium/tools/generate_stubs/generate_stubs_unittest.py b/chromium/tools/generate_stubs/generate_stubs_unittest.py
new file mode 100755
index 00000000000..13a2bc15e59
--- /dev/null
+++ b/chromium/tools/generate_stubs/generate_stubs_unittest.py
@@ -0,0 +1,297 @@
+#!/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.
+
+"""Unittest for the generate_stubs.py.
+
+Since generate_stubs.py is a code generator, it is hard to do a very good
+test. Instead of creating a golden-file test, which might be flakey, this
+test elects instead to verify that various components "exist" within the
+generated file as a sanity check. In particular, there is a simple hit
+test to make sure that umbrella functions, etc., do try and include every
+function they are responsible for invoking. Missing an invocation is quite
+easily missed.
+
+There is no attempt to verify ordering of different components, or whether
+or not those components are going to parse incorrectly because of prior
+errors or positioning. Most of that should be caught really fast anyways
+during any attempt to use a badly behaving script.
+"""
+
+import generate_stubs as gs
+import re
+import StringIO
+import sys
+import unittest
+
+
+def _MakeSignature(return_type, name, params):
+ return {'return_type': return_type,
+ 'name': name,
+ 'params': params}
+
+
+SIMPLE_SIGNATURES = [
+ ('int foo(int a)', _MakeSignature('int', 'foo', ['int a'])),
+ ('int bar(int a, double b)', _MakeSignature('int', 'bar',
+ ['int a', 'double b'])),
+ ('int baz(void)', _MakeSignature('int', 'baz', ['void'])),
+ ('void quux(void)', _MakeSignature('void', 'quux', ['void'])),
+ ('void waldo(void);', _MakeSignature('void', 'waldo', ['void'])),
+ ('int corge(void);', _MakeSignature('int', 'corge', ['void'])),
+ ]
+
+TRICKY_SIGNATURES = [
+ ('const struct name *foo(int a, struct Test* b); ',
+ _MakeSignature('const struct name *',
+ 'foo',
+ ['int a', 'struct Test* b'])),
+ ('const struct name &foo(int a, struct Test* b);',
+ _MakeSignature('const struct name &',
+ 'foo',
+ ['int a', 'struct Test* b'])),
+ ('const struct name &_foo(int a, struct Test* b);',
+ _MakeSignature('const struct name &',
+ '_foo',
+ ['int a', 'struct Test* b'])),
+ ('struct name const * const _foo(int a, struct Test* b) '
+ '__attribute__((inline));',
+ _MakeSignature('struct name const * const',
+ '_foo',
+ ['int a', 'struct Test* b']))
+ ]
+
+INVALID_SIGNATURES = ['I am bad', 'Seriously bad(', ';;;']
+
+
+class GenerateStubModuleFunctionsUnittest(unittest.TestCase):
+ def testExtractModuleName(self):
+ self.assertEqual('somefile-2', gs.ExtractModuleName('somefile-2.ext'))
+
+ def testParseSignatures_EmptyFile(self):
+ # Empty file just generates empty signatures.
+ infile = StringIO.StringIO()
+ signatures = gs.ParseSignatures(infile)
+ self.assertEqual(0, len(signatures))
+
+ def testParseSignatures_SimpleSignatures(self):
+ file_contents = '\n'.join([x[0] for x in SIMPLE_SIGNATURES])
+ infile = StringIO.StringIO(file_contents)
+ signatures = gs.ParseSignatures(infile)
+ self.assertEqual(len(SIMPLE_SIGNATURES), len(signatures))
+
+ # We assume signatures are in order.
+ for i in xrange(len(SIMPLE_SIGNATURES)):
+ self.assertEqual(SIMPLE_SIGNATURES[i][1], signatures[i],
+ msg='Expected %s\nActual %s\nFor %s' %
+ (SIMPLE_SIGNATURES[i][1],
+ signatures[i],
+ SIMPLE_SIGNATURES[i][0]))
+
+ def testParseSignatures_TrickySignatures(self):
+ file_contents = '\n'.join([x[0] for x in TRICKY_SIGNATURES])
+ infile = StringIO.StringIO(file_contents)
+ signatures = gs.ParseSignatures(infile)
+ self.assertEqual(len(TRICKY_SIGNATURES), len(signatures))
+
+ # We assume signatures are in order.
+ for i in xrange(len(TRICKY_SIGNATURES)):
+ self.assertEqual(TRICKY_SIGNATURES[i][1], signatures[i],
+ msg='Expected %s\nActual %s\nFor %s' %
+ (TRICKY_SIGNATURES[i][1],
+ signatures[i],
+ TRICKY_SIGNATURES[i][0]))
+
+ def testParseSignatures_InvalidSignatures(self):
+ for i in INVALID_SIGNATURES:
+ infile = StringIO.StringIO(i)
+ self.assertRaises(gs.BadSignatureError, gs.ParseSignatures, infile)
+
+ def testParseSignatures_CommentsIgnored(self):
+ my_sigs = []
+ my_sigs.append('# a comment')
+ my_sigs.append(SIMPLE_SIGNATURES[0][0])
+ my_sigs.append('# another comment')
+ my_sigs.append(SIMPLE_SIGNATURES[0][0])
+ my_sigs.append('# a third comment')
+ my_sigs.append(SIMPLE_SIGNATURES[0][0])
+
+ file_contents = '\n'.join(my_sigs)
+ infile = StringIO.StringIO(file_contents)
+ signatures = gs.ParseSignatures(infile)
+ self.assertEqual(3, len(signatures))
+
+
+class WindowsLibUnittest(unittest.TestCase):
+ def testWriteWindowsDefFile(self):
+ module_name = 'my_module-1'
+ signatures = [sig[1] for sig in SIMPLE_SIGNATURES]
+ outfile = StringIO.StringIO()
+ gs.WriteWindowsDefFile(module_name, signatures, outfile)
+ contents = outfile.getvalue()
+
+ # Check that the file header is correct.
+ self.assertTrue(contents.startswith("""LIBRARY %s
+EXPORTS
+""" % module_name))
+
+ # Check that the signatures were exported.
+ for sig in signatures:
+ pattern = '\n %s\n' % sig['name']
+ self.assertTrue(re.search(pattern, contents),
+ msg='Expected match of "%s" in %s' % (pattern, contents))
+
+ def testQuietRun(self):
+ output = StringIO.StringIO()
+ gs.QuietRun([sys.executable,
+ '-c', 'print "line 1 and suffix\\nline 2"'],
+ write_to=output)
+ self.assertEqual('line 1 and suffix\nline 2\n', output.getvalue())
+
+ output = StringIO.StringIO()
+ gs.QuietRun([sys.executable,
+ '-c', 'print "line 1 and suffix\\nline 2"'],
+ filter='line 1', write_to=output)
+ self.assertEqual('line 2\n', output.getvalue())
+
+
+class PosixStubWriterUnittest(unittest.TestCase):
+ def setUp(self):
+ self.module_name = 'my_module-1'
+ self.signatures = [sig[1] for sig in SIMPLE_SIGNATURES]
+ self.out_dir = 'out_dir'
+ self.writer = gs.PosixStubWriter(self.module_name, self.signatures)
+
+ def testEnumName(self):
+ self.assertEqual('kModuleMy_module1',
+ gs.PosixStubWriter.EnumName(self.module_name))
+
+ def testIsInitializedName(self):
+ self.assertEqual('IsMy_module1Initialized',
+ gs.PosixStubWriter.IsInitializedName(self.module_name))
+
+ def testInitializeModuleName(self):
+ self.assertEqual(
+ 'InitializeMy_module1',
+ gs.PosixStubWriter.InitializeModuleName(self.module_name))
+
+ def testUninitializeModuleName(self):
+ self.assertEqual(
+ 'UninitializeMy_module1',
+ gs.PosixStubWriter.UninitializeModuleName(self.module_name))
+
+ def testStubFunctionPointer(self):
+ self.assertEqual(
+ 'static int (*foo_ptr)(int a) = NULL;',
+ gs.PosixStubWriter.StubFunctionPointer(SIMPLE_SIGNATURES[0][1]))
+
+ def testStubFunction(self):
+ # Test for a signature with a return value and a parameter.
+ self.assertEqual("""extern int foo(int a) __attribute__((weak));
+int foo(int a) {
+ return foo_ptr(a);
+}""", gs.PosixStubWriter.StubFunction(SIMPLE_SIGNATURES[0][1]))
+
+ # Test for a signature with a void return value and no parameters.
+ self.assertEqual("""extern void waldo(void) __attribute__((weak));
+void waldo(void) {
+ waldo_ptr();
+}""", gs.PosixStubWriter.StubFunction(SIMPLE_SIGNATURES[4][1]))
+
+ def testWriteImplemenationContents(self):
+ outfile = StringIO.StringIO()
+ self.writer.WriteImplementationContents('my_namespace', outfile)
+ contents = outfile.getvalue()
+
+ # Verify namespace exists somewhere.
+ self.assertTrue(contents.find('namespace my_namespace {') != -1)
+
+ # Verify that each signature has an _ptr and a function call in the file.
+ # Check that the signatures were exported.
+ for sig in self.signatures:
+ decl = gs.PosixStubWriter.StubFunctionPointer(sig)
+ self.assertTrue(contents.find(decl) != -1,
+ msg='Expected "%s" in %s' % (decl, contents))
+
+ # Verify that each signature has an stub function generated for it.
+ for sig in self.signatures:
+ decl = gs.PosixStubWriter.StubFunction(sig)
+ self.assertTrue(contents.find(decl) != -1,
+ msg='Expected "%s" in %s' % (decl, contents))
+
+ # Find module initializer functions. Make sure all 3 exist.
+ decl = gs.PosixStubWriter.InitializeModuleName(self.module_name)
+ self.assertTrue(contents.find(decl) != -1,
+ msg='Expected "%s" in %s' % (decl, contents))
+ decl = gs.PosixStubWriter.UninitializeModuleName(self.module_name)
+ self.assertTrue(contents.find(decl) != -1,
+ msg='Expected "%s" in %s' % (decl, contents))
+ decl = gs.PosixStubWriter.IsInitializedName(self.module_name)
+ self.assertTrue(contents.find(decl) != -1,
+ msg='Expected "%s" in %s' % (decl, contents))
+
+ def testWriteHeaderContents(self):
+ # Data for header generation.
+ module_names = ['oneModule', 'twoModule']
+
+ # Make the header.
+ outfile = StringIO.StringIO()
+ self.writer.WriteHeaderContents(module_names, 'my_namespace', 'GUARD_',
+ outfile)
+ contents = outfile.getvalue()
+
+ # Check for namespace and header guard.
+ self.assertTrue(contents.find('namespace my_namespace {') != -1)
+ self.assertTrue(contents.find('#ifndef GUARD_') != -1)
+
+ # Check for umbrella initializer.
+ self.assertTrue(contents.find('InitializeStubs(') != -1)
+
+ # Check per-module declarations.
+ for name in module_names:
+ # Check for enums.
+ decl = gs.PosixStubWriter.EnumName(name)
+ self.assertTrue(contents.find(decl) != -1,
+ msg='Expected "%s" in %s' % (decl, contents))
+
+ # Check for module initializer functions.
+ decl = gs.PosixStubWriter.IsInitializedName(name)
+ self.assertTrue(contents.find(decl) != -1,
+ msg='Expected "%s" in %s' % (decl, contents))
+ decl = gs.PosixStubWriter.InitializeModuleName(name)
+ self.assertTrue(contents.find(decl) != -1,
+ msg='Expected "%s" in %s' % (decl, contents))
+ decl = gs.PosixStubWriter.UninitializeModuleName(name)
+ self.assertTrue(contents.find(decl) != -1,
+ msg='Expected "%s" in %s' % (decl, contents))
+
+ def testWriteUmbrellaInitializer(self):
+ # Data for header generation.
+ module_names = ['oneModule', 'twoModule']
+
+ # Make the header.
+ outfile = StringIO.StringIO()
+ self.writer.WriteUmbrellaInitializer(module_names, 'my_namespace', outfile)
+ contents = outfile.getvalue()
+
+ # Check for umbrella initializer declaration.
+ self.assertTrue(contents.find('bool InitializeStubs(') != -1)
+
+ # If the umbrella initializer is correctly written, each module will have
+ # its initializer called, checked, and uninitialized on failure. Sanity
+ # check that here.
+ for name in module_names:
+ # Check for module initializer functions.
+ decl = gs.PosixStubWriter.IsInitializedName(name)
+ self.assertTrue(contents.find(decl) != -1,
+ msg='Expected "%s" in %s' % (decl, contents))
+ decl = gs.PosixStubWriter.InitializeModuleName(name)
+ self.assertTrue(contents.find(decl) != -1,
+ msg='Expected "%s" in %s' % (decl, contents))
+ decl = gs.PosixStubWriter.UninitializeModuleName(name)
+ self.assertTrue(contents.find(decl) != -1,
+ msg='Expected "%s" in %s' % (decl, contents))
+
+if __name__ == '__main__':
+ unittest.main()