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 testSimpleConstructorsAndDestructor(self):
     69     source = """
     70 class Foo {
     71  public:
     72   Foo();
     73   Foo(int x);
     74   Foo(const Foo& f);
     75   Foo(Foo&& f);
     76   ~Foo();
     77   virtual int Bar() = 0;
     78 };
     79 """
     80     # The constructors and destructor should be ignored.
     81     self.assertEqualIgnoreLeadingWhitespace(
     82         'MOCK_METHOD0(Bar,\nint());',
     83         self.GenerateMethodSource(source))
     84 
     85   def testVirtualDestructor(self):
     86     source = """
     87 class Foo {
     88  public:
     89   virtual ~Foo();
     90   virtual int Bar() = 0;
     91 };
     92 """
     93     # The destructor should be ignored.
     94     self.assertEqualIgnoreLeadingWhitespace(
     95         'MOCK_METHOD0(Bar,\nint());',
     96         self.GenerateMethodSource(source))
     97 
     98   def testExplicitlyDefaultedConstructorsAndDestructor(self):
     99     source = """
    100 class Foo {
    101  public:
    102   Foo() = default;
    103   Foo(const Foo& f) = default;
    104   Foo(Foo&& f) = default;
    105   ~Foo() = default;
    106   virtual int Bar() = 0;
    107 };
    108 """
    109     # The constructors and destructor should be ignored.
    110     self.assertEqualIgnoreLeadingWhitespace(
    111         'MOCK_METHOD0(Bar,\nint());',
    112         self.GenerateMethodSource(source))
    113 
    114   def testExplicitlyDeletedConstructorsAndDestructor(self):
    115     source = """
    116 class Foo {
    117  public:
    118   Foo() = delete;
    119   Foo(const Foo& f) = delete;
    120   Foo(Foo&& f) = delete;
    121   ~Foo() = delete;
    122   virtual int Bar() = 0;
    123 };
    124 """
    125     # The constructors and destructor should be ignored.
    126     self.assertEqualIgnoreLeadingWhitespace(
    127         'MOCK_METHOD0(Bar,\nint());',
    128         self.GenerateMethodSource(source))
    129 
    130   def testSimpleOverrideMethod(self):
    131     source = """
    132 class Foo {
    133  public:
    134   int Bar() override;
    135 };
    136 """
    137     self.assertEqualIgnoreLeadingWhitespace(
    138         'MOCK_METHOD0(Bar,\nint());',
    139         self.GenerateMethodSource(source))
    140 
    141   def testSimpleConstMethod(self):
    142     source = """
    143 class Foo {
    144  public:
    145   virtual void Bar(bool flag) const;
    146 };
    147 """
    148     self.assertEqualIgnoreLeadingWhitespace(
    149         'MOCK_CONST_METHOD1(Bar,\nvoid(bool flag));',
    150         self.GenerateMethodSource(source))
    151 
    152   def testExplicitVoid(self):
    153     source = """
    154 class Foo {
    155  public:
    156   virtual int Bar(void);
    157 };
    158 """
    159     self.assertEqualIgnoreLeadingWhitespace(
    160         'MOCK_METHOD0(Bar,\nint(void));',
    161         self.GenerateMethodSource(source))
    162 
    163   def testStrangeNewlineInParameter(self):
    164     source = """
    165 class Foo {
    166  public:
    167   virtual void Bar(int
    168 a) = 0;
    169 };
    170 """
    171     self.assertEqualIgnoreLeadingWhitespace(
    172         'MOCK_METHOD1(Bar,\nvoid(int a));',
    173         self.GenerateMethodSource(source))
    174 
    175   def testDefaultParameters(self):
    176     source = """
    177 class Foo {
    178  public:
    179   virtual void Bar(int a, char c = 'x') = 0;
    180 };
    181 """
    182     self.assertEqualIgnoreLeadingWhitespace(
    183         'MOCK_METHOD2(Bar,\nvoid(int, char));',
    184         self.GenerateMethodSource(source))
    185 
    186   def testMultipleDefaultParameters(self):
    187     source = """
    188 class Foo {
    189  public:
    190   virtual void Bar(int a = 42, char c = 'x') = 0;
    191 };
    192 """
    193     self.assertEqualIgnoreLeadingWhitespace(
    194         'MOCK_METHOD2(Bar,\nvoid(int, char));',
    195         self.GenerateMethodSource(source))
    196 
    197   def testRemovesCommentsWhenDefaultsArePresent(self):
    198     source = """
    199 class Foo {
    200  public:
    201   virtual void Bar(int a = 42 /* a comment */,
    202                    char /* other comment */ c= 'x') = 0;
    203 };
    204 """
    205     self.assertEqualIgnoreLeadingWhitespace(
    206         'MOCK_METHOD2(Bar,\nvoid(int, char));',
    207         self.GenerateMethodSource(source))
    208 
    209   def testDoubleSlashCommentsInParameterListAreRemoved(self):
    210     source = """
    211 class Foo {
    212  public:
    213   virtual void Bar(int a,  // inline comments should be elided.
    214                    int b   // inline comments should be elided.
    215                    ) const = 0;
    216 };
    217 """
    218     self.assertEqualIgnoreLeadingWhitespace(
    219         'MOCK_CONST_METHOD2(Bar,\nvoid(int a, int b));',
    220         self.GenerateMethodSource(source))
    221 
    222   def testCStyleCommentsInParameterListAreNotRemoved(self):
    223     # NOTE(nnorwitz): I'm not sure if it's the best behavior to keep these
    224     # comments.  Also note that C style comments after the last parameter
    225     # are still elided.
    226     source = """
    227 class Foo {
    228  public:
    229   virtual const string& Bar(int /* keeper */, int b);
    230 };
    231 """
    232     self.assertEqualIgnoreLeadingWhitespace(
    233         'MOCK_METHOD2(Bar,\nconst string&(int /* keeper */, int b));',
    234         self.GenerateMethodSource(source))
    235 
    236   def testArgsOfTemplateTypes(self):
    237     source = """
    238 class Foo {
    239  public:
    240   virtual int Bar(const vector<int>& v, map<int, string>* output);
    241 };"""
    242     self.assertEqualIgnoreLeadingWhitespace(
    243         'MOCK_METHOD2(Bar,\n'
    244         'int(const vector<int>& v, map<int, string>* output));',
    245         self.GenerateMethodSource(source))
    246 
    247   def testReturnTypeWithOneTemplateArg(self):
    248     source = """
    249 class Foo {
    250  public:
    251   virtual vector<int>* Bar(int n);
    252 };"""
    253     self.assertEqualIgnoreLeadingWhitespace(
    254         'MOCK_METHOD1(Bar,\nvector<int>*(int n));',
    255         self.GenerateMethodSource(source))
    256 
    257   def testReturnTypeWithManyTemplateArgs(self):
    258     source = """
    259 class Foo {
    260  public:
    261   virtual map<int, string> Bar();
    262 };"""
    263     # Comparing the comment text is brittle - we'll think of something
    264     # better in case this gets annoying, but for now let's keep it simple.
    265     self.assertEqualIgnoreLeadingWhitespace(
    266         '// The following line won\'t really compile, as the return\n'
    267         '// type has multiple template arguments.  To fix it, use a\n'
    268         '// typedef for the return type.\n'
    269         'MOCK_METHOD0(Bar,\nmap<int, string>());',
    270         self.GenerateMethodSource(source))
    271 
    272   def testSimpleMethodInTemplatedClass(self):
    273     source = """
    274 template<class T>
    275 class Foo {
    276  public:
    277   virtual int Bar();
    278 };
    279 """
    280     self.assertEqualIgnoreLeadingWhitespace(
    281         'MOCK_METHOD0_T(Bar,\nint());',
    282         self.GenerateMethodSource(source))
    283 
    284   def testPointerArgWithoutNames(self):
    285     source = """
    286 class Foo {
    287   virtual int Bar(C*);
    288 };
    289 """
    290     self.assertEqualIgnoreLeadingWhitespace(
    291         'MOCK_METHOD1(Bar,\nint(C*));',
    292         self.GenerateMethodSource(source))
    293 
    294   def testReferenceArgWithoutNames(self):
    295     source = """
    296 class Foo {
    297   virtual int Bar(C&);
    298 };
    299 """
    300     self.assertEqualIgnoreLeadingWhitespace(
    301         'MOCK_METHOD1(Bar,\nint(C&));',
    302         self.GenerateMethodSource(source))
    303 
    304   def testArrayArgWithoutNames(self):
    305     source = """
    306 class Foo {
    307   virtual int Bar(C[]);
    308 };
    309 """
    310     self.assertEqualIgnoreLeadingWhitespace(
    311         'MOCK_METHOD1(Bar,\nint(C[]));',
    312         self.GenerateMethodSource(source))
    313 
    314 
    315 class GenerateMocksTest(TestCase):
    316 
    317   def GenerateMocks(self, cpp_source):
    318     """Convert C++ source to complete Google Mock output source."""
    319     # <test> is a pseudo-filename, it is not read or written.
    320     filename = '<test>'
    321     builder = ast.BuilderFromSource(cpp_source, filename)
    322     ast_list = list(builder.Generate())
    323     lines = gmock_class._GenerateMocks(filename, cpp_source, ast_list, None)
    324     return '\n'.join(lines)
    325 
    326   def testNamespaces(self):
    327     source = """
    328 namespace Foo {
    329 namespace Bar { class Forward; }
    330 namespace Baz {
    331 
    332 class Test {
    333  public:
    334   virtual void Foo();
    335 };
    336 
    337 }  // namespace Baz
    338 }  // namespace Foo
    339 """
    340     expected = """\
    341 namespace Foo {
    342 namespace Baz {
    343 
    344 class MockTest : public Test {
    345 public:
    346 MOCK_METHOD0(Foo,
    347 void());
    348 };
    349 
    350 }  // namespace Baz
    351 }  // namespace Foo
    352 """
    353     self.assertEqualIgnoreLeadingWhitespace(
    354         expected, self.GenerateMocks(source))
    355 
    356   def testClassWithStorageSpecifierMacro(self):
    357     source = """
    358 class STORAGE_SPECIFIER Test {
    359  public:
    360   virtual void Foo();
    361 };
    362 """
    363     expected = """\
    364 class MockTest : public Test {
    365 public:
    366 MOCK_METHOD0(Foo,
    367 void());
    368 };
    369 """
    370     self.assertEqualIgnoreLeadingWhitespace(
    371         expected, self.GenerateMocks(source))
    372 
    373   def testTemplatedForwardDeclaration(self):
    374     source = """
    375 template <class T> class Forward;  // Forward declaration should be ignored.
    376 class Test {
    377  public:
    378   virtual void Foo();
    379 };
    380 """
    381     expected = """\
    382 class MockTest : public Test {
    383 public:
    384 MOCK_METHOD0(Foo,
    385 void());
    386 };
    387 """
    388     self.assertEqualIgnoreLeadingWhitespace(
    389         expected, self.GenerateMocks(source))
    390 
    391   def testTemplatedClass(self):
    392     source = """
    393 template <typename S, typename T>
    394 class Test {
    395  public:
    396   virtual void Foo();
    397 };
    398 """
    399     expected = """\
    400 template <typename T0, typename T1>
    401 class MockTest : public Test<T0, T1> {
    402 public:
    403 MOCK_METHOD0_T(Foo,
    404 void());
    405 };
    406 """
    407     self.assertEqualIgnoreLeadingWhitespace(
    408         expected, self.GenerateMocks(source))
    409 
    410   def testTemplateInATemplateTypedef(self):
    411     source = """
    412 class Test {
    413  public:
    414   typedef std::vector<std::list<int>> FooType;
    415   virtual void Bar(const FooType& test_arg);
    416 };
    417 """
    418     expected = """\
    419 class MockTest : public Test {
    420 public:
    421 MOCK_METHOD1(Bar,
    422 void(const FooType& test_arg));
    423 };
    424 """
    425     self.assertEqualIgnoreLeadingWhitespace(
    426         expected, self.GenerateMocks(source))
    427 
    428   def testTemplateInATemplateTypedefWithComma(self):
    429     source = """
    430 class Test {
    431  public:
    432   typedef std::function<void(
    433       const vector<std::list<int>>&, int> FooType;
    434   virtual void Bar(const FooType& test_arg);
    435 };
    436 """
    437     expected = """\
    438 class MockTest : public Test {
    439 public:
    440 MOCK_METHOD1(Bar,
    441 void(const FooType& test_arg));
    442 };
    443 """
    444     self.assertEqualIgnoreLeadingWhitespace(
    445         expected, self.GenerateMocks(source))
    446 
    447 if __name__ == '__main__':
    448   unittest.main()
    449