From 5f8de423f190bbb79a62f804151bc24824fa32d8 Mon Sep 17 00:00:00 2001 From: "Matt A. Tobin" Date: Fri, 2 Feb 2018 04:16:08 -0500 Subject: Add m-esr52 at 52.6.0 --- .../webrtc/trunk/testing/generate_gmock_mutant.py | 455 +++++++++++++++++++++ 1 file changed, 455 insertions(+) create mode 100755 media/webrtc/trunk/testing/generate_gmock_mutant.py (limited to 'media/webrtc/trunk/testing/generate_gmock_mutant.py') diff --git a/media/webrtc/trunk/testing/generate_gmock_mutant.py b/media/webrtc/trunk/testing/generate_gmock_mutant.py new file mode 100755 index 000000000..01176da39 --- /dev/null +++ b/media/webrtc/trunk/testing/generate_gmock_mutant.py @@ -0,0 +1,455 @@ +#!/usr/bin/env python +# Copyright (c) 2011 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import string +import sys + +HEADER = """\ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// This file automatically generated by testing/generate_gmock_mutant.py. +// DO NOT EDIT. + +#ifndef TESTING_GMOCK_MUTANT_H_ +#define TESTING_GMOCK_MUTANT_H_ + +// The intention of this file is to make possible using GMock actions in +// all of its syntactic beauty. Classes and helper functions can be used as +// more generic variants of Task and Callback classes (see base/task.h) +// Mutant supports both pre-bound arguments (like Task) and call-time +// arguments (like Callback) - hence the name. :-) +// +// DispatchToMethod/Function supports two sets of arguments: pre-bound (P) and +// call-time (C). The arguments as well as the return type are templatized. +// DispatchToMethod/Function will also try to call the selected method or +// function even if provided pre-bound arguments does not match exactly with +// the function signature hence the X1, X2 ... XN parameters in CreateFunctor. +// DispatchToMethod will try to invoke method that may not belong to the +// object's class itself but to the object's class base class. +// +// Additionally you can bind the object at calltime by binding a pointer to +// pointer to the object at creation time - before including this file you +// have to #define GMOCK_MUTANT_INCLUDE_LATE_OBJECT_BINDING. +// +// TODO(stoyan): It's yet not clear to me should we use T& and T&* instead +// of T* and T** when we invoke CreateFunctor to match the EXPECT_CALL style. +// +// +// Sample usage with gMock: +// +// struct Mock : public ObjectDelegate { +// MOCK_METHOD2(string, OnRequest(int n, const string& request)); +// MOCK_METHOD1(void, OnQuit(int exit_code)); +// MOCK_METHOD2(void, LogMessage(int level, const string& message)); +// +// string HandleFlowers(const string& reply, int n, const string& request) { +// string result = SStringPrintf("In request of %d %s ", n, request); +// for (int i = 0; i < n; ++i) result.append(reply) +// return result; +// } +// +// void DoLogMessage(int level, const string& message) { +// } +// +// void QuitMessageLoop(int seconds) { +// MessageLoop* loop = MessageLoop::current(); +// loop->PostDelayedTask(FROM_HERE, MessageLoop::QuitClosure(), +// 1000 * seconds); +// } +// }; +// +// Mock mock; +// // Will invoke mock.HandleFlowers("orchids", n, request) +// // "orchids" is a pre-bound argument, and and are call-time +// // arguments - they are not known until the OnRequest mock is invoked. +// EXPECT_CALL(mock, OnRequest(Ge(5), StartsWith("flower")) +// .Times(1) +// .WillOnce(Invoke(CreateFunctor(&mock, &Mock::HandleFlowers, +// string("orchids")))); +// +// +// // No pre-bound arguments, two call-time arguments passed +// // directly to DoLogMessage +// EXPECT_CALL(mock, OnLogMessage(_, _)) +// .Times(AnyNumber()) +// .WillAlways(Invoke(CreateFunctor, &mock, &Mock::DoLogMessage)); +// +// +// // In this case we have a single pre-bound argument - 3. We ignore +// // all of the arguments of OnQuit. +// EXCEPT_CALL(mock, OnQuit(_)) +// .Times(1) +// .WillOnce(InvokeWithoutArgs(CreateFunctor( +// &mock, &Mock::QuitMessageLoop, 3))); +// +// MessageLoop loop; +// loop.Run(); +// +// +// // Here is another example of how we can set an action that invokes +// // method of an object that is not yet created. +// struct Mock : public ObjectDelegate { +// MOCK_METHOD1(void, DemiurgeCreated(Demiurge*)); +// MOCK_METHOD2(void, OnRequest(int count, const string&)); +// +// void StoreDemiurge(Demiurge* w) { +// demiurge_ = w; +// } +// +// Demiurge* demiurge; +// } +// +// EXPECT_CALL(mock, DemiurgeCreated(_)).Times(1) +// .WillOnce(Invoke(CreateFunctor(&mock, &Mock::StoreDemiurge))); +// +// EXPECT_CALL(mock, OnRequest(_, StrEq("Moby Dick"))) +// .Times(AnyNumber()) +// .WillAlways(WithArgs<0>(Invoke( +// CreateFunctor(&mock->demiurge_, &Demiurge::DecreaseMonsters)))); +// + +#include "base/memory/linked_ptr.h" +#include "base/tuple.h" // for Tuple + +namespace testing {""" + +MUTANT = """\ + +// Interface that is exposed to the consumer, that does the actual calling +// of the method. +template +class MutantRunner { + public: + virtual R RunWithParams(const Params& params) = 0; + virtual ~MutantRunner() {} +}; + +// Mutant holds pre-bound arguments (like Task). Like Callback +// allows call-time arguments. You bind a pointer to the object +// at creation time. +template +class Mutant : public MutantRunner { + public: + Mutant(T* obj, Method method, const PreBound& pb) + : obj_(obj), method_(method), pb_(pb) { + } + + // MutantRunner implementation + virtual R RunWithParams(const Params& params) { + return DispatchToMethod(this->obj_, this->method_, pb_, params); + } + + T* obj_; + Method method_; + PreBound pb_; +}; + +template +class MutantFunction : public MutantRunner { + public: + MutantFunction(Function function, const PreBound& pb) + : function_(function), pb_(pb) { + } + + // MutantRunner implementation + virtual R RunWithParams(const Params& params) { + return DispatchToFunction(function_, pb_, params); + } + + Function function_; + PreBound pb_; +}; + +#ifdef GMOCK_MUTANT_INCLUDE_LATE_OBJECT_BINDING +// MutantLateBind is like Mutant, but you bind a pointer to a pointer +// to the object. This way you can create actions for an object +// that is not yet created (has only storage for a pointer to it). +template +class MutantLateObjectBind : public MutantRunner { + public: + MutantLateObjectBind(T** obj, Method method, const PreBound& pb) + : obj_(obj), method_(method), pb_(pb) { + } + + // MutantRunner implementation. + virtual R RunWithParams(const Params& params) { + EXPECT_THAT(*this->obj_, testing::NotNull()); + if (NULL == *this->obj_) + return R(); + return DispatchToMethod( *this->obj_, this->method_, pb_, params); + } + + T** obj_; + Method method_; + PreBound pb_; +}; +#endif + +// Simple MutantRunner<> wrapper acting as a functor. +// Redirects operator() to MutantRunner::Run() +template +struct MutantFunctor { + explicit MutantFunctor(MutantRunner* cb) : impl_(cb) { + } + + ~MutantFunctor() { + } + + inline R operator()() { + return impl_->RunWithParams(Tuple0()); + } + + template + inline R operator()(const Arg1& a) { + return impl_->RunWithParams(Params(a)); + } + + template + inline R operator()(const Arg1& a, const Arg2& b) { + return impl_->RunWithParams(Params(a, b)); + } + + template + inline R operator()(const Arg1& a, const Arg2& b, const Arg3& c) { + return impl_->RunWithParams(Params(a, b, c)); + } + + template + inline R operator()(const Arg1& a, const Arg2& b, const Arg3& c, + const Arg4& d) { + return impl_->RunWithParams(Params(a, b, c, d)); + } + + private: + // We need copy constructor since MutantFunctor is copied few times + // inside GMock machinery, hence no DISALLOW_EVIL_CONTRUCTORS + MutantFunctor(); + linked_ptr > impl_; +}; +""" + +FOOTER = """\ +} // namespace testing + +#endif // TESTING_GMOCK_MUTANT_H_""" + +# Templates for DispatchToMethod/DispatchToFunction functions. +# template_params - typename P1, typename P2.. typename C1.. +# prebound - TupleN +# calltime - TupleN +# args - p.a, p.b.., c.a, c.b.. +DISPATCH_TO_METHOD_TEMPLATE = """\ +template +inline R DispatchToMethod(T* obj, Method method, + const %(prebound)s& p, + const %(calltime)s& c) { + return (obj->*method)(%(args)s); +} +""" + +DISPATCH_TO_FUNCTION_TEMPLATE = """\ +template +inline R DispatchToFunction(Function function, + const %(prebound)s& p, + const %(calltime)s& c) { + return (*function)(%(args)s); +} +""" + +# Templates for CreateFunctor functions. +# template_params - typename P1, typename P2.. typename C1.. typename X1.. +# prebound - TupleN +# calltime - TupleN +# params - X1,.. , A1, .. +# args - const P1& p1 .. +# call_args - p1, p2, p3.. +CREATE_METHOD_FUNCTOR_TEMPLATE = """\ +template +inline MutantFunctor +CreateFunctor(T* obj, R (U::*method)(%(params)s), %(args)s) { + MutantRunner* t = + new Mutant + (obj, method, base::MakeTuple(%(call_args)s)); + return MutantFunctor(t); +} +""" + +CREATE_FUNCTION_FUNCTOR_TEMPLATE = """\ +template +inline MutantFunctor +CreateFunctor(R (*function)(%(params)s), %(args)s) { + MutantRunner* t = + new MutantFunction + (function, base::MakeTuple(%(call_args)s)); + return MutantFunctor(t); +} +""" + +def SplitLine(line, width): + """Splits a single line at comma, at most |width| characters long.""" + if len(line) < width: + return (line, None) + n = 1 + line[:width].rfind(",") + if n == 0: # If comma cannot be found give up and return the entire line. + return (line, None) + # Assume there is a space after the comma + assert line[n] == " " + return (line[:n], line[n + 1:]) + + +def Wrap(s, width, subsequent_offset=4): + """Wraps a single line |s| at commas so every line is at most |width| + characters long. + """ + w = [] + spaces = " " * subsequent_offset + while s: + (f, s) = SplitLine(s, width) + w.append(f) + if s: + s = spaces + s + return "\n".join(w) + + +def Clean(s): + """Cleans artifacts from generated C++ code. + + Our simple string formatting/concatenation may introduce extra commas. + """ + s = s.replace("<>", "") + s = s.replace(", >", ">") + s = s.replace(", )", ")") + s = s.replace(">>", "> >") + return s + + +def ExpandPattern(pattern, it): + """Return list of expanded pattern strings. + + Each string is created by replacing all '%' in |pattern| with element of |it|. + """ + return [pattern.replace("%", x) for x in it] + + +def Gen(pattern, n): + """Expands pattern replacing '%' with sequential integers. + + Expanded patterns will be joined with comma separator. + GenAlphs("X%", 3) will return "X1, X2, X3". + """ + it = string.hexdigits[1:n + 1] + return ", ".join(ExpandPattern(pattern, it)) + + +def GenAlpha(pattern, n): + """Expands pattern replacing '%' with sequential small ASCII letters. + + Expanded patterns will be joined with comma separator. + GenAlphs("X%", 3) will return "Xa, Xb, Xc". + """ + it = string.ascii_lowercase[0:n] + return ", ".join(ExpandPattern(pattern, it)) + + +def Merge(a): + return ", ".join(filter(len, a)) + + +def GenTuple(pattern, n): + return Clean("Tuple%d<%s>" % (n, Gen(pattern, n))) + + +def FixCode(s): + lines = Clean(s).splitlines() + # Wrap sometimes very long 1st and 3rd line at 80th column. + lines[0] = Wrap(lines[0], 80, 10) + lines[2] = Wrap(lines[2], 80, 4) + return "\n".join(lines) + + +def GenerateDispatch(prebound, calltime): + print "\n// %d - %d" % (prebound, calltime) + args = { + "template_params": Merge([Gen("typename P%", prebound), + Gen("typename C%", calltime)]), + "prebound": GenTuple("P%", prebound), + "calltime": GenTuple("C%", calltime), + "args": Merge([GenAlpha("p.%", prebound), GenAlpha("c.%", calltime)]), + } + + print FixCode(DISPATCH_TO_METHOD_TEMPLATE % args) + print FixCode(DISPATCH_TO_FUNCTION_TEMPLATE % args) + + +def GenerateCreateFunctor(prebound, calltime): + print "// %d - %d" % (prebound, calltime) + args = { + "calltime": GenTuple("A%", calltime), + "prebound": GenTuple("P%", prebound), + "params": Merge([Gen("X%", prebound), Gen("A%", calltime)]), + "args": Gen("const P%& p%", prebound), + "call_args": Gen("p%", prebound), + "template_params": Merge([Gen("typename P%", prebound), + Gen("typename A%", calltime), + Gen("typename X%", prebound)]) + } + + mutant = FixCode(CREATE_METHOD_FUNCTOR_TEMPLATE % args) + print mutant + + # Slightly different version for free function call. + print "\n", FixCode(CREATE_FUNCTION_FUNCTOR_TEMPLATE % args) + + # Functor with pointer to a pointer of the object. + print "\n#ifdef GMOCK_MUTANT_INCLUDE_LATE_OBJECT_BINDING" + mutant2 = mutant.replace("CreateFunctor(T* obj,", "CreateFunctor(T** obj,") + mutant2 = mutant2.replace("new Mutant", "new MutantLateObjectBind") + mutant2 = mutant2.replace(" " * 17 + "Tuple", " " * 31 + "Tuple") + print mutant2 + print "#endif // GMOCK_MUTANT_INCLUDE_LATE_OBJECT_BINDING\n" + + # OS_WIN specific. Same functors but with stdcall calling conventions. + # Functor for method with __stdcall calling conventions. + print "#if defined (OS_WIN)" + stdcall_method = CREATE_METHOD_FUNCTOR_TEMPLATE + stdcall_method = stdcall_method.replace("U::", "__stdcall U::") + stdcall_method = FixCode(stdcall_method % args) + print stdcall_method + # Functor for free function with __stdcall calling conventions. + stdcall_function = CREATE_FUNCTION_FUNCTOR_TEMPLATE + stdcall_function = stdcall_function.replace("R (*", "R (__stdcall *"); + print "\n", FixCode(stdcall_function % args) + + print "#ifdef GMOCK_MUTANT_INCLUDE_LATE_OBJECT_BINDING" + stdcall2 = stdcall_method; + stdcall2 = stdcall2.replace("CreateFunctor(T* obj,", "CreateFunctor(T** obj,") + stdcall2 = stdcall2.replace("new Mutant", "new MutantLateObjectBind") + stdcall2 = stdcall2.replace(" " * 17 + "Tuple", " " * 31 + "Tuple") + print stdcall2 + print "#endif // GMOCK_MUTANT_INCLUDE_LATE_OBJECT_BINDING" + print "#endif // OS_WIN\n" + + +def main(): + print HEADER + for prebound in xrange(0, 6 + 1): + for args in xrange(0, 6 + 1): + GenerateDispatch(prebound, args) + print MUTANT + for prebound in xrange(0, 6 + 1): + for args in xrange(0, 6 + 1): + GenerateCreateFunctor(prebound, args) + print FOOTER + return 0 + + +if __name__ == "__main__": + sys.exit(main()) -- cgit v1.2.3