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@google.com (Neal Norwitz)' 21 22 23import os 24import sys 25import unittest 26 27# Allow the cpp imports below to work when run as a standalone script. 28sys.path.append(os.path.join(os.path.dirname(__file__), '..')) 29 30from cpp import ast 31from cpp import gmock_class 32 33 34class 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 46class 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 = """ 59class 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 = """ 70class 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 testExplicitVoid(self): 80 source = """ 81class Foo { 82 public: 83 virtual int Bar(void); 84}; 85""" 86 self.assertEqualIgnoreLeadingWhitespace( 87 'MOCK_METHOD0(Bar,\nint(void));', 88 self.GenerateMethodSource(source)) 89 90 def testStrangeNewlineInParameter(self): 91 source = """ 92class Foo { 93 public: 94 virtual void Bar(int 95a) = 0; 96}; 97""" 98 self.assertEqualIgnoreLeadingWhitespace( 99 'MOCK_METHOD1(Bar,\nvoid(int a));', 100 self.GenerateMethodSource(source)) 101 102 def testDefaultParameters(self): 103 source = """ 104class Foo { 105 public: 106 virtual void Bar(int a, char c = 'x') = 0; 107}; 108""" 109 self.assertEqualIgnoreLeadingWhitespace( 110 'MOCK_METHOD2(Bar,\nvoid(int, char));', 111 self.GenerateMethodSource(source)) 112 113 def testMultipleDefaultParameters(self): 114 source = """ 115class Foo { 116 public: 117 virtual void Bar(int a = 42, char c = 'x') = 0; 118}; 119""" 120 self.assertEqualIgnoreLeadingWhitespace( 121 'MOCK_METHOD2(Bar,\nvoid(int, char));', 122 self.GenerateMethodSource(source)) 123 124 def testRemovesCommentsWhenDefaultsArePresent(self): 125 source = """ 126class Foo { 127 public: 128 virtual void Bar(int a = 42 /* a comment */, 129 char /* other comment */ c= 'x') = 0; 130}; 131""" 132 self.assertEqualIgnoreLeadingWhitespace( 133 'MOCK_METHOD2(Bar,\nvoid(int, char));', 134 self.GenerateMethodSource(source)) 135 136 def testDoubleSlashCommentsInParameterListAreRemoved(self): 137 source = """ 138class Foo { 139 public: 140 virtual void Bar(int a, // inline comments should be elided. 141 int b // inline comments should be elided. 142 ) const = 0; 143}; 144""" 145 self.assertEqualIgnoreLeadingWhitespace( 146 'MOCK_CONST_METHOD2(Bar,\nvoid(int a, int b));', 147 self.GenerateMethodSource(source)) 148 149 def testCStyleCommentsInParameterListAreNotRemoved(self): 150 # NOTE(nnorwitz): I'm not sure if it's the best behavior to keep these 151 # comments. Also note that C style comments after the last parameter 152 # are still elided. 153 source = """ 154class Foo { 155 public: 156 virtual const string& Bar(int /* keeper */, int b); 157}; 158""" 159 self.assertEqualIgnoreLeadingWhitespace( 160 'MOCK_METHOD2(Bar,\nconst string&(int /* keeper */, int b));', 161 self.GenerateMethodSource(source)) 162 163 def testArgsOfTemplateTypes(self): 164 source = """ 165class Foo { 166 public: 167 virtual int Bar(const vector<int>& v, map<int, string>* output); 168};""" 169 self.assertEqualIgnoreLeadingWhitespace( 170 'MOCK_METHOD2(Bar,\n' 171 'int(const vector<int>& v, map<int, string>* output));', 172 self.GenerateMethodSource(source)) 173 174 def testReturnTypeWithOneTemplateArg(self): 175 source = """ 176class Foo { 177 public: 178 virtual vector<int>* Bar(int n); 179};""" 180 self.assertEqualIgnoreLeadingWhitespace( 181 'MOCK_METHOD1(Bar,\nvector<int>*(int n));', 182 self.GenerateMethodSource(source)) 183 184 def testReturnTypeWithManyTemplateArgs(self): 185 source = """ 186class Foo { 187 public: 188 virtual map<int, string> Bar(); 189};""" 190 # Comparing the comment text is brittle - we'll think of something 191 # better in case this gets annoying, but for now let's keep it simple. 192 self.assertEqualIgnoreLeadingWhitespace( 193 '// The following line won\'t really compile, as the return\n' 194 '// type has multiple template arguments. To fix it, use a\n' 195 '// typedef for the return type.\n' 196 'MOCK_METHOD0(Bar,\nmap<int, string>());', 197 self.GenerateMethodSource(source)) 198 199 200class GenerateMocksTest(TestCase): 201 202 def GenerateMocks(self, cpp_source): 203 """Convert C++ source to complete Google Mock output source.""" 204 # <test> is a pseudo-filename, it is not read or written. 205 filename = '<test>' 206 builder = ast.BuilderFromSource(cpp_source, filename) 207 ast_list = list(builder.Generate()) 208 lines = gmock_class._GenerateMocks(filename, cpp_source, ast_list, None) 209 return '\n'.join(lines) 210 211 def testNamespaces(self): 212 source = """ 213namespace Foo { 214namespace Bar { class Forward; } 215namespace Baz { 216 217class Test { 218 public: 219 virtual void Foo(); 220}; 221 222} // namespace Baz 223} // namespace Foo 224""" 225 expected = """\ 226namespace Foo { 227namespace Baz { 228 229class MockTest : public Test { 230public: 231MOCK_METHOD0(Foo, 232void()); 233}; 234 235} // namespace Baz 236} // namespace Foo 237""" 238 self.assertEqualIgnoreLeadingWhitespace( 239 expected, self.GenerateMocks(source)) 240 241 def testClassWithStorageSpecifierMacro(self): 242 source = """ 243class STORAGE_SPECIFIER Test { 244 public: 245 virtual void Foo(); 246}; 247""" 248 expected = """\ 249class MockTest : public Test { 250public: 251MOCK_METHOD0(Foo, 252void()); 253}; 254""" 255 self.assertEqualIgnoreLeadingWhitespace( 256 expected, self.GenerateMocks(source)) 257 258if __name__ == '__main__': 259 unittest.main() 260