1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/media/webrtc/trunk/testing/generate_gmock_mutant.py Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,455 @@ 1.4 +#!/usr/bin/env python 1.5 +# Copyright (c) 2011 The Chromium Authors. All rights reserved. 1.6 +# Use of this source code is governed by a BSD-style license that can be 1.7 +# found in the LICENSE file. 1.8 + 1.9 +import string 1.10 +import sys 1.11 + 1.12 +HEADER = """\ 1.13 +// Copyright (c) 2011 The Chromium Authors. All rights reserved. 1.14 +// Use of this source code is governed by a BSD-style license that can be 1.15 +// found in the LICENSE file. 1.16 + 1.17 +// This file automatically generated by testing/generate_gmock_mutant.py. 1.18 +// DO NOT EDIT. 1.19 + 1.20 +#ifndef TESTING_GMOCK_MUTANT_H_ 1.21 +#define TESTING_GMOCK_MUTANT_H_ 1.22 + 1.23 +// The intention of this file is to make possible using GMock actions in 1.24 +// all of its syntactic beauty. Classes and helper functions can be used as 1.25 +// more generic variants of Task and Callback classes (see base/task.h) 1.26 +// Mutant supports both pre-bound arguments (like Task) and call-time 1.27 +// arguments (like Callback) - hence the name. :-) 1.28 +// 1.29 +// DispatchToMethod/Function supports two sets of arguments: pre-bound (P) and 1.30 +// call-time (C). The arguments as well as the return type are templatized. 1.31 +// DispatchToMethod/Function will also try to call the selected method or 1.32 +// function even if provided pre-bound arguments does not match exactly with 1.33 +// the function signature hence the X1, X2 ... XN parameters in CreateFunctor. 1.34 +// DispatchToMethod will try to invoke method that may not belong to the 1.35 +// object's class itself but to the object's class base class. 1.36 +// 1.37 +// Additionally you can bind the object at calltime by binding a pointer to 1.38 +// pointer to the object at creation time - before including this file you 1.39 +// have to #define GMOCK_MUTANT_INCLUDE_LATE_OBJECT_BINDING. 1.40 +// 1.41 +// TODO(stoyan): It's yet not clear to me should we use T& and T&* instead 1.42 +// of T* and T** when we invoke CreateFunctor to match the EXPECT_CALL style. 1.43 +// 1.44 +// 1.45 +// Sample usage with gMock: 1.46 +// 1.47 +// struct Mock : public ObjectDelegate { 1.48 +// MOCK_METHOD2(string, OnRequest(int n, const string& request)); 1.49 +// MOCK_METHOD1(void, OnQuit(int exit_code)); 1.50 +// MOCK_METHOD2(void, LogMessage(int level, const string& message)); 1.51 +// 1.52 +// string HandleFlowers(const string& reply, int n, const string& request) { 1.53 +// string result = SStringPrintf("In request of %d %s ", n, request); 1.54 +// for (int i = 0; i < n; ++i) result.append(reply) 1.55 +// return result; 1.56 +// } 1.57 +// 1.58 +// void DoLogMessage(int level, const string& message) { 1.59 +// } 1.60 +// 1.61 +// void QuitMessageLoop(int seconds) { 1.62 +// MessageLoop* loop = MessageLoop::current(); 1.63 +// loop->PostDelayedTask(FROM_HERE, MessageLoop::QuitClosure(), 1.64 +// 1000 * seconds); 1.65 +// } 1.66 +// }; 1.67 +// 1.68 +// Mock mock; 1.69 +// // Will invoke mock.HandleFlowers("orchids", n, request) 1.70 +// // "orchids" is a pre-bound argument, and <n> and <request> are call-time 1.71 +// // arguments - they are not known until the OnRequest mock is invoked. 1.72 +// EXPECT_CALL(mock, OnRequest(Ge(5), StartsWith("flower")) 1.73 +// .Times(1) 1.74 +// .WillOnce(Invoke(CreateFunctor(&mock, &Mock::HandleFlowers, 1.75 +// string("orchids")))); 1.76 +// 1.77 +// 1.78 +// // No pre-bound arguments, two call-time arguments passed 1.79 +// // directly to DoLogMessage 1.80 +// EXPECT_CALL(mock, OnLogMessage(_, _)) 1.81 +// .Times(AnyNumber()) 1.82 +// .WillAlways(Invoke(CreateFunctor, &mock, &Mock::DoLogMessage)); 1.83 +// 1.84 +// 1.85 +// // In this case we have a single pre-bound argument - 3. We ignore 1.86 +// // all of the arguments of OnQuit. 1.87 +// EXCEPT_CALL(mock, OnQuit(_)) 1.88 +// .Times(1) 1.89 +// .WillOnce(InvokeWithoutArgs(CreateFunctor( 1.90 +// &mock, &Mock::QuitMessageLoop, 3))); 1.91 +// 1.92 +// MessageLoop loop; 1.93 +// loop.Run(); 1.94 +// 1.95 +// 1.96 +// // Here is another example of how we can set an action that invokes 1.97 +// // method of an object that is not yet created. 1.98 +// struct Mock : public ObjectDelegate { 1.99 +// MOCK_METHOD1(void, DemiurgeCreated(Demiurge*)); 1.100 +// MOCK_METHOD2(void, OnRequest(int count, const string&)); 1.101 +// 1.102 +// void StoreDemiurge(Demiurge* w) { 1.103 +// demiurge_ = w; 1.104 +// } 1.105 +// 1.106 +// Demiurge* demiurge; 1.107 +// } 1.108 +// 1.109 +// EXPECT_CALL(mock, DemiurgeCreated(_)).Times(1) 1.110 +// .WillOnce(Invoke(CreateFunctor(&mock, &Mock::StoreDemiurge))); 1.111 +// 1.112 +// EXPECT_CALL(mock, OnRequest(_, StrEq("Moby Dick"))) 1.113 +// .Times(AnyNumber()) 1.114 +// .WillAlways(WithArgs<0>(Invoke( 1.115 +// CreateFunctor(&mock->demiurge_, &Demiurge::DecreaseMonsters)))); 1.116 +// 1.117 + 1.118 +#include "base/memory/linked_ptr.h" 1.119 +#include "base/tuple.h" // for Tuple 1.120 + 1.121 +namespace testing {""" 1.122 + 1.123 +MUTANT = """\ 1.124 + 1.125 +// Interface that is exposed to the consumer, that does the actual calling 1.126 +// of the method. 1.127 +template <typename R, typename Params> 1.128 +class MutantRunner { 1.129 + public: 1.130 + virtual R RunWithParams(const Params& params) = 0; 1.131 + virtual ~MutantRunner() {} 1.132 +}; 1.133 + 1.134 +// Mutant holds pre-bound arguments (like Task). Like Callback 1.135 +// allows call-time arguments. You bind a pointer to the object 1.136 +// at creation time. 1.137 +template <typename R, typename T, typename Method, 1.138 + typename PreBound, typename Params> 1.139 +class Mutant : public MutantRunner<R, Params> { 1.140 + public: 1.141 + Mutant(T* obj, Method method, const PreBound& pb) 1.142 + : obj_(obj), method_(method), pb_(pb) { 1.143 + } 1.144 + 1.145 + // MutantRunner implementation 1.146 + virtual R RunWithParams(const Params& params) { 1.147 + return DispatchToMethod<R>(this->obj_, this->method_, pb_, params); 1.148 + } 1.149 + 1.150 + T* obj_; 1.151 + Method method_; 1.152 + PreBound pb_; 1.153 +}; 1.154 + 1.155 +template <typename R, typename Function, typename PreBound, typename Params> 1.156 +class MutantFunction : public MutantRunner<R, Params> { 1.157 + public: 1.158 + MutantFunction(Function function, const PreBound& pb) 1.159 + : function_(function), pb_(pb) { 1.160 + } 1.161 + 1.162 + // MutantRunner implementation 1.163 + virtual R RunWithParams(const Params& params) { 1.164 + return DispatchToFunction<R>(function_, pb_, params); 1.165 + } 1.166 + 1.167 + Function function_; 1.168 + PreBound pb_; 1.169 +}; 1.170 + 1.171 +#ifdef GMOCK_MUTANT_INCLUDE_LATE_OBJECT_BINDING 1.172 +// MutantLateBind is like Mutant, but you bind a pointer to a pointer 1.173 +// to the object. This way you can create actions for an object 1.174 +// that is not yet created (has only storage for a pointer to it). 1.175 +template <typename R, typename T, typename Method, 1.176 + typename PreBound, typename Params> 1.177 +class MutantLateObjectBind : public MutantRunner<R, Params> { 1.178 + public: 1.179 + MutantLateObjectBind(T** obj, Method method, const PreBound& pb) 1.180 + : obj_(obj), method_(method), pb_(pb) { 1.181 + } 1.182 + 1.183 + // MutantRunner implementation. 1.184 + virtual R RunWithParams(const Params& params) { 1.185 + EXPECT_THAT(*this->obj_, testing::NotNull()); 1.186 + if (NULL == *this->obj_) 1.187 + return R(); 1.188 + return DispatchToMethod<R>( *this->obj_, this->method_, pb_, params); 1.189 + } 1.190 + 1.191 + T** obj_; 1.192 + Method method_; 1.193 + PreBound pb_; 1.194 +}; 1.195 +#endif 1.196 + 1.197 +// Simple MutantRunner<> wrapper acting as a functor. 1.198 +// Redirects operator() to MutantRunner<Params>::Run() 1.199 +template <typename R, typename Params> 1.200 +struct MutantFunctor { 1.201 + explicit MutantFunctor(MutantRunner<R, Params>* cb) : impl_(cb) { 1.202 + } 1.203 + 1.204 + ~MutantFunctor() { 1.205 + } 1.206 + 1.207 + inline R operator()() { 1.208 + return impl_->RunWithParams(Tuple0()); 1.209 + } 1.210 + 1.211 + template <typename Arg1> 1.212 + inline R operator()(const Arg1& a) { 1.213 + return impl_->RunWithParams(Params(a)); 1.214 + } 1.215 + 1.216 + template <typename Arg1, typename Arg2> 1.217 + inline R operator()(const Arg1& a, const Arg2& b) { 1.218 + return impl_->RunWithParams(Params(a, b)); 1.219 + } 1.220 + 1.221 + template <typename Arg1, typename Arg2, typename Arg3> 1.222 + inline R operator()(const Arg1& a, const Arg2& b, const Arg3& c) { 1.223 + return impl_->RunWithParams(Params(a, b, c)); 1.224 + } 1.225 + 1.226 + template <typename Arg1, typename Arg2, typename Arg3, typename Arg4> 1.227 + inline R operator()(const Arg1& a, const Arg2& b, const Arg3& c, 1.228 + const Arg4& d) { 1.229 + return impl_->RunWithParams(Params(a, b, c, d)); 1.230 + } 1.231 + 1.232 + private: 1.233 + // We need copy constructor since MutantFunctor is copied few times 1.234 + // inside GMock machinery, hence no DISALLOW_EVIL_CONTRUCTORS 1.235 + MutantFunctor(); 1.236 + linked_ptr<MutantRunner<R, Params> > impl_; 1.237 +}; 1.238 +""" 1.239 + 1.240 +FOOTER = """\ 1.241 +} // namespace testing 1.242 + 1.243 +#endif // TESTING_GMOCK_MUTANT_H_""" 1.244 + 1.245 +# Templates for DispatchToMethod/DispatchToFunction functions. 1.246 +# template_params - typename P1, typename P2.. typename C1.. 1.247 +# prebound - TupleN<P1, .. PN> 1.248 +# calltime - TupleN<C1, .. CN> 1.249 +# args - p.a, p.b.., c.a, c.b.. 1.250 +DISPATCH_TO_METHOD_TEMPLATE = """\ 1.251 +template <typename R, typename T, typename Method, %(template_params)s> 1.252 +inline R DispatchToMethod(T* obj, Method method, 1.253 + const %(prebound)s& p, 1.254 + const %(calltime)s& c) { 1.255 + return (obj->*method)(%(args)s); 1.256 +} 1.257 +""" 1.258 + 1.259 +DISPATCH_TO_FUNCTION_TEMPLATE = """\ 1.260 +template <typename R, typename Function, %(template_params)s> 1.261 +inline R DispatchToFunction(Function function, 1.262 + const %(prebound)s& p, 1.263 + const %(calltime)s& c) { 1.264 + return (*function)(%(args)s); 1.265 +} 1.266 +""" 1.267 + 1.268 +# Templates for CreateFunctor functions. 1.269 +# template_params - typename P1, typename P2.. typename C1.. typename X1.. 1.270 +# prebound - TupleN<P1, .. PN> 1.271 +# calltime - TupleN<A1, .. AN> 1.272 +# params - X1,.. , A1, .. 1.273 +# args - const P1& p1 .. 1.274 +# call_args - p1, p2, p3.. 1.275 +CREATE_METHOD_FUNCTOR_TEMPLATE = """\ 1.276 +template <typename R, typename T, typename U, %(template_params)s> 1.277 +inline MutantFunctor<R, %(calltime)s> 1.278 +CreateFunctor(T* obj, R (U::*method)(%(params)s), %(args)s) { 1.279 + MutantRunner<R, %(calltime)s>* t = 1.280 + new Mutant<R, T, R (U::*)(%(params)s), 1.281 + %(prebound)s, %(calltime)s> 1.282 + (obj, method, MakeTuple(%(call_args)s)); 1.283 + return MutantFunctor<R, %(calltime)s>(t); 1.284 +} 1.285 +""" 1.286 + 1.287 +CREATE_FUNCTION_FUNCTOR_TEMPLATE = """\ 1.288 +template <typename R, %(template_params)s> 1.289 +inline MutantFunctor<R, %(calltime)s> 1.290 +CreateFunctor(R (*function)(%(params)s), %(args)s) { 1.291 + MutantRunner<R, %(calltime)s>* t = 1.292 + new MutantFunction<R, R (*)(%(params)s), 1.293 + %(prebound)s, %(calltime)s> 1.294 + (function, MakeTuple(%(call_args)s)); 1.295 + return MutantFunctor<R, %(calltime)s>(t); 1.296 +} 1.297 +""" 1.298 + 1.299 +def SplitLine(line, width): 1.300 + """Splits a single line at comma, at most |width| characters long.""" 1.301 + if len(line) < width: 1.302 + return (line, None) 1.303 + n = 1 + line[:width].rfind(",") 1.304 + if n == 0: # If comma cannot be found give up and return the entire line. 1.305 + return (line, None) 1.306 + # Assume there is a space after the comma 1.307 + assert line[n] == " " 1.308 + return (line[:n], line[n + 1:]) 1.309 + 1.310 + 1.311 +def Wrap(s, width, subsequent_offset=4): 1.312 + """Wraps a single line |s| at commas so every line is at most |width| 1.313 + characters long. 1.314 + """ 1.315 + w = [] 1.316 + spaces = " " * subsequent_offset 1.317 + while s: 1.318 + (f, s) = SplitLine(s, width) 1.319 + w.append(f) 1.320 + if s: 1.321 + s = spaces + s 1.322 + return "\n".join(w) 1.323 + 1.324 + 1.325 +def Clean(s): 1.326 + """Cleans artifacts from generated C++ code. 1.327 + 1.328 + Our simple string formatting/concatenation may introduce extra commas. 1.329 + """ 1.330 + s = s.replace("<>", "") 1.331 + s = s.replace(", >", ">") 1.332 + s = s.replace(", )", ")") 1.333 + s = s.replace(">>", "> >") 1.334 + return s 1.335 + 1.336 + 1.337 +def ExpandPattern(pattern, it): 1.338 + """Return list of expanded pattern strings. 1.339 + 1.340 + Each string is created by replacing all '%' in |pattern| with element of |it|. 1.341 + """ 1.342 + return [pattern.replace("%", x) for x in it] 1.343 + 1.344 + 1.345 +def Gen(pattern, n): 1.346 + """Expands pattern replacing '%' with sequential integers. 1.347 + 1.348 + Expanded patterns will be joined with comma separator. 1.349 + GenAlphs("X%", 3) will return "X1, X2, X3". 1.350 + """ 1.351 + it = string.hexdigits[1:n + 1] 1.352 + return ", ".join(ExpandPattern(pattern, it)) 1.353 + 1.354 + 1.355 +def GenAlpha(pattern, n): 1.356 + """Expands pattern replacing '%' with sequential small ASCII letters. 1.357 + 1.358 + Expanded patterns will be joined with comma separator. 1.359 + GenAlphs("X%", 3) will return "Xa, Xb, Xc". 1.360 + """ 1.361 + it = string.ascii_lowercase[0:n] 1.362 + return ", ".join(ExpandPattern(pattern, it)) 1.363 + 1.364 + 1.365 +def Merge(a): 1.366 + return ", ".join(filter(len, a)) 1.367 + 1.368 + 1.369 +def GenTuple(pattern, n): 1.370 + return Clean("Tuple%d<%s>" % (n, Gen(pattern, n))) 1.371 + 1.372 + 1.373 +def FixCode(s): 1.374 + lines = Clean(s).splitlines() 1.375 + # Wrap sometimes very long 1st and 3rd line at 80th column. 1.376 + lines[0] = Wrap(lines[0], 80, 10) 1.377 + lines[2] = Wrap(lines[2], 80, 4) 1.378 + return "\n".join(lines) 1.379 + 1.380 + 1.381 +def GenerateDispatch(prebound, calltime): 1.382 + print "\n// %d - %d" % (prebound, calltime) 1.383 + args = { 1.384 + "template_params": Merge([Gen("typename P%", prebound), 1.385 + Gen("typename C%", calltime)]), 1.386 + "prebound": GenTuple("P%", prebound), 1.387 + "calltime": GenTuple("C%", calltime), 1.388 + "args": Merge([GenAlpha("p.%", prebound), GenAlpha("c.%", calltime)]), 1.389 + } 1.390 + 1.391 + print FixCode(DISPATCH_TO_METHOD_TEMPLATE % args) 1.392 + print FixCode(DISPATCH_TO_FUNCTION_TEMPLATE % args) 1.393 + 1.394 + 1.395 +def GenerateCreateFunctor(prebound, calltime): 1.396 + print "// %d - %d" % (prebound, calltime) 1.397 + args = { 1.398 + "calltime": GenTuple("A%", calltime), 1.399 + "prebound": GenTuple("P%", prebound), 1.400 + "params": Merge([Gen("X%", prebound), Gen("A%", calltime)]), 1.401 + "args": Gen("const P%& p%", prebound), 1.402 + "call_args": Gen("p%", prebound), 1.403 + "template_params": Merge([Gen("typename P%", prebound), 1.404 + Gen("typename A%", calltime), 1.405 + Gen("typename X%", prebound)]) 1.406 + } 1.407 + 1.408 + mutant = FixCode(CREATE_METHOD_FUNCTOR_TEMPLATE % args) 1.409 + print mutant 1.410 + 1.411 + # Slightly different version for free function call. 1.412 + print "\n", FixCode(CREATE_FUNCTION_FUNCTOR_TEMPLATE % args) 1.413 + 1.414 + # Functor with pointer to a pointer of the object. 1.415 + print "\n#ifdef GMOCK_MUTANT_INCLUDE_LATE_OBJECT_BINDING" 1.416 + mutant2 = mutant.replace("CreateFunctor(T* obj,", "CreateFunctor(T** obj,") 1.417 + mutant2 = mutant2.replace("new Mutant", "new MutantLateObjectBind") 1.418 + mutant2 = mutant2.replace(" " * 17 + "Tuple", " " * 31 + "Tuple") 1.419 + print mutant2 1.420 + print "#endif // GMOCK_MUTANT_INCLUDE_LATE_OBJECT_BINDING\n" 1.421 + 1.422 + # OS_WIN specific. Same functors but with stdcall calling conventions. 1.423 + # Functor for method with __stdcall calling conventions. 1.424 + print "#if defined (OS_WIN)" 1.425 + stdcall_method = CREATE_METHOD_FUNCTOR_TEMPLATE 1.426 + stdcall_method = stdcall_method.replace("U::", "__stdcall U::") 1.427 + stdcall_method = FixCode(stdcall_method % args) 1.428 + print stdcall_method 1.429 + # Functor for free function with __stdcall calling conventions. 1.430 + stdcall_function = CREATE_FUNCTION_FUNCTOR_TEMPLATE 1.431 + stdcall_function = stdcall_function.replace("R (*", "R (__stdcall *"); 1.432 + print "\n", FixCode(stdcall_function % args) 1.433 + 1.434 + print "#ifdef GMOCK_MUTANT_INCLUDE_LATE_OBJECT_BINDING" 1.435 + stdcall2 = stdcall_method; 1.436 + stdcall2 = stdcall2.replace("CreateFunctor(T* obj,", "CreateFunctor(T** obj,") 1.437 + stdcall2 = stdcall2.replace("new Mutant", "new MutantLateObjectBind") 1.438 + stdcall2 = stdcall2.replace(" " * 17 + "Tuple", " " * 31 + "Tuple") 1.439 + print stdcall2 1.440 + print "#endif // GMOCK_MUTANT_INCLUDE_LATE_OBJECT_BINDING" 1.441 + print "#endif // OS_WIN\n" 1.442 + 1.443 + 1.444 +def main(): 1.445 + print HEADER 1.446 + for prebound in xrange(0, 6 + 1): 1.447 + for args in xrange(0, 6 + 1): 1.448 + GenerateDispatch(prebound, args) 1.449 + print MUTANT 1.450 + for prebound in xrange(0, 6 + 1): 1.451 + for args in xrange(0, 6 + 1): 1.452 + GenerateCreateFunctor(prebound, args) 1.453 + print FOOTER 1.454 + return 0 1.455 + 1.456 + 1.457 +if __name__ == "__main__": 1.458 + sys.exit(main())