OLD | NEW |
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. |
3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
5 | 5 |
6 import string | 6 import string |
7 import sys | 7 import sys |
8 | 8 |
9 HEADER = """\ | 9 HEADER = """\ |
10 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 10 // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
49 // string HandleFlowers(const string& reply, int n, const string& request) { | 49 // string HandleFlowers(const string& reply, int n, const string& request) { |
50 // string result = SStringPrintf("In request of %d %s ", n, request); | 50 // string result = SStringPrintf("In request of %d %s ", n, request); |
51 // for (int i = 0; i < n; ++i) result.append(reply) | 51 // for (int i = 0; i < n; ++i) result.append(reply) |
52 // return result; | 52 // return result; |
53 // } | 53 // } |
54 // | 54 // |
55 // void DoLogMessage(int level, const string& message) { | 55 // void DoLogMessage(int level, const string& message) { |
56 // } | 56 // } |
57 // | 57 // |
58 // void QuitMessageLoop(int seconds) { | 58 // void QuitMessageLoop(int seconds) { |
59 // base::MessageLoop* loop = base::MessageLoop::current(); | 59 // MessageLoop* loop = MessageLoop::current(); |
60 // loop->PostDelayedTask(FROM_HERE, base::MessageLoop::QuitClosure(), | 60 // loop->PostDelayedTask(FROM_HERE, MessageLoop::QuitClosure(), |
61 // 1000 * seconds); | 61 // 1000 * seconds); |
62 // } | 62 // } |
63 // }; | 63 // }; |
64 // | 64 // |
65 // Mock mock; | 65 // Mock mock; |
66 // // Will invoke mock.HandleFlowers("orchids", n, request) | 66 // // Will invoke mock.HandleFlowers("orchids", n, request) |
67 // // "orchids" is a pre-bound argument, and <n> and <request> are call-time | 67 // // "orchids" is a pre-bound argument, and <n> and <request> are call-time |
68 // // arguments - they are not known until the OnRequest mock is invoked. | 68 // // arguments - they are not known until the OnRequest mock is invoked. |
69 // EXPECT_CALL(mock, OnRequest(Ge(5), StartsWith("flower")) | 69 // EXPECT_CALL(mock, OnRequest(Ge(5), StartsWith("flower")) |
70 // .Times(1) | 70 // .Times(1) |
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
195 // Redirects operator() to MutantRunner<Params>::Run() | 195 // Redirects operator() to MutantRunner<Params>::Run() |
196 template <typename R, typename Params> | 196 template <typename R, typename Params> |
197 struct MutantFunctor { | 197 struct MutantFunctor { |
198 explicit MutantFunctor(MutantRunner<R, Params>* cb) : impl_(cb) { | 198 explicit MutantFunctor(MutantRunner<R, Params>* cb) : impl_(cb) { |
199 } | 199 } |
200 | 200 |
201 ~MutantFunctor() { | 201 ~MutantFunctor() { |
202 } | 202 } |
203 | 203 |
204 inline R operator()() { | 204 inline R operator()() { |
205 return impl_->RunWithParams(Tuple<>()); | 205 return impl_->RunWithParams(Tuple0()); |
206 } | 206 } |
207 | 207 |
208 template <typename Arg1> | 208 template <typename Arg1> |
209 inline R operator()(const Arg1& a) { | 209 inline R operator()(const Arg1& a) { |
210 return impl_->RunWithParams(Params(a)); | 210 return impl_->RunWithParams(Params(a)); |
211 } | 211 } |
212 | 212 |
213 template <typename Arg1, typename Arg2> | 213 template <typename Arg1, typename Arg2> |
214 inline R operator()(const Arg1& a, const Arg2& b) { | 214 inline R operator()(const Arg1& a, const Arg2& b) { |
215 return impl_->RunWithParams(Params(a, b)); | 215 return impl_->RunWithParams(Params(a, b)); |
(...skipping 18 matching lines...) Expand all Loading... |
234 }; | 234 }; |
235 """ | 235 """ |
236 | 236 |
237 FOOTER = """\ | 237 FOOTER = """\ |
238 } // namespace testing | 238 } // namespace testing |
239 | 239 |
240 #endif // TESTING_GMOCK_MUTANT_H_""" | 240 #endif // TESTING_GMOCK_MUTANT_H_""" |
241 | 241 |
242 # Templates for DispatchToMethod/DispatchToFunction functions. | 242 # Templates for DispatchToMethod/DispatchToFunction functions. |
243 # template_params - typename P1, typename P2.. typename C1.. | 243 # template_params - typename P1, typename P2.. typename C1.. |
244 # prebound - Tuple<P1, .. PN> | 244 # prebound - TupleN<P1, .. PN> |
245 # calltime - Tuple<C1, .. CN> | 245 # calltime - TupleN<C1, .. CN> |
246 # args - p.a, p.b.., c.a, c.b.. | 246 # args - p.a, p.b.., c.a, c.b.. |
247 DISPATCH_TO_METHOD_TEMPLATE = """\ | 247 DISPATCH_TO_METHOD_TEMPLATE = """\ |
248 template <typename R, typename T, typename Method, %(template_params)s> | 248 template <typename R, typename T, typename Method, %(template_params)s> |
249 inline R DispatchToMethod(T* obj, Method method, | 249 inline R DispatchToMethod(T* obj, Method method, |
250 const %(prebound)s& p, | 250 const %(prebound)s& p, |
251 const %(calltime)s& c) { | 251 const %(calltime)s& c) { |
252 return (obj->*method)(%(args)s); | 252 return (obj->*method)(%(args)s); |
253 } | 253 } |
254 """ | 254 """ |
255 | 255 |
256 DISPATCH_TO_FUNCTION_TEMPLATE = """\ | 256 DISPATCH_TO_FUNCTION_TEMPLATE = """\ |
257 template <typename R, typename Function, %(template_params)s> | 257 template <typename R, typename Function, %(template_params)s> |
258 inline R DispatchToFunction(Function function, | 258 inline R DispatchToFunction(Function function, |
259 const %(prebound)s& p, | 259 const %(prebound)s& p, |
260 const %(calltime)s& c) { | 260 const %(calltime)s& c) { |
261 return (*function)(%(args)s); | 261 return (*function)(%(args)s); |
262 } | 262 } |
263 """ | 263 """ |
264 | 264 |
265 # Templates for CreateFunctor functions. | 265 # Templates for CreateFunctor functions. |
266 # template_params - typename P1, typename P2.. typename C1.. typename X1.. | 266 # template_params - typename P1, typename P2.. typename C1.. typename X1.. |
267 # prebound - Tuple<P1, .. PN> | 267 # prebound - TupleN<P1, .. PN> |
268 # calltime - Tuple<A1, .. AN> | 268 # calltime - TupleN<A1, .. AN> |
269 # params - X1,.. , A1, .. | 269 # params - X1,.. , A1, .. |
270 # args - const P1& p1 .. | 270 # args - const P1& p1 .. |
271 # call_args - p1, p2, p3.. | 271 # call_args - p1, p2, p3.. |
272 CREATE_METHOD_FUNCTOR_TEMPLATE = """\ | 272 CREATE_METHOD_FUNCTOR_TEMPLATE = """\ |
273 template <typename R, typename T, typename U, %(template_params)s> | 273 template <typename R, typename T, typename U, %(template_params)s> |
274 inline MutantFunctor<R, %(calltime)s> | 274 inline MutantFunctor<R, %(calltime)s> |
275 CreateFunctor(T* obj, R (U::*method)(%(params)s), %(args)s) { | 275 CreateFunctor(T* obj, R (U::*method)(%(params)s), %(args)s) { |
276 MutantRunner<R, %(calltime)s>* t = | 276 MutantRunner<R, %(calltime)s>* t = |
277 new Mutant<R, T, R (U::*)(%(params)s), | 277 new Mutant<R, T, R (U::*)(%(params)s), |
278 %(prebound)s, %(calltime)s> | 278 %(prebound)s, %(calltime)s> |
(...skipping 19 matching lines...) Expand all Loading... |
298 if len(line) < width: | 298 if len(line) < width: |
299 return (line, None) | 299 return (line, None) |
300 n = 1 + line[:width].rfind(",") | 300 n = 1 + line[:width].rfind(",") |
301 if n == 0: # If comma cannot be found give up and return the entire line. | 301 if n == 0: # If comma cannot be found give up and return the entire line. |
302 return (line, None) | 302 return (line, None) |
303 # Assume there is a space after the comma | 303 # Assume there is a space after the comma |
304 assert line[n] == " " | 304 assert line[n] == " " |
305 return (line[:n], line[n + 1:]) | 305 return (line[:n], line[n + 1:]) |
306 | 306 |
307 | 307 |
308 def Wrap(s, width, subsequent_offset): | 308 def Wrap(s, width, subsequent_offset=4): |
309 """Wraps a single line |s| at commas so every line is at most |width| | 309 """Wraps a single line |s| at commas so every line is at most |width| |
310 characters long. | 310 characters long. |
311 """ | 311 """ |
312 w = [] | 312 w = [] |
313 spaces = " " * subsequent_offset | 313 spaces = " " * subsequent_offset |
314 while s: | 314 while s: |
315 (f, s) = SplitLine(s, width) | 315 (f, s) = SplitLine(s, width) |
316 w.append(f) | 316 w.append(f) |
317 if s: | 317 if s: |
318 s = spaces + s | 318 s = spaces + s |
319 return "\n".join(w) | 319 return "\n".join(w) |
320 | 320 |
321 | 321 |
322 def Clean(s): | 322 def Clean(s): |
323 """Cleans artifacts from generated C++ code. | 323 """Cleans artifacts from generated C++ code. |
324 | 324 |
325 Our simple string formatting/concatenation may introduce extra commas. | 325 Our simple string formatting/concatenation may introduce extra commas. |
326 """ | 326 """ |
| 327 s = s.replace("<>", "") |
327 s = s.replace(", >", ">") | 328 s = s.replace(", >", ">") |
328 s = s.replace(", )", ")") | 329 s = s.replace(", )", ")") |
| 330 s = s.replace(">>", "> >") |
329 return s | 331 return s |
330 | 332 |
331 | 333 |
332 def ExpandPattern(pattern, it): | 334 def ExpandPattern(pattern, it): |
333 """Return list of expanded pattern strings. | 335 """Return list of expanded pattern strings. |
334 | 336 |
335 Each string is created by replacing all '%' in |pattern| with element of |it|. | 337 Each string is created by replacing all '%' in |pattern| with element of |it|. |
336 """ | 338 """ |
337 return [pattern.replace("%", x) for x in it] | 339 return [pattern.replace("%", x) for x in it] |
338 | 340 |
339 | 341 |
340 def Gen(pattern, n, start): | 342 def Gen(pattern, n): |
341 """Expands pattern replacing '%' with sequential integers starting with start. | 343 """Expands pattern replacing '%' with sequential integers. |
342 | 344 |
343 Expanded patterns will be joined with comma separator. | 345 Expanded patterns will be joined with comma separator. |
344 Gen("X%", 3, 1) will return "X1, X2, X3". | 346 GenAlphs("X%", 3) will return "X1, X2, X3". |
345 """ | 347 """ |
346 it = string.hexdigits[start:n + start] | 348 it = string.hexdigits[1:n + 1] |
347 return ", ".join(ExpandPattern(pattern, it)) | 349 return ", ".join(ExpandPattern(pattern, it)) |
348 | 350 |
349 | 351 |
| 352 def GenAlpha(pattern, n): |
| 353 """Expands pattern replacing '%' with sequential small ASCII letters. |
| 354 |
| 355 Expanded patterns will be joined with comma separator. |
| 356 GenAlphs("X%", 3) will return "Xa, Xb, Xc". |
| 357 """ |
| 358 it = string.ascii_lowercase[0:n] |
| 359 return ", ".join(ExpandPattern(pattern, it)) |
| 360 |
| 361 |
350 def Merge(a): | 362 def Merge(a): |
351 return ", ".join(filter(len, a)) | 363 return ", ".join(filter(len, a)) |
352 | 364 |
353 | 365 |
354 def GenTuple(pattern, n): | 366 def GenTuple(pattern, n): |
355 return Clean("Tuple<%s>" % (Gen(pattern, n, 1))) | 367 return Clean("Tuple%d<%s>" % (n, Gen(pattern, n))) |
356 | 368 |
357 | 369 |
358 def FixCode(s): | 370 def FixCode(s): |
359 lines = Clean(s).splitlines() | 371 lines = Clean(s).splitlines() |
360 # Wrap sometimes very long 1st and 3rd line at 80th column. | 372 # Wrap sometimes very long 1st and 3rd line at 80th column. |
361 lines[0] = Wrap(lines[0], 80, 10) | 373 lines[0] = Wrap(lines[0], 80, 10) |
362 lines[2] = Wrap(lines[2], 80, 4) | 374 lines[2] = Wrap(lines[2], 80, 4) |
363 return "\n".join(lines) | 375 return "\n".join(lines) |
364 | 376 |
365 | 377 |
366 def GenerateDispatch(prebound, calltime): | 378 def GenerateDispatch(prebound, calltime): |
367 print "\n// %d - %d" % (prebound, calltime) | 379 print "\n// %d - %d" % (prebound, calltime) |
368 args = { | 380 args = { |
369 "template_params": Merge([Gen("typename P%", prebound, 1), | 381 "template_params": Merge([Gen("typename P%", prebound), |
370 Gen("typename C%", calltime, 1)]), | 382 Gen("typename C%", calltime)]), |
371 "prebound": GenTuple("P%", prebound), | 383 "prebound": GenTuple("P%", prebound), |
372 "calltime": GenTuple("C%", calltime), | 384 "calltime": GenTuple("C%", calltime), |
373 "args": Merge([Gen("get<%>(p)", prebound, 0), | 385 "args": Merge([GenAlpha("p.%", prebound), GenAlpha("c.%", calltime)]), |
374 Gen("get<%>(c)", calltime, 0)]), | |
375 } | 386 } |
376 | 387 |
377 print FixCode(DISPATCH_TO_METHOD_TEMPLATE % args) | 388 print FixCode(DISPATCH_TO_METHOD_TEMPLATE % args) |
378 print FixCode(DISPATCH_TO_FUNCTION_TEMPLATE % args) | 389 print FixCode(DISPATCH_TO_FUNCTION_TEMPLATE % args) |
379 | 390 |
380 | 391 |
381 def GenerateCreateFunctor(prebound, calltime): | 392 def GenerateCreateFunctor(prebound, calltime): |
382 print "// %d - %d" % (prebound, calltime) | 393 print "// %d - %d" % (prebound, calltime) |
383 args = { | 394 args = { |
384 "calltime": GenTuple("A%", calltime), | 395 "calltime": GenTuple("A%", calltime), |
385 "prebound": GenTuple("P%", prebound), | 396 "prebound": GenTuple("P%", prebound), |
386 "params": Merge([Gen("X%", prebound, 1), Gen("A%", calltime, 1)]), | 397 "params": Merge([Gen("X%", prebound), Gen("A%", calltime)]), |
387 "args": Gen("const P%& p%", prebound, 1), | 398 "args": Gen("const P%& p%", prebound), |
388 "call_args": Gen("p%", prebound, 1), | 399 "call_args": Gen("p%", prebound), |
389 "template_params": Merge([Gen("typename P%", prebound, 1), | 400 "template_params": Merge([Gen("typename P%", prebound), |
390 Gen("typename A%", calltime, 1), | 401 Gen("typename A%", calltime), |
391 Gen("typename X%", prebound, 1)]) | 402 Gen("typename X%", prebound)]) |
392 } | 403 } |
393 | 404 |
394 mutant = FixCode(CREATE_METHOD_FUNCTOR_TEMPLATE % args) | 405 mutant = FixCode(CREATE_METHOD_FUNCTOR_TEMPLATE % args) |
395 print mutant | 406 print mutant |
396 | 407 |
397 # Slightly different version for free function call. | 408 # Slightly different version for free function call. |
398 print "\n", FixCode(CREATE_FUNCTION_FUNCTOR_TEMPLATE % args) | 409 print "\n", FixCode(CREATE_FUNCTION_FUNCTOR_TEMPLATE % args) |
399 | 410 |
400 # Functor with pointer to a pointer of the object. | 411 # Functor with pointer to a pointer of the object. |
401 print "\n#ifdef GMOCK_MUTANT_INCLUDE_LATE_OBJECT_BINDING" | 412 print "\n#ifdef GMOCK_MUTANT_INCLUDE_LATE_OBJECT_BINDING" |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
437 print MUTANT | 448 print MUTANT |
438 for prebound in xrange(0, 6 + 1): | 449 for prebound in xrange(0, 6 + 1): |
439 for args in xrange(0, 6 + 1): | 450 for args in xrange(0, 6 + 1): |
440 GenerateCreateFunctor(prebound, args) | 451 GenerateCreateFunctor(prebound, args) |
441 print FOOTER | 452 print FOOTER |
442 return 0 | 453 return 0 |
443 | 454 |
444 | 455 |
445 if __name__ == "__main__": | 456 if __name__ == "__main__": |
446 sys.exit(main()) | 457 sys.exit(main()) |
OLD | NEW |