Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(176)

Side by Side Diff: testing/gmock/scripts/gmock_doctor.py

Issue 115846: Retry to checkin a version of gmock, modified to use our boost_tuple in VS2005. (Closed)
Patch Set: Created 11 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « testing/gmock/scripts/gmock-config.in ('k') | testing/gmock/scripts/test/Makefile » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 #!/usr/bin/python2.4
2 #
3 # Copyright 2008, Google Inc.
4 # All rights reserved.
5 #
6 # Redistribution and use in source and binary forms, with or without
7 # modification, are permitted provided that the following conditions are
8 # met:
9 #
10 # * Redistributions of source code must retain the above copyright
11 # notice, this list of conditions and the following disclaimer.
12 # * Redistributions in binary form must reproduce the above
13 # copyright notice, this list of conditions and the following disclaimer
14 # in the documentation and/or other materials provided with the
15 # distribution.
16 # * Neither the name of Google Inc. nor the names of its
17 # contributors may be used to endorse or promote products derived from
18 # this software without specific prior written permission.
19 #
20 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31
32 """Converts gcc errors in code using Google Mock to plain English."""
33
34 __author__ = 'wan@google.com (Zhanyong Wan)'
35
36 import re
37 import sys
38
39 _VERSION = '1.0.0'
40
41 _COMMON_GMOCK_SYMBOLS = [
42 # Matchers
43 '_',
44 'A',
45 'AddressSatisfies',
46 'AllOf',
47 'An',
48 'AnyOf',
49 'ContainsRegex',
50 'DoubleEq',
51 'EndsWith',
52 'Eq',
53 'Field',
54 'FloatEq',
55 'Ge',
56 'Gt',
57 'HasSubstr',
58 'IsInitializedProto',
59 'Le',
60 'Lt',
61 'MatcherCast',
62 'MatchesRegex',
63 'Ne',
64 'Not',
65 'NotNull',
66 'Pointee',
67 'PointeeIsInitializedProto',
68 'Property',
69 'Ref',
70 'StartsWith',
71 'StrCaseEq',
72 'StrCaseNe',
73 'StrEq',
74 'StrNe',
75 'Truly',
76 'TypedEq',
77
78 # Actions
79 'ByRef',
80 'DoAll',
81 'DoDefault',
82 'IgnoreResult',
83 'Invoke',
84 'InvokeArgument',
85 'InvokeWithoutArgs',
86 'Return',
87 'ReturnNull',
88 'ReturnRef',
89 'SetArgumentPointee',
90 'SetArrayArgument',
91 'WithArgs',
92
93 # Cardinalities
94 'AnyNumber',
95 'AtLeast',
96 'AtMost',
97 'Between',
98 'Exactly',
99
100 # Sequences
101 'InSequence',
102 'Sequence',
103
104 # Misc
105 'DefaultValue',
106 'Mock',
107 ]
108
109
110 def _FindAllMatches(regex, s):
111 """Generates all matches of regex in string s."""
112
113 r = re.compile(regex)
114 return r.finditer(s)
115
116
117 def _GenericDiagnoser(short_name, long_name, regex, diagnosis, msg):
118 """Diagnoses the given disease by pattern matching.
119
120 Args:
121 short_name: Short name of the disease.
122 long_name: Long name of the disease.
123 regex: Regex for matching the symptoms.
124 diagnosis: Pattern for formatting the diagnosis.
125 msg: Gcc's error messages.
126 Yields:
127 Tuples of the form
128 (short name of disease, long name of disease, diagnosis).
129 """
130
131 for m in _FindAllMatches(regex, msg):
132 yield (short_name, long_name, diagnosis % m.groupdict())
133
134
135 def _NeedToReturnReferenceDiagnoser(msg):
136 """Diagnoses the NRR disease, given the error messages by gcc."""
137
138 regex = (r'In member function \'testing::internal::ReturnAction<R>.*\n'
139 r'(?P<file>.*):(?P<line>\d+):\s+instantiated from here\n'
140 r'.*gmock-actions\.h.*error: creating array with negative size')
141 diagnosis = """%(file)s:%(line)s:
142 You are using an Return() action in a function that returns a reference.
143 Please use ReturnRef() instead."""
144 return _GenericDiagnoser('NRR', 'Need to Return Reference',
145 regex, diagnosis, msg)
146
147
148 def _NeedToReturnSomethingDiagnoser(msg):
149 """Diagnoses the NRS disease, given the error messages by gcc."""
150
151 regex = (r'(?P<file>.*):(?P<line>\d+):\s+'
152 r'(instantiated from here\n.'
153 r'*gmock-actions\.h.*error: void value not ignored)'
154 r'|(error: control reaches end of non-void function)')
155 diagnosis = """%(file)s:%(line)s:
156 You are using an action that returns void, but it needs to return
157 *something*. Please tell it *what* to return. Perhaps you can use
158 the pattern DoAll(some_action, Return(some_value))?"""
159 return _GenericDiagnoser('NRS', 'Need to Return Something',
160 regex, diagnosis, msg)
161
162
163 def _NeedToReturnNothingDiagnoser(msg):
164 """Diagnoses the NRN disease, given the error messages by gcc."""
165
166 regex = (r'(?P<file>.*):(?P<line>\d+):\s+instantiated from here\n'
167 r'.*gmock-actions\.h.*error: return-statement with a value, '
168 r'in function returning \'void\'')
169 diagnosis = """%(file)s:%(line)s:
170 You are using an action that returns *something*, but it needs to return
171 void. Please use a void-returning action instead.
172
173 All actions but the last in DoAll(...) must return void. Perhaps you need
174 to re-arrange the order of actions in a DoAll(), if you are using one?"""
175 return _GenericDiagnoser('NRN', 'Need to Return Nothing',
176 regex, diagnosis, msg)
177
178
179 def _IncompleteByReferenceArgumentDiagnoser(msg):
180 """Diagnoses the IBRA disease, given the error messages by gcc."""
181
182 regex = (r'(?P<file>.*):(?P<line>\d+):\s+instantiated from here\n'
183 r'.*gmock-printers\.h.*error: invalid application of '
184 r'\'sizeof\' to incomplete type \'(?P<type>.*)\'')
185 diagnosis = """%(file)s:%(line)s:
186 In order to mock this function, Google Mock needs to see the definition
187 of type "%(type)s" - declaration alone is not enough. Either #include
188 the header that defines it, or change the argument to be passed
189 by pointer."""
190 return _GenericDiagnoser('IBRA', 'Incomplete By-Reference Argument Type',
191 regex, diagnosis, msg)
192
193
194 def _OverloadedFunctionMatcherDiagnoser(msg):
195 """Diagnoses the OFM disease, given the error messages by gcc."""
196
197 regex = (r'(?P<file>.*):(?P<line>\d+): error: no matching function for '
198 r'call to \'Truly\(<unresolved overloaded function type>\)')
199 diagnosis = """%(file)s:%(line)s:
200 The argument you gave to Truly() is an overloaded function. Please tell
201 gcc which overloaded version you want to use.
202
203 For example, if you want to use the version whose signature is
204 bool Foo(int n);
205 you should write
206 Truly(static_cast<bool (*)(int n)>(Foo))"""
207 return _GenericDiagnoser('OFM', 'Overloaded Function Matcher',
208 regex, diagnosis, msg)
209
210
211 def _OverloadedFunctionActionDiagnoser(msg):
212 """Diagnoses the OFA disease, given the error messages by gcc."""
213
214 regex = (r'(?P<file>.*):(?P<line>\d+): error: '
215 r'no matching function for call to \'Invoke\('
216 r'<unresolved overloaded function type>')
217 diagnosis = """%(file)s:%(line)s:
218 You are passing an overloaded function to Invoke(). Please tell gcc
219 which overloaded version you want to use.
220
221 For example, if you want to use the version whose signature is
222 bool MyFunction(int n, double x);
223 you should write something like
224 Invoke(static_cast<bool (*)(int n, double x)>(MyFunction))"""
225 return _GenericDiagnoser('OFA', 'Overloaded Function Action',
226 regex, diagnosis, msg)
227
228
229 def _OverloadedMethodActionDiagnoser1(msg):
230 """Diagnoses the OMA disease, given the error messages by gcc."""
231
232 regex = (r'(?P<file>.*):(?P<line>\d+): error: '
233 r'.*no matching function for call to \'Invoke\(.*, '
234 r'unresolved overloaded function type>')
235 diagnosis = """%(file)s:%(line)s:
236 The second argument you gave to Invoke() is an overloaded method. Please
237 tell gcc which overloaded version you want to use.
238
239 For example, if you want to use the version whose signature is
240 class Foo {
241 ...
242 bool Bar(int n, double x);
243 };
244 you should write something like
245 Invoke(foo, static_cast<bool (Foo::*)(int n, double x)>(&Foo::Bar))"""
246 return _GenericDiagnoser('OMA', 'Overloaded Method Action',
247 regex, diagnosis, msg)
248
249
250 def _MockObjectPointerDiagnoser(msg):
251 """Diagnoses the MOP disease, given the error messages by gcc."""
252
253 regex = (r'(?P<file>.*):(?P<line>\d+): error: request for member '
254 r'\'gmock_(?P<method>.+)\' in \'(?P<mock_object>.+)\', '
255 r'which is of non-class type \'(.*::)*(?P<class_name>.+)\*\'')
256 diagnosis = """%(file)s:%(line)s:
257 The first argument to ON_CALL() and EXPECT_CALL() must be a mock *object*,
258 not a *pointer* to it. Please write '*(%(mock_object)s)' instead of
259 '%(mock_object)s' as your first argument.
260
261 For example, given the mock class:
262
263 class %(class_name)s : public ... {
264 ...
265 MOCK_METHOD0(%(method)s, ...);
266 };
267
268 and the following mock instance:
269
270 %(class_name)s* mock_ptr = ...
271
272 you should use the EXPECT_CALL like this:
273
274 EXPECT_CALL(*mock_ptr, %(method)s(...));"""
275 return _GenericDiagnoser('MOP', 'Mock Object Pointer',
276 regex, diagnosis, msg)
277
278
279 def _OverloadedMethodActionDiagnoser2(msg):
280 """Diagnoses the OMA disease, given the error messages by gcc."""
281
282 regex = (r'(?P<file>.*):(?P<line>\d+): error: no matching function for '
283 r'call to \'Invoke\(.+, <unresolved overloaded function type>\)')
284 diagnosis = """%(file)s:%(line)s:
285 The second argument you gave to Invoke() is an overloaded method. Please
286 tell gcc which overloaded version you want to use.
287
288 For example, if you want to use the version whose signature is
289 class Foo {
290 ...
291 bool Bar(int n, double x);
292 };
293 you should write something like
294 Invoke(foo, static_cast<bool (Foo::*)(int n, double x)>(&Foo::Bar))"""
295 return _GenericDiagnoser('OMA', 'Overloaded Method Action',
296 regex, diagnosis, msg)
297
298
299 def _NeedToUseSymbolDiagnoser(msg):
300 """Diagnoses the NUS disease, given the error messages by gcc."""
301
302 regex = (r'(?P<file>.*):(?P<line>\d+): error: \'(?P<symbol>.+)\' '
303 r'(was not declared in this scope|has not been declared)')
304 diagnosis = """%(file)s:%(line)s:
305 '%(symbol)s' is defined by Google Mock in the testing namespace.
306 Did you forget to write
307 using testing::%(symbol)s;
308 ?"""
309 for m in _FindAllMatches(regex, msg):
310 symbol = m.groupdict()['symbol']
311 if symbol in _COMMON_GMOCK_SYMBOLS:
312 yield ('NUS', 'Need to Use Symbol', diagnosis % m.groupdict())
313
314
315 def _NeedToUseReturnNullDiagnoser(msg):
316 """Diagnoses the NRNULL disease, given the error messages by gcc."""
317
318 regex = (r'(?P<file>.*):(?P<line>\d+):\s+instantiated from here\n'
319 r'.*gmock-actions\.h.*error: invalid conversion from '
320 r'\'long int\' to \'(?P<type>.+\*)')
321
322 diagnosis = """%(file)s:%(line)s:
323 You are probably calling Return(NULL) and the compiler isn't sure how to turn
324 NULL into a %(type)s*. Use ReturnNull() instead.
325 Note: the line number may be off; please fix all instances of Return(NULL)."""
326 return _GenericDiagnoser('NRNULL', 'Need to use ReturnNull',
327 regex, diagnosis, msg)
328
329
330 def _WrongMockMethodMacroDiagnoser(msg):
331 """Diagnoses the WMM disease, given the error messages by gcc."""
332
333 regex = (r'(?P<file>.*):(?P<line>\d+):\s+'
334 r'.*this_method_does_not_take_(?P<wrong_args>\d+)_argument.*\n'
335 r'.*\n'
336 r'.*candidates are.*FunctionMocker<[^>]+A(?P<args>\d+)\)>'
337 )
338
339 diagnosis = """%(file)s:%(line)s:
340 You are using MOCK_METHOD%(wrong_args)s to define a mock method that has
341 %(args)s arguments. Use MOCK_METHOD%(args)s (or MOCK_CONST_METHOD%(args)s,
342 MOCK_METHOD%(args)s_T, MOCK_CONST_METHOD%(args)s_T as appropriate) instead."""
343 return _GenericDiagnoser('WMM', 'Wrong MOCK_METHODn macro',
344 regex, diagnosis, msg)
345
346
347
348 _DIAGNOSERS = [
349 _IncompleteByReferenceArgumentDiagnoser,
350 _MockObjectPointerDiagnoser,
351 _NeedToReturnNothingDiagnoser,
352 _NeedToReturnReferenceDiagnoser,
353 _NeedToReturnSomethingDiagnoser,
354 _NeedToUseReturnNullDiagnoser,
355 _NeedToUseSymbolDiagnoser,
356 _OverloadedFunctionActionDiagnoser,
357 _OverloadedFunctionMatcherDiagnoser,
358 _OverloadedMethodActionDiagnoser1,
359 _OverloadedMethodActionDiagnoser2,
360 _WrongMockMethodMacroDiagnoser,
361 ]
362
363
364 def Diagnose(msg):
365 """Generates all possible diagnoses given the gcc error message."""
366
367 for diagnoser in _DIAGNOSERS:
368 for diagnosis in diagnoser(msg):
369 yield '[%s - %s]\n%s' % diagnosis
370
371
372 def main():
373 print ('Google Mock Doctor v%s - '
374 'diagnoses problems in code using Google Mock.' % _VERSION)
375
376 if sys.stdin.isatty():
377 print ('Please copy and paste the compiler errors here. Press c-D when '
378 'you are done:')
379 else:
380 print 'Waiting for compiler errors on stdin . . .'
381
382 msg = sys.stdin.read().strip()
383 diagnoses = list(Diagnose(msg))
384 count = len(diagnoses)
385 if not count:
386 print '\nGcc complained:'
387 print '8<------------------------------------------------------------'
388 print msg
389 print '------------------------------------------------------------>8'
390 print """
391 Uh-oh, I'm not smart enough to figure out what the problem is. :-(
392 However...
393 If you send your source code and gcc's error messages to
394 googlemock@googlegroups.com, you can be helped and I can get smarter --
395 win-win for us!"""
396 else:
397 print '------------------------------------------------------------'
398 print 'Your code appears to have the following',
399 if count > 1:
400 print '%s diseases:' % (count,)
401 else:
402 print 'disease:'
403 i = 0
404 for d in diagnoses:
405 i += 1
406 if count > 1:
407 print '\n#%s:' % (i,)
408 print d
409 print """
410 How did I do? If you think I'm wrong or unhelpful, please send your
411 source code and gcc's error messages to googlemock@googlegroups.com. Then
412 you can be helped and I can get smarter -- I promise I won't be upset!"""
413
414
415 if __name__ == '__main__':
416 main()
OLDNEW
« no previous file with comments | « testing/gmock/scripts/gmock-config.in ('k') | testing/gmock/scripts/test/Makefile » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698