/tools/generate_stubs/generate_stubs_unittest.py
Python | 325 lines | 316 code | 1 blank | 8 comment | 2 complexity | a54ddc9d83865d9f38be8338414d2322 MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception, Apache-2.0, BSD-3-Clause
- #!/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 flaky, 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'])),
- ('int ferda(char **argv[]);',
- _MakeSignature('int', 'ferda', ['char **argv[]'])),
- ]
- 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])
- my_sigs.append('// a fourth comment')
- my_sigs.append(SIMPLE_SIGNATURES[0][0])
- my_sigs.append('//')
- my_sigs.append(SIMPLE_SIGNATURES[0][0])
- file_contents = '\n'.join(my_sigs)
- infile = StringIO.StringIO(file_contents)
- signatures = gs.ParseSignatures(infile)
- self.assertEqual(5, 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',
- 'from __future__ import print_function; 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',
- 'from __future__ import print_function; 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,
- 'VLOG(1)', 'base/logging.h')
- 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]))
- # Test export macros.
- sig = _MakeSignature('int*', 'foo', ['bool b'])
- sig['export'] = 'TEST_EXPORT'
- self.assertEqual("""extern int* foo(bool b) __attribute__((weak));
- int* TEST_EXPORT foo(bool b) {
- return foo_ptr(b);
- }""", gs.PosixStubWriter.StubFunction(sig))
- # Test for a signature where an array is passed. It should be passed without
- # square brackets otherwise the compilation failure will occur..
- self.assertEqual("""extern int ferda(char **argv[]) __attribute__((weak));
- int ferda(char **argv[]) {
- return ferda_ptr(argv);
- }""", gs.PosixStubWriter.StubFunction(SIMPLE_SIGNATURES[6][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, 'base/logging.h')
- 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,
- 'VLOG(1)')
- 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()