Home | History | Annotate | Download | only in cpp
      1 #!/usr/bin/env python
      2 #
      3 # Copyright 2009 Neal Norwitz All Rights Reserved.
      4 # Portions Copyright 2009 Google Inc. All Rights Reserved.
      5 #
      6 # Licensed under the Apache License, Version 2.0 (the "License");
      7 # you may not use this file except in compliance with the License.
      8 # You may obtain a copy of the License at
      9 #
     10 #      http://www.apache.org/licenses/LICENSE-2.0
     11 #
     12 # Unless required by applicable law or agreed to in writing, software
     13 # distributed under the License is distributed on an "AS IS" BASIS,
     14 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     15 # See the License for the specific language governing permissions and
     16 # limitations under the License.
     17 
     18 """Tests for gmock.scripts.generator.cpp.gmock_class."""
     19 
     20 __author__ = 'nnorwitz (at] google.com (Neal Norwitz)'
     21 
     22 
     23 import os
     24 import sys
     25 import unittest
     26 
     27 # Allow the cpp imports below to work when run as a standalone script.
     28 sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
     29 
     30 from cpp import ast
     31 from cpp import gmock_class
     32 
     33 
     34 class TestCase(unittest.TestCase):
     35   """Helper class that adds assert methods."""
     36 
     37   def StripLeadingWhitespace(self, lines):
     38     """Strip leading whitespace in each line in 'lines'."""
     39     return '\n'.join([s.lstrip() for s in lines.split('\n')])
     40 
     41   def assertEqualIgnoreLeadingWhitespace(self, expected_lines, lines):
     42     """Specialized assert that ignores the indent level."""
     43     self.assertEqual(expected_lines, self.StripLeadingWhitespace(lines))
     44 
     45 
     46 class GenerateMethodsTest(TestCase):
     47 
     48   def GenerateMethodSource(self, cpp_source):
     49     """Convert C++ source to Google Mock output source lines."""
     50     method_source_lines = []
     51     # <test> is a pseudo-filename, it is not read or written.
     52     builder = ast.BuilderFromSource(cpp_source, '<test>')
     53     ast_list = list(builder.Generate())
     54     gmock_class._GenerateMethods(method_source_lines, cpp_source, ast_list[0])
     55     return '\n'.join(method_source_lines)
     56 
     57   def testSimpleMethod(self):
     58     source = """
     59 class Foo {
     60  public:
     61   virtual int Bar();
     62 };
     63 """
     64     self.assertEqualIgnoreLeadingWhitespace(
     65         'MOCK_METHOD0(Bar,\nint());',
     66         self.GenerateMethodSource(source))
     67 
     68   def testSimpleConstMethod(self):
     69     source = """
     70 class Foo {
     71  public:
     72   virtual void Bar(bool flag) const;
     73 };
     74 """
     75     self.assertEqualIgnoreLeadingWhitespace(
     76         'MOCK_CONST_METHOD1(Bar,\nvoid(bool flag));',
     77         self.GenerateMethodSource(source))
     78 
     79   def testStrangeNewlineInParameter(self):
     80     source = """
     81 class Foo {
     82  public:
     83   virtual void Bar(int
     84 a) = 0;
     85 };
     86 """
     87     self.assertEqualIgnoreLeadingWhitespace(
     88         'MOCK_METHOD1(Bar,\nvoid(int a));',
     89         self.GenerateMethodSource(source))
     90 
     91   def testDoubleSlashCommentsInParameterListAreRemoved(self):
     92     source = """
     93 class Foo {
     94  public:
     95   virtual void Bar(int a,  // inline comments should be elided.
     96                    int b   // inline comments should be elided.
     97                    ) const = 0;
     98 };
     99 """
    100     self.assertEqualIgnoreLeadingWhitespace(
    101         'MOCK_CONST_METHOD2(Bar,\nvoid(int a, int b));',
    102         self.GenerateMethodSource(source))
    103 
    104   def testCStyleCommentsInParameterListAreNotRemoved(self):
    105     # NOTE(nnorwitz): I'm not sure if it's the best behavior to keep these
    106     # comments.  Also note that C style comments after the last parameter
    107     # are still elided.
    108     source = """
    109 class Foo {
    110  public:
    111   virtual const string& Bar(int /* keeper */, int b);
    112 };
    113 """
    114     self.assertEqualIgnoreLeadingWhitespace(
    115         'MOCK_METHOD2(Bar,\nconst string&(int /* keeper */, int b));',
    116         self.GenerateMethodSource(source))
    117 
    118   def testArgsOfTemplateTypes(self):
    119     source = """
    120 class Foo {
    121  public:
    122   virtual int Bar(const vector<int>& v, map<int, string>* output);
    123 };"""
    124     self.assertEqualIgnoreLeadingWhitespace(
    125         'MOCK_METHOD2(Bar,\n'
    126         'int(const vector<int>& v, map<int, string>* output));',
    127         self.GenerateMethodSource(source))
    128 
    129   def testReturnTypeWithOneTemplateArg(self):
    130     source = """
    131 class Foo {
    132  public:
    133   virtual vector<int>* Bar(int n);
    134 };"""
    135     self.assertEqualIgnoreLeadingWhitespace(
    136         'MOCK_METHOD1(Bar,\nvector<int>*(int n));',
    137         self.GenerateMethodSource(source))
    138 
    139   def testReturnTypeWithManyTemplateArgs(self):
    140     source = """
    141 class Foo {
    142  public:
    143   virtual map<int, string> Bar();
    144 };"""
    145     # Comparing the comment text is brittle - we'll think of something
    146     # better in case this gets annoying, but for now let's keep it simple.
    147     self.assertEqualIgnoreLeadingWhitespace(
    148         '// The following line won\'t really compile, as the return\n'
    149         '// type has multiple template arguments.  To fix it, use a\n'
    150         '// typedef for the return type.\n'
    151         'MOCK_METHOD0(Bar,\nmap<int, string>());',
    152         self.GenerateMethodSource(source))
    153 
    154 
    155 class GenerateMocksTest(TestCase):
    156 
    157   def GenerateMocks(self, cpp_source):
    158     """Convert C++ source to complete Google Mock output source."""
    159     # <test> is a pseudo-filename, it is not read or written.
    160     filename = '<test>'
    161     builder = ast.BuilderFromSource(cpp_source, filename)
    162     ast_list = list(builder.Generate())
    163     lines = gmock_class._GenerateMocks(filename, cpp_source, ast_list, None)
    164     return '\n'.join(lines)
    165 
    166   def testNamespaces(self):
    167     source = """
    168 namespace Foo {
    169 namespace Bar { class Forward; }
    170 namespace Baz {
    171 
    172 class Test {
    173  public:
    174   virtual void Foo();
    175 };
    176 
    177 }  // namespace Baz
    178 }  // namespace Foo
    179 """
    180     expected = """\
    181 namespace Foo {
    182 namespace Baz {
    183 
    184 class MockTest : public Test {
    185 public:
    186 MOCK_METHOD0(Foo,
    187 void());
    188 };
    189 
    190 }  // namespace Baz
    191 }  // namespace Foo
    192 """
    193     self.assertEqualIgnoreLeadingWhitespace(
    194         expected, self.GenerateMocks(source))
    195 
    196   def testClassWithStorageSpecifierMacro(self):
    197     source = """
    198 class STORAGE_SPECIFIER Test {
    199  public:
    200   virtual void Foo();
    201 };
    202 """
    203     expected = """\
    204 class MockTest : public Test {
    205 public:
    206 MOCK_METHOD0(Foo,
    207 void());
    208 };
    209 """
    210     self.assertEqualIgnoreLeadingWhitespace(
    211         expected, self.GenerateMocks(source))
    212 
    213 if __name__ == '__main__':
    214   unittest.main()
    215