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