diff options
Diffstat (limited to 'googlemock')
48 files changed, 5025 insertions, 9231 deletions
diff --git a/googlemock/CMakeLists.txt b/googlemock/CMakeLists.txt index d32b70b5..8ab59d7f 100644 --- a/googlemock/CMakeLists.txt +++ b/googlemock/CMakeLists.txt @@ -166,7 +166,6 @@ $env:Path = \"$project_bin;$env:Path\" cxx_test(gmock_ex_test gmock_main) cxx_test(gmock-function-mocker_test gmock_main) cxx_test(gmock-generated-actions_test gmock_main) - cxx_test(gmock-generated-function-mockers_test gmock_main) cxx_test(gmock-generated-matchers_test gmock_main) cxx_test(gmock-internal-utils_test gmock_main) cxx_test(gmock-matchers_test gmock_main) diff --git a/googlemock/cmake/gmock.pc.in b/googlemock/cmake/gmock.pc.in index 08e04547..5780fcaa 100644 --- a/googlemock/cmake/gmock.pc.in +++ b/googlemock/cmake/gmock.pc.in @@ -1,6 +1,5 @@ -prefix=${pcfiledir}/../.. -libdir=${prefix}/@CMAKE_INSTALL_LIBDIR@ -includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@ +libdir=@CMAKE_INSTALL_FULL_LIBDIR@ +includedir=@CMAKE_INSTALL_FULL_INCLUDEDIR@ Name: gmock Description: GoogleMock (without main() function) @@ -8,4 +7,4 @@ Version: @PROJECT_VERSION@ URL: https://github.com/google/googletest Requires: gtest Libs: -L${libdir} -lgmock @CMAKE_THREAD_LIBS_INIT@ -Cflags: -I${includedir} @GTEST_HAS_PTHREAD_MACRO@ @CMAKE_THREAD_LIBS_INIT@ +Cflags: -I${includedir} @GTEST_HAS_PTHREAD_MACRO@ diff --git a/googlemock/cmake/gmock_main.pc.in b/googlemock/cmake/gmock_main.pc.in index b22fe614..f2dfe69e 100644 --- a/googlemock/cmake/gmock_main.pc.in +++ b/googlemock/cmake/gmock_main.pc.in @@ -1,6 +1,5 @@ -prefix=${pcfiledir}/../.. -libdir=${prefix}/@CMAKE_INSTALL_LIBDIR@ -includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@ +libdir=@CMAKE_INSTALL_FULL_LIBDIR@ +includedir=@CMAKE_INSTALL_FULL_INCLUDEDIR@ Name: gmock_main Description: GoogleMock (with main() function) @@ -8,4 +7,4 @@ Version: @PROJECT_VERSION@ URL: https://github.com/google/googletest Requires: gmock Libs: -L${libdir} -lgmock_main @CMAKE_THREAD_LIBS_INIT@ -Cflags: -I${includedir} @GTEST_HAS_PTHREAD_MACRO@ @CMAKE_THREAD_LIBS_INIT@ +Cflags: -I${includedir} @GTEST_HAS_PTHREAD_MACRO@ diff --git a/googlemock/docs/cheat_sheet.md b/googlemock/docs/cheat_sheet.md index 850963af..1e0541ba 100644 --- a/googlemock/docs/cheat_sheet.md +++ b/googlemock/docs/cheat_sheet.md @@ -266,7 +266,7 @@ Matcher | Description | `IsTrue()` | `argument` evaluates to `true` in a Boolean context. | | `IsNull()` | `argument` is a `NULL` pointer (raw or smart). | | `NotNull()` | `argument` is a non-null pointer (raw or smart). | -| `Optional(m)` | `argument` is `optional<>` that contains a value matching `m`. | +| `Optional(m)` | `argument` is `optional<>` that contains a value matching `m`. (For testing whether an `optional<>` is set, check for equality with `nullopt`. You may need to use `Eq(nullopt)` if the inner type doesn't have `==`.)| | `VariantWith<T>(m)` | `argument` is `variant<>` that holds the alternative of type T with a value matching `m`. | | `Ref(variable)` | `argument` is a reference to `variable`. | | `TypedEq<type>(value)` | `argument` has type `type` and is equal to `value`. You may need to use this instead of `Eq(value)` when the mock function is overloaded. | @@ -278,6 +278,12 @@ copy constructor, try wrap it in `ByRef()`, e.g. `Eq(ByRef(non_copyable_value))`. If you do that, make sure `non_copyable_value` is not changed afterwards, or the meaning of your matcher will be changed. +`IsTrue` and `IsFalse` are useful when you need to use a matcher, or for types +that can be explicitly converted to Boolean, but are not implicitly converted to +Boolean. In other cases, you can use the basic +[`EXPECT_TRUE` and `EXPECT_FALSE`](../../googletest/docs/primer#basic-assertions) +assertions. + #### Floating-Point Matchers {#FpMatchers} <!-- mdformat off(no multiline tables) --> @@ -287,6 +293,7 @@ is not changed afterwards, or the meaning of your matcher will be changed. | `FloatEq(a_float)` | `argument` is a `float` value approximately equal to `a_float`, treating two NaNs as unequal. | | `NanSensitiveDoubleEq(a_double)` | `argument` is a `double` value approximately equal to `a_double`, treating two NaNs as equal. | | `NanSensitiveFloatEq(a_float)` | `argument` is a `float` value approximately equal to `a_float`, treating two NaNs as equal. | +| `IsNan()` | `argument` is any floating-point type with a NaN value. | <!-- mdformat on --> The above matchers use ULP-based comparison (the same as used in googletest). @@ -325,9 +332,9 @@ The `argument` can be either a C string or a C++ string object: `ContainsRegex()` and `MatchesRegex()` take ownership of the `RE` object. They use the regular expression syntax defined -[here](../../googletest/docs/advanced.md#regular-expression-syntax). -`StrCaseEq()`, `StrCaseNe()`, `StrEq()`, and `StrNe()` work for wide strings as -well. +[here](../../googletest/docs/advanced.md#regular-expression-syntax). All of +these matchers, except `ContainsRegex()` and `MatchesRegex()` work for wide +strings as well. #### Container Matchers @@ -482,7 +489,7 @@ which must be a permanent callback. | Matcher | Description | | :----------------------------------- | :------------------------------------ | | `MATCHER(IsEven, "") { return (arg % 2) == 0; }` | Defines a matcher `IsEven()` to match an even number. | -| `MATCHER_P(IsDivisibleBy, n, "") { *result_listener << "where the remainder is " << (arg % n); return (arg % n) == 0; }` | Defines a macher `IsDivisibleBy(n)` to match a number divisible by `n`. | +| `MATCHER_P(IsDivisibleBy, n, "") { *result_listener << "where the remainder is " << (arg % n); return (arg % n) == 0; }` | Defines a matcher `IsDivisibleBy(n)` to match a number divisible by `n`. | | `MATCHER_P2(IsBetween, a, b, std::string(negation ? "isn't" : "is") + " between " + PrintToString(a) + " and " + PrintToString(b)) { return a <= arg && arg <= b; }` | Defines a matcher `IsBetween(a, b)` to match a value in the range [`a`, `b`]. | <!-- mdformat on --> @@ -502,16 +509,17 @@ which must be a permanent callback. #### Returning a Value <!-- mdformat off(no multiline tables) --> -| | | -| :-------------------------- | :-------------------------------------------- | -| `Return()` | Return from a `void` mock function. | -| `Return(value)` | Return `value`. If the type of `value` is different to the mock function's return type, `value` is converted to the latter type <i>at the time the expectation is set</i>, not when the action is executed. | -| `ReturnArg<N>()` | Return the `N`-th (0-based) argument. | -| `ReturnNew<T>(a1, ..., ak)` | Return `new T(a1, ..., ak)`; a different object is created each time. | -| `ReturnNull()` | Return a null pointer. | -| `ReturnPointee(ptr)` | Return the value pointed to by `ptr`. | -| `ReturnRef(variable)` | Return a reference to `variable`. | -| `ReturnRefOfCopy(value)` | Return a reference to a copy of `value`; the copy lives as long as the action. | +| | | +| :-------------------------------- | :-------------------------------------------- | +| `Return()` | Return from a `void` mock function. | +| `Return(value)` | Return `value`. If the type of `value` is different to the mock function's return type, `value` is converted to the latter type <i>at the time the expectation is set</i>, not when the action is executed. | +| `ReturnArg<N>()` | Return the `N`-th (0-based) argument. | +| `ReturnNew<T>(a1, ..., ak)` | Return `new T(a1, ..., ak)`; a different object is created each time. | +| `ReturnNull()` | Return a null pointer. | +| `ReturnPointee(ptr)` | Return the value pointed to by `ptr`. | +| `ReturnRef(variable)` | Return a reference to `variable`. | +| `ReturnRefOfCopy(value)` | Return a reference to a copy of `value`; the copy lives as long as the action. | +| `ReturnRoundRobin({a1, ..., ak})` | Each call will return the next `ai` in the list, starting at the beginning when the end of the list is reached. | <!-- mdformat on --> #### Side Effects @@ -612,19 +620,6 @@ composite action - trying to do so will result in a run-time error. #### Defining Actions -<table border="1" cellspacing="0" cellpadding="1"> - <tr> - <td>`struct SumAction {` <br> -  `template <typename T>` <br> -  `T operator()(T x, Ty) { return x + y; }` <br> - `};` - </td> - <td> Defines a generic functor that can be used as an action summing its - arguments. </td> </tr> - <tr> - </tr> -</table> - <!-- mdformat off(no multiline tables) --> | | | | :--------------------------------- | :-------------------------------------- | diff --git a/googlemock/docs/cook_book.md b/googlemock/docs/cook_book.md index ea55ab35..51eb94a9 100644 --- a/googlemock/docs/cook_book.md +++ b/googlemock/docs/cook_book.md @@ -421,7 +421,7 @@ sadly they are side effects of C++'s limitations): `NiceMock<StrictMock<MockFoo> >`) is **not** supported. 2. `NiceMock<MockFoo>` and `StrictMock<MockFoo>` may not work correctly if the destructor of `MockFoo` is not virtual. We would like to fix this, but it - requires cleaning up existing tests. http://b/28934720 tracks the issue. + requires cleaning up existing tests. 3. During the constructor or destructor of `MockFoo`, the mock object is *not* nice or strict. This may cause surprises if the constructor or destructor calls a mock method on `this` object. (This behavior, however, is consistent @@ -1024,9 +1024,8 @@ using ::testing::Lt; says that the first argument of `InRange()` must not be 0, and must be less than the second argument. -The expression inside `With()` must be a matcher of type -`Matcher< ::std::tuple<A1, ..., An> >`, where `A1`, ..., `An` are the types of -the function arguments. +The expression inside `With()` must be a matcher of type `Matcher<std::tuple<A1, +..., An>>`, where `A1`, ..., `An` are the types of the function arguments. You can also write `AllArgs(m)` instead of `m` inside `.With()`. The two forms are equivalent, but `.With(AllArgs(Lt()))` is more readable than `.With(Lt())`. @@ -1054,8 +1053,8 @@ complete list. Note that if you want to pass the arguments to a predicate of your own (e.g. `.With(Args<0, 1>(Truly(&MyPredicate)))`), that predicate MUST be written to -take a `::std::tuple` as its argument; gMock will pass the `n` selected -arguments as *one* single tuple to the predicate. +take a `std::tuple` as its argument; gMock will pass the `n` selected arguments +as *one* single tuple to the predicate. ### Using Matchers as Predicates @@ -1331,11 +1330,11 @@ class BarPlusBazEqMatcher : public MatcherInterface<const Foo&> { return (foo.bar() + foo.baz()) == expected_sum_; } - void DescribeTo(::std::ostream* os) const override { + void DescribeTo(std::ostream* os) const override { *os << "bar() + baz() equals " << expected_sum_; } - void DescribeNegationTo(::std::ostream* os) const override { + void DescribeNegationTo(std::ostream* os) const override { *os << "bar() + baz() does not equal " << expected_sum_; } private: @@ -2175,7 +2174,7 @@ own precedence order distinct from the `ON_CALL` precedence order. ### Using Functions/Methods/Functors/Lambdas as Actions {#FunctionsAsActions} If the built-in actions don't suit you, you can use an existing callable -(function, `std::function`, method, functor, lambda as an action. +(function, `std::function`, method, functor, lambda) as an action. <!-- GOOGLETEST_CM0024 DO NOT DELETE --> @@ -2203,7 +2202,8 @@ class Helper { .WillOnce(&CalculateSum) .WillRepeatedly(Invoke(NewPermanentCallback(Sum3, 1))); EXPECT_CALL(foo, ComplexJob(_)) - .WillOnce(Invoke(&helper, &Helper::ComplexJob)); + .WillOnce(Invoke(&helper, &Helper::ComplexJob)) + .WillOnce([] { return true; }) .WillRepeatedly([](int x) { return x > 0; }); foo.Sum(5, 6); // Invokes CalculateSum(5, 6). @@ -2213,11 +2213,11 @@ class Helper { ``` The only requirement is that the type of the function, etc must be *compatible* -with the signature of the mock function, meaning that the latter's arguments can -be implicitly converted to the corresponding arguments of the former, and the -former's return type can be implicitly converted to that of the latter. So, you -can invoke something whose type is *not* exactly the same as the mock function, -as long as it's safe to do so - nice, huh? +with the signature of the mock function, meaning that the latter's arguments (if +it takes any) can be implicitly converted to the corresponding arguments of the +former, and the former's return type can be implicitly converted to that of the +latter. So, you can invoke something whose type is *not* exactly the same as the +mock function, as long as it's safe to do so - nice, huh? **`Note:`{.escaped}** @@ -2268,19 +2268,20 @@ TEST_F(FooTest, Test) { ### Invoking a Function/Method/Functor/Lambda/Callback Without Arguments -`Invoke()` is very useful for doing actions that are more complex. It passes the -mock function's arguments to the function, etc being invoked such that the -callee has the full context of the call to work with. If the invoked function is -not interested in some or all of the arguments, it can simply ignore them. +`Invoke()` passes the mock function's arguments to the function, etc being +invoked such that the callee has the full context of the call to work with. If +the invoked function is not interested in some or all of the arguments, it can +simply ignore them. Yet, a common pattern is that a test author wants to invoke a function without -the arguments of the mock function. `Invoke()` allows her to do that using a -wrapper function that throws away the arguments before invoking an underlining -nullary function. Needless to say, this can be tedious and obscures the intent -of the test. +the arguments of the mock function. She could do that using a wrapper function +that throws away the arguments before invoking an underlining nullary function. +Needless to say, this can be tedious and obscures the intent of the test. -`InvokeWithoutArgs()` solves this problem. It's like `Invoke()` except that it -doesn't pass the mock function's arguments to the callee. Here's an example: +There are two solutions to this problem. First, you can pass any callable of +zero args as an action. Alternatively, use `InvokeWithoutArgs()`, which is like +`Invoke()` except that it doesn't pass the mock function's arguments to the +callee. Here's an example of each: ```cpp using ::testing::_; @@ -2297,7 +2298,7 @@ bool Job2(int n, char c) { ... } ... MockFoo foo; EXPECT_CALL(foo, ComplexJob(_)) - .WillOnce(InvokeWithoutArgs(Job1)) + .WillOnce([] { Job1(); }); .WillOnce(InvokeWithoutArgs(NewPermanentCallback(Job2, 5, 'a'))); foo.ComplexJob(10); // Invokes Job1(). @@ -3565,7 +3566,7 @@ class MatchResultListener { MatchResultListener& operator<<(const T& x); // Returns the underlying ostream. - ::std::ostream* stream(); + std::ostream* stream(); }; template <typename T> @@ -3578,10 +3579,10 @@ class MatcherInterface { virtual bool MatchAndExplain(T x, MatchResultListener* listener) const = 0; // Describes this matcher to an ostream. - virtual void DescribeTo(::std::ostream* os) const = 0; + virtual void DescribeTo(std::ostream* os) const = 0; // Describes the negation of this matcher to an ostream. - virtual void DescribeNegationTo(::std::ostream* os) const; + virtual void DescribeNegationTo(std::ostream* os) const; }; ``` @@ -3609,11 +3610,11 @@ class DivisibleBy7Matcher : public MatcherInterface<int> { return (n % 7) == 0; } - void DescribeTo(::std::ostream* os) const override { + void DescribeTo(std::ostream* os) const override { *os << "is divisible by 7"; } - void DescribeNegationTo(::std::ostream* os) const override { + void DescribeNegationTo(std::ostream* os) const override { *os << "is not divisible by 7"; } }; @@ -3995,7 +3996,7 @@ ACTION_TEMPLATE(DuplicateArg, // Note the comma between int and k: HAS_2_TEMPLATE_PARAMS(int, k, typename, T), AND_1_VALUE_PARAMS(output)) { - *output = T(::std::get<k>(args)); + *output = T(std::get<k>(args)); } ``` @@ -4087,7 +4088,7 @@ class ActionInterface { // // For example, if F is int(bool, const string&), then Result would - // be int, and ArgumentTuple would be ::std::tuple<bool, const string&>. + // be int, and ArgumentTuple would be std::tuple<bool, const string&>. virtual Result Perform(const ArgumentTuple& args) = 0; }; ``` @@ -4102,8 +4103,8 @@ typedef int IncrementMethod(int*); class IncrementArgumentAction : public ActionInterface<IncrementMethod> { public: - int Perform(const ::std::tuple<int*>& args) override { - int* p = ::std::get<0>(args); // Grabs the first argument. + int Perform(const std::tuple<int*>& args) override { + int* p = std::get<0>(args); // Grabs the first argument. return *p++; } }; @@ -4148,8 +4149,8 @@ class ReturnSecondArgumentAction { public: template <typename Result, typename ArgumentTuple> Result Perform(const ArgumentTuple& args) const { - // To get the i-th (0-based) argument, use ::std::get(args). - return ::std::get<1>(args); + // To get the i-th (0-based) argument, use std::get(args). + return std::get<1>(args); } }; ``` diff --git a/googlemock/docs/for_dummies.md b/googlemock/docs/for_dummies.md index e11c18d9..93cf06f3 100644 --- a/googlemock/docs/for_dummies.md +++ b/googlemock/docs/for_dummies.md @@ -213,7 +213,7 @@ specific domain much better than `Foo` does. Once you have a mock class, using it is easy. The typical work flow is: 1. Import the gMock names from the `testing` namespace such that you can use - them unqualified (You only have to do it once per file. Remember that + them unqualified (You only have to do it once per file). Remember that namespaces are a good idea. 2. Create some mock objects. 3. Specify your expectations on them (How many times will a method be called? diff --git a/googlemock/docs/pump_manual.md b/googlemock/docs/pump_manual.md new file mode 100644 index 00000000..cdf7c57d --- /dev/null +++ b/googlemock/docs/pump_manual.md @@ -0,0 +1,187 @@ +<b>P</b>ump is <b>U</b>seful for <b>M</b>eta <b>P</b>rogramming. + +# The Problem + +Template and macro libraries often need to define many classes, functions, or +macros that vary only (or almost only) in the number of arguments they take. +It's a lot of repetitive, mechanical, and error-prone work. + +Our experience is that it's tedious to write custom scripts, which tend to +reflect the structure of the generated code poorly and are often hard to read +and edit. For example, a small change needed in the generated code may require +some non-intuitive, non-trivial changes in the script. This is especially +painful when experimenting with the code. + +This script may be useful for generating meta code, for example a series of +macros of FOO1, FOO2, etc. Nevertheless, please make it your last resort +technique by favouring C++ template metaprogramming or variadic macros. + +# Our Solution + +Pump (for Pump is Useful for Meta Programming, Pretty Useful for Meta +Programming, or Practical Utility for Meta Programming, whichever you prefer) is +a simple meta-programming tool for C++. The idea is that a programmer writes a +`foo.pump` file which contains C++ code plus meta code that manipulates the C++ +code. The meta code can handle iterations over a range, nested iterations, local +meta variable definitions, simple arithmetic, and conditional expressions. You +can view it as a small Domain-Specific Language. The meta language is designed +to be non-intrusive (s.t. it won't confuse Emacs' C++ mode, for example) and +concise, making Pump code intuitive and easy to maintain. + +## Highlights + +* The implementation is in a single Python script and thus ultra portable: no + build or installation is needed and it works cross platforms. +* Pump tries to be smart with respect to + [Google's style guide](https://github.com/google/styleguide): it breaks long + lines (easy to have when they are generated) at acceptable places to fit + within 80 columns and indent the continuation lines correctly. +* The format is human-readable and more concise than XML. +* The format works relatively well with Emacs' C++ mode. + +## Examples + +The following Pump code (where meta keywords start with `$`, `[[` and `]]` are +meta brackets, and `$$` starts a meta comment that ends with the line): + +``` +$var n = 3 $$ Defines a meta variable n. +$range i 0..n $$ Declares the range of meta iterator i (inclusive). +$for i [[ + $$ Meta loop. +// Foo$i does blah for $i-ary predicates. +$range j 1..i +template <size_t N $for j [[, typename A$j]]> +class Foo$i { +$if i == 0 [[ + blah a; +]] $elif i <= 2 [[ + blah b; +]] $else [[ + blah c; +]] +}; + +]] +``` + +will be translated by the Pump compiler to: + +```cpp +// Foo0 does blah for 0-ary predicates. +template <size_t N> +class Foo0 { + blah a; +}; + +// Foo1 does blah for 1-ary predicates. +template <size_t N, typename A1> +class Foo1 { + blah b; +}; + +// Foo2 does blah for 2-ary predicates. +template <size_t N, typename A1, typename A2> +class Foo2 { + blah b; +}; + +// Foo3 does blah for 3-ary predicates. +template <size_t N, typename A1, typename A2, typename A3> +class Foo3 { + blah c; +}; +``` + +In another example, + +``` +$range i 1..n +Func($for i + [[a$i]]); +$$ The text between i and [[ is the separator between iterations. +``` + +will generate one of the following lines (without the comments), depending on +the value of `n`: + +```cpp +Func(); // If n is 0. +Func(a1); // If n is 1. +Func(a1 + a2); // If n is 2. +Func(a1 + a2 + a3); // If n is 3. +// And so on... +``` + +## Constructs + +We support the following meta programming constructs: + +| `$var id = exp` | Defines a named constant value. `$id` is | +: : valid util the end of the current meta : +: : lexical block. : +| :------------------------------- | :--------------------------------------- | +| `$range id exp..exp` | Sets the range of an iteration variable, | +: : which can be reused in multiple loops : +: : later. : +| `$for id sep [[ code ]]` | Iteration. The range of `id` must have | +: : been defined earlier. `$id` is valid in : +: : `code`. : +| `$($)` | Generates a single `$` character. | +| `$id` | Value of the named constant or iteration | +: : variable. : +| `$(exp)` | Value of the expression. | +| `$if exp [[ code ]] else_branch` | Conditional. | +| `[[ code ]]` | Meta lexical block. | +| `cpp_code` | Raw C++ code. | +| `$$ comment` | Meta comment. | + +**Note:** To give the user some freedom in formatting the Pump source code, Pump +ignores a new-line character if it's right after `$for foo` or next to `[[` or +`]]`. Without this rule you'll often be forced to write very long lines to get +the desired output. Therefore sometimes you may need to insert an extra new-line +in such places for a new-line to show up in your output. + +## Grammar + +```ebnf +code ::= atomic_code* +atomic_code ::= $var id = exp + | $var id = [[ code ]] + | $range id exp..exp + | $for id sep [[ code ]] + | $($) + | $id + | $(exp) + | $if exp [[ code ]] else_branch + | [[ code ]] + | cpp_code +sep ::= cpp_code | empty_string +else_branch ::= $else [[ code ]] + | $elif exp [[ code ]] else_branch + | empty_string +exp ::= simple_expression_in_Python_syntax +``` + +## Code + +You can find the source code of Pump in [scripts/pump.py](../scripts/pump.py). +It is still very unpolished and lacks automated tests, although it has been +successfully used many times. If you find a chance to use it in your project, +please let us know what you think! We also welcome help on improving Pump. + +## Real Examples + +You can find real-world applications of Pump in +[Google Test](https://github.com/google/googletest/tree/master/googletest) and +[Google Mock](https://github.com/google/googletest/tree/master/googlemock). The +source file `foo.h.pump` generates `foo.h`. + +## Tips + +* If a meta variable is followed by a letter or digit, you can separate them + using `[[]]`, which inserts an empty string. For example `Foo$j[[]]Helper` + generate `Foo1Helper` when `j` is 1. +* To avoid extra-long Pump source lines, you can break a line anywhere you + want by inserting `[[]]` followed by a new line. Since any new-line + character next to `[[` or `]]` is ignored, the generated code won't contain + this new line. diff --git a/googlemock/include/gmock/gmock-actions.h b/googlemock/include/gmock/gmock-actions.h index f12d39be..b4127e93 100644 --- a/googlemock/include/gmock/gmock-actions.h +++ b/googlemock/include/gmock/gmock-actions.h @@ -30,7 +30,100 @@ // Google Mock - a framework for writing C++ mock classes. // -// This file implements some commonly used actions. +// The ACTION* family of macros can be used in a namespace scope to +// define custom actions easily. The syntax: +// +// ACTION(name) { statements; } +// +// will define an action with the given name that executes the +// statements. The value returned by the statements will be used as +// the return value of the action. Inside the statements, you can +// refer to the K-th (0-based) argument of the mock function by +// 'argK', and refer to its type by 'argK_type'. For example: +// +// ACTION(IncrementArg1) { +// arg1_type temp = arg1; +// return ++(*temp); +// } +// +// allows you to write +// +// ...WillOnce(IncrementArg1()); +// +// You can also refer to the entire argument tuple and its type by +// 'args' and 'args_type', and refer to the mock function type and its +// return type by 'function_type' and 'return_type'. +// +// Note that you don't need to specify the types of the mock function +// arguments. However rest assured that your code is still type-safe: +// you'll get a compiler error if *arg1 doesn't support the ++ +// operator, or if the type of ++(*arg1) isn't compatible with the +// mock function's return type, for example. +// +// Sometimes you'll want to parameterize the action. For that you can use +// another macro: +// +// ACTION_P(name, param_name) { statements; } +// +// For example: +// +// ACTION_P(Add, n) { return arg0 + n; } +// +// will allow you to write: +// +// ...WillOnce(Add(5)); +// +// Note that you don't need to provide the type of the parameter +// either. If you need to reference the type of a parameter named +// 'foo', you can write 'foo_type'. For example, in the body of +// ACTION_P(Add, n) above, you can write 'n_type' to refer to the type +// of 'n'. +// +// We also provide ACTION_P2, ACTION_P3, ..., up to ACTION_P10 to support +// multi-parameter actions. +// +// For the purpose of typing, you can view +// +// ACTION_Pk(Foo, p1, ..., pk) { ... } +// +// as shorthand for +// +// template <typename p1_type, ..., typename pk_type> +// FooActionPk<p1_type, ..., pk_type> Foo(p1_type p1, ..., pk_type pk) { ... } +// +// In particular, you can provide the template type arguments +// explicitly when invoking Foo(), as in Foo<long, bool>(5, false); +// although usually you can rely on the compiler to infer the types +// for you automatically. You can assign the result of expression +// Foo(p1, ..., pk) to a variable of type FooActionPk<p1_type, ..., +// pk_type>. This can be useful when composing actions. +// +// You can also overload actions with different numbers of parameters: +// +// ACTION_P(Plus, a) { ... } +// ACTION_P2(Plus, a, b) { ... } +// +// While it's tempting to always use the ACTION* macros when defining +// a new action, you should also consider implementing ActionInterface +// or using MakePolymorphicAction() instead, especially if you need to +// use the action a lot. While these approaches require more work, +// they give you more control on the types of the mock function +// arguments and the action parameters, which in general leads to +// better compiler error messages that pay off in the long run. They +// also allow overloading actions based on parameter types (as opposed +// to just based on the number of parameters). +// +// CAVEAT: +// +// ACTION*() can only be used in a namespace scope as templates cannot be +// declared inside of a local class. +// Users can, however, define any local functors (e.g. a lambda) that +// can be used as actions. +// +// MORE INFORMATION: +// +// To learn more about using these macros, please search for 'ACTION' on +// https://github.com/google/googletest/blob/master/googlemock/docs/cook_book.md // GOOGLETEST_CM0002 DO NOT DELETE @@ -50,6 +143,7 @@ #include "gmock/internal/gmock-internal-utils.h" #include "gmock/internal/gmock-port.h" +#include "gmock/internal/gmock-pp.h" #ifdef _MSC_VER # pragma warning(push) @@ -162,13 +256,17 @@ GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(unsigned int, 0U); GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(signed int, 0); GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(unsigned long, 0UL); // NOLINT GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(signed long, 0L); // NOLINT -GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(UInt64, 0); -GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(Int64, 0); +GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(unsigned long long, 0); // NOLINT +GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(signed long long, 0); // NOLINT GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(float, 0); GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(double, 0); #undef GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_ +// Simple two-arg form of std::disjunction. +template <typename P, typename Q> +using disjunction = typename ::std::conditional<P::value, P, Q>::type; + } // namespace internal // When an unexpected function call is encountered, Google Mock will @@ -362,9 +460,15 @@ class Action { // This cannot take std::function directly, because then Action would not be // directly constructible from lambda (it would require two conversions). template <typename G, - typename = typename ::std::enable_if< - ::std::is_constructible<::std::function<F>, G>::value>::type> - Action(G&& fun) : fun_(::std::forward<G>(fun)) {} // NOLINT + typename IsCompatibleFunctor = + ::std::is_constructible<::std::function<F>, G>, + typename IsNoArgsFunctor = + ::std::is_constructible<::std::function<Result()>, G>, + typename = typename ::std::enable_if<internal::disjunction< + IsCompatibleFunctor, IsNoArgsFunctor>::value>::type> + Action(G&& fun) { // NOLINT + Init(::std::forward<G>(fun), IsCompatibleFunctor()); + } // Constructs an Action from its implementation. explicit Action(ActionInterface<F>* impl) @@ -396,6 +500,26 @@ class Action { template <typename G> friend class Action; + template <typename G> + void Init(G&& g, ::std::true_type) { + fun_ = ::std::forward<G>(g); + } + + template <typename G> + void Init(G&& g, ::std::false_type) { + fun_ = IgnoreArgs<typename ::std::decay<G>::type>{::std::forward<G>(g)}; + } + + template <typename FunctionImpl> + struct IgnoreArgs { + template <typename... Args> + Result operator()(const Args&...) const { + return function_impl(); + } + + FunctionImpl function_impl; + }; + // fun_ is an empty function if and only if this is the DoDefault() action. ::std::function<F> fun_; }; @@ -716,6 +840,36 @@ class ReturnRefOfCopyAction { GTEST_DISALLOW_ASSIGN_(ReturnRefOfCopyAction); }; +// Implements the polymorphic ReturnRoundRobin(v) action, which can be +// used in any function that returns the element_type of v. +template <typename T> +class ReturnRoundRobinAction { + public: + explicit ReturnRoundRobinAction(std::vector<T> values) { + GTEST_CHECK_(!values.empty()) + << "ReturnRoundRobin requires at least one element."; + state_->values = std::move(values); + } + + template <typename... Args> + T operator()(Args&&...) const { + return state_->Next(); + } + + private: + struct State { + T Next() { + T ret_val = values[i++]; + if (i == values.size()) i = 0; + return ret_val; + } + + std::vector<T> values; + size_t i = 0; + }; + std::shared_ptr<State> state_ = std::make_shared<State>(); +}; + // Implements the polymorphic DoDefault() action. class DoDefaultAction { public: @@ -886,7 +1040,8 @@ struct WithArgsAction { // We use the conversion operator to detect the signature of the inner Action. template <typename R, typename... Args> operator Action<R(Args...)>() const { // NOLINT - Action<R(typename std::tuple_element<I, std::tuple<Args...>>::type...)> + using TupleType = std::tuple<Args...>; + Action<R(typename std::tuple_element<I, TupleType>::type...)> converted(action); return [converted](Args... args) -> R { @@ -1022,6 +1177,10 @@ inline internal::ReturnRefAction<R> ReturnRef(R& x) { // NOLINT return internal::ReturnRefAction<R>(x); } +// Prevent using ReturnRef on reference to temporary. +template <typename R, R* = nullptr> +internal::ReturnRefAction<R> ReturnRef(R&&) = delete; + // Creates an action that returns the reference to a copy of the // argument. The copy is created when the action is constructed and // lives as long as the action. @@ -1039,6 +1198,23 @@ internal::ByMoveWrapper<R> ByMove(R x) { return internal::ByMoveWrapper<R>(std::move(x)); } +// Creates an action that returns an element of `vals`. Calling this action will +// repeatedly return the next value from `vals` until it reaches the end and +// will restart from the beginning. +template <typename T> +internal::ReturnRoundRobinAction<T> ReturnRoundRobin(std::vector<T> vals) { + return internal::ReturnRoundRobinAction<T>(std::move(vals)); +} + +// Creates an action that returns an element of `vals`. Calling this action will +// repeatedly return the next value from `vals` until it reaches the end and +// will restart from the beginning. +template <typename T> +internal::ReturnRoundRobinAction<T> ReturnRoundRobin( + std::initializer_list<T> vals) { + return internal::ReturnRoundRobinAction<T>(std::vector<T>(vals)); +} + // Creates an action that does the default action for the give mock function. inline internal::DoDefaultAction DoDefault() { return internal::DoDefaultAction(); @@ -1047,14 +1223,14 @@ inline internal::DoDefaultAction DoDefault() { // Creates an action that sets the variable pointed by the N-th // (0-based) function argument to 'value'. template <size_t N, typename T> -internal::SetArgumentPointeeAction<N, T> SetArgPointee(T x) { - return {std::move(x)}; +internal::SetArgumentPointeeAction<N, T> SetArgPointee(T value) { + return {std::move(value)}; } // The following version is DEPRECATED. template <size_t N, typename T> -internal::SetArgumentPointeeAction<N, T> SetArgumentPointee(T x) { - return {std::move(x)}; +internal::SetArgumentPointeeAction<N, T> SetArgumentPointee(T value) { + return {std::move(value)}; } // Creates an action that sets a pointer referent to a given value. @@ -1132,6 +1308,254 @@ inline ::std::reference_wrapper<T> ByRef(T& l_value) { // NOLINT return ::std::reference_wrapper<T>(l_value); } +namespace internal { + +// A macro from the ACTION* family (defined later in gmock-generated-actions.h) +// defines an action that can be used in a mock function. Typically, +// these actions only care about a subset of the arguments of the mock +// function. For example, if such an action only uses the second +// argument, it can be used in any mock function that takes >= 2 +// arguments where the type of the second argument is compatible. +// +// Therefore, the action implementation must be prepared to take more +// arguments than it needs. The ExcessiveArg type is used to +// represent those excessive arguments. In order to keep the compiler +// error messages tractable, we define it in the testing namespace +// instead of testing::internal. However, this is an INTERNAL TYPE +// and subject to change without notice, so a user MUST NOT USE THIS +// TYPE DIRECTLY. +struct ExcessiveArg {}; + +// A helper class needed for implementing the ACTION* macros. +template <typename Result, class Impl> +class ActionHelper { + public: + template <typename... Ts> + static Result Perform(Impl* impl, const std::tuple<Ts...>& args) { + return Apply(impl, args, MakeIndexSequence<sizeof...(Ts)>{}, + MakeIndexSequence<10 - sizeof...(Ts)>{}); + } + + private: + template <typename... Ts, std::size_t... tuple_ids, std::size_t... rest_ids> + static Result Apply(Impl* impl, const std::tuple<Ts...>& args, + IndexSequence<tuple_ids...>, IndexSequence<rest_ids...>) { + return impl->template gmock_PerformImpl<Ts...>( + args, std::get<tuple_ids>(args)..., + ((void)rest_ids, ExcessiveArg())...); + } +}; + +// A helper base class needed for implementing the ACTION* macros. +// Implements constructor and conversion operator for Action. +// +// Template specialization for parameterless Action. +template <typename Derived> +class ActionImpl { + public: + ActionImpl() = default; + + template <typename F> + operator ::testing::Action<F>() const { // NOLINT(runtime/explicit) + return ::testing::Action<F>(new typename Derived::template gmock_Impl<F>()); + } +}; + +// Template specialization for parameterized Action. +template <template <typename...> class Derived, typename... Ts> +class ActionImpl<Derived<Ts...>> { + public: + explicit ActionImpl(Ts... params) : params_(std::forward<Ts>(params)...) {} + + template <typename F> + operator ::testing::Action<F>() const { // NOLINT(runtime/explicit) + return Apply<F>(MakeIndexSequence<sizeof...(Ts)>{}); + } + + private: + template <typename F, std::size_t... tuple_ids> + ::testing::Action<F> Apply(IndexSequence<tuple_ids...>) const { + return ::testing::Action<F>(new + typename Derived<Ts...>::template gmock_Impl<F>( + std::get<tuple_ids>(params_)...)); + } + + std::tuple<Ts...> params_; +}; + +namespace invoke_argument { + +// Appears in InvokeArgumentAdl's argument list to help avoid +// accidental calls to user functions of the same name. +struct AdlTag {}; + +// InvokeArgumentAdl - a helper for InvokeArgument. +// The basic overloads are provided here for generic functors. +// Overloads for other custom-callables are provided in the +// internal/custom/gmock-generated-actions.h header. +template <typename F, typename... Args> +auto InvokeArgumentAdl(AdlTag, F f, Args... args) -> decltype(f(args...)) { + return f(args...); +} + +} // namespace invoke_argument + +#define GMOCK_INTERNAL_ARG_UNUSED(i, data, el) \ + , const arg##i##_type& arg##i GTEST_ATTRIBUTE_UNUSED_ +#define GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_ \ + const args_type& args GTEST_ATTRIBUTE_UNUSED_ GMOCK_PP_REPEAT( \ + GMOCK_INTERNAL_ARG_UNUSED, , 10) + +#define GMOCK_INTERNAL_ARG(i, data, el) , const arg##i##_type& arg##i +#define GMOCK_ACTION_ARG_TYPES_AND_NAMES_ \ + const args_type& args GMOCK_PP_REPEAT(GMOCK_INTERNAL_ARG, , 10) + +#define GMOCK_INTERNAL_TEMPLATE_ARG(i, data, el) , typename arg##i##_type +#define GMOCK_ACTION_TEMPLATE_ARGS_NAMES_ \ + GMOCK_PP_TAIL(GMOCK_PP_REPEAT(GMOCK_INTERNAL_TEMPLATE_ARG, , 10)) + +#define GMOCK_INTERNAL_TYPENAME_PARAM(i, data, param) , typename param##_type +#define GMOCK_ACTION_TYPENAME_PARAMS_(params) \ + GMOCK_PP_TAIL(GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_TYPENAME_PARAM, , params)) + +#define GMOCK_INTERNAL_TYPE_PARAM(i, data, param) , param##_type +#define GMOCK_ACTION_TYPE_PARAMS_(params) \ + GMOCK_PP_TAIL(GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_TYPE_PARAM, , params)) + +#define GMOCK_INTERNAL_TYPE_GVALUE_PARAM(i, data, param) \ + , param##_type gmock_p##i +#define GMOCK_ACTION_TYPE_GVALUE_PARAMS_(params) \ + GMOCK_PP_TAIL(GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_TYPE_GVALUE_PARAM, , params)) + +#define GMOCK_INTERNAL_GVALUE_PARAM(i, data, param) \ + , std::forward<param##_type>(gmock_p##i) +#define GMOCK_ACTION_GVALUE_PARAMS_(params) \ + GMOCK_PP_TAIL(GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_GVALUE_PARAM, , params)) + +#define GMOCK_INTERNAL_INIT_PARAM(i, data, param) \ + , param(::std::forward<param##_type>(gmock_p##i)) +#define GMOCK_ACTION_INIT_PARAMS_(params) \ + GMOCK_PP_TAIL(GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_INIT_PARAM, , params)) + +#define GMOCK_INTERNAL_FIELD_PARAM(i, data, param) param##_type param; +#define GMOCK_ACTION_FIELD_PARAMS_(params) \ + GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_FIELD_PARAM, , params) + +#define GMOCK_INTERNAL_ACTION(name, full_name, params) \ + template <GMOCK_ACTION_TYPENAME_PARAMS_(params)> \ + class full_name : public ::testing::internal::ActionImpl< \ + full_name<GMOCK_ACTION_TYPE_PARAMS_(params)>> { \ + using base_type = ::testing::internal::ActionImpl<full_name>; \ + \ + public: \ + using base_type::base_type; \ + template <typename F> \ + class gmock_Impl : public ::testing::ActionInterface<F> { \ + public: \ + typedef F function_type; \ + typedef typename ::testing::internal::Function<F>::Result return_type; \ + typedef \ + typename ::testing::internal::Function<F>::ArgumentTuple args_type; \ + explicit gmock_Impl(GMOCK_ACTION_TYPE_GVALUE_PARAMS_(params)) \ + : GMOCK_ACTION_INIT_PARAMS_(params) {} \ + return_type Perform(const args_type& args) override { \ + return ::testing::internal::ActionHelper<return_type, \ + gmock_Impl>::Perform(this, \ + args); \ + } \ + template <GMOCK_ACTION_TEMPLATE_ARGS_NAMES_> \ + return_type gmock_PerformImpl(GMOCK_ACTION_ARG_TYPES_AND_NAMES_) const; \ + GMOCK_ACTION_FIELD_PARAMS_(params) \ + \ + private: \ + GTEST_DISALLOW_ASSIGN_(gmock_Impl); \ + }; \ + \ + private: \ + GTEST_DISALLOW_ASSIGN_(full_name); \ + }; \ + template <GMOCK_ACTION_TYPENAME_PARAMS_(params)> \ + inline full_name<GMOCK_ACTION_TYPE_PARAMS_(params)> name( \ + GMOCK_ACTION_TYPE_GVALUE_PARAMS_(params)) { \ + return full_name<GMOCK_ACTION_TYPE_PARAMS_(params)>( \ + GMOCK_ACTION_GVALUE_PARAMS_(params)); \ + } \ + template <GMOCK_ACTION_TYPENAME_PARAMS_(params)> \ + template <typename F> \ + template <GMOCK_ACTION_TEMPLATE_ARGS_NAMES_> \ + typename ::testing::internal::Function<F>::Result \ + full_name<GMOCK_ACTION_TYPE_PARAMS_(params)>::gmock_Impl< \ + F>::gmock_PerformImpl(GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) \ + const + +} // namespace internal + +#define ACTION(name) \ + class name##Action : public ::testing::internal::ActionImpl<name##Action> { \ + using base_type = ::testing::internal::ActionImpl<name##Action>; \ + \ + public: \ + using base_type::base_type; \ + template <typename F> \ + class gmock_Impl : public ::testing::ActionInterface<F> { \ + public: \ + typedef F function_type; \ + typedef typename ::testing::internal::Function<F>::Result return_type; \ + typedef \ + typename ::testing::internal::Function<F>::ArgumentTuple args_type; \ + gmock_Impl() {} \ + return_type Perform(const args_type& args) override { \ + return ::testing::internal::ActionHelper<return_type, \ + gmock_Impl>::Perform(this, \ + args); \ + } \ + template <GMOCK_ACTION_TEMPLATE_ARGS_NAMES_> \ + return_type gmock_PerformImpl(GMOCK_ACTION_ARG_TYPES_AND_NAMES_) const; \ + \ + private: \ + GTEST_DISALLOW_ASSIGN_(gmock_Impl); \ + }; \ + \ + private: \ + GTEST_DISALLOW_ASSIGN_(name##Action); \ + }; \ + inline name##Action name() { return name##Action(); } \ + template <typename F> \ + template <GMOCK_ACTION_TEMPLATE_ARGS_NAMES_> \ + typename ::testing::internal::Function<F>::Result \ + name##Action::gmock_Impl<F>::gmock_PerformImpl( \ + GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const + +#define ACTION_P(name, ...) \ + GMOCK_INTERNAL_ACTION(name, name##ActionP, (__VA_ARGS__)) + +#define ACTION_P2(name, ...) \ + GMOCK_INTERNAL_ACTION(name, name##ActionP2, (__VA_ARGS__)) + +#define ACTION_P3(name, ...) \ + GMOCK_INTERNAL_ACTION(name, name##ActionP3, (__VA_ARGS__)) + +#define ACTION_P4(name, ...) \ + GMOCK_INTERNAL_ACTION(name, name##ActionP4, (__VA_ARGS__)) + +#define ACTION_P5(name, ...) \ + GMOCK_INTERNAL_ACTION(name, name##ActionP5, (__VA_ARGS__)) + +#define ACTION_P6(name, ...) \ + GMOCK_INTERNAL_ACTION(name, name##ActionP6, (__VA_ARGS__)) + +#define ACTION_P7(name, ...) \ + GMOCK_INTERNAL_ACTION(name, name##ActionP7, (__VA_ARGS__)) + +#define ACTION_P8(name, ...) \ + GMOCK_INTERNAL_ACTION(name, name##ActionP8, (__VA_ARGS__)) + +#define ACTION_P9(name, ...) \ + GMOCK_INTERNAL_ACTION(name, name##ActionP9, (__VA_ARGS__)) + +#define ACTION_P10(name, ...) \ + GMOCK_INTERNAL_ACTION(name, name##ActionP10, (__VA_ARGS__)) + } // namespace testing #ifdef _MSC_VER diff --git a/googlemock/include/gmock/gmock-function-mocker.h b/googlemock/include/gmock/gmock-function-mocker.h index cc1535c8..317d6c2b 100644 --- a/googlemock/include/gmock/gmock-function-mocker.h +++ b/googlemock/include/gmock/gmock-function-mocker.h @@ -36,9 +36,38 @@ #ifndef THIRD_PARTY_GOOGLETEST_GOOGLEMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_FUNCTION_MOCKER_H_ // NOLINT #define THIRD_PARTY_GOOGLETEST_GOOGLEMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_FUNCTION_MOCKER_H_ // NOLINT -#include "gmock/gmock-generated-function-mockers.h" // NOLINT +#include <type_traits> // IWYU pragma: keep +#include <utility> // IWYU pragma: keep + +#include "gmock/gmock-spec-builders.h" +#include "gmock/internal/gmock-internal-utils.h" #include "gmock/internal/gmock-pp.h" +namespace testing { +namespace internal { +template <typename T> +using identity_t = T; + +template <typename MockType> +const MockType* AdjustConstness_const(const MockType* mock) { + return mock; +} + +template <typename MockType> +MockType* AdjustConstness_(const MockType* mock) { + return const_cast<MockType*>(mock); +} + +} // namespace internal + +// The style guide prohibits "using" statements in a namespace scope +// inside a header file. However, the FunctionMocker class template +// is meant to be defined in the ::testing namespace. The following +// line is just a trick for working around a bug in MSVC 8.0, which +// cannot handle it if we define FunctionMocker in ::testing. +using internal::FunctionMocker; +} // namespace testing + #define MOCK_METHOD(...) \ GMOCK_PP_VARIADIC_CALL(GMOCK_INTERNAL_MOCK_METHOD_ARG_, __VA_ARGS__) @@ -51,16 +80,17 @@ #define GMOCK_INTERNAL_MOCK_METHOD_ARG_3(_Ret, _MethodName, _Args) \ GMOCK_INTERNAL_MOCK_METHOD_ARG_4(_Ret, _MethodName, _Args, ()) -#define GMOCK_INTERNAL_MOCK_METHOD_ARG_4(_Ret, _MethodName, _Args, _Spec) \ - GMOCK_INTERNAL_ASSERT_PARENTHESIS(_Args); \ - GMOCK_INTERNAL_ASSERT_PARENTHESIS(_Spec); \ - GMOCK_INTERNAL_ASSERT_VALID_SIGNATURE( \ - GMOCK_PP_NARG0 _Args, GMOCK_INTERNAL_SIGNATURE(_Ret, _Args)); \ - GMOCK_INTERNAL_ASSERT_VALID_SPEC(_Spec) \ - GMOCK_INTERNAL_MOCK_METHOD_IMPL( \ - GMOCK_PP_NARG0 _Args, _MethodName, GMOCK_INTERNAL_HAS_CONST(_Spec), \ - GMOCK_INTERNAL_HAS_OVERRIDE(_Spec), GMOCK_INTERNAL_HAS_FINAL(_Spec), \ - GMOCK_INTERNAL_HAS_NOEXCEPT(_Spec), GMOCK_INTERNAL_GET_CALLTYPE(_Spec), \ +#define GMOCK_INTERNAL_MOCK_METHOD_ARG_4(_Ret, _MethodName, _Args, _Spec) \ + GMOCK_INTERNAL_ASSERT_PARENTHESIS(_Args); \ + GMOCK_INTERNAL_ASSERT_PARENTHESIS(_Spec); \ + GMOCK_INTERNAL_ASSERT_VALID_SIGNATURE( \ + GMOCK_PP_NARG0 _Args, GMOCK_INTERNAL_SIGNATURE(_Ret, _Args)); \ + GMOCK_INTERNAL_ASSERT_VALID_SPEC(_Spec) \ + GMOCK_INTERNAL_MOCK_METHOD_IMPL( \ + GMOCK_PP_NARG0 _Args, _MethodName, GMOCK_INTERNAL_HAS_CONST(_Spec), \ + GMOCK_INTERNAL_HAS_OVERRIDE(_Spec), GMOCK_INTERNAL_HAS_FINAL(_Spec), \ + GMOCK_INTERNAL_GET_NOEXCEPT_SPEC(_Spec), \ + GMOCK_INTERNAL_GET_CALLTYPE(_Spec), \ (GMOCK_INTERNAL_SIGNATURE(_Ret, _Args))) #define GMOCK_INTERNAL_MOCK_METHOD_ARG_5(...) \ @@ -100,15 +130,14 @@ GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_ASSERT_VALID_SPEC_ELEMENT, ~, _Spec) #define GMOCK_INTERNAL_MOCK_METHOD_IMPL(_N, _MethodName, _Constness, \ - _Override, _Final, _Noexcept, \ + _Override, _Final, _NoexceptSpec, \ _CallType, _Signature) \ typename ::testing::internal::Function<GMOCK_PP_REMOVE_PARENS( \ _Signature)>::Result \ GMOCK_INTERNAL_EXPAND(_CallType) \ _MethodName(GMOCK_PP_REPEAT(GMOCK_INTERNAL_PARAMETER, _Signature, _N)) \ - GMOCK_PP_IF(_Constness, const, ) GMOCK_PP_IF(_Noexcept, noexcept, ) \ - GMOCK_PP_IF(_Override, override, ) \ - GMOCK_PP_IF(_Final, final, ) { \ + GMOCK_PP_IF(_Constness, const, ) _NoexceptSpec \ + GMOCK_PP_IF(_Override, override, ) GMOCK_PP_IF(_Final, final, ) { \ GMOCK_MOCKER_(_N, _Constness, _MethodName) \ .SetOwnerAndName(this, #_MethodName); \ return GMOCK_MOCKER_(_N, _Constness, _MethodName) \ @@ -124,8 +153,7 @@ ::testing::MockSpec<GMOCK_PP_REMOVE_PARENS(_Signature)> gmock_##_MethodName( \ const ::testing::internal::WithoutMatchers&, \ GMOCK_PP_IF(_Constness, const, )::testing::internal::Function< \ - GMOCK_PP_REMOVE_PARENS(_Signature)>*) \ - const GMOCK_PP_IF(_Noexcept, noexcept, ) { \ + GMOCK_PP_REMOVE_PARENS(_Signature)>*) const _NoexceptSpec { \ return GMOCK_PP_CAT(::testing::internal::AdjustConstness_, \ GMOCK_PP_IF(_Constness, const, ))(this) \ ->gmock_##_MethodName(GMOCK_PP_REPEAT( \ @@ -147,9 +175,13 @@ #define GMOCK_INTERNAL_HAS_FINAL(_Tuple) \ GMOCK_PP_HAS_COMMA(GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_DETECT_FINAL, ~, _Tuple)) -#define GMOCK_INTERNAL_HAS_NOEXCEPT(_Tuple) \ - GMOCK_PP_HAS_COMMA( \ - GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_DETECT_NOEXCEPT, ~, _Tuple)) +#define GMOCK_INTERNAL_GET_NOEXCEPT_SPEC(_Tuple) \ + GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_NOEXCEPT_SPEC_IF_NOEXCEPT, ~, _Tuple) + +#define GMOCK_INTERNAL_NOEXCEPT_SPEC_IF_NOEXCEPT(_i, _, _elem) \ + GMOCK_PP_IF( \ + GMOCK_PP_HAS_COMMA(GMOCK_INTERNAL_DETECT_NOEXCEPT(_i, _, _elem)), \ + _elem, ) #define GMOCK_INTERNAL_GET_CALLTYPE(_Tuple) \ GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_GET_CALLTYPE_IMPL, ~, _Tuple) @@ -180,7 +212,6 @@ #define GMOCK_INTERNAL_DETECT_FINAL_I_final , -// TODO(iserna): Maybe noexcept should accept an argument here as well. #define GMOCK_INTERNAL_DETECT_NOEXCEPT(_i, _, _elem) \ GMOCK_PP_CAT(GMOCK_INTERNAL_DETECT_NOEXCEPT_I_, _elem) @@ -207,10 +238,24 @@ #define GMOCK_INTERNAL_IS_CALLTYPE_HELPER_Calltype -#define GMOCK_INTERNAL_SIGNATURE(_Ret, _Args) \ - GMOCK_PP_IF(GMOCK_PP_IS_BEGIN_PARENS(_Ret), GMOCK_PP_REMOVE_PARENS, \ - GMOCK_PP_IDENTITY) \ - (_Ret)(GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_GET_TYPE, _, _Args)) +// Note: The use of `identity_t` here allows _Ret to represent return types that +// would normally need to be specified in a different way. For example, a method +// returning a function pointer must be written as +// +// fn_ptr_return_t (*method(method_args_t...))(fn_ptr_args_t...) +// +// But we only support placing the return type at the beginning. To handle this, +// we wrap all calls in identity_t, so that a declaration will be expanded to +// +// identity_t<fn_ptr_return_t (*)(fn_ptr_args_t...)> method(method_args_t...) +// +// This allows us to work around the syntactic oddities of function/method +// types. +#define GMOCK_INTERNAL_SIGNATURE(_Ret, _Args) \ + ::testing::internal::identity_t<GMOCK_PP_IF(GMOCK_PP_IS_BEGIN_PARENS(_Ret), \ + GMOCK_PP_REMOVE_PARENS, \ + GMOCK_PP_IDENTITY)(_Ret)>( \ + GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_GET_TYPE, _, _Args)) #define GMOCK_INTERNAL_GET_TYPE(_i, _, _elem) \ GMOCK_PP_COMMA_IF(_i) \ @@ -218,36 +263,196 @@ GMOCK_PP_IDENTITY) \ (_elem) -#define GMOCK_INTERNAL_PARAMETER(_i, _Signature, _) \ - GMOCK_PP_COMMA_IF(_i) \ - GMOCK_INTERNAL_ARG_O(typename, GMOCK_PP_INC(_i), \ - GMOCK_PP_REMOVE_PARENS(_Signature)) \ +#define GMOCK_INTERNAL_PARAMETER(_i, _Signature, _) \ + GMOCK_PP_COMMA_IF(_i) \ + GMOCK_INTERNAL_ARG_O(_i, GMOCK_PP_REMOVE_PARENS(_Signature)) \ gmock_a##_i -#define GMOCK_INTERNAL_FORWARD_ARG(_i, _Signature, _) \ - GMOCK_PP_COMMA_IF(_i) \ - ::std::forward<GMOCK_INTERNAL_ARG_O(typename, GMOCK_PP_INC(_i), \ - GMOCK_PP_REMOVE_PARENS(_Signature))>( \ - gmock_a##_i) +#define GMOCK_INTERNAL_FORWARD_ARG(_i, _Signature, _) \ + GMOCK_PP_COMMA_IF(_i) \ + ::std::forward<GMOCK_INTERNAL_ARG_O( \ + _i, GMOCK_PP_REMOVE_PARENS(_Signature))>(gmock_a##_i) -#define GMOCK_INTERNAL_MATCHER_PARAMETER(_i, _Signature, _) \ - GMOCK_PP_COMMA_IF(_i) \ - GMOCK_INTERNAL_MATCHER_O(typename, GMOCK_PP_INC(_i), \ - GMOCK_PP_REMOVE_PARENS(_Signature)) \ +#define GMOCK_INTERNAL_MATCHER_PARAMETER(_i, _Signature, _) \ + GMOCK_PP_COMMA_IF(_i) \ + GMOCK_INTERNAL_MATCHER_O(_i, GMOCK_PP_REMOVE_PARENS(_Signature)) \ gmock_a##_i #define GMOCK_INTERNAL_MATCHER_ARGUMENT(_i, _1, _2) \ GMOCK_PP_COMMA_IF(_i) \ gmock_a##_i -#define GMOCK_INTERNAL_A_MATCHER_ARGUMENT(_i, _Signature, _) \ - GMOCK_PP_COMMA_IF(_i) \ - ::testing::A<GMOCK_INTERNAL_ARG_O(typename, GMOCK_PP_INC(_i), \ - GMOCK_PP_REMOVE_PARENS(_Signature))>() - -#define GMOCK_INTERNAL_ARG_O(_tn, _i, ...) GMOCK_ARG_(_tn, _i, __VA_ARGS__) - -#define GMOCK_INTERNAL_MATCHER_O(_tn, _i, ...) \ - GMOCK_MATCHER_(_tn, _i, __VA_ARGS__) +#define GMOCK_INTERNAL_A_MATCHER_ARGUMENT(_i, _Signature, _) \ + GMOCK_PP_COMMA_IF(_i) \ + ::testing::A<GMOCK_INTERNAL_ARG_O(_i, GMOCK_PP_REMOVE_PARENS(_Signature))>() + +#define GMOCK_INTERNAL_ARG_O(_i, ...) \ + typename ::testing::internal::Function<__VA_ARGS__>::template Arg<_i>::type + +#define GMOCK_INTERNAL_MATCHER_O(_i, ...) \ + const ::testing::Matcher<typename ::testing::internal::Function< \ + __VA_ARGS__>::template Arg<_i>::type>& + +#define MOCK_METHOD0(m, ...) GMOCK_INTERNAL_MOCK_METHODN(, , m, 0, __VA_ARGS__) +#define MOCK_METHOD1(m, ...) GMOCK_INTERNAL_MOCK_METHODN(, , m, 1, __VA_ARGS__) +#define MOCK_METHOD2(m, ...) GMOCK_INTERNAL_MOCK_METHODN(, , m, 2, __VA_ARGS__) +#define MOCK_METHOD3(m, ...) GMOCK_INTERNAL_MOCK_METHODN(, , m, 3, __VA_ARGS__) +#define MOCK_METHOD4(m, ...) GMOCK_INTERNAL_MOCK_METHODN(, , m, 4, __VA_ARGS__) +#define MOCK_METHOD5(m, ...) GMOCK_INTERNAL_MOCK_METHODN(, , m, 5, __VA_ARGS__) +#define MOCK_METHOD6(m, ...) GMOCK_INTERNAL_MOCK_METHODN(, , m, 6, __VA_ARGS__) +#define MOCK_METHOD7(m, ...) GMOCK_INTERNAL_MOCK_METHODN(, , m, 7, __VA_ARGS__) +#define MOCK_METHOD8(m, ...) GMOCK_INTERNAL_MOCK_METHODN(, , m, 8, __VA_ARGS__) +#define MOCK_METHOD9(m, ...) GMOCK_INTERNAL_MOCK_METHODN(, , m, 9, __VA_ARGS__) +#define MOCK_METHOD10(m, ...) \ + GMOCK_INTERNAL_MOCK_METHODN(, , m, 10, __VA_ARGS__) + +#define MOCK_CONST_METHOD0(m, ...) \ + GMOCK_INTERNAL_MOCK_METHODN(const, , m, 0, __VA_ARGS__) +#define MOCK_CONST_METHOD1(m, ...) \ + GMOCK_INTERNAL_MOCK_METHODN(const, , m, 1, __VA_ARGS__) +#define MOCK_CONST_METHOD2(m, ...) \ + GMOCK_INTERNAL_MOCK_METHODN(const, , m, 2, __VA_ARGS__) +#define MOCK_CONST_METHOD3(m, ...) \ + GMOCK_INTERNAL_MOCK_METHODN(const, , m, 3, __VA_ARGS__) +#define MOCK_CONST_METHOD4(m, ...) \ + GMOCK_INTERNAL_MOCK_METHODN(const, , m, 4, __VA_ARGS__) +#define MOCK_CONST_METHOD5(m, ...) \ + GMOCK_INTERNAL_MOCK_METHODN(const, , m, 5, __VA_ARGS__) +#define MOCK_CONST_METHOD6(m, ...) \ + GMOCK_INTERNAL_MOCK_METHODN(const, , m, 6, __VA_ARGS__) +#define MOCK_CONST_METHOD7(m, ...) \ + GMOCK_INTERNAL_MOCK_METHODN(const, , m, 7, __VA_ARGS__) +#define MOCK_CONST_METHOD8(m, ...) \ + GMOCK_INTERNAL_MOCK_METHODN(const, , m, 8, __VA_ARGS__) +#define MOCK_CONST_METHOD9(m, ...) \ + GMOCK_INTERNAL_MOCK_METHODN(const, , m, 9, __VA_ARGS__) +#define MOCK_CONST_METHOD10(m, ...) \ + GMOCK_INTERNAL_MOCK_METHODN(const, , m, 10, __VA_ARGS__) + +#define MOCK_METHOD0_T(m, ...) MOCK_METHOD0(m, __VA_ARGS__) +#define MOCK_METHOD1_T(m, ...) MOCK_METHOD1(m, __VA_ARGS__) +#define MOCK_METHOD2_T(m, ...) MOCK_METHOD2(m, __VA_ARGS__) +#define MOCK_METHOD3_T(m, ...) MOCK_METHOD3(m, __VA_ARGS__) +#define MOCK_METHOD4_T(m, ...) MOCK_METHOD4(m, __VA_ARGS__) +#define MOCK_METHOD5_T(m, ...) MOCK_METHOD5(m, __VA_ARGS__) +#define MOCK_METHOD6_T(m, ...) MOCK_METHOD6(m, __VA_ARGS__) +#define MOCK_METHOD7_T(m, ...) MOCK_METHOD7(m, __VA_ARGS__) +#define MOCK_METHOD8_T(m, ...) MOCK_METHOD8(m, __VA_ARGS__) +#define MOCK_METHOD9_T(m, ...) MOCK_METHOD9(m, __VA_ARGS__) +#define MOCK_METHOD10_T(m, ...) MOCK_METHOD10(m, __VA_ARGS__) + +#define MOCK_CONST_METHOD0_T(m, ...) MOCK_CONST_METHOD0(m, __VA_ARGS__) +#define MOCK_CONST_METHOD1_T(m, ...) MOCK_CONST_METHOD1(m, __VA_ARGS__) +#define MOCK_CONST_METHOD2_T(m, ...) MOCK_CONST_METHOD2(m, __VA_ARGS__) +#define MOCK_CONST_METHOD3_T(m, ...) MOCK_CONST_METHOD3(m, __VA_ARGS__) +#define MOCK_CONST_METHOD4_T(m, ...) MOCK_CONST_METHOD4(m, __VA_ARGS__) +#define MOCK_CONST_METHOD5_T(m, ...) MOCK_CONST_METHOD5(m, __VA_ARGS__) +#define MOCK_CONST_METHOD6_T(m, ...) MOCK_CONST_METHOD6(m, __VA_ARGS__) +#define MOCK_CONST_METHOD7_T(m, ...) MOCK_CONST_METHOD7(m, __VA_ARGS__) +#define MOCK_CONST_METHOD8_T(m, ...) MOCK_CONST_METHOD8(m, __VA_ARGS__) +#define MOCK_CONST_METHOD9_T(m, ...) MOCK_CONST_METHOD9(m, __VA_ARGS__) +#define MOCK_CONST_METHOD10_T(m, ...) MOCK_CONST_METHOD10(m, __VA_ARGS__) + +#define MOCK_METHOD0_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_INTERNAL_MOCK_METHODN(, ct, m, 0, __VA_ARGS__) +#define MOCK_METHOD1_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_INTERNAL_MOCK_METHODN(, ct, m, 1, __VA_ARGS__) +#define MOCK_METHOD2_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_INTERNAL_MOCK_METHODN(, ct, m, 2, __VA_ARGS__) +#define MOCK_METHOD3_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_INTERNAL_MOCK_METHODN(, ct, m, 3, __VA_ARGS__) +#define MOCK_METHOD4_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_INTERNAL_MOCK_METHODN(, ct, m, 4, __VA_ARGS__) +#define MOCK_METHOD5_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_INTERNAL_MOCK_METHODN(, ct, m, 5, __VA_ARGS__) +#define MOCK_METHOD6_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_INTERNAL_MOCK_METHODN(, ct, m, 6, __VA_ARGS__) +#define MOCK_METHOD7_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_INTERNAL_MOCK_METHODN(, ct, m, 7, __VA_ARGS__) +#define MOCK_METHOD8_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_INTERNAL_MOCK_METHODN(, ct, m, 8, __VA_ARGS__) +#define MOCK_METHOD9_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_INTERNAL_MOCK_METHODN(, ct, m, 9, __VA_ARGS__) +#define MOCK_METHOD10_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_INTERNAL_MOCK_METHODN(, ct, m, 10, __VA_ARGS__) + +#define MOCK_CONST_METHOD0_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_INTERNAL_MOCK_METHODN(const, ct, m, 0, __VA_ARGS__) +#define MOCK_CONST_METHOD1_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_INTERNAL_MOCK_METHODN(const, ct, m, 1, __VA_ARGS__) +#define MOCK_CONST_METHOD2_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_INTERNAL_MOCK_METHODN(const, ct, m, 2, __VA_ARGS__) +#define MOCK_CONST_METHOD3_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_INTERNAL_MOCK_METHODN(const, ct, m, 3, __VA_ARGS__) +#define MOCK_CONST_METHOD4_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_INTERNAL_MOCK_METHODN(const, ct, m, 4, __VA_ARGS__) +#define MOCK_CONST_METHOD5_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_INTERNAL_MOCK_METHODN(const, ct, m, 5, __VA_ARGS__) +#define MOCK_CONST_METHOD6_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_INTERNAL_MOCK_METHODN(const, ct, m, 6, __VA_ARGS__) +#define MOCK_CONST_METHOD7_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_INTERNAL_MOCK_METHODN(const, ct, m, 7, __VA_ARGS__) +#define MOCK_CONST_METHOD8_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_INTERNAL_MOCK_METHODN(const, ct, m, 8, __VA_ARGS__) +#define MOCK_CONST_METHOD9_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_INTERNAL_MOCK_METHODN(const, ct, m, 9, __VA_ARGS__) +#define MOCK_CONST_METHOD10_WITH_CALLTYPE(ct, m, ...) \ + GMOCK_INTERNAL_MOCK_METHODN(const, ct, m, 10, __VA_ARGS__) + +#define MOCK_METHOD0_T_WITH_CALLTYPE(ct, m, ...) \ + MOCK_METHOD0_WITH_CALLTYPE(ct, m, __VA_ARGS__) +#define MOCK_METHOD1_T_WITH_CALLTYPE(ct, m, ...) \ + MOCK_METHOD1_WITH_CALLTYPE(ct, m, __VA_ARGS__) +#define MOCK_METHOD2_T_WITH_CALLTYPE(ct, m, ...) \ + MOCK_METHOD2_WITH_CALLTYPE(ct, m, __VA_ARGS__) +#define MOCK_METHOD3_T_WITH_CALLTYPE(ct, m, ...) \ + MOCK_METHOD3_WITH_CALLTYPE(ct, m, __VA_ARGS__) +#define MOCK_METHOD4_T_WITH_CALLTYPE(ct, m, ...) \ + MOCK_METHOD4_WITH_CALLTYPE(ct, m, __VA_ARGS__) +#define MOCK_METHOD5_T_WITH_CALLTYPE(ct, m, ...) \ + MOCK_METHOD5_WITH_CALLTYPE(ct, m, __VA_ARGS__) +#define MOCK_METHOD6_T_WITH_CALLTYPE(ct, m, ...) \ + MOCK_METHOD6_WITH_CALLTYPE(ct, m, __VA_ARGS__) +#define MOCK_METHOD7_T_WITH_CALLTYPE(ct, m, ...) \ + MOCK_METHOD7_WITH_CALLTYPE(ct, m, __VA_ARGS__) +#define MOCK_METHOD8_T_WITH_CALLTYPE(ct, m, ...) \ + MOCK_METHOD8_WITH_CALLTYPE(ct, m, __VA_ARGS__) +#define MOCK_METHOD9_T_WITH_CALLTYPE(ct, m, ...) \ + MOCK_METHOD9_WITH_CALLTYPE(ct, m, __VA_ARGS__) +#define MOCK_METHOD10_T_WITH_CALLTYPE(ct, m, ...) \ + MOCK_METHOD10_WITH_CALLTYPE(ct, m, __VA_ARGS__) + +#define MOCK_CONST_METHOD0_T_WITH_CALLTYPE(ct, m, ...) \ + MOCK_CONST_METHOD0_WITH_CALLTYPE(ct, m, __VA_ARGS__) +#define MOCK_CONST_METHOD1_T_WITH_CALLTYPE(ct, m, ...) \ + MOCK_CONST_METHOD1_WITH_CALLTYPE(ct, m, __VA_ARGS__) +#define MOCK_CONST_METHOD2_T_WITH_CALLTYPE(ct, m, ...) \ + MOCK_CONST_METHOD2_WITH_CALLTYPE(ct, m, __VA_ARGS__) +#define MOCK_CONST_METHOD3_T_WITH_CALLTYPE(ct, m, ...) \ + MOCK_CONST_METHOD3_WITH_CALLTYPE(ct, m, __VA_ARGS__) +#define MOCK_CONST_METHOD4_T_WITH_CALLTYPE(ct, m, ...) \ + MOCK_CONST_METHOD4_WITH_CALLTYPE(ct, m, __VA_ARGS__) +#define MOCK_CONST_METHOD5_T_WITH_CALLTYPE(ct, m, ...) \ + MOCK_CONST_METHOD5_WITH_CALLTYPE(ct, m, __VA_ARGS__) +#define MOCK_CONST_METHOD6_T_WITH_CALLTYPE(ct, m, ...) \ + MOCK_CONST_METHOD6_WITH_CALLTYPE(ct, m, __VA_ARGS__) +#define MOCK_CONST_METHOD7_T_WITH_CALLTYPE(ct, m, ...) \ + MOCK_CONST_METHOD7_WITH_CALLTYPE(ct, m, __VA_ARGS__) +#define MOCK_CONST_METHOD8_T_WITH_CALLTYPE(ct, m, ...) \ + MOCK_CONST_METHOD8_WITH_CALLTYPE(ct, m, __VA_ARGS__) +#define MOCK_CONST_METHOD9_T_WITH_CALLTYPE(ct, m, ...) \ + MOCK_CONST_METHOD9_WITH_CALLTYPE(ct, m, __VA_ARGS__) +#define MOCK_CONST_METHOD10_T_WITH_CALLTYPE(ct, m, ...) \ + MOCK_CONST_METHOD10_WITH_CALLTYPE(ct, m, __VA_ARGS__) + +#define GMOCK_INTERNAL_MOCK_METHODN(constness, ct, Method, args_num, ...) \ + GMOCK_INTERNAL_ASSERT_VALID_SIGNATURE( \ + args_num, ::testing::internal::identity_t<__VA_ARGS__>); \ + GMOCK_INTERNAL_MOCK_METHOD_IMPL( \ + args_num, Method, GMOCK_PP_NARG0(constness), 0, 0, , ct, \ + (::testing::internal::identity_t<__VA_ARGS__>)) + +#define GMOCK_MOCKER_(arity, constness, Method) \ + GTEST_CONCAT_TOKEN_(gmock##constness##arity##_##Method##_, __LINE__) #endif // THIRD_PARTY_GOOGLETEST_GOOGLEMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_FUNCTION_MOCKER_H_ diff --git a/googlemock/include/gmock/gmock-generated-actions.h b/googlemock/include/gmock/gmock-generated-actions.h index 981af78f..c78debef 100644 --- a/googlemock/include/gmock/gmock-generated-actions.h +++ b/googlemock/include/gmock/gmock-generated-actions.h @@ -47,241 +47,6 @@ #include "gmock/gmock-actions.h" #include "gmock/internal/gmock-port.h" -namespace testing { -namespace internal { - -// A macro from the ACTION* family (defined later in this file) -// defines an action that can be used in a mock function. Typically, -// these actions only care about a subset of the arguments of the mock -// function. For example, if such an action only uses the second -// argument, it can be used in any mock function that takes >= 2 -// arguments where the type of the second argument is compatible. -// -// Therefore, the action implementation must be prepared to take more -// arguments than it needs. The ExcessiveArg type is used to -// represent those excessive arguments. In order to keep the compiler -// error messages tractable, we define it in the testing namespace -// instead of testing::internal. However, this is an INTERNAL TYPE -// and subject to change without notice, so a user MUST NOT USE THIS -// TYPE DIRECTLY. -struct ExcessiveArg {}; - -// A helper class needed for implementing the ACTION* macros. -template <typename Result, class Impl> -class ActionHelper { - public: - static Result Perform(Impl* impl, const ::std::tuple<>& args) { - return impl->template gmock_PerformImpl<>(args, ExcessiveArg(), - ExcessiveArg(), ExcessiveArg(), ExcessiveArg(), ExcessiveArg(), - ExcessiveArg(), ExcessiveArg(), ExcessiveArg(), ExcessiveArg(), - ExcessiveArg()); - } - - template <typename A0> - static Result Perform(Impl* impl, const ::std::tuple<A0>& args) { - return impl->template gmock_PerformImpl<A0>(args, std::get<0>(args), - ExcessiveArg(), ExcessiveArg(), ExcessiveArg(), ExcessiveArg(), - ExcessiveArg(), ExcessiveArg(), ExcessiveArg(), ExcessiveArg(), - ExcessiveArg()); - } - - template <typename A0, typename A1> - static Result Perform(Impl* impl, const ::std::tuple<A0, A1>& args) { - return impl->template gmock_PerformImpl<A0, A1>(args, std::get<0>(args), - std::get<1>(args), ExcessiveArg(), ExcessiveArg(), ExcessiveArg(), - ExcessiveArg(), ExcessiveArg(), ExcessiveArg(), ExcessiveArg(), - ExcessiveArg()); - } - - template <typename A0, typename A1, typename A2> - static Result Perform(Impl* impl, const ::std::tuple<A0, A1, A2>& args) { - return impl->template gmock_PerformImpl<A0, A1, A2>(args, - std::get<0>(args), std::get<1>(args), std::get<2>(args), - ExcessiveArg(), ExcessiveArg(), ExcessiveArg(), ExcessiveArg(), - ExcessiveArg(), ExcessiveArg(), ExcessiveArg()); - } - - template <typename A0, typename A1, typename A2, typename A3> - static Result Perform(Impl* impl, const ::std::tuple<A0, A1, A2, A3>& args) { - return impl->template gmock_PerformImpl<A0, A1, A2, A3>(args, - std::get<0>(args), std::get<1>(args), std::get<2>(args), - std::get<3>(args), ExcessiveArg(), ExcessiveArg(), ExcessiveArg(), - ExcessiveArg(), ExcessiveArg(), ExcessiveArg()); - } - - template <typename A0, typename A1, typename A2, typename A3, typename A4> - static Result Perform(Impl* impl, const ::std::tuple<A0, A1, A2, A3, - A4>& args) { - return impl->template gmock_PerformImpl<A0, A1, A2, A3, A4>(args, - std::get<0>(args), std::get<1>(args), std::get<2>(args), - std::get<3>(args), std::get<4>(args), ExcessiveArg(), ExcessiveArg(), - ExcessiveArg(), ExcessiveArg(), ExcessiveArg()); - } - - template <typename A0, typename A1, typename A2, typename A3, typename A4, - typename A5> - static Result Perform(Impl* impl, const ::std::tuple<A0, A1, A2, A3, A4, - A5>& args) { - return impl->template gmock_PerformImpl<A0, A1, A2, A3, A4, A5>(args, - std::get<0>(args), std::get<1>(args), std::get<2>(args), - std::get<3>(args), std::get<4>(args), std::get<5>(args), - ExcessiveArg(), ExcessiveArg(), ExcessiveArg(), ExcessiveArg()); - } - - template <typename A0, typename A1, typename A2, typename A3, typename A4, - typename A5, typename A6> - static Result Perform(Impl* impl, const ::std::tuple<A0, A1, A2, A3, A4, A5, - A6>& args) { - return impl->template gmock_PerformImpl<A0, A1, A2, A3, A4, A5, A6>(args, - std::get<0>(args), std::get<1>(args), std::get<2>(args), - std::get<3>(args), std::get<4>(args), std::get<5>(args), - std::get<6>(args), ExcessiveArg(), ExcessiveArg(), ExcessiveArg()); - } - - template <typename A0, typename A1, typename A2, typename A3, typename A4, - typename A5, typename A6, typename A7> - static Result Perform(Impl* impl, const ::std::tuple<A0, A1, A2, A3, A4, A5, - A6, A7>& args) { - return impl->template gmock_PerformImpl<A0, A1, A2, A3, A4, A5, A6, - A7>(args, std::get<0>(args), std::get<1>(args), std::get<2>(args), - std::get<3>(args), std::get<4>(args), std::get<5>(args), - std::get<6>(args), std::get<7>(args), ExcessiveArg(), ExcessiveArg()); - } - - template <typename A0, typename A1, typename A2, typename A3, typename A4, - typename A5, typename A6, typename A7, typename A8> - static Result Perform(Impl* impl, const ::std::tuple<A0, A1, A2, A3, A4, A5, - A6, A7, A8>& args) { - return impl->template gmock_PerformImpl<A0, A1, A2, A3, A4, A5, A6, A7, - A8>(args, std::get<0>(args), std::get<1>(args), std::get<2>(args), - std::get<3>(args), std::get<4>(args), std::get<5>(args), - std::get<6>(args), std::get<7>(args), std::get<8>(args), - ExcessiveArg()); - } - - template <typename A0, typename A1, typename A2, typename A3, typename A4, - typename A5, typename A6, typename A7, typename A8, typename A9> - static Result Perform(Impl* impl, const ::std::tuple<A0, A1, A2, A3, A4, A5, - A6, A7, A8, A9>& args) { - return impl->template gmock_PerformImpl<A0, A1, A2, A3, A4, A5, A6, A7, A8, - A9>(args, std::get<0>(args), std::get<1>(args), std::get<2>(args), - std::get<3>(args), std::get<4>(args), std::get<5>(args), - std::get<6>(args), std::get<7>(args), std::get<8>(args), - std::get<9>(args)); - } -}; - -} // namespace internal -} // namespace testing - -// The ACTION* family of macros can be used in a namespace scope to -// define custom actions easily. The syntax: -// -// ACTION(name) { statements; } -// -// will define an action with the given name that executes the -// statements. The value returned by the statements will be used as -// the return value of the action. Inside the statements, you can -// refer to the K-th (0-based) argument of the mock function by -// 'argK', and refer to its type by 'argK_type'. For example: -// -// ACTION(IncrementArg1) { -// arg1_type temp = arg1; -// return ++(*temp); -// } -// -// allows you to write -// -// ...WillOnce(IncrementArg1()); -// -// You can also refer to the entire argument tuple and its type by -// 'args' and 'args_type', and refer to the mock function type and its -// return type by 'function_type' and 'return_type'. -// -// Note that you don't need to specify the types of the mock function -// arguments. However rest assured that your code is still type-safe: -// you'll get a compiler error if *arg1 doesn't support the ++ -// operator, or if the type of ++(*arg1) isn't compatible with the -// mock function's return type, for example. -// -// Sometimes you'll want to parameterize the action. For that you can use -// another macro: -// -// ACTION_P(name, param_name) { statements; } -// -// For example: -// -// ACTION_P(Add, n) { return arg0 + n; } -// -// will allow you to write: -// -// ...WillOnce(Add(5)); -// -// Note that you don't need to provide the type of the parameter -// either. If you need to reference the type of a parameter named -// 'foo', you can write 'foo_type'. For example, in the body of -// ACTION_P(Add, n) above, you can write 'n_type' to refer to the type -// of 'n'. -// -// We also provide ACTION_P2, ACTION_P3, ..., up to ACTION_P10 to support -// multi-parameter actions. -// -// For the purpose of typing, you can view -// -// ACTION_Pk(Foo, p1, ..., pk) { ... } -// -// as shorthand for -// -// template <typename p1_type, ..., typename pk_type> -// FooActionPk<p1_type, ..., pk_type> Foo(p1_type p1, ..., pk_type pk) { ... } -// -// In particular, you can provide the template type arguments -// explicitly when invoking Foo(), as in Foo<long, bool>(5, false); -// although usually you can rely on the compiler to infer the types -// for you automatically. You can assign the result of expression -// Foo(p1, ..., pk) to a variable of type FooActionPk<p1_type, ..., -// pk_type>. This can be useful when composing actions. -// -// You can also overload actions with different numbers of parameters: -// -// ACTION_P(Plus, a) { ... } -// ACTION_P2(Plus, a, b) { ... } -// -// While it's tempting to always use the ACTION* macros when defining -// a new action, you should also consider implementing ActionInterface -// or using MakePolymorphicAction() instead, especially if you need to -// use the action a lot. While these approaches require more work, -// they give you more control on the types of the mock function -// arguments and the action parameters, which in general leads to -// better compiler error messages that pay off in the long run. They -// also allow overloading actions based on parameter types (as opposed -// to just based on the number of parameters). -// -// CAVEAT: -// -// ACTION*() can only be used in a namespace scope as templates cannot be -// declared inside of a local class. -// Users can, however, define any local functors (e.g. a lambda) that -// can be used as actions. -// -// MORE INFORMATION: -// -// To learn more about using these macros, please search for 'ACTION' on -// https://github.com/google/googletest/blob/master/googlemock/docs/cook_book.md - -// An internal macro needed for implementing ACTION*(). -#define GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_\ - const args_type& args GTEST_ATTRIBUTE_UNUSED_, \ - const arg0_type& arg0 GTEST_ATTRIBUTE_UNUSED_, \ - const arg1_type& arg1 GTEST_ATTRIBUTE_UNUSED_, \ - const arg2_type& arg2 GTEST_ATTRIBUTE_UNUSED_, \ - const arg3_type& arg3 GTEST_ATTRIBUTE_UNUSED_, \ - const arg4_type& arg4 GTEST_ATTRIBUTE_UNUSED_, \ - const arg5_type& arg5 GTEST_ATTRIBUTE_UNUSED_, \ - const arg6_type& arg6 GTEST_ATTRIBUTE_UNUSED_, \ - const arg7_type& arg7 GTEST_ATTRIBUTE_UNUSED_, \ - const arg8_type& arg8 GTEST_ATTRIBUTE_UNUSED_, \ - const arg9_type& arg9 GTEST_ATTRIBUTE_UNUSED_ // Sometimes you want to give an action explicit template parameters // that cannot be inferred from its value parameters. ACTION() and @@ -663,20 +428,12 @@ class ActionHelper { typedef typename ::testing::internal::Function<F>::ArgumentTuple\ args_type;\ explicit gmock_Impl GMOCK_INTERNAL_INIT_##value_params {}\ - virtual return_type Perform(const args_type& args) {\ + return_type Perform(const args_type& args) override {\ return ::testing::internal::ActionHelper<return_type, gmock_Impl>::\ Perform(this, args);\ }\ - template <typename arg0_type, typename arg1_type, typename arg2_type, \ - typename arg3_type, typename arg4_type, typename arg5_type, \ - typename arg6_type, typename arg7_type, typename arg8_type, \ - typename arg9_type>\ - return_type gmock_PerformImpl(const args_type& args, \ - const arg0_type& arg0, const arg1_type& arg1, \ - const arg2_type& arg2, const arg3_type& arg3, \ - const arg4_type& arg4, const arg5_type& arg5, \ - const arg6_type& arg6, const arg7_type& arg7, \ - const arg8_type& arg8, const arg9_type& arg9) const;\ + template <GMOCK_ACTION_TEMPLATE_ARGS_NAMES_>\ + return_type gmock_PerformImpl(GMOCK_ACTION_ARG_TYPES_AND_NAMES_) const;\ GMOCK_INTERNAL_DEFN_##value_params\ private:\ GTEST_DISALLOW_ASSIGN_(gmock_Impl);\ @@ -703,10 +460,7 @@ class ActionHelper { template <GMOCK_INTERNAL_DECL_##template_params\ GMOCK_INTERNAL_DECL_TYPE_##value_params>\ template <typename F>\ - template <typename arg0_type, typename arg1_type, typename arg2_type, \ - typename arg3_type, typename arg4_type, typename arg5_type, \ - typename arg6_type, typename arg7_type, typename arg8_type, \ - typename arg9_type>\ + template <GMOCK_ACTION_TEMPLATE_ARGS_NAMES_>\ typename ::testing::internal::Function<F>::Result\ GMOCK_ACTION_CLASS_(name, value_params)<\ GMOCK_INTERNAL_LIST_##template_params\ @@ -714,876 +468,6 @@ class ActionHelper { gmock_PerformImpl(\ GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const -#define ACTION(name)\ - class name##Action {\ - public:\ - name##Action() {}\ - template <typename F>\ - class gmock_Impl : public ::testing::ActionInterface<F> {\ - public:\ - typedef F function_type;\ - typedef typename ::testing::internal::Function<F>::Result return_type;\ - typedef typename ::testing::internal::Function<F>::ArgumentTuple\ - args_type;\ - gmock_Impl() {}\ - virtual return_type Perform(const args_type& args) {\ - return ::testing::internal::ActionHelper<return_type, gmock_Impl>::\ - Perform(this, args);\ - }\ - template <typename arg0_type, typename arg1_type, typename arg2_type, \ - typename arg3_type, typename arg4_type, typename arg5_type, \ - typename arg6_type, typename arg7_type, typename arg8_type, \ - typename arg9_type>\ - return_type gmock_PerformImpl(const args_type& args, \ - const arg0_type& arg0, const arg1_type& arg1, \ - const arg2_type& arg2, const arg3_type& arg3, \ - const arg4_type& arg4, const arg5_type& arg5, \ - const arg6_type& arg6, const arg7_type& arg7, \ - const arg8_type& arg8, const arg9_type& arg9) const;\ - private:\ - GTEST_DISALLOW_ASSIGN_(gmock_Impl);\ - };\ - template <typename F> operator ::testing::Action<F>() const {\ - return ::testing::Action<F>(new gmock_Impl<F>());\ - }\ - private:\ - GTEST_DISALLOW_ASSIGN_(name##Action);\ - };\ - inline name##Action name() {\ - return name##Action();\ - }\ - template <typename F>\ - template <typename arg0_type, typename arg1_type, typename arg2_type, \ - typename arg3_type, typename arg4_type, typename arg5_type, \ - typename arg6_type, typename arg7_type, typename arg8_type, \ - typename arg9_type>\ - typename ::testing::internal::Function<F>::Result\ - name##Action::gmock_Impl<F>::gmock_PerformImpl(\ - GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const - -#define ACTION_P(name, p0)\ - template <typename p0##_type>\ - class name##ActionP {\ - public:\ - explicit name##ActionP(p0##_type gmock_p0) : \ - p0(::std::forward<p0##_type>(gmock_p0)) {}\ - template <typename F>\ - class gmock_Impl : public ::testing::ActionInterface<F> {\ - public:\ - typedef F function_type;\ - typedef typename ::testing::internal::Function<F>::Result return_type;\ - typedef typename ::testing::internal::Function<F>::ArgumentTuple\ - args_type;\ - explicit gmock_Impl(p0##_type gmock_p0) : \ - p0(::std::forward<p0##_type>(gmock_p0)) {}\ - virtual return_type Perform(const args_type& args) {\ - return ::testing::internal::ActionHelper<return_type, gmock_Impl>::\ - Perform(this, args);\ - }\ - template <typename arg0_type, typename arg1_type, typename arg2_type, \ - typename arg3_type, typename arg4_type, typename arg5_type, \ - typename arg6_type, typename arg7_type, typename arg8_type, \ - typename arg9_type>\ - return_type gmock_PerformImpl(const args_type& args, \ - const arg0_type& arg0, const arg1_type& arg1, \ - const arg2_type& arg2, const arg3_type& arg3, \ - const arg4_type& arg4, const arg5_type& arg5, \ - const arg6_type& arg6, const arg7_type& arg7, \ - const arg8_type& arg8, const arg9_type& arg9) const;\ - p0##_type p0;\ - private:\ - GTEST_DISALLOW_ASSIGN_(gmock_Impl);\ - };\ - template <typename F> operator ::testing::Action<F>() const {\ - return ::testing::Action<F>(new gmock_Impl<F>(p0));\ - }\ - p0##_type p0;\ - private:\ - GTEST_DISALLOW_ASSIGN_(name##ActionP);\ - };\ - template <typename p0##_type>\ - inline name##ActionP<p0##_type> name(p0##_type p0) {\ - return name##ActionP<p0##_type>(p0);\ - }\ - template <typename p0##_type>\ - template <typename F>\ - template <typename arg0_type, typename arg1_type, typename arg2_type, \ - typename arg3_type, typename arg4_type, typename arg5_type, \ - typename arg6_type, typename arg7_type, typename arg8_type, \ - typename arg9_type>\ - typename ::testing::internal::Function<F>::Result\ - name##ActionP<p0##_type>::gmock_Impl<F>::gmock_PerformImpl(\ - GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const - -#define ACTION_P2(name, p0, p1)\ - template <typename p0##_type, typename p1##_type>\ - class name##ActionP2 {\ - public:\ - name##ActionP2(p0##_type gmock_p0, \ - p1##_type gmock_p1) : p0(::std::forward<p0##_type>(gmock_p0)), \ - p1(::std::forward<p1##_type>(gmock_p1)) {}\ - template <typename F>\ - class gmock_Impl : public ::testing::ActionInterface<F> {\ - public:\ - typedef F function_type;\ - typedef typename ::testing::internal::Function<F>::Result return_type;\ - typedef typename ::testing::internal::Function<F>::ArgumentTuple\ - args_type;\ - gmock_Impl(p0##_type gmock_p0, \ - p1##_type gmock_p1) : p0(::std::forward<p0##_type>(gmock_p0)), \ - p1(::std::forward<p1##_type>(gmock_p1)) {}\ - virtual return_type Perform(const args_type& args) {\ - return ::testing::internal::ActionHelper<return_type, gmock_Impl>::\ - Perform(this, args);\ - }\ - template <typename arg0_type, typename arg1_type, typename arg2_type, \ - typename arg3_type, typename arg4_type, typename arg5_type, \ - typename arg6_type, typename arg7_type, typename arg8_type, \ - typename arg9_type>\ - return_type gmock_PerformImpl(const args_type& args, \ - const arg0_type& arg0, const arg1_type& arg1, \ - const arg2_type& arg2, const arg3_type& arg3, \ - const arg4_type& arg4, const arg5_type& arg5, \ - const arg6_type& arg6, const arg7_type& arg7, \ - const arg8_type& arg8, const arg9_type& arg9) const;\ - p0##_type p0;\ - p1##_type p1;\ - private:\ - GTEST_DISALLOW_ASSIGN_(gmock_Impl);\ - };\ - template <typename F> operator ::testing::Action<F>() const {\ - return ::testing::Action<F>(new gmock_Impl<F>(p0, p1));\ - }\ - p0##_type p0;\ - p1##_type p1;\ - private:\ - GTEST_DISALLOW_ASSIGN_(name##ActionP2);\ - };\ - template <typename p0##_type, typename p1##_type>\ - inline name##ActionP2<p0##_type, p1##_type> name(p0##_type p0, \ - p1##_type p1) {\ - return name##ActionP2<p0##_type, p1##_type>(p0, p1);\ - }\ - template <typename p0##_type, typename p1##_type>\ - template <typename F>\ - template <typename arg0_type, typename arg1_type, typename arg2_type, \ - typename arg3_type, typename arg4_type, typename arg5_type, \ - typename arg6_type, typename arg7_type, typename arg8_type, \ - typename arg9_type>\ - typename ::testing::internal::Function<F>::Result\ - name##ActionP2<p0##_type, p1##_type>::gmock_Impl<F>::gmock_PerformImpl(\ - GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const - -#define ACTION_P3(name, p0, p1, p2)\ - template <typename p0##_type, typename p1##_type, typename p2##_type>\ - class name##ActionP3 {\ - public:\ - name##ActionP3(p0##_type gmock_p0, p1##_type gmock_p1, \ - p2##_type gmock_p2) : p0(::std::forward<p0##_type>(gmock_p0)), \ - p1(::std::forward<p1##_type>(gmock_p1)), \ - p2(::std::forward<p2##_type>(gmock_p2)) {}\ - template <typename F>\ - class gmock_Impl : public ::testing::ActionInterface<F> {\ - public:\ - typedef F function_type;\ - typedef typename ::testing::internal::Function<F>::Result return_type;\ - typedef typename ::testing::internal::Function<F>::ArgumentTuple\ - args_type;\ - gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, \ - p2##_type gmock_p2) : p0(::std::forward<p0##_type>(gmock_p0)), \ - p1(::std::forward<p1##_type>(gmock_p1)), \ - p2(::std::forward<p2##_type>(gmock_p2)) {}\ - virtual return_type Perform(const args_type& args) {\ - return ::testing::internal::ActionHelper<return_type, gmock_Impl>::\ - Perform(this, args);\ - }\ - template <typename arg0_type, typename arg1_type, typename arg2_type, \ - typename arg3_type, typename arg4_type, typename arg5_type, \ - typename arg6_type, typename arg7_type, typename arg8_type, \ - typename arg9_type>\ - return_type gmock_PerformImpl(const args_type& args, \ - const arg0_type& arg0, const arg1_type& arg1, \ - const arg2_type& arg2, const arg3_type& arg3, \ - const arg4_type& arg4, const arg5_type& arg5, \ - const arg6_type& arg6, const arg7_type& arg7, \ - const arg8_type& arg8, const arg9_type& arg9) const;\ - p0##_type p0;\ - p1##_type p1;\ - p2##_type p2;\ - private:\ - GTEST_DISALLOW_ASSIGN_(gmock_Impl);\ - };\ - template <typename F> operator ::testing::Action<F>() const {\ - return ::testing::Action<F>(new gmock_Impl<F>(p0, p1, p2));\ - }\ - p0##_type p0;\ - p1##_type p1;\ - p2##_type p2;\ - private:\ - GTEST_DISALLOW_ASSIGN_(name##ActionP3);\ - };\ - template <typename p0##_type, typename p1##_type, typename p2##_type>\ - inline name##ActionP3<p0##_type, p1##_type, p2##_type> name(p0##_type p0, \ - p1##_type p1, p2##_type p2) {\ - return name##ActionP3<p0##_type, p1##_type, p2##_type>(p0, p1, p2);\ - }\ - template <typename p0##_type, typename p1##_type, typename p2##_type>\ - template <typename F>\ - template <typename arg0_type, typename arg1_type, typename arg2_type, \ - typename arg3_type, typename arg4_type, typename arg5_type, \ - typename arg6_type, typename arg7_type, typename arg8_type, \ - typename arg9_type>\ - typename ::testing::internal::Function<F>::Result\ - name##ActionP3<p0##_type, p1##_type, \ - p2##_type>::gmock_Impl<F>::gmock_PerformImpl(\ - GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const - -#define ACTION_P4(name, p0, p1, p2, p3)\ - template <typename p0##_type, typename p1##_type, typename p2##_type, \ - typename p3##_type>\ - class name##ActionP4 {\ - public:\ - name##ActionP4(p0##_type gmock_p0, p1##_type gmock_p1, \ - p2##_type gmock_p2, \ - p3##_type gmock_p3) : p0(::std::forward<p0##_type>(gmock_p0)), \ - p1(::std::forward<p1##_type>(gmock_p1)), \ - p2(::std::forward<p2##_type>(gmock_p2)), \ - p3(::std::forward<p3##_type>(gmock_p3)) {}\ - template <typename F>\ - class gmock_Impl : public ::testing::ActionInterface<F> {\ - public:\ - typedef F function_type;\ - typedef typename ::testing::internal::Function<F>::Result return_type;\ - typedef typename ::testing::internal::Function<F>::ArgumentTuple\ - args_type;\ - gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \ - p3##_type gmock_p3) : p0(::std::forward<p0##_type>(gmock_p0)), \ - p1(::std::forward<p1##_type>(gmock_p1)), \ - p2(::std::forward<p2##_type>(gmock_p2)), \ - p3(::std::forward<p3##_type>(gmock_p3)) {}\ - virtual return_type Perform(const args_type& args) {\ - return ::testing::internal::ActionHelper<return_type, gmock_Impl>::\ - Perform(this, args);\ - }\ - template <typename arg0_type, typename arg1_type, typename arg2_type, \ - typename arg3_type, typename arg4_type, typename arg5_type, \ - typename arg6_type, typename arg7_type, typename arg8_type, \ - typename arg9_type>\ - return_type gmock_PerformImpl(const args_type& args, \ - const arg0_type& arg0, const arg1_type& arg1, \ - const arg2_type& arg2, const arg3_type& arg3, \ - const arg4_type& arg4, const arg5_type& arg5, \ - const arg6_type& arg6, const arg7_type& arg7, \ - const arg8_type& arg8, const arg9_type& arg9) const;\ - p0##_type p0;\ - p1##_type p1;\ - p2##_type p2;\ - p3##_type p3;\ - private:\ - GTEST_DISALLOW_ASSIGN_(gmock_Impl);\ - };\ - template <typename F> operator ::testing::Action<F>() const {\ - return ::testing::Action<F>(new gmock_Impl<F>(p0, p1, p2, p3));\ - }\ - p0##_type p0;\ - p1##_type p1;\ - p2##_type p2;\ - p3##_type p3;\ - private:\ - GTEST_DISALLOW_ASSIGN_(name##ActionP4);\ - };\ - template <typename p0##_type, typename p1##_type, typename p2##_type, \ - typename p3##_type>\ - inline name##ActionP4<p0##_type, p1##_type, p2##_type, \ - p3##_type> name(p0##_type p0, p1##_type p1, p2##_type p2, \ - p3##_type p3) {\ - return name##ActionP4<p0##_type, p1##_type, p2##_type, p3##_type>(p0, p1, \ - p2, p3);\ - }\ - template <typename p0##_type, typename p1##_type, typename p2##_type, \ - typename p3##_type>\ - template <typename F>\ - template <typename arg0_type, typename arg1_type, typename arg2_type, \ - typename arg3_type, typename arg4_type, typename arg5_type, \ - typename arg6_type, typename arg7_type, typename arg8_type, \ - typename arg9_type>\ - typename ::testing::internal::Function<F>::Result\ - name##ActionP4<p0##_type, p1##_type, p2##_type, \ - p3##_type>::gmock_Impl<F>::gmock_PerformImpl(\ - GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const - -#define ACTION_P5(name, p0, p1, p2, p3, p4)\ - template <typename p0##_type, typename p1##_type, typename p2##_type, \ - typename p3##_type, typename p4##_type>\ - class name##ActionP5 {\ - public:\ - name##ActionP5(p0##_type gmock_p0, p1##_type gmock_p1, \ - p2##_type gmock_p2, p3##_type gmock_p3, \ - p4##_type gmock_p4) : p0(::std::forward<p0##_type>(gmock_p0)), \ - p1(::std::forward<p1##_type>(gmock_p1)), \ - p2(::std::forward<p2##_type>(gmock_p2)), \ - p3(::std::forward<p3##_type>(gmock_p3)), \ - p4(::std::forward<p4##_type>(gmock_p4)) {}\ - template <typename F>\ - class gmock_Impl : public ::testing::ActionInterface<F> {\ - public:\ - typedef F function_type;\ - typedef typename ::testing::internal::Function<F>::Result return_type;\ - typedef typename ::testing::internal::Function<F>::ArgumentTuple\ - args_type;\ - gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \ - p3##_type gmock_p3, \ - p4##_type gmock_p4) : p0(::std::forward<p0##_type>(gmock_p0)), \ - p1(::std::forward<p1##_type>(gmock_p1)), \ - p2(::std::forward<p2##_type>(gmock_p2)), \ - p3(::std::forward<p3##_type>(gmock_p3)), \ - p4(::std::forward<p4##_type>(gmock_p4)) {}\ - virtual return_type Perform(const args_type& args) {\ - return ::testing::internal::ActionHelper<return_type, gmock_Impl>::\ - Perform(this, args);\ - }\ - template <typename arg0_type, typename arg1_type, typename arg2_type, \ - typename arg3_type, typename arg4_type, typename arg5_type, \ - typename arg6_type, typename arg7_type, typename arg8_type, \ - typename arg9_type>\ - return_type gmock_PerformImpl(const args_type& args, \ - const arg0_type& arg0, const arg1_type& arg1, \ - const arg2_type& arg2, const arg3_type& arg3, \ - const arg4_type& arg4, const arg5_type& arg5, \ - const arg6_type& arg6, const arg7_type& arg7, \ - const arg8_type& arg8, const arg9_type& arg9) const;\ - p0##_type p0;\ - p1##_type p1;\ - p2##_type p2;\ - p3##_type p3;\ - p4##_type p4;\ - private:\ - GTEST_DISALLOW_ASSIGN_(gmock_Impl);\ - };\ - template <typename F> operator ::testing::Action<F>() const {\ - return ::testing::Action<F>(new gmock_Impl<F>(p0, p1, p2, p3, p4));\ - }\ - p0##_type p0;\ - p1##_type p1;\ - p2##_type p2;\ - p3##_type p3;\ - p4##_type p4;\ - private:\ - GTEST_DISALLOW_ASSIGN_(name##ActionP5);\ - };\ - template <typename p0##_type, typename p1##_type, typename p2##_type, \ - typename p3##_type, typename p4##_type>\ - inline name##ActionP5<p0##_type, p1##_type, p2##_type, p3##_type, \ - p4##_type> name(p0##_type p0, p1##_type p1, p2##_type p2, p3##_type p3, \ - p4##_type p4) {\ - return name##ActionP5<p0##_type, p1##_type, p2##_type, p3##_type, \ - p4##_type>(p0, p1, p2, p3, p4);\ - }\ - template <typename p0##_type, typename p1##_type, typename p2##_type, \ - typename p3##_type, typename p4##_type>\ - template <typename F>\ - template <typename arg0_type, typename arg1_type, typename arg2_type, \ - typename arg3_type, typename arg4_type, typename arg5_type, \ - typename arg6_type, typename arg7_type, typename arg8_type, \ - typename arg9_type>\ - typename ::testing::internal::Function<F>::Result\ - name##ActionP5<p0##_type, p1##_type, p2##_type, p3##_type, \ - p4##_type>::gmock_Impl<F>::gmock_PerformImpl(\ - GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const - -#define ACTION_P6(name, p0, p1, p2, p3, p4, p5)\ - template <typename p0##_type, typename p1##_type, typename p2##_type, \ - typename p3##_type, typename p4##_type, typename p5##_type>\ - class name##ActionP6 {\ - public:\ - name##ActionP6(p0##_type gmock_p0, p1##_type gmock_p1, \ - p2##_type gmock_p2, p3##_type gmock_p3, p4##_type gmock_p4, \ - p5##_type gmock_p5) : p0(::std::forward<p0##_type>(gmock_p0)), \ - p1(::std::forward<p1##_type>(gmock_p1)), \ - p2(::std::forward<p2##_type>(gmock_p2)), \ - p3(::std::forward<p3##_type>(gmock_p3)), \ - p4(::std::forward<p4##_type>(gmock_p4)), \ - p5(::std::forward<p5##_type>(gmock_p5)) {}\ - template <typename F>\ - class gmock_Impl : public ::testing::ActionInterface<F> {\ - public:\ - typedef F function_type;\ - typedef typename ::testing::internal::Function<F>::Result return_type;\ - typedef typename ::testing::internal::Function<F>::ArgumentTuple\ - args_type;\ - gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \ - p3##_type gmock_p3, p4##_type gmock_p4, \ - p5##_type gmock_p5) : p0(::std::forward<p0##_type>(gmock_p0)), \ - p1(::std::forward<p1##_type>(gmock_p1)), \ - p2(::std::forward<p2##_type>(gmock_p2)), \ - p3(::std::forward<p3##_type>(gmock_p3)), \ - p4(::std::forward<p4##_type>(gmock_p4)), \ - p5(::std::forward<p5##_type>(gmock_p5)) {}\ - virtual return_type Perform(const args_type& args) {\ - return ::testing::internal::ActionHelper<return_type, gmock_Impl>::\ - Perform(this, args);\ - }\ - template <typename arg0_type, typename arg1_type, typename arg2_type, \ - typename arg3_type, typename arg4_type, typename arg5_type, \ - typename arg6_type, typename arg7_type, typename arg8_type, \ - typename arg9_type>\ - return_type gmock_PerformImpl(const args_type& args, \ - const arg0_type& arg0, const arg1_type& arg1, \ - const arg2_type& arg2, const arg3_type& arg3, \ - const arg4_type& arg4, const arg5_type& arg5, \ - const arg6_type& arg6, const arg7_type& arg7, \ - const arg8_type& arg8, const arg9_type& arg9) const;\ - p0##_type p0;\ - p1##_type p1;\ - p2##_type p2;\ - p3##_type p3;\ - p4##_type p4;\ - p5##_type p5;\ - private:\ - GTEST_DISALLOW_ASSIGN_(gmock_Impl);\ - };\ - template <typename F> operator ::testing::Action<F>() const {\ - return ::testing::Action<F>(new gmock_Impl<F>(p0, p1, p2, p3, p4, p5));\ - }\ - p0##_type p0;\ - p1##_type p1;\ - p2##_type p2;\ - p3##_type p3;\ - p4##_type p4;\ - p5##_type p5;\ - private:\ - GTEST_DISALLOW_ASSIGN_(name##ActionP6);\ - };\ - template <typename p0##_type, typename p1##_type, typename p2##_type, \ - typename p3##_type, typename p4##_type, typename p5##_type>\ - inline name##ActionP6<p0##_type, p1##_type, p2##_type, p3##_type, \ - p4##_type, p5##_type> name(p0##_type p0, p1##_type p1, p2##_type p2, \ - p3##_type p3, p4##_type p4, p5##_type p5) {\ - return name##ActionP6<p0##_type, p1##_type, p2##_type, p3##_type, \ - p4##_type, p5##_type>(p0, p1, p2, p3, p4, p5);\ - }\ - template <typename p0##_type, typename p1##_type, typename p2##_type, \ - typename p3##_type, typename p4##_type, typename p5##_type>\ - template <typename F>\ - template <typename arg0_type, typename arg1_type, typename arg2_type, \ - typename arg3_type, typename arg4_type, typename arg5_type, \ - typename arg6_type, typename arg7_type, typename arg8_type, \ - typename arg9_type>\ - typename ::testing::internal::Function<F>::Result\ - name##ActionP6<p0##_type, p1##_type, p2##_type, p3##_type, p4##_type, \ - p5##_type>::gmock_Impl<F>::gmock_PerformImpl(\ - GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const - -#define ACTION_P7(name, p0, p1, p2, p3, p4, p5, p6)\ - template <typename p0##_type, typename p1##_type, typename p2##_type, \ - typename p3##_type, typename p4##_type, typename p5##_type, \ - typename p6##_type>\ - class name##ActionP7 {\ - public:\ - name##ActionP7(p0##_type gmock_p0, p1##_type gmock_p1, \ - p2##_type gmock_p2, p3##_type gmock_p3, p4##_type gmock_p4, \ - p5##_type gmock_p5, \ - p6##_type gmock_p6) : p0(::std::forward<p0##_type>(gmock_p0)), \ - p1(::std::forward<p1##_type>(gmock_p1)), \ - p2(::std::forward<p2##_type>(gmock_p2)), \ - p3(::std::forward<p3##_type>(gmock_p3)), \ - p4(::std::forward<p4##_type>(gmock_p4)), \ - p5(::std::forward<p5##_type>(gmock_p5)), \ - p6(::std::forward<p6##_type>(gmock_p6)) {}\ - template <typename F>\ - class gmock_Impl : public ::testing::ActionInterface<F> {\ - public:\ - typedef F function_type;\ - typedef typename ::testing::internal::Function<F>::Result return_type;\ - typedef typename ::testing::internal::Function<F>::ArgumentTuple\ - args_type;\ - gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \ - p3##_type gmock_p3, p4##_type gmock_p4, p5##_type gmock_p5, \ - p6##_type gmock_p6) : p0(::std::forward<p0##_type>(gmock_p0)), \ - p1(::std::forward<p1##_type>(gmock_p1)), \ - p2(::std::forward<p2##_type>(gmock_p2)), \ - p3(::std::forward<p3##_type>(gmock_p3)), \ - p4(::std::forward<p4##_type>(gmock_p4)), \ - p5(::std::forward<p5##_type>(gmock_p5)), \ - p6(::std::forward<p6##_type>(gmock_p6)) {}\ - virtual return_type Perform(const args_type& args) {\ - return ::testing::internal::ActionHelper<return_type, gmock_Impl>::\ - Perform(this, args);\ - }\ - template <typename arg0_type, typename arg1_type, typename arg2_type, \ - typename arg3_type, typename arg4_type, typename arg5_type, \ - typename arg6_type, typename arg7_type, typename arg8_type, \ - typename arg9_type>\ - return_type gmock_PerformImpl(const args_type& args, \ - const arg0_type& arg0, const arg1_type& arg1, \ - const arg2_type& arg2, const arg3_type& arg3, \ - const arg4_type& arg4, const arg5_type& arg5, \ - const arg6_type& arg6, const arg7_type& arg7, \ - const arg8_type& arg8, const arg9_type& arg9) const;\ - p0##_type p0;\ - p1##_type p1;\ - p2##_type p2;\ - p3##_type p3;\ - p4##_type p4;\ - p5##_type p5;\ - p6##_type p6;\ - private:\ - GTEST_DISALLOW_ASSIGN_(gmock_Impl);\ - };\ - template <typename F> operator ::testing::Action<F>() const {\ - return ::testing::Action<F>(new gmock_Impl<F>(p0, p1, p2, p3, p4, p5, \ - p6));\ - }\ - p0##_type p0;\ - p1##_type p1;\ - p2##_type p2;\ - p3##_type p3;\ - p4##_type p4;\ - p5##_type p5;\ - p6##_type p6;\ - private:\ - GTEST_DISALLOW_ASSIGN_(name##ActionP7);\ - };\ - template <typename p0##_type, typename p1##_type, typename p2##_type, \ - typename p3##_type, typename p4##_type, typename p5##_type, \ - typename p6##_type>\ - inline name##ActionP7<p0##_type, p1##_type, p2##_type, p3##_type, \ - p4##_type, p5##_type, p6##_type> name(p0##_type p0, p1##_type p1, \ - p2##_type p2, p3##_type p3, p4##_type p4, p5##_type p5, \ - p6##_type p6) {\ - return name##ActionP7<p0##_type, p1##_type, p2##_type, p3##_type, \ - p4##_type, p5##_type, p6##_type>(p0, p1, p2, p3, p4, p5, p6);\ - }\ - template <typename p0##_type, typename p1##_type, typename p2##_type, \ - typename p3##_type, typename p4##_type, typename p5##_type, \ - typename p6##_type>\ - template <typename F>\ - template <typename arg0_type, typename arg1_type, typename arg2_type, \ - typename arg3_type, typename arg4_type, typename arg5_type, \ - typename arg6_type, typename arg7_type, typename arg8_type, \ - typename arg9_type>\ - typename ::testing::internal::Function<F>::Result\ - name##ActionP7<p0##_type, p1##_type, p2##_type, p3##_type, p4##_type, \ - p5##_type, p6##_type>::gmock_Impl<F>::gmock_PerformImpl(\ - GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const - -#define ACTION_P8(name, p0, p1, p2, p3, p4, p5, p6, p7)\ - template <typename p0##_type, typename p1##_type, typename p2##_type, \ - typename p3##_type, typename p4##_type, typename p5##_type, \ - typename p6##_type, typename p7##_type>\ - class name##ActionP8 {\ - public:\ - name##ActionP8(p0##_type gmock_p0, p1##_type gmock_p1, \ - p2##_type gmock_p2, p3##_type gmock_p3, p4##_type gmock_p4, \ - p5##_type gmock_p5, p6##_type gmock_p6, \ - p7##_type gmock_p7) : p0(::std::forward<p0##_type>(gmock_p0)), \ - p1(::std::forward<p1##_type>(gmock_p1)), \ - p2(::std::forward<p2##_type>(gmock_p2)), \ - p3(::std::forward<p3##_type>(gmock_p3)), \ - p4(::std::forward<p4##_type>(gmock_p4)), \ - p5(::std::forward<p5##_type>(gmock_p5)), \ - p6(::std::forward<p6##_type>(gmock_p6)), \ - p7(::std::forward<p7##_type>(gmock_p7)) {}\ - template <typename F>\ - class gmock_Impl : public ::testing::ActionInterface<F> {\ - public:\ - typedef F function_type;\ - typedef typename ::testing::internal::Function<F>::Result return_type;\ - typedef typename ::testing::internal::Function<F>::ArgumentTuple\ - args_type;\ - gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \ - p3##_type gmock_p3, p4##_type gmock_p4, p5##_type gmock_p5, \ - p6##_type gmock_p6, \ - p7##_type gmock_p7) : p0(::std::forward<p0##_type>(gmock_p0)), \ - p1(::std::forward<p1##_type>(gmock_p1)), \ - p2(::std::forward<p2##_type>(gmock_p2)), \ - p3(::std::forward<p3##_type>(gmock_p3)), \ - p4(::std::forward<p4##_type>(gmock_p4)), \ - p5(::std::forward<p5##_type>(gmock_p5)), \ - p6(::std::forward<p6##_type>(gmock_p6)), \ - p7(::std::forward<p7##_type>(gmock_p7)) {}\ - virtual return_type Perform(const args_type& args) {\ - return ::testing::internal::ActionHelper<return_type, gmock_Impl>::\ - Perform(this, args);\ - }\ - template <typename arg0_type, typename arg1_type, typename arg2_type, \ - typename arg3_type, typename arg4_type, typename arg5_type, \ - typename arg6_type, typename arg7_type, typename arg8_type, \ - typename arg9_type>\ - return_type gmock_PerformImpl(const args_type& args, \ - const arg0_type& arg0, const arg1_type& arg1, \ - const arg2_type& arg2, const arg3_type& arg3, \ - const arg4_type& arg4, const arg5_type& arg5, \ - const arg6_type& arg6, const arg7_type& arg7, \ - const arg8_type& arg8, const arg9_type& arg9) const;\ - p0##_type p0;\ - p1##_type p1;\ - p2##_type p2;\ - p3##_type p3;\ - p4##_type p4;\ - p5##_type p5;\ - p6##_type p6;\ - p7##_type p7;\ - private:\ - GTEST_DISALLOW_ASSIGN_(gmock_Impl);\ - };\ - template <typename F> operator ::testing::Action<F>() const {\ - return ::testing::Action<F>(new gmock_Impl<F>(p0, p1, p2, p3, p4, p5, \ - p6, p7));\ - }\ - p0##_type p0;\ - p1##_type p1;\ - p2##_type p2;\ - p3##_type p3;\ - p4##_type p4;\ - p5##_type p5;\ - p6##_type p6;\ - p7##_type p7;\ - private:\ - GTEST_DISALLOW_ASSIGN_(name##ActionP8);\ - };\ - template <typename p0##_type, typename p1##_type, typename p2##_type, \ - typename p3##_type, typename p4##_type, typename p5##_type, \ - typename p6##_type, typename p7##_type>\ - inline name##ActionP8<p0##_type, p1##_type, p2##_type, p3##_type, \ - p4##_type, p5##_type, p6##_type, p7##_type> name(p0##_type p0, \ - p1##_type p1, p2##_type p2, p3##_type p3, p4##_type p4, p5##_type p5, \ - p6##_type p6, p7##_type p7) {\ - return name##ActionP8<p0##_type, p1##_type, p2##_type, p3##_type, \ - p4##_type, p5##_type, p6##_type, p7##_type>(p0, p1, p2, p3, p4, p5, \ - p6, p7);\ - }\ - template <typename p0##_type, typename p1##_type, typename p2##_type, \ - typename p3##_type, typename p4##_type, typename p5##_type, \ - typename p6##_type, typename p7##_type>\ - template <typename F>\ - template <typename arg0_type, typename arg1_type, typename arg2_type, \ - typename arg3_type, typename arg4_type, typename arg5_type, \ - typename arg6_type, typename arg7_type, typename arg8_type, \ - typename arg9_type>\ - typename ::testing::internal::Function<F>::Result\ - name##ActionP8<p0##_type, p1##_type, p2##_type, p3##_type, p4##_type, \ - p5##_type, p6##_type, \ - p7##_type>::gmock_Impl<F>::gmock_PerformImpl(\ - GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const - -#define ACTION_P9(name, p0, p1, p2, p3, p4, p5, p6, p7, p8)\ - template <typename p0##_type, typename p1##_type, typename p2##_type, \ - typename p3##_type, typename p4##_type, typename p5##_type, \ - typename p6##_type, typename p7##_type, typename p8##_type>\ - class name##ActionP9 {\ - public:\ - name##ActionP9(p0##_type gmock_p0, p1##_type gmock_p1, \ - p2##_type gmock_p2, p3##_type gmock_p3, p4##_type gmock_p4, \ - p5##_type gmock_p5, p6##_type gmock_p6, p7##_type gmock_p7, \ - p8##_type gmock_p8) : p0(::std::forward<p0##_type>(gmock_p0)), \ - p1(::std::forward<p1##_type>(gmock_p1)), \ - p2(::std::forward<p2##_type>(gmock_p2)), \ - p3(::std::forward<p3##_type>(gmock_p3)), \ - p4(::std::forward<p4##_type>(gmock_p4)), \ - p5(::std::forward<p5##_type>(gmock_p5)), \ - p6(::std::forward<p6##_type>(gmock_p6)), \ - p7(::std::forward<p7##_type>(gmock_p7)), \ - p8(::std::forward<p8##_type>(gmock_p8)) {}\ - template <typename F>\ - class gmock_Impl : public ::testing::ActionInterface<F> {\ - public:\ - typedef F function_type;\ - typedef typename ::testing::internal::Function<F>::Result return_type;\ - typedef typename ::testing::internal::Function<F>::ArgumentTuple\ - args_type;\ - gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \ - p3##_type gmock_p3, p4##_type gmock_p4, p5##_type gmock_p5, \ - p6##_type gmock_p6, p7##_type gmock_p7, \ - p8##_type gmock_p8) : p0(::std::forward<p0##_type>(gmock_p0)), \ - p1(::std::forward<p1##_type>(gmock_p1)), \ - p2(::std::forward<p2##_type>(gmock_p2)), \ - p3(::std::forward<p3##_type>(gmock_p3)), \ - p4(::std::forward<p4##_type>(gmock_p4)), \ - p5(::std::forward<p5##_type>(gmock_p5)), \ - p6(::std::forward<p6##_type>(gmock_p6)), \ - p7(::std::forward<p7##_type>(gmock_p7)), \ - p8(::std::forward<p8##_type>(gmock_p8)) {}\ - virtual return_type Perform(const args_type& args) {\ - return ::testing::internal::ActionHelper<return_type, gmock_Impl>::\ - Perform(this, args);\ - }\ - template <typename arg0_type, typename arg1_type, typename arg2_type, \ - typename arg3_type, typename arg4_type, typename arg5_type, \ - typename arg6_type, typename arg7_type, typename arg8_type, \ - typename arg9_type>\ - return_type gmock_PerformImpl(const args_type& args, \ - const arg0_type& arg0, const arg1_type& arg1, \ - const arg2_type& arg2, const arg3_type& arg3, \ - const arg4_type& arg4, const arg5_type& arg5, \ - const arg6_type& arg6, const arg7_type& arg7, \ - const arg8_type& arg8, const arg9_type& arg9) const;\ - p0##_type p0;\ - p1##_type p1;\ - p2##_type p2;\ - p3##_type p3;\ - p4##_type p4;\ - p5##_type p5;\ - p6##_type p6;\ - p7##_type p7;\ - p8##_type p8;\ - private:\ - GTEST_DISALLOW_ASSIGN_(gmock_Impl);\ - };\ - template <typename F> operator ::testing::Action<F>() const {\ - return ::testing::Action<F>(new gmock_Impl<F>(p0, p1, p2, p3, p4, p5, \ - p6, p7, p8));\ - }\ - p0##_type p0;\ - p1##_type p1;\ - p2##_type p2;\ - p3##_type p3;\ - p4##_type p4;\ - p5##_type p5;\ - p6##_type p6;\ - p7##_type p7;\ - p8##_type p8;\ - private:\ - GTEST_DISALLOW_ASSIGN_(name##ActionP9);\ - };\ - template <typename p0##_type, typename p1##_type, typename p2##_type, \ - typename p3##_type, typename p4##_type, typename p5##_type, \ - typename p6##_type, typename p7##_type, typename p8##_type>\ - inline name##ActionP9<p0##_type, p1##_type, p2##_type, p3##_type, \ - p4##_type, p5##_type, p6##_type, p7##_type, \ - p8##_type> name(p0##_type p0, p1##_type p1, p2##_type p2, p3##_type p3, \ - p4##_type p4, p5##_type p5, p6##_type p6, p7##_type p7, \ - p8##_type p8) {\ - return name##ActionP9<p0##_type, p1##_type, p2##_type, p3##_type, \ - p4##_type, p5##_type, p6##_type, p7##_type, p8##_type>(p0, p1, p2, \ - p3, p4, p5, p6, p7, p8);\ - }\ - template <typename p0##_type, typename p1##_type, typename p2##_type, \ - typename p3##_type, typename p4##_type, typename p5##_type, \ - typename p6##_type, typename p7##_type, typename p8##_type>\ - template <typename F>\ - template <typename arg0_type, typename arg1_type, typename arg2_type, \ - typename arg3_type, typename arg4_type, typename arg5_type, \ - typename arg6_type, typename arg7_type, typename arg8_type, \ - typename arg9_type>\ - typename ::testing::internal::Function<F>::Result\ - name##ActionP9<p0##_type, p1##_type, p2##_type, p3##_type, p4##_type, \ - p5##_type, p6##_type, p7##_type, \ - p8##_type>::gmock_Impl<F>::gmock_PerformImpl(\ - GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const - -#define ACTION_P10(name, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9)\ - template <typename p0##_type, typename p1##_type, typename p2##_type, \ - typename p3##_type, typename p4##_type, typename p5##_type, \ - typename p6##_type, typename p7##_type, typename p8##_type, \ - typename p9##_type>\ - class name##ActionP10 {\ - public:\ - name##ActionP10(p0##_type gmock_p0, p1##_type gmock_p1, \ - p2##_type gmock_p2, p3##_type gmock_p3, p4##_type gmock_p4, \ - p5##_type gmock_p5, p6##_type gmock_p6, p7##_type gmock_p7, \ - p8##_type gmock_p8, \ - p9##_type gmock_p9) : p0(::std::forward<p0##_type>(gmock_p0)), \ - p1(::std::forward<p1##_type>(gmock_p1)), \ - p2(::std::forward<p2##_type>(gmock_p2)), \ - p3(::std::forward<p3##_type>(gmock_p3)), \ - p4(::std::forward<p4##_type>(gmock_p4)), \ - p5(::std::forward<p5##_type>(gmock_p5)), \ - p6(::std::forward<p6##_type>(gmock_p6)), \ - p7(::std::forward<p7##_type>(gmock_p7)), \ - p8(::std::forward<p8##_type>(gmock_p8)), \ - p9(::std::forward<p9##_type>(gmock_p9)) {}\ - template <typename F>\ - class gmock_Impl : public ::testing::ActionInterface<F> {\ - public:\ - typedef F function_type;\ - typedef typename ::testing::internal::Function<F>::Result return_type;\ - typedef typename ::testing::internal::Function<F>::ArgumentTuple\ - args_type;\ - gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \ - p3##_type gmock_p3, p4##_type gmock_p4, p5##_type gmock_p5, \ - p6##_type gmock_p6, p7##_type gmock_p7, p8##_type gmock_p8, \ - p9##_type gmock_p9) : p0(::std::forward<p0##_type>(gmock_p0)), \ - p1(::std::forward<p1##_type>(gmock_p1)), \ - p2(::std::forward<p2##_type>(gmock_p2)), \ - p3(::std::forward<p3##_type>(gmock_p3)), \ - p4(::std::forward<p4##_type>(gmock_p4)), \ - p5(::std::forward<p5##_type>(gmock_p5)), \ - p6(::std::forward<p6##_type>(gmock_p6)), \ - p7(::std::forward<p7##_type>(gmock_p7)), \ - p8(::std::forward<p8##_type>(gmock_p8)), \ - p9(::std::forward<p9##_type>(gmock_p9)) {}\ - virtual return_type Perform(const args_type& args) {\ - return ::testing::internal::ActionHelper<return_type, gmock_Impl>::\ - Perform(this, args);\ - }\ - template <typename arg0_type, typename arg1_type, typename arg2_type, \ - typename arg3_type, typename arg4_type, typename arg5_type, \ - typename arg6_type, typename arg7_type, typename arg8_type, \ - typename arg9_type>\ - return_type gmock_PerformImpl(const args_type& args, \ - const arg0_type& arg0, const arg1_type& arg1, \ - const arg2_type& arg2, const arg3_type& arg3, \ - const arg4_type& arg4, const arg5_type& arg5, \ - const arg6_type& arg6, const arg7_type& arg7, \ - const arg8_type& arg8, const arg9_type& arg9) const;\ - p0##_type p0;\ - p1##_type p1;\ - p2##_type p2;\ - p3##_type p3;\ - p4##_type p4;\ - p5##_type p5;\ - p6##_type p6;\ - p7##_type p7;\ - p8##_type p8;\ - p9##_type p9;\ - private:\ - GTEST_DISALLOW_ASSIGN_(gmock_Impl);\ - };\ - template <typename F> operator ::testing::Action<F>() const {\ - return ::testing::Action<F>(new gmock_Impl<F>(p0, p1, p2, p3, p4, p5, \ - p6, p7, p8, p9));\ - }\ - p0##_type p0;\ - p1##_type p1;\ - p2##_type p2;\ - p3##_type p3;\ - p4##_type p4;\ - p5##_type p5;\ - p6##_type p6;\ - p7##_type p7;\ - p8##_type p8;\ - p9##_type p9;\ - private:\ - GTEST_DISALLOW_ASSIGN_(name##ActionP10);\ - };\ - template <typename p0##_type, typename p1##_type, typename p2##_type, \ - typename p3##_type, typename p4##_type, typename p5##_type, \ - typename p6##_type, typename p7##_type, typename p8##_type, \ - typename p9##_type>\ - inline name##ActionP10<p0##_type, p1##_type, p2##_type, p3##_type, \ - p4##_type, p5##_type, p6##_type, p7##_type, p8##_type, \ - p9##_type> name(p0##_type p0, p1##_type p1, p2##_type p2, p3##_type p3, \ - p4##_type p4, p5##_type p5, p6##_type p6, p7##_type p7, p8##_type p8, \ - p9##_type p9) {\ - return name##ActionP10<p0##_type, p1##_type, p2##_type, p3##_type, \ - p4##_type, p5##_type, p6##_type, p7##_type, p8##_type, p9##_type>(p0, \ - p1, p2, p3, p4, p5, p6, p7, p8, p9);\ - }\ - template <typename p0##_type, typename p1##_type, typename p2##_type, \ - typename p3##_type, typename p4##_type, typename p5##_type, \ - typename p6##_type, typename p7##_type, typename p8##_type, \ - typename p9##_type>\ - template <typename F>\ - template <typename arg0_type, typename arg1_type, typename arg2_type, \ - typename arg3_type, typename arg4_type, typename arg5_type, \ - typename arg6_type, typename arg7_type, typename arg8_type, \ - typename arg9_type>\ - typename ::testing::internal::Function<F>::Result\ - name##ActionP10<p0##_type, p1##_type, p2##_type, p3##_type, p4##_type, \ - p5##_type, p6##_type, p7##_type, p8##_type, \ - p9##_type>::gmock_Impl<F>::gmock_PerformImpl(\ - GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const namespace testing { @@ -1628,175 +512,94 @@ namespace testing { // InvokeArgument action from temporary values and have it performed // later. -namespace internal { -namespace invoke_argument { - -// Appears in InvokeArgumentAdl's argument list to help avoid -// accidental calls to user functions of the same name. -struct AdlTag {}; - -// InvokeArgumentAdl - a helper for InvokeArgument. -// The basic overloads are provided here for generic functors. -// Overloads for other custom-callables are provided in the -// internal/custom/callback-actions.h header. - -template <typename R, typename F> -R InvokeArgumentAdl(AdlTag, F f) { - return f(); -} -template <typename R, typename F, typename A1> -R InvokeArgumentAdl(AdlTag, F f, A1 a1) { - return f(a1); -} -template <typename R, typename F, typename A1, typename A2> -R InvokeArgumentAdl(AdlTag, F f, A1 a1, A2 a2) { - return f(a1, a2); -} -template <typename R, typename F, typename A1, typename A2, typename A3> -R InvokeArgumentAdl(AdlTag, F f, A1 a1, A2 a2, A3 a3) { - return f(a1, a2, a3); -} -template <typename R, typename F, typename A1, typename A2, typename A3, - typename A4> -R InvokeArgumentAdl(AdlTag, F f, A1 a1, A2 a2, A3 a3, A4 a4) { - return f(a1, a2, a3, a4); -} -template <typename R, typename F, typename A1, typename A2, typename A3, - typename A4, typename A5> -R InvokeArgumentAdl(AdlTag, F f, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) { - return f(a1, a2, a3, a4, a5); -} -template <typename R, typename F, typename A1, typename A2, typename A3, - typename A4, typename A5, typename A6> -R InvokeArgumentAdl(AdlTag, F f, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) { - return f(a1, a2, a3, a4, a5, a6); -} -template <typename R, typename F, typename A1, typename A2, typename A3, - typename A4, typename A5, typename A6, typename A7> -R InvokeArgumentAdl(AdlTag, F f, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, - A7 a7) { - return f(a1, a2, a3, a4, a5, a6, a7); -} -template <typename R, typename F, typename A1, typename A2, typename A3, - typename A4, typename A5, typename A6, typename A7, typename A8> -R InvokeArgumentAdl(AdlTag, F f, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, - A7 a7, A8 a8) { - return f(a1, a2, a3, a4, a5, a6, a7, a8); -} -template <typename R, typename F, typename A1, typename A2, typename A3, - typename A4, typename A5, typename A6, typename A7, typename A8, - typename A9> -R InvokeArgumentAdl(AdlTag, F f, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, - A7 a7, A8 a8, A9 a9) { - return f(a1, a2, a3, a4, a5, a6, a7, a8, a9); -} -template <typename R, typename F, typename A1, typename A2, typename A3, - typename A4, typename A5, typename A6, typename A7, typename A8, - typename A9, typename A10> -R InvokeArgumentAdl(AdlTag, F f, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, - A7 a7, A8 a8, A9 a9, A10 a10) { - return f(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10); -} -} // namespace invoke_argument -} // namespace internal - ACTION_TEMPLATE(InvokeArgument, HAS_1_TEMPLATE_PARAMS(int, k), AND_0_VALUE_PARAMS()) { using internal::invoke_argument::InvokeArgumentAdl; - return InvokeArgumentAdl<return_type>( - internal::invoke_argument::AdlTag(), - ::std::get<k>(args)); + return InvokeArgumentAdl(internal::invoke_argument::AdlTag(), + ::std::get<k>(args)); } ACTION_TEMPLATE(InvokeArgument, HAS_1_TEMPLATE_PARAMS(int, k), AND_1_VALUE_PARAMS(p0)) { using internal::invoke_argument::InvokeArgumentAdl; - return InvokeArgumentAdl<return_type>( - internal::invoke_argument::AdlTag(), - ::std::get<k>(args), p0); + return InvokeArgumentAdl(internal::invoke_argument::AdlTag(), + ::std::get<k>(args), p0); } ACTION_TEMPLATE(InvokeArgument, HAS_1_TEMPLATE_PARAMS(int, k), AND_2_VALUE_PARAMS(p0, p1)) { using internal::invoke_argument::InvokeArgumentAdl; - return InvokeArgumentAdl<return_type>( - internal::invoke_argument::AdlTag(), - ::std::get<k>(args), p0, p1); + return InvokeArgumentAdl(internal::invoke_argument::AdlTag(), + ::std::get<k>(args), p0, p1); } ACTION_TEMPLATE(InvokeArgument, HAS_1_TEMPLATE_PARAMS(int, k), AND_3_VALUE_PARAMS(p0, p1, p2)) { using internal::invoke_argument::InvokeArgumentAdl; - return InvokeArgumentAdl<return_type>( - internal::invoke_argument::AdlTag(), - ::std::get<k>(args), p0, p1, p2); + return InvokeArgumentAdl(internal::invoke_argument::AdlTag(), + ::std::get<k>(args), p0, p1, p2); } ACTION_TEMPLATE(InvokeArgument, HAS_1_TEMPLATE_PARAMS(int, k), AND_4_VALUE_PARAMS(p0, p1, p2, p3)) { using internal::invoke_argument::InvokeArgumentAdl; - return InvokeArgumentAdl<return_type>( - internal::invoke_argument::AdlTag(), - ::std::get<k>(args), p0, p1, p2, p3); + return InvokeArgumentAdl(internal::invoke_argument::AdlTag(), + ::std::get<k>(args), p0, p1, p2, p3); } ACTION_TEMPLATE(InvokeArgument, HAS_1_TEMPLATE_PARAMS(int, k), AND_5_VALUE_PARAMS(p0, p1, p2, p3, p4)) { using internal::invoke_argument::InvokeArgumentAdl; - return InvokeArgumentAdl<return_type>( - internal::invoke_argument::AdlTag(), - ::std::get<k>(args), p0, p1, p2, p3, p4); + return InvokeArgumentAdl(internal::invoke_argument::AdlTag(), + ::std::get<k>(args), p0, p1, p2, p3, p4); } ACTION_TEMPLATE(InvokeArgument, HAS_1_TEMPLATE_PARAMS(int, k), AND_6_VALUE_PARAMS(p0, p1, p2, p3, p4, p5)) { using internal::invoke_argument::InvokeArgumentAdl; - return InvokeArgumentAdl<return_type>( - internal::invoke_argument::AdlTag(), - ::std::get<k>(args), p0, p1, p2, p3, p4, p5); + return InvokeArgumentAdl(internal::invoke_argument::AdlTag(), + ::std::get<k>(args), p0, p1, p2, p3, p4, p5); } ACTION_TEMPLATE(InvokeArgument, HAS_1_TEMPLATE_PARAMS(int, k), AND_7_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6)) { using internal::invoke_argument::InvokeArgumentAdl; - return InvokeArgumentAdl<return_type>( - internal::invoke_argument::AdlTag(), - ::std::get<k>(args), p0, p1, p2, p3, p4, p5, p6); + return InvokeArgumentAdl(internal::invoke_argument::AdlTag(), + ::std::get<k>(args), p0, p1, p2, p3, p4, p5, p6); } ACTION_TEMPLATE(InvokeArgument, HAS_1_TEMPLATE_PARAMS(int, k), AND_8_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, p7)) { using internal::invoke_argument::InvokeArgumentAdl; - return InvokeArgumentAdl<return_type>( - internal::invoke_argument::AdlTag(), - ::std::get<k>(args), p0, p1, p2, p3, p4, p5, p6, p7); + return InvokeArgumentAdl(internal::invoke_argument::AdlTag(), + ::std::get<k>(args), p0, p1, p2, p3, p4, p5, p6, p7); } ACTION_TEMPLATE(InvokeArgument, HAS_1_TEMPLATE_PARAMS(int, k), AND_9_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, p7, p8)) { using internal::invoke_argument::InvokeArgumentAdl; - return InvokeArgumentAdl<return_type>( - internal::invoke_argument::AdlTag(), - ::std::get<k>(args), p0, p1, p2, p3, p4, p5, p6, p7, p8); + return InvokeArgumentAdl(internal::invoke_argument::AdlTag(), + ::std::get<k>(args), p0, p1, p2, p3, p4, p5, p6, p7, + p8); } ACTION_TEMPLATE(InvokeArgument, HAS_1_TEMPLATE_PARAMS(int, k), AND_10_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9)) { using internal::invoke_argument::InvokeArgumentAdl; - return InvokeArgumentAdl<return_type>( - internal::invoke_argument::AdlTag(), - ::std::get<k>(args), p0, p1, p2, p3, p4, p5, p6, p7, p8, p9); + return InvokeArgumentAdl(internal::invoke_argument::AdlTag(), + ::std::get<k>(args), p0, p1, p2, p3, p4, p5, p6, p7, + p8, p9); } // Various overloads for ReturnNew<T>(). diff --git a/googlemock/include/gmock/gmock-generated-actions.h.pump b/googlemock/include/gmock/gmock-generated-actions.h.pump index 209603c5..be9d99fe 100644 --- a/googlemock/include/gmock/gmock-generated-actions.h.pump +++ b/googlemock/include/gmock/gmock-generated-actions.h.pump @@ -49,158 +49,9 @@ $$}} This meta comment fixes auto-indentation in editors. #include "gmock/gmock-actions.h" #include "gmock/internal/gmock-port.h" -namespace testing { -namespace internal { - -// A macro from the ACTION* family (defined later in this file) -// defines an action that can be used in a mock function. Typically, -// these actions only care about a subset of the arguments of the mock -// function. For example, if such an action only uses the second -// argument, it can be used in any mock function that takes >= 2 -// arguments where the type of the second argument is compatible. -// -// Therefore, the action implementation must be prepared to take more -// arguments than it needs. The ExcessiveArg type is used to -// represent those excessive arguments. In order to keep the compiler -// error messages tractable, we define it in the testing namespace -// instead of testing::internal. However, this is an INTERNAL TYPE -// and subject to change without notice, so a user MUST NOT USE THIS -// TYPE DIRECTLY. -struct ExcessiveArg {}; - -// A helper class needed for implementing the ACTION* macros. -template <typename Result, class Impl> -class ActionHelper { - public: -$range i 0..n -$for i - -[[ -$var template = [[$if i==0 [[]] $else [[ -$range j 0..i-1 - template <$for j, [[typename A$j]]> -]]]] -$range j 0..i-1 -$var As = [[$for j, [[A$j]]]] -$var as = [[$for j, [[std::get<$j>(args)]]]] -$range k 1..n-i -$var eas = [[$for k, [[ExcessiveArg()]]]] -$var arg_list = [[$if (i==0) | (i==n) [[$as$eas]] $else [[$as, $eas]]]] -$template - static Result Perform(Impl* impl, const ::std::tuple<$As>& args) { - return impl->template gmock_PerformImpl<$As>(args, $arg_list); - } - -]] -}; - -} // namespace internal -} // namespace testing - -// The ACTION* family of macros can be used in a namespace scope to -// define custom actions easily. The syntax: -// -// ACTION(name) { statements; } -// -// will define an action with the given name that executes the -// statements. The value returned by the statements will be used as -// the return value of the action. Inside the statements, you can -// refer to the K-th (0-based) argument of the mock function by -// 'argK', and refer to its type by 'argK_type'. For example: -// -// ACTION(IncrementArg1) { -// arg1_type temp = arg1; -// return ++(*temp); -// } -// -// allows you to write -// -// ...WillOnce(IncrementArg1()); -// -// You can also refer to the entire argument tuple and its type by -// 'args' and 'args_type', and refer to the mock function type and its -// return type by 'function_type' and 'return_type'. -// -// Note that you don't need to specify the types of the mock function -// arguments. However rest assured that your code is still type-safe: -// you'll get a compiler error if *arg1 doesn't support the ++ -// operator, or if the type of ++(*arg1) isn't compatible with the -// mock function's return type, for example. -// -// Sometimes you'll want to parameterize the action. For that you can use -// another macro: -// -// ACTION_P(name, param_name) { statements; } -// -// For example: -// -// ACTION_P(Add, n) { return arg0 + n; } -// -// will allow you to write: -// -// ...WillOnce(Add(5)); -// -// Note that you don't need to provide the type of the parameter -// either. If you need to reference the type of a parameter named -// 'foo', you can write 'foo_type'. For example, in the body of -// ACTION_P(Add, n) above, you can write 'n_type' to refer to the type -// of 'n'. -// -// We also provide ACTION_P2, ACTION_P3, ..., up to ACTION_P$n to support -// multi-parameter actions. -// -// For the purpose of typing, you can view -// -// ACTION_Pk(Foo, p1, ..., pk) { ... } -// -// as shorthand for -// -// template <typename p1_type, ..., typename pk_type> -// FooActionPk<p1_type, ..., pk_type> Foo(p1_type p1, ..., pk_type pk) { ... } -// -// In particular, you can provide the template type arguments -// explicitly when invoking Foo(), as in Foo<long, bool>(5, false); -// although usually you can rely on the compiler to infer the types -// for you automatically. You can assign the result of expression -// Foo(p1, ..., pk) to a variable of type FooActionPk<p1_type, ..., -// pk_type>. This can be useful when composing actions. -// -// You can also overload actions with different numbers of parameters: -// -// ACTION_P(Plus, a) { ... } -// ACTION_P2(Plus, a, b) { ... } -// -// While it's tempting to always use the ACTION* macros when defining -// a new action, you should also consider implementing ActionInterface -// or using MakePolymorphicAction() instead, especially if you need to -// use the action a lot. While these approaches require more work, -// they give you more control on the types of the mock function -// arguments and the action parameters, which in general leads to -// better compiler error messages that pay off in the long run. They -// also allow overloading actions based on parameter types (as opposed -// to just based on the number of parameters). -// -// CAVEAT: -// -// ACTION*() can only be used in a namespace scope as templates cannot be -// declared inside of a local class. -// Users can, however, define any local functors (e.g. a lambda) that -// can be used as actions. -// -// MORE INFORMATION: -// -// To learn more about using these macros, please search for 'ACTION' on -// https://github.com/google/googletest/blob/master/googlemock/docs/cook_book.md - $range i 0..n $range k 0..n-1 -// An internal macro needed for implementing ACTION*(). -#define GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_\ - const args_type& args GTEST_ATTRIBUTE_UNUSED_ -$for k [[, \ - const arg$k[[]]_type& arg$k GTEST_ATTRIBUTE_UNUSED_]] - // Sometimes you want to give an action explicit template parameters // that cannot be inferred from its value parameters. ACTION() and @@ -395,13 +246,12 @@ $range k 0..n-1 typedef typename ::testing::internal::Function<F>::ArgumentTuple\ args_type;\ explicit gmock_Impl GMOCK_INTERNAL_INIT_##value_params {}\ - virtual return_type Perform(const args_type& args) {\ + return_type Perform(const args_type& args) override {\ return ::testing::internal::ActionHelper<return_type, gmock_Impl>::\ Perform(this, args);\ }\ - template <$for k, [[typename arg$k[[]]_type]]>\ - return_type gmock_PerformImpl(const args_type& args[[]] -$for k [[, const arg$k[[]]_type& arg$k]]) const;\ + template <GMOCK_ACTION_TEMPLATE_ARGS_NAMES_>\ + return_type gmock_PerformImpl(GMOCK_ACTION_ARG_TYPES_AND_NAMES_) const;\ GMOCK_INTERNAL_DEFN_##value_params\ private:\ GTEST_DISALLOW_ASSIGN_(gmock_Impl);\ @@ -428,10 +278,7 @@ $for k [[, const arg$k[[]]_type& arg$k]]) const;\ template <GMOCK_INTERNAL_DECL_##template_params\ GMOCK_INTERNAL_DECL_TYPE_##value_params>\ template <typename F>\ - template <typename arg0_type, typename arg1_type, typename arg2_type, \ - typename arg3_type, typename arg4_type, typename arg5_type, \ - typename arg6_type, typename arg7_type, typename arg8_type, \ - typename arg9_type>\ + template <GMOCK_ACTION_TEMPLATE_ARGS_NAMES_>\ typename ::testing::internal::Function<F>::Result\ GMOCK_ACTION_CLASS_(name, value_params)<\ GMOCK_INTERNAL_LIST_##template_params\ @@ -439,77 +286,6 @@ $for k [[, const arg$k[[]]_type& arg$k]]) const;\ gmock_PerformImpl(\ GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const -$for i - -[[ -$var template = [[$if i==0 [[]] $else [[ -$range j 0..i-1 - - template <$for j, [[typename p$j##_type]]>\ -]]]] -$var class_name = [[name##Action[[$if i==0 [[]] $elif i==1 [[P]] - $else [[P$i]]]]]] -$range j 0..i-1 -$var ctor_param_list = [[$for j, [[p$j##_type gmock_p$j]]]] -$var param_types_and_names = [[$for j, [[p$j##_type p$j]]]] -$var inits = [[$if i==0 [[]] $else [[ : $for j, [[p$j(::std::forward<p$j##_type>(gmock_p$j))]]]]]] -$var param_field_decls = [[$for j -[[ - - p$j##_type p$j;\ -]]]] -$var param_field_decls2 = [[$for j -[[ - - p$j##_type p$j;\ -]]]] -$var params = [[$for j, [[p$j]]]] -$var param_types = [[$if i==0 [[]] $else [[<$for j, [[p$j##_type]]>]]]] -$var typename_arg_types = [[$for k, [[typename arg$k[[]]_type]]]] -$var arg_types_and_names = [[$for k, [[const arg$k[[]]_type& arg$k]]]] -$var macro_name = [[$if i==0 [[ACTION]] $elif i==1 [[ACTION_P]] - $else [[ACTION_P$i]]]] - -#define $macro_name(name$for j [[, p$j]])\$template - class $class_name {\ - public:\ - [[$if i==1 [[explicit ]]]]$class_name($ctor_param_list)$inits {}\ - template <typename F>\ - class gmock_Impl : public ::testing::ActionInterface<F> {\ - public:\ - typedef F function_type;\ - typedef typename ::testing::internal::Function<F>::Result return_type;\ - typedef typename ::testing::internal::Function<F>::ArgumentTuple\ - args_type;\ - [[$if i==1 [[explicit ]]]]gmock_Impl($ctor_param_list)$inits {}\ - virtual return_type Perform(const args_type& args) {\ - return ::testing::internal::ActionHelper<return_type, gmock_Impl>::\ - Perform(this, args);\ - }\ - template <$typename_arg_types>\ - return_type gmock_PerformImpl(const args_type& args, [[]] -$arg_types_and_names) const;\$param_field_decls - private:\ - GTEST_DISALLOW_ASSIGN_(gmock_Impl);\ - };\ - template <typename F> operator ::testing::Action<F>() const {\ - return ::testing::Action<F>(new gmock_Impl<F>($params));\ - }\$param_field_decls2 - private:\ - GTEST_DISALLOW_ASSIGN_($class_name);\ - };\$template - inline $class_name$param_types name($param_types_and_names) {\ - return $class_name$param_types($params);\ - }\$template - template <typename F>\ - template <$typename_arg_types>\ - typename ::testing::internal::Function<F>::Result\ - $class_name$param_types::gmock_Impl<F>::gmock_PerformImpl(\ - GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const -]] -$$ } // This meta comment fixes auto-indentation in Emacs. It won't -$$ // show up in the generated code. - namespace testing { @@ -554,32 +330,6 @@ namespace testing { // InvokeArgument action from temporary values and have it performed // later. -namespace internal { -namespace invoke_argument { - -// Appears in InvokeArgumentAdl's argument list to help avoid -// accidental calls to user functions of the same name. -struct AdlTag {}; - -// InvokeArgumentAdl - a helper for InvokeArgument. -// The basic overloads are provided here for generic functors. -// Overloads for other custom-callables are provided in the -// internal/custom/callback-actions.h header. - -$range i 0..n -$for i -[[ -$range j 1..i - -template <typename R, typename F[[$for j [[, typename A$j]]]]> -R InvokeArgumentAdl(AdlTag, F f[[$for j [[, A$j a$j]]]]) { - return f([[$for j, [[a$j]]]]); -} -]] - -} // namespace invoke_argument -} // namespace internal - $range i 0..n $for i [[ $range j 0..i-1 @@ -588,9 +338,8 @@ ACTION_TEMPLATE(InvokeArgument, HAS_1_TEMPLATE_PARAMS(int, k), AND_$i[[]]_VALUE_PARAMS($for j, [[p$j]])) { using internal::invoke_argument::InvokeArgumentAdl; - return InvokeArgumentAdl<return_type>( - internal::invoke_argument::AdlTag(), - ::std::get<k>(args)$for j [[, p$j]]); + return InvokeArgumentAdl(internal::invoke_argument::AdlTag(), + ::std::get<k>(args)$for j[[, p$j]]); } ]] diff --git a/googlemock/include/gmock/gmock-generated-function-mockers.h b/googlemock/include/gmock/gmock-generated-function-mockers.h deleted file mode 100644 index cd957817..00000000 --- a/googlemock/include/gmock/gmock-generated-function-mockers.h +++ /dev/null @@ -1,752 +0,0 @@ -// This file was GENERATED by command: -// pump.py gmock-generated-function-mockers.h.pump -// DO NOT EDIT BY HAND!!! - -// Copyright 2007, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - -// Google Mock - a framework for writing C++ mock classes. -// -// This file implements function mockers of various arities. - -// GOOGLETEST_CM0002 DO NOT DELETE - -#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_FUNCTION_MOCKERS_H_ -#define GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_FUNCTION_MOCKERS_H_ - -#include <functional> -#include <utility> - -#include "gmock/gmock-spec-builders.h" -#include "gmock/internal/gmock-internal-utils.h" - -namespace testing { -namespace internal { -// Removes the given pointer; this is a helper for the expectation setter method -// for parameterless matchers. -// -// We want to make sure that the user cannot set a parameterless expectation on -// overloaded methods, including methods which are overloaded on const. Example: -// -// class MockClass { -// MOCK_METHOD0(GetName, string&()); -// MOCK_CONST_METHOD0(GetName, const string&()); -// }; -// -// TEST() { -// // This should be an error, as it's not clear which overload is expected. -// EXPECT_CALL(mock, GetName).WillOnce(ReturnRef(value)); -// } -// -// Here are the generated expectation-setter methods: -// -// class MockClass { -// // Overload 1 -// MockSpec<string&()> gmock_GetName() { ... } -// // Overload 2. Declared const so that the compiler will generate an -// // error when trying to resolve between this and overload 4 in -// // 'gmock_GetName(WithoutMatchers(), nullptr)'. -// MockSpec<string&()> gmock_GetName( -// const WithoutMatchers&, const Function<string&()>*) const { -// // Removes const from this, calls overload 1 -// return AdjustConstness_(this)->gmock_GetName(); -// } -// -// // Overload 3 -// const string& gmock_GetName() const { ... } -// // Overload 4 -// MockSpec<const string&()> gmock_GetName( -// const WithoutMatchers&, const Function<const string&()>*) const { -// // Does not remove const, calls overload 3 -// return AdjustConstness_const(this)->gmock_GetName(); -// } -// } -// -template <typename MockType> -const MockType* AdjustConstness_const(const MockType* mock) { - return mock; -} - -// Removes const from and returns the given pointer; this is a helper for the -// expectation setter method for parameterless matchers. -template <typename MockType> -MockType* AdjustConstness_(const MockType* mock) { - return const_cast<MockType*>(mock); -} - -} // namespace internal - -// The style guide prohibits "using" statements in a namespace scope -// inside a header file. However, the FunctionMocker class template -// is meant to be defined in the ::testing namespace. The following -// line is just a trick for working around a bug in MSVC 8.0, which -// cannot handle it if we define FunctionMocker in ::testing. -using internal::FunctionMocker; - -// GMOCK_RESULT_(tn, F) expands to the result type of function type F. -// We define this as a variadic macro in case F contains unprotected -// commas (the same reason that we use variadic macros in other places -// in this file). -// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!! -#define GMOCK_RESULT_(tn, ...) \ - tn ::testing::internal::Function<__VA_ARGS__>::Result - -// The type of argument N of the given function type. -// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!! -#define GMOCK_ARG_(tn, N, ...) \ - tn ::testing::internal::Function<__VA_ARGS__>::template Arg<N-1>::type - -// The matcher type for argument N of the given function type. -// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!! -#define GMOCK_MATCHER_(tn, N, ...) \ - const ::testing::Matcher<GMOCK_ARG_(tn, N, __VA_ARGS__)>& - -// The variable for mocking the given method. -// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!! -#define GMOCK_MOCKER_(arity, constness, Method) \ - GTEST_CONCAT_TOKEN_(gmock##constness##arity##_##Method##_, __LINE__) - -// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!! -#define GMOCK_METHOD0_(tn, constness, ct, Method, ...) \ - static_assert(0 == \ - ::testing::internal::Function<__VA_ARGS__>::ArgumentCount, \ - "MOCK_METHOD<N> must match argument count.");\ - GMOCK_RESULT_(tn, __VA_ARGS__) ct Method( \ - ) constness { \ - GMOCK_MOCKER_(0, constness, Method).SetOwnerAndName(this, #Method); \ - return GMOCK_MOCKER_(0, constness, Method).Invoke(); \ - } \ - ::testing::MockSpec<__VA_ARGS__> \ - gmock_##Method() constness { \ - GMOCK_MOCKER_(0, constness, Method).RegisterOwner(this); \ - return GMOCK_MOCKER_(0, constness, Method).With(); \ - } \ - ::testing::MockSpec<__VA_ARGS__> gmock_##Method( \ - const ::testing::internal::WithoutMatchers&, \ - constness ::testing::internal::Function<__VA_ARGS__>* ) const { \ - return ::testing::internal::AdjustConstness_##constness(this)-> \ - gmock_##Method(); \ - } \ - mutable ::testing::FunctionMocker<__VA_ARGS__> GMOCK_MOCKER_(0, constness, \ - Method) - -// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!! -#define GMOCK_METHOD1_(tn, constness, ct, Method, ...) \ - static_assert(1 == \ - ::testing::internal::Function<__VA_ARGS__>::ArgumentCount, \ - "MOCK_METHOD<N> must match argument count.");\ - GMOCK_RESULT_(tn, __VA_ARGS__) ct Method( \ - GMOCK_ARG_(tn, 1, __VA_ARGS__) gmock_a1) constness { \ - GMOCK_MOCKER_(1, constness, Method).SetOwnerAndName(this, #Method); \ - return GMOCK_MOCKER_(1, constness, \ - Method).Invoke(::std::forward<GMOCK_ARG_(tn, 1, \ - __VA_ARGS__)>(gmock_a1)); \ - } \ - ::testing::MockSpec<__VA_ARGS__> \ - gmock_##Method(GMOCK_MATCHER_(tn, 1, __VA_ARGS__) gmock_a1) constness { \ - GMOCK_MOCKER_(1, constness, Method).RegisterOwner(this); \ - return GMOCK_MOCKER_(1, constness, Method).With(gmock_a1); \ - } \ - ::testing::MockSpec<__VA_ARGS__> gmock_##Method( \ - const ::testing::internal::WithoutMatchers&, \ - constness ::testing::internal::Function<__VA_ARGS__>* ) const { \ - return ::testing::internal::AdjustConstness_##constness(this)-> \ - gmock_##Method(::testing::A<GMOCK_ARG_(tn, 1, __VA_ARGS__)>()); \ - } \ - mutable ::testing::FunctionMocker<__VA_ARGS__> GMOCK_MOCKER_(1, constness, \ - Method) - -// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!! -#define GMOCK_METHOD2_(tn, constness, ct, Method, ...) \ - static_assert(2 == \ - ::testing::internal::Function<__VA_ARGS__>::ArgumentCount, \ - "MOCK_METHOD<N> must match argument count.");\ - GMOCK_RESULT_(tn, __VA_ARGS__) ct Method( \ - GMOCK_ARG_(tn, 1, __VA_ARGS__) gmock_a1, GMOCK_ARG_(tn, 2, \ - __VA_ARGS__) gmock_a2) constness { \ - GMOCK_MOCKER_(2, constness, Method).SetOwnerAndName(this, #Method); \ - return GMOCK_MOCKER_(2, constness, \ - Method).Invoke(::std::forward<GMOCK_ARG_(tn, 1, \ - __VA_ARGS__)>(gmock_a1), \ - ::std::forward<GMOCK_ARG_(tn, 2, __VA_ARGS__)>(gmock_a2)); \ - } \ - ::testing::MockSpec<__VA_ARGS__> \ - gmock_##Method(GMOCK_MATCHER_(tn, 1, __VA_ARGS__) gmock_a1, \ - GMOCK_MATCHER_(tn, 2, __VA_ARGS__) gmock_a2) constness { \ - GMOCK_MOCKER_(2, constness, Method).RegisterOwner(this); \ - return GMOCK_MOCKER_(2, constness, Method).With(gmock_a1, gmock_a2); \ - } \ - ::testing::MockSpec<__VA_ARGS__> gmock_##Method( \ - const ::testing::internal::WithoutMatchers&, \ - constness ::testing::internal::Function<__VA_ARGS__>* ) const { \ - return ::testing::internal::AdjustConstness_##constness(this)-> \ - gmock_##Method(::testing::A<GMOCK_ARG_(tn, 1, __VA_ARGS__)>(), \ - ::testing::A<GMOCK_ARG_(tn, 2, __VA_ARGS__)>()); \ - } \ - mutable ::testing::FunctionMocker<__VA_ARGS__> GMOCK_MOCKER_(2, constness, \ - Method) - -// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!! -#define GMOCK_METHOD3_(tn, constness, ct, Method, ...) \ - static_assert(3 == \ - ::testing::internal::Function<__VA_ARGS__>::ArgumentCount, \ - "MOCK_METHOD<N> must match argument count.");\ - GMOCK_RESULT_(tn, __VA_ARGS__) ct Method( \ - GMOCK_ARG_(tn, 1, __VA_ARGS__) gmock_a1, GMOCK_ARG_(tn, 2, \ - __VA_ARGS__) gmock_a2, GMOCK_ARG_(tn, 3, \ - __VA_ARGS__) gmock_a3) constness { \ - GMOCK_MOCKER_(3, constness, Method).SetOwnerAndName(this, #Method); \ - return GMOCK_MOCKER_(3, constness, \ - Method).Invoke(::std::forward<GMOCK_ARG_(tn, 1, \ - __VA_ARGS__)>(gmock_a1), \ - ::std::forward<GMOCK_ARG_(tn, 2, __VA_ARGS__)>(gmock_a2), \ - ::std::forward<GMOCK_ARG_(tn, 3, __VA_ARGS__)>(gmock_a3)); \ - } \ - ::testing::MockSpec<__VA_ARGS__> \ - gmock_##Method(GMOCK_MATCHER_(tn, 1, __VA_ARGS__) gmock_a1, \ - GMOCK_MATCHER_(tn, 2, __VA_ARGS__) gmock_a2, \ - GMOCK_MATCHER_(tn, 3, __VA_ARGS__) gmock_a3) constness { \ - GMOCK_MOCKER_(3, constness, Method).RegisterOwner(this); \ - return GMOCK_MOCKER_(3, constness, Method).With(gmock_a1, gmock_a2, \ - gmock_a3); \ - } \ - ::testing::MockSpec<__VA_ARGS__> gmock_##Method( \ - const ::testing::internal::WithoutMatchers&, \ - constness ::testing::internal::Function<__VA_ARGS__>* ) const { \ - return ::testing::internal::AdjustConstness_##constness(this)-> \ - gmock_##Method(::testing::A<GMOCK_ARG_(tn, 1, __VA_ARGS__)>(), \ - ::testing::A<GMOCK_ARG_(tn, 2, __VA_ARGS__)>(), \ - ::testing::A<GMOCK_ARG_(tn, 3, __VA_ARGS__)>()); \ - } \ - mutable ::testing::FunctionMocker<__VA_ARGS__> GMOCK_MOCKER_(3, constness, \ - Method) - -// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!! -#define GMOCK_METHOD4_(tn, constness, ct, Method, ...) \ - static_assert(4 == \ - ::testing::internal::Function<__VA_ARGS__>::ArgumentCount, \ - "MOCK_METHOD<N> must match argument count.");\ - GMOCK_RESULT_(tn, __VA_ARGS__) ct Method( \ - GMOCK_ARG_(tn, 1, __VA_ARGS__) gmock_a1, GMOCK_ARG_(tn, 2, \ - __VA_ARGS__) gmock_a2, GMOCK_ARG_(tn, 3, __VA_ARGS__) gmock_a3, \ - GMOCK_ARG_(tn, 4, __VA_ARGS__) gmock_a4) constness { \ - GMOCK_MOCKER_(4, constness, Method).SetOwnerAndName(this, #Method); \ - return GMOCK_MOCKER_(4, constness, \ - Method).Invoke(::std::forward<GMOCK_ARG_(tn, 1, \ - __VA_ARGS__)>(gmock_a1), \ - ::std::forward<GMOCK_ARG_(tn, 2, __VA_ARGS__)>(gmock_a2), \ - ::std::forward<GMOCK_ARG_(tn, 3, __VA_ARGS__)>(gmock_a3), \ - ::std::forward<GMOCK_ARG_(tn, 4, __VA_ARGS__)>(gmock_a4)); \ - } \ - ::testing::MockSpec<__VA_ARGS__> \ - gmock_##Method(GMOCK_MATCHER_(tn, 1, __VA_ARGS__) gmock_a1, \ - GMOCK_MATCHER_(tn, 2, __VA_ARGS__) gmock_a2, \ - GMOCK_MATCHER_(tn, 3, __VA_ARGS__) gmock_a3, \ - GMOCK_MATCHER_(tn, 4, __VA_ARGS__) gmock_a4) constness { \ - GMOCK_MOCKER_(4, constness, Method).RegisterOwner(this); \ - return GMOCK_MOCKER_(4, constness, Method).With(gmock_a1, gmock_a2, \ - gmock_a3, gmock_a4); \ - } \ - ::testing::MockSpec<__VA_ARGS__> gmock_##Method( \ - const ::testing::internal::WithoutMatchers&, \ - constness ::testing::internal::Function<__VA_ARGS__>* ) const { \ - return ::testing::internal::AdjustConstness_##constness(this)-> \ - gmock_##Method(::testing::A<GMOCK_ARG_(tn, 1, __VA_ARGS__)>(), \ - ::testing::A<GMOCK_ARG_(tn, 2, __VA_ARGS__)>(), \ - ::testing::A<GMOCK_ARG_(tn, 3, __VA_ARGS__)>(), \ - ::testing::A<GMOCK_ARG_(tn, 4, __VA_ARGS__)>()); \ - } \ - mutable ::testing::FunctionMocker<__VA_ARGS__> GMOCK_MOCKER_(4, constness, \ - Method) - -// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!! -#define GMOCK_METHOD5_(tn, constness, ct, Method, ...) \ - static_assert(5 == \ - ::testing::internal::Function<__VA_ARGS__>::ArgumentCount, \ - "MOCK_METHOD<N> must match argument count.");\ - GMOCK_RESULT_(tn, __VA_ARGS__) ct Method( \ - GMOCK_ARG_(tn, 1, __VA_ARGS__) gmock_a1, GMOCK_ARG_(tn, 2, \ - __VA_ARGS__) gmock_a2, GMOCK_ARG_(tn, 3, __VA_ARGS__) gmock_a3, \ - GMOCK_ARG_(tn, 4, __VA_ARGS__) gmock_a4, GMOCK_ARG_(tn, 5, \ - __VA_ARGS__) gmock_a5) constness { \ - GMOCK_MOCKER_(5, constness, Method).SetOwnerAndName(this, #Method); \ - return GMOCK_MOCKER_(5, constness, \ - Method).Invoke(::std::forward<GMOCK_ARG_(tn, 1, \ - __VA_ARGS__)>(gmock_a1), \ - ::std::forward<GMOCK_ARG_(tn, 2, __VA_ARGS__)>(gmock_a2), \ - ::std::forward<GMOCK_ARG_(tn, 3, __VA_ARGS__)>(gmock_a3), \ - ::std::forward<GMOCK_ARG_(tn, 4, __VA_ARGS__)>(gmock_a4), \ - ::std::forward<GMOCK_ARG_(tn, 5, __VA_ARGS__)>(gmock_a5)); \ - } \ - ::testing::MockSpec<__VA_ARGS__> \ - gmock_##Method(GMOCK_MATCHER_(tn, 1, __VA_ARGS__) gmock_a1, \ - GMOCK_MATCHER_(tn, 2, __VA_ARGS__) gmock_a2, \ - GMOCK_MATCHER_(tn, 3, __VA_ARGS__) gmock_a3, \ - GMOCK_MATCHER_(tn, 4, __VA_ARGS__) gmock_a4, \ - GMOCK_MATCHER_(tn, 5, __VA_ARGS__) gmock_a5) constness { \ - GMOCK_MOCKER_(5, constness, Method).RegisterOwner(this); \ - return GMOCK_MOCKER_(5, constness, Method).With(gmock_a1, gmock_a2, \ - gmock_a3, gmock_a4, gmock_a5); \ - } \ - ::testing::MockSpec<__VA_ARGS__> gmock_##Method( \ - const ::testing::internal::WithoutMatchers&, \ - constness ::testing::internal::Function<__VA_ARGS__>* ) const { \ - return ::testing::internal::AdjustConstness_##constness(this)-> \ - gmock_##Method(::testing::A<GMOCK_ARG_(tn, 1, __VA_ARGS__)>(), \ - ::testing::A<GMOCK_ARG_(tn, 2, __VA_ARGS__)>(), \ - ::testing::A<GMOCK_ARG_(tn, 3, __VA_ARGS__)>(), \ - ::testing::A<GMOCK_ARG_(tn, 4, __VA_ARGS__)>(), \ - ::testing::A<GMOCK_ARG_(tn, 5, __VA_ARGS__)>()); \ - } \ - mutable ::testing::FunctionMocker<__VA_ARGS__> GMOCK_MOCKER_(5, constness, \ - Method) - -// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!! -#define GMOCK_METHOD6_(tn, constness, ct, Method, ...) \ - static_assert(6 == \ - ::testing::internal::Function<__VA_ARGS__>::ArgumentCount, \ - "MOCK_METHOD<N> must match argument count.");\ - GMOCK_RESULT_(tn, __VA_ARGS__) ct Method( \ - GMOCK_ARG_(tn, 1, __VA_ARGS__) gmock_a1, GMOCK_ARG_(tn, 2, \ - __VA_ARGS__) gmock_a2, GMOCK_ARG_(tn, 3, __VA_ARGS__) gmock_a3, \ - GMOCK_ARG_(tn, 4, __VA_ARGS__) gmock_a4, GMOCK_ARG_(tn, 5, \ - __VA_ARGS__) gmock_a5, GMOCK_ARG_(tn, 6, \ - __VA_ARGS__) gmock_a6) constness { \ - GMOCK_MOCKER_(6, constness, Method).SetOwnerAndName(this, #Method); \ - return GMOCK_MOCKER_(6, constness, \ - Method).Invoke(::std::forward<GMOCK_ARG_(tn, 1, \ - __VA_ARGS__)>(gmock_a1), \ - ::std::forward<GMOCK_ARG_(tn, 2, __VA_ARGS__)>(gmock_a2), \ - ::std::forward<GMOCK_ARG_(tn, 3, __VA_ARGS__)>(gmock_a3), \ - ::std::forward<GMOCK_ARG_(tn, 4, __VA_ARGS__)>(gmock_a4), \ - ::std::forward<GMOCK_ARG_(tn, 5, __VA_ARGS__)>(gmock_a5), \ - ::std::forward<GMOCK_ARG_(tn, 6, __VA_ARGS__)>(gmock_a6)); \ - } \ - ::testing::MockSpec<__VA_ARGS__> \ - gmock_##Method(GMOCK_MATCHER_(tn, 1, __VA_ARGS__) gmock_a1, \ - GMOCK_MATCHER_(tn, 2, __VA_ARGS__) gmock_a2, \ - GMOCK_MATCHER_(tn, 3, __VA_ARGS__) gmock_a3, \ - GMOCK_MATCHER_(tn, 4, __VA_ARGS__) gmock_a4, \ - GMOCK_MATCHER_(tn, 5, __VA_ARGS__) gmock_a5, \ - GMOCK_MATCHER_(tn, 6, __VA_ARGS__) gmock_a6) constness { \ - GMOCK_MOCKER_(6, constness, Method).RegisterOwner(this); \ - return GMOCK_MOCKER_(6, constness, Method).With(gmock_a1, gmock_a2, \ - gmock_a3, gmock_a4, gmock_a5, gmock_a6); \ - } \ - ::testing::MockSpec<__VA_ARGS__> gmock_##Method( \ - const ::testing::internal::WithoutMatchers&, \ - constness ::testing::internal::Function<__VA_ARGS__>* ) const { \ - return ::testing::internal::AdjustConstness_##constness(this)-> \ - gmock_##Method(::testing::A<GMOCK_ARG_(tn, 1, __VA_ARGS__)>(), \ - ::testing::A<GMOCK_ARG_(tn, 2, __VA_ARGS__)>(), \ - ::testing::A<GMOCK_ARG_(tn, 3, __VA_ARGS__)>(), \ - ::testing::A<GMOCK_ARG_(tn, 4, __VA_ARGS__)>(), \ - ::testing::A<GMOCK_ARG_(tn, 5, __VA_ARGS__)>(), \ - ::testing::A<GMOCK_ARG_(tn, 6, __VA_ARGS__)>()); \ - } \ - mutable ::testing::FunctionMocker<__VA_ARGS__> GMOCK_MOCKER_(6, constness, \ - Method) - -// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!! -#define GMOCK_METHOD7_(tn, constness, ct, Method, ...) \ - static_assert(7 == \ - ::testing::internal::Function<__VA_ARGS__>::ArgumentCount, \ - "MOCK_METHOD<N> must match argument count.");\ - GMOCK_RESULT_(tn, __VA_ARGS__) ct Method( \ - GMOCK_ARG_(tn, 1, __VA_ARGS__) gmock_a1, GMOCK_ARG_(tn, 2, \ - __VA_ARGS__) gmock_a2, GMOCK_ARG_(tn, 3, __VA_ARGS__) gmock_a3, \ - GMOCK_ARG_(tn, 4, __VA_ARGS__) gmock_a4, GMOCK_ARG_(tn, 5, \ - __VA_ARGS__) gmock_a5, GMOCK_ARG_(tn, 6, __VA_ARGS__) gmock_a6, \ - GMOCK_ARG_(tn, 7, __VA_ARGS__) gmock_a7) constness { \ - GMOCK_MOCKER_(7, constness, Method).SetOwnerAndName(this, #Method); \ - return GMOCK_MOCKER_(7, constness, \ - Method).Invoke(::std::forward<GMOCK_ARG_(tn, 1, \ - __VA_ARGS__)>(gmock_a1), \ - ::std::forward<GMOCK_ARG_(tn, 2, __VA_ARGS__)>(gmock_a2), \ - ::std::forward<GMOCK_ARG_(tn, 3, __VA_ARGS__)>(gmock_a3), \ - ::std::forward<GMOCK_ARG_(tn, 4, __VA_ARGS__)>(gmock_a4), \ - ::std::forward<GMOCK_ARG_(tn, 5, __VA_ARGS__)>(gmock_a5), \ - ::std::forward<GMOCK_ARG_(tn, 6, __VA_ARGS__)>(gmock_a6), \ - ::std::forward<GMOCK_ARG_(tn, 7, __VA_ARGS__)>(gmock_a7)); \ - } \ - ::testing::MockSpec<__VA_ARGS__> \ - gmock_##Method(GMOCK_MATCHER_(tn, 1, __VA_ARGS__) gmock_a1, \ - GMOCK_MATCHER_(tn, 2, __VA_ARGS__) gmock_a2, \ - GMOCK_MATCHER_(tn, 3, __VA_ARGS__) gmock_a3, \ - GMOCK_MATCHER_(tn, 4, __VA_ARGS__) gmock_a4, \ - GMOCK_MATCHER_(tn, 5, __VA_ARGS__) gmock_a5, \ - GMOCK_MATCHER_(tn, 6, __VA_ARGS__) gmock_a6, \ - GMOCK_MATCHER_(tn, 7, __VA_ARGS__) gmock_a7) constness { \ - GMOCK_MOCKER_(7, constness, Method).RegisterOwner(this); \ - return GMOCK_MOCKER_(7, constness, Method).With(gmock_a1, gmock_a2, \ - gmock_a3, gmock_a4, gmock_a5, gmock_a6, gmock_a7); \ - } \ - ::testing::MockSpec<__VA_ARGS__> gmock_##Method( \ - const ::testing::internal::WithoutMatchers&, \ - constness ::testing::internal::Function<__VA_ARGS__>* ) const { \ - return ::testing::internal::AdjustConstness_##constness(this)-> \ - gmock_##Method(::testing::A<GMOCK_ARG_(tn, 1, __VA_ARGS__)>(), \ - ::testing::A<GMOCK_ARG_(tn, 2, __VA_ARGS__)>(), \ - ::testing::A<GMOCK_ARG_(tn, 3, __VA_ARGS__)>(), \ - ::testing::A<GMOCK_ARG_(tn, 4, __VA_ARGS__)>(), \ - ::testing::A<GMOCK_ARG_(tn, 5, __VA_ARGS__)>(), \ - ::testing::A<GMOCK_ARG_(tn, 6, __VA_ARGS__)>(), \ - ::testing::A<GMOCK_ARG_(tn, 7, __VA_ARGS__)>()); \ - } \ - mutable ::testing::FunctionMocker<__VA_ARGS__> GMOCK_MOCKER_(7, constness, \ - Method) - -// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!! -#define GMOCK_METHOD8_(tn, constness, ct, Method, ...) \ - static_assert(8 == \ - ::testing::internal::Function<__VA_ARGS__>::ArgumentCount, \ - "MOCK_METHOD<N> must match argument count.");\ - GMOCK_RESULT_(tn, __VA_ARGS__) ct Method( \ - GMOCK_ARG_(tn, 1, __VA_ARGS__) gmock_a1, GMOCK_ARG_(tn, 2, \ - __VA_ARGS__) gmock_a2, GMOCK_ARG_(tn, 3, __VA_ARGS__) gmock_a3, \ - GMOCK_ARG_(tn, 4, __VA_ARGS__) gmock_a4, GMOCK_ARG_(tn, 5, \ - __VA_ARGS__) gmock_a5, GMOCK_ARG_(tn, 6, __VA_ARGS__) gmock_a6, \ - GMOCK_ARG_(tn, 7, __VA_ARGS__) gmock_a7, GMOCK_ARG_(tn, 8, \ - __VA_ARGS__) gmock_a8) constness { \ - GMOCK_MOCKER_(8, constness, Method).SetOwnerAndName(this, #Method); \ - return GMOCK_MOCKER_(8, constness, \ - Method).Invoke(::std::forward<GMOCK_ARG_(tn, 1, \ - __VA_ARGS__)>(gmock_a1), \ - ::std::forward<GMOCK_ARG_(tn, 2, __VA_ARGS__)>(gmock_a2), \ - ::std::forward<GMOCK_ARG_(tn, 3, __VA_ARGS__)>(gmock_a3), \ - ::std::forward<GMOCK_ARG_(tn, 4, __VA_ARGS__)>(gmock_a4), \ - ::std::forward<GMOCK_ARG_(tn, 5, __VA_ARGS__)>(gmock_a5), \ - ::std::forward<GMOCK_ARG_(tn, 6, __VA_ARGS__)>(gmock_a6), \ - ::std::forward<GMOCK_ARG_(tn, 7, __VA_ARGS__)>(gmock_a7), \ - ::std::forward<GMOCK_ARG_(tn, 8, __VA_ARGS__)>(gmock_a8)); \ - } \ - ::testing::MockSpec<__VA_ARGS__> \ - gmock_##Method(GMOCK_MATCHER_(tn, 1, __VA_ARGS__) gmock_a1, \ - GMOCK_MATCHER_(tn, 2, __VA_ARGS__) gmock_a2, \ - GMOCK_MATCHER_(tn, 3, __VA_ARGS__) gmock_a3, \ - GMOCK_MATCHER_(tn, 4, __VA_ARGS__) gmock_a4, \ - GMOCK_MATCHER_(tn, 5, __VA_ARGS__) gmock_a5, \ - GMOCK_MATCHER_(tn, 6, __VA_ARGS__) gmock_a6, \ - GMOCK_MATCHER_(tn, 7, __VA_ARGS__) gmock_a7, \ - GMOCK_MATCHER_(tn, 8, __VA_ARGS__) gmock_a8) constness { \ - GMOCK_MOCKER_(8, constness, Method).RegisterOwner(this); \ - return GMOCK_MOCKER_(8, constness, Method).With(gmock_a1, gmock_a2, \ - gmock_a3, gmock_a4, gmock_a5, gmock_a6, gmock_a7, gmock_a8); \ - } \ - ::testing::MockSpec<__VA_ARGS__> gmock_##Method( \ - const ::testing::internal::WithoutMatchers&, \ - constness ::testing::internal::Function<__VA_ARGS__>* ) const { \ - return ::testing::internal::AdjustConstness_##constness(this)-> \ - gmock_##Method(::testing::A<GMOCK_ARG_(tn, 1, __VA_ARGS__)>(), \ - ::testing::A<GMOCK_ARG_(tn, 2, __VA_ARGS__)>(), \ - ::testing::A<GMOCK_ARG_(tn, 3, __VA_ARGS__)>(), \ - ::testing::A<GMOCK_ARG_(tn, 4, __VA_ARGS__)>(), \ - ::testing::A<GMOCK_ARG_(tn, 5, __VA_ARGS__)>(), \ - ::testing::A<GMOCK_ARG_(tn, 6, __VA_ARGS__)>(), \ - ::testing::A<GMOCK_ARG_(tn, 7, __VA_ARGS__)>(), \ - ::testing::A<GMOCK_ARG_(tn, 8, __VA_ARGS__)>()); \ - } \ - mutable ::testing::FunctionMocker<__VA_ARGS__> GMOCK_MOCKER_(8, constness, \ - Method) - -// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!! -#define GMOCK_METHOD9_(tn, constness, ct, Method, ...) \ - static_assert(9 == \ - ::testing::internal::Function<__VA_ARGS__>::ArgumentCount, \ - "MOCK_METHOD<N> must match argument count.");\ - GMOCK_RESULT_(tn, __VA_ARGS__) ct Method( \ - GMOCK_ARG_(tn, 1, __VA_ARGS__) gmock_a1, GMOCK_ARG_(tn, 2, \ - __VA_ARGS__) gmock_a2, GMOCK_ARG_(tn, 3, __VA_ARGS__) gmock_a3, \ - GMOCK_ARG_(tn, 4, __VA_ARGS__) gmock_a4, GMOCK_ARG_(tn, 5, \ - __VA_ARGS__) gmock_a5, GMOCK_ARG_(tn, 6, __VA_ARGS__) gmock_a6, \ - GMOCK_ARG_(tn, 7, __VA_ARGS__) gmock_a7, GMOCK_ARG_(tn, 8, \ - __VA_ARGS__) gmock_a8, GMOCK_ARG_(tn, 9, \ - __VA_ARGS__) gmock_a9) constness { \ - GMOCK_MOCKER_(9, constness, Method).SetOwnerAndName(this, #Method); \ - return GMOCK_MOCKER_(9, constness, \ - Method).Invoke(::std::forward<GMOCK_ARG_(tn, 1, \ - __VA_ARGS__)>(gmock_a1), \ - ::std::forward<GMOCK_ARG_(tn, 2, __VA_ARGS__)>(gmock_a2), \ - ::std::forward<GMOCK_ARG_(tn, 3, __VA_ARGS__)>(gmock_a3), \ - ::std::forward<GMOCK_ARG_(tn, 4, __VA_ARGS__)>(gmock_a4), \ - ::std::forward<GMOCK_ARG_(tn, 5, __VA_ARGS__)>(gmock_a5), \ - ::std::forward<GMOCK_ARG_(tn, 6, __VA_ARGS__)>(gmock_a6), \ - ::std::forward<GMOCK_ARG_(tn, 7, __VA_ARGS__)>(gmock_a7), \ - ::std::forward<GMOCK_ARG_(tn, 8, __VA_ARGS__)>(gmock_a8), \ - ::std::forward<GMOCK_ARG_(tn, 9, __VA_ARGS__)>(gmock_a9)); \ - } \ - ::testing::MockSpec<__VA_ARGS__> \ - gmock_##Method(GMOCK_MATCHER_(tn, 1, __VA_ARGS__) gmock_a1, \ - GMOCK_MATCHER_(tn, 2, __VA_ARGS__) gmock_a2, \ - GMOCK_MATCHER_(tn, 3, __VA_ARGS__) gmock_a3, \ - GMOCK_MATCHER_(tn, 4, __VA_ARGS__) gmock_a4, \ - GMOCK_MATCHER_(tn, 5, __VA_ARGS__) gmock_a5, \ - GMOCK_MATCHER_(tn, 6, __VA_ARGS__) gmock_a6, \ - GMOCK_MATCHER_(tn, 7, __VA_ARGS__) gmock_a7, \ - GMOCK_MATCHER_(tn, 8, __VA_ARGS__) gmock_a8, \ - GMOCK_MATCHER_(tn, 9, __VA_ARGS__) gmock_a9) constness { \ - GMOCK_MOCKER_(9, constness, Method).RegisterOwner(this); \ - return GMOCK_MOCKER_(9, constness, Method).With(gmock_a1, gmock_a2, \ - gmock_a3, gmock_a4, gmock_a5, gmock_a6, gmock_a7, gmock_a8, \ - gmock_a9); \ - } \ - ::testing::MockSpec<__VA_ARGS__> gmock_##Method( \ - const ::testing::internal::WithoutMatchers&, \ - constness ::testing::internal::Function<__VA_ARGS__>* ) const { \ - return ::testing::internal::AdjustConstness_##constness(this)-> \ - gmock_##Method(::testing::A<GMOCK_ARG_(tn, 1, __VA_ARGS__)>(), \ - ::testing::A<GMOCK_ARG_(tn, 2, __VA_ARGS__)>(), \ - ::testing::A<GMOCK_ARG_(tn, 3, __VA_ARGS__)>(), \ - ::testing::A<GMOCK_ARG_(tn, 4, __VA_ARGS__)>(), \ - ::testing::A<GMOCK_ARG_(tn, 5, __VA_ARGS__)>(), \ - ::testing::A<GMOCK_ARG_(tn, 6, __VA_ARGS__)>(), \ - ::testing::A<GMOCK_ARG_(tn, 7, __VA_ARGS__)>(), \ - ::testing::A<GMOCK_ARG_(tn, 8, __VA_ARGS__)>(), \ - ::testing::A<GMOCK_ARG_(tn, 9, __VA_ARGS__)>()); \ - } \ - mutable ::testing::FunctionMocker<__VA_ARGS__> GMOCK_MOCKER_(9, constness, \ - Method) - -// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!! -#define GMOCK_METHOD10_(tn, constness, ct, Method, ...) \ - static_assert(10 == \ - ::testing::internal::Function<__VA_ARGS__>::ArgumentCount, \ - "MOCK_METHOD<N> must match argument count.");\ - GMOCK_RESULT_(tn, __VA_ARGS__) ct Method( \ - GMOCK_ARG_(tn, 1, __VA_ARGS__) gmock_a1, GMOCK_ARG_(tn, 2, \ - __VA_ARGS__) gmock_a2, GMOCK_ARG_(tn, 3, __VA_ARGS__) gmock_a3, \ - GMOCK_ARG_(tn, 4, __VA_ARGS__) gmock_a4, GMOCK_ARG_(tn, 5, \ - __VA_ARGS__) gmock_a5, GMOCK_ARG_(tn, 6, __VA_ARGS__) gmock_a6, \ - GMOCK_ARG_(tn, 7, __VA_ARGS__) gmock_a7, GMOCK_ARG_(tn, 8, \ - __VA_ARGS__) gmock_a8, GMOCK_ARG_(tn, 9, __VA_ARGS__) gmock_a9, \ - GMOCK_ARG_(tn, 10, __VA_ARGS__) gmock_a10) constness { \ - GMOCK_MOCKER_(10, constness, Method).SetOwnerAndName(this, #Method); \ - return GMOCK_MOCKER_(10, constness, \ - Method).Invoke(::std::forward<GMOCK_ARG_(tn, 1, \ - __VA_ARGS__)>(gmock_a1), \ - ::std::forward<GMOCK_ARG_(tn, 2, __VA_ARGS__)>(gmock_a2), \ - ::std::forward<GMOCK_ARG_(tn, 3, __VA_ARGS__)>(gmock_a3), \ - ::std::forward<GMOCK_ARG_(tn, 4, __VA_ARGS__)>(gmock_a4), \ - ::std::forward<GMOCK_ARG_(tn, 5, __VA_ARGS__)>(gmock_a5), \ - ::std::forward<GMOCK_ARG_(tn, 6, __VA_ARGS__)>(gmock_a6), \ - ::std::forward<GMOCK_ARG_(tn, 7, __VA_ARGS__)>(gmock_a7), \ - ::std::forward<GMOCK_ARG_(tn, 8, __VA_ARGS__)>(gmock_a8), \ - ::std::forward<GMOCK_ARG_(tn, 9, __VA_ARGS__)>(gmock_a9), \ - ::std::forward<GMOCK_ARG_(tn, 10, __VA_ARGS__)>(gmock_a10)); \ - } \ - ::testing::MockSpec<__VA_ARGS__> \ - gmock_##Method(GMOCK_MATCHER_(tn, 1, __VA_ARGS__) gmock_a1, \ - GMOCK_MATCHER_(tn, 2, __VA_ARGS__) gmock_a2, \ - GMOCK_MATCHER_(tn, 3, __VA_ARGS__) gmock_a3, \ - GMOCK_MATCHER_(tn, 4, __VA_ARGS__) gmock_a4, \ - GMOCK_MATCHER_(tn, 5, __VA_ARGS__) gmock_a5, \ - GMOCK_MATCHER_(tn, 6, __VA_ARGS__) gmock_a6, \ - GMOCK_MATCHER_(tn, 7, __VA_ARGS__) gmock_a7, \ - GMOCK_MATCHER_(tn, 8, __VA_ARGS__) gmock_a8, \ - GMOCK_MATCHER_(tn, 9, __VA_ARGS__) gmock_a9, \ - GMOCK_MATCHER_(tn, 10, \ - __VA_ARGS__) gmock_a10) constness { \ - GMOCK_MOCKER_(10, constness, Method).RegisterOwner(this); \ - return GMOCK_MOCKER_(10, constness, Method).With(gmock_a1, gmock_a2, \ - gmock_a3, gmock_a4, gmock_a5, gmock_a6, gmock_a7, gmock_a8, gmock_a9, \ - gmock_a10); \ - } \ - ::testing::MockSpec<__VA_ARGS__> gmock_##Method( \ - const ::testing::internal::WithoutMatchers&, \ - constness ::testing::internal::Function<__VA_ARGS__>* ) const { \ - return ::testing::internal::AdjustConstness_##constness(this)-> \ - gmock_##Method(::testing::A<GMOCK_ARG_(tn, 1, __VA_ARGS__)>(), \ - ::testing::A<GMOCK_ARG_(tn, 2, __VA_ARGS__)>(), \ - ::testing::A<GMOCK_ARG_(tn, 3, __VA_ARGS__)>(), \ - ::testing::A<GMOCK_ARG_(tn, 4, __VA_ARGS__)>(), \ - ::testing::A<GMOCK_ARG_(tn, 5, __VA_ARGS__)>(), \ - ::testing::A<GMOCK_ARG_(tn, 6, __VA_ARGS__)>(), \ - ::testing::A<GMOCK_ARG_(tn, 7, __VA_ARGS__)>(), \ - ::testing::A<GMOCK_ARG_(tn, 8, __VA_ARGS__)>(), \ - ::testing::A<GMOCK_ARG_(tn, 9, __VA_ARGS__)>(), \ - ::testing::A<GMOCK_ARG_(tn, 10, __VA_ARGS__)>()); \ - } \ - mutable ::testing::FunctionMocker<__VA_ARGS__> GMOCK_MOCKER_(10, constness, \ - Method) - -#define MOCK_METHOD0(m, ...) GMOCK_METHOD0_(, , , m, __VA_ARGS__) -#define MOCK_METHOD1(m, ...) GMOCK_METHOD1_(, , , m, __VA_ARGS__) -#define MOCK_METHOD2(m, ...) GMOCK_METHOD2_(, , , m, __VA_ARGS__) -#define MOCK_METHOD3(m, ...) GMOCK_METHOD3_(, , , m, __VA_ARGS__) -#define MOCK_METHOD4(m, ...) GMOCK_METHOD4_(, , , m, __VA_ARGS__) -#define MOCK_METHOD5(m, ...) GMOCK_METHOD5_(, , , m, __VA_ARGS__) -#define MOCK_METHOD6(m, ...) GMOCK_METHOD6_(, , , m, __VA_ARGS__) -#define MOCK_METHOD7(m, ...) GMOCK_METHOD7_(, , , m, __VA_ARGS__) -#define MOCK_METHOD8(m, ...) GMOCK_METHOD8_(, , , m, __VA_ARGS__) -#define MOCK_METHOD9(m, ...) GMOCK_METHOD9_(, , , m, __VA_ARGS__) -#define MOCK_METHOD10(m, ...) GMOCK_METHOD10_(, , , m, __VA_ARGS__) - -#define MOCK_CONST_METHOD0(m, ...) GMOCK_METHOD0_(, const, , m, __VA_ARGS__) -#define MOCK_CONST_METHOD1(m, ...) GMOCK_METHOD1_(, const, , m, __VA_ARGS__) -#define MOCK_CONST_METHOD2(m, ...) GMOCK_METHOD2_(, const, , m, __VA_ARGS__) -#define MOCK_CONST_METHOD3(m, ...) GMOCK_METHOD3_(, const, , m, __VA_ARGS__) -#define MOCK_CONST_METHOD4(m, ...) GMOCK_METHOD4_(, const, , m, __VA_ARGS__) -#define MOCK_CONST_METHOD5(m, ...) GMOCK_METHOD5_(, const, , m, __VA_ARGS__) -#define MOCK_CONST_METHOD6(m, ...) GMOCK_METHOD6_(, const, , m, __VA_ARGS__) -#define MOCK_CONST_METHOD7(m, ...) GMOCK_METHOD7_(, const, , m, __VA_ARGS__) -#define MOCK_CONST_METHOD8(m, ...) GMOCK_METHOD8_(, const, , m, __VA_ARGS__) -#define MOCK_CONST_METHOD9(m, ...) GMOCK_METHOD9_(, const, , m, __VA_ARGS__) -#define MOCK_CONST_METHOD10(m, ...) GMOCK_METHOD10_(, const, , m, __VA_ARGS__) - -#define MOCK_METHOD0_T(m, ...) GMOCK_METHOD0_(typename, , , m, __VA_ARGS__) -#define MOCK_METHOD1_T(m, ...) GMOCK_METHOD1_(typename, , , m, __VA_ARGS__) -#define MOCK_METHOD2_T(m, ...) GMOCK_METHOD2_(typename, , , m, __VA_ARGS__) -#define MOCK_METHOD3_T(m, ...) GMOCK_METHOD3_(typename, , , m, __VA_ARGS__) -#define MOCK_METHOD4_T(m, ...) GMOCK_METHOD4_(typename, , , m, __VA_ARGS__) -#define MOCK_METHOD5_T(m, ...) GMOCK_METHOD5_(typename, , , m, __VA_ARGS__) -#define MOCK_METHOD6_T(m, ...) GMOCK_METHOD6_(typename, , , m, __VA_ARGS__) -#define MOCK_METHOD7_T(m, ...) GMOCK_METHOD7_(typename, , , m, __VA_ARGS__) -#define MOCK_METHOD8_T(m, ...) GMOCK_METHOD8_(typename, , , m, __VA_ARGS__) -#define MOCK_METHOD9_T(m, ...) GMOCK_METHOD9_(typename, , , m, __VA_ARGS__) -#define MOCK_METHOD10_T(m, ...) GMOCK_METHOD10_(typename, , , m, __VA_ARGS__) - -#define MOCK_CONST_METHOD0_T(m, ...) \ - GMOCK_METHOD0_(typename, const, , m, __VA_ARGS__) -#define MOCK_CONST_METHOD1_T(m, ...) \ - GMOCK_METHOD1_(typename, const, , m, __VA_ARGS__) -#define MOCK_CONST_METHOD2_T(m, ...) \ - GMOCK_METHOD2_(typename, const, , m, __VA_ARGS__) -#define MOCK_CONST_METHOD3_T(m, ...) \ - GMOCK_METHOD3_(typename, const, , m, __VA_ARGS__) -#define MOCK_CONST_METHOD4_T(m, ...) \ - GMOCK_METHOD4_(typename, const, , m, __VA_ARGS__) -#define MOCK_CONST_METHOD5_T(m, ...) \ - GMOCK_METHOD5_(typename, const, , m, __VA_ARGS__) -#define MOCK_CONST_METHOD6_T(m, ...) \ - GMOCK_METHOD6_(typename, const, , m, __VA_ARGS__) -#define MOCK_CONST_METHOD7_T(m, ...) \ - GMOCK_METHOD7_(typename, const, , m, __VA_ARGS__) -#define MOCK_CONST_METHOD8_T(m, ...) \ - GMOCK_METHOD8_(typename, const, , m, __VA_ARGS__) -#define MOCK_CONST_METHOD9_T(m, ...) \ - GMOCK_METHOD9_(typename, const, , m, __VA_ARGS__) -#define MOCK_CONST_METHOD10_T(m, ...) \ - GMOCK_METHOD10_(typename, const, , m, __VA_ARGS__) - -#define MOCK_METHOD0_WITH_CALLTYPE(ct, m, ...) \ - GMOCK_METHOD0_(, , ct, m, __VA_ARGS__) -#define MOCK_METHOD1_WITH_CALLTYPE(ct, m, ...) \ - GMOCK_METHOD1_(, , ct, m, __VA_ARGS__) -#define MOCK_METHOD2_WITH_CALLTYPE(ct, m, ...) \ - GMOCK_METHOD2_(, , ct, m, __VA_ARGS__) -#define MOCK_METHOD3_WITH_CALLTYPE(ct, m, ...) \ - GMOCK_METHOD3_(, , ct, m, __VA_ARGS__) -#define MOCK_METHOD4_WITH_CALLTYPE(ct, m, ...) \ - GMOCK_METHOD4_(, , ct, m, __VA_ARGS__) -#define MOCK_METHOD5_WITH_CALLTYPE(ct, m, ...) \ - GMOCK_METHOD5_(, , ct, m, __VA_ARGS__) -#define MOCK_METHOD6_WITH_CALLTYPE(ct, m, ...) \ - GMOCK_METHOD6_(, , ct, m, __VA_ARGS__) -#define MOCK_METHOD7_WITH_CALLTYPE(ct, m, ...) \ - GMOCK_METHOD7_(, , ct, m, __VA_ARGS__) -#define MOCK_METHOD8_WITH_CALLTYPE(ct, m, ...) \ - GMOCK_METHOD8_(, , ct, m, __VA_ARGS__) -#define MOCK_METHOD9_WITH_CALLTYPE(ct, m, ...) \ - GMOCK_METHOD9_(, , ct, m, __VA_ARGS__) -#define MOCK_METHOD10_WITH_CALLTYPE(ct, m, ...) \ - GMOCK_METHOD10_(, , ct, m, __VA_ARGS__) - -#define MOCK_CONST_METHOD0_WITH_CALLTYPE(ct, m, ...) \ - GMOCK_METHOD0_(, const, ct, m, __VA_ARGS__) -#define MOCK_CONST_METHOD1_WITH_CALLTYPE(ct, m, ...) \ - GMOCK_METHOD1_(, const, ct, m, __VA_ARGS__) -#define MOCK_CONST_METHOD2_WITH_CALLTYPE(ct, m, ...) \ - GMOCK_METHOD2_(, const, ct, m, __VA_ARGS__) -#define MOCK_CONST_METHOD3_WITH_CALLTYPE(ct, m, ...) \ - GMOCK_METHOD3_(, const, ct, m, __VA_ARGS__) -#define MOCK_CONST_METHOD4_WITH_CALLTYPE(ct, m, ...) \ - GMOCK_METHOD4_(, const, ct, m, __VA_ARGS__) -#define MOCK_CONST_METHOD5_WITH_CALLTYPE(ct, m, ...) \ - GMOCK_METHOD5_(, const, ct, m, __VA_ARGS__) -#define MOCK_CONST_METHOD6_WITH_CALLTYPE(ct, m, ...) \ - GMOCK_METHOD6_(, const, ct, m, __VA_ARGS__) -#define MOCK_CONST_METHOD7_WITH_CALLTYPE(ct, m, ...) \ - GMOCK_METHOD7_(, const, ct, m, __VA_ARGS__) -#define MOCK_CONST_METHOD8_WITH_CALLTYPE(ct, m, ...) \ - GMOCK_METHOD8_(, const, ct, m, __VA_ARGS__) -#define MOCK_CONST_METHOD9_WITH_CALLTYPE(ct, m, ...) \ - GMOCK_METHOD9_(, const, ct, m, __VA_ARGS__) -#define MOCK_CONST_METHOD10_WITH_CALLTYPE(ct, m, ...) \ - GMOCK_METHOD10_(, const, ct, m, __VA_ARGS__) - -#define MOCK_METHOD0_T_WITH_CALLTYPE(ct, m, ...) \ - GMOCK_METHOD0_(typename, , ct, m, __VA_ARGS__) -#define MOCK_METHOD1_T_WITH_CALLTYPE(ct, m, ...) \ - GMOCK_METHOD1_(typename, , ct, m, __VA_ARGS__) -#define MOCK_METHOD2_T_WITH_CALLTYPE(ct, m, ...) \ - GMOCK_METHOD2_(typename, , ct, m, __VA_ARGS__) -#define MOCK_METHOD3_T_WITH_CALLTYPE(ct, m, ...) \ - GMOCK_METHOD3_(typename, , ct, m, __VA_ARGS__) -#define MOCK_METHOD4_T_WITH_CALLTYPE(ct, m, ...) \ - GMOCK_METHOD4_(typename, , ct, m, __VA_ARGS__) -#define MOCK_METHOD5_T_WITH_CALLTYPE(ct, m, ...) \ - GMOCK_METHOD5_(typename, , ct, m, __VA_ARGS__) -#define MOCK_METHOD6_T_WITH_CALLTYPE(ct, m, ...) \ - GMOCK_METHOD6_(typename, , ct, m, __VA_ARGS__) -#define MOCK_METHOD7_T_WITH_CALLTYPE(ct, m, ...) \ - GMOCK_METHOD7_(typename, , ct, m, __VA_ARGS__) -#define MOCK_METHOD8_T_WITH_CALLTYPE(ct, m, ...) \ - GMOCK_METHOD8_(typename, , ct, m, __VA_ARGS__) -#define MOCK_METHOD9_T_WITH_CALLTYPE(ct, m, ...) \ - GMOCK_METHOD9_(typename, , ct, m, __VA_ARGS__) -#define MOCK_METHOD10_T_WITH_CALLTYPE(ct, m, ...) \ - GMOCK_METHOD10_(typename, , ct, m, __VA_ARGS__) - -#define MOCK_CONST_METHOD0_T_WITH_CALLTYPE(ct, m, ...) \ - GMOCK_METHOD0_(typename, const, ct, m, __VA_ARGS__) -#define MOCK_CONST_METHOD1_T_WITH_CALLTYPE(ct, m, ...) \ - GMOCK_METHOD1_(typename, const, ct, m, __VA_ARGS__) -#define MOCK_CONST_METHOD2_T_WITH_CALLTYPE(ct, m, ...) \ - GMOCK_METHOD2_(typename, const, ct, m, __VA_ARGS__) -#define MOCK_CONST_METHOD3_T_WITH_CALLTYPE(ct, m, ...) \ - GMOCK_METHOD3_(typename, const, ct, m, __VA_ARGS__) -#define MOCK_CONST_METHOD4_T_WITH_CALLTYPE(ct, m, ...) \ - GMOCK_METHOD4_(typename, const, ct, m, __VA_ARGS__) -#define MOCK_CONST_METHOD5_T_WITH_CALLTYPE(ct, m, ...) \ - GMOCK_METHOD5_(typename, const, ct, m, __VA_ARGS__) -#define MOCK_CONST_METHOD6_T_WITH_CALLTYPE(ct, m, ...) \ - GMOCK_METHOD6_(typename, const, ct, m, __VA_ARGS__) -#define MOCK_CONST_METHOD7_T_WITH_CALLTYPE(ct, m, ...) \ - GMOCK_METHOD7_(typename, const, ct, m, __VA_ARGS__) -#define MOCK_CONST_METHOD8_T_WITH_CALLTYPE(ct, m, ...) \ - GMOCK_METHOD8_(typename, const, ct, m, __VA_ARGS__) -#define MOCK_CONST_METHOD9_T_WITH_CALLTYPE(ct, m, ...) \ - GMOCK_METHOD9_(typename, const, ct, m, __VA_ARGS__) -#define MOCK_CONST_METHOD10_T_WITH_CALLTYPE(ct, m, ...) \ - GMOCK_METHOD10_(typename, const, ct, m, __VA_ARGS__) - -} // namespace testing - -#endif // GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_FUNCTION_MOCKERS_H_ diff --git a/googlemock/include/gmock/gmock-generated-function-mockers.h.pump b/googlemock/include/gmock/gmock-generated-function-mockers.h.pump deleted file mode 100644 index a56e132f..00000000 --- a/googlemock/include/gmock/gmock-generated-function-mockers.h.pump +++ /dev/null @@ -1,227 +0,0 @@ -$$ -*- mode: c++; -*- -$$ This is a Pump source file. Please use Pump to convert -$$ it to gmock-generated-function-mockers.h. -$$ -$var n = 10 $$ The maximum arity we support. -// Copyright 2007, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - -// Google Mock - a framework for writing C++ mock classes. -// -// This file implements function mockers of various arities. - -// GOOGLETEST_CM0002 DO NOT DELETE - -#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_FUNCTION_MOCKERS_H_ -#define GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_FUNCTION_MOCKERS_H_ - -#include <functional> -#include <utility> - -#include "gmock/gmock-spec-builders.h" -#include "gmock/internal/gmock-internal-utils.h" - -namespace testing { -namespace internal { - -$range i 0..n -// Removes the given pointer; this is a helper for the expectation setter method -// for parameterless matchers. -// -// We want to make sure that the user cannot set a parameterless expectation on -// overloaded methods, including methods which are overloaded on const. Example: -// -// class MockClass { -// MOCK_METHOD0(GetName, string&()); -// MOCK_CONST_METHOD0(GetName, const string&()); -// }; -// -// TEST() { -// // This should be an error, as it's not clear which overload is expected. -// EXPECT_CALL(mock, GetName).WillOnce(ReturnRef(value)); -// } -// -// Here are the generated expectation-setter methods: -// -// class MockClass { -// // Overload 1 -// MockSpec<string&()> gmock_GetName() { ... } -// // Overload 2. Declared const so that the compiler will generate an -// // error when trying to resolve between this and overload 4 in -// // 'gmock_GetName(WithoutMatchers(), nullptr)'. -// MockSpec<string&()> gmock_GetName( -// const WithoutMatchers&, const Function<string&()>*) const { -// // Removes const from this, calls overload 1 -// return AdjustConstness_(this)->gmock_GetName(); -// } -// -// // Overload 3 -// const string& gmock_GetName() const { ... } -// // Overload 4 -// MockSpec<const string&()> gmock_GetName( -// const WithoutMatchers&, const Function<const string&()>*) const { -// // Does not remove const, calls overload 3 -// return AdjustConstness_const(this)->gmock_GetName(); -// } -// } -// -template <typename MockType> -const MockType* AdjustConstness_const(const MockType* mock) { - return mock; -} - -// Removes const from and returns the given pointer; this is a helper for the -// expectation setter method for parameterless matchers. -template <typename MockType> -MockType* AdjustConstness_(const MockType* mock) { - return const_cast<MockType*>(mock); -} - -} // namespace internal - -// The style guide prohibits "using" statements in a namespace scope -// inside a header file. However, the FunctionMocker class template -// is meant to be defined in the ::testing namespace. The following -// line is just a trick for working around a bug in MSVC 8.0, which -// cannot handle it if we define FunctionMocker in ::testing. -using internal::FunctionMocker; - -// GMOCK_RESULT_(tn, F) expands to the result type of function type F. -// We define this as a variadic macro in case F contains unprotected -// commas (the same reason that we use variadic macros in other places -// in this file). -// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!! -#define GMOCK_RESULT_(tn, ...) \ - tn ::testing::internal::Function<__VA_ARGS__>::Result - -// The type of argument N of the given function type. -// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!! -#define GMOCK_ARG_(tn, N, ...) \ - tn ::testing::internal::Function<__VA_ARGS__>::template Arg<N-1>::type - -// The matcher type for argument N of the given function type. -// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!! -#define GMOCK_MATCHER_(tn, N, ...) \ - const ::testing::Matcher<GMOCK_ARG_(tn, N, __VA_ARGS__)>& - -// The variable for mocking the given method. -// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!! -#define GMOCK_MOCKER_(arity, constness, Method) \ - GTEST_CONCAT_TOKEN_(gmock##constness##arity##_##Method##_, __LINE__) - - -$for i [[ -$range j 1..i -$var arg_as = [[$for j, [[GMOCK_ARG_(tn, $j, __VA_ARGS__) gmock_a$j]]]] -$var as = [[$for j, \ - [[::std::forward<GMOCK_ARG_(tn, $j, __VA_ARGS__)>(gmock_a$j)]]]] -$var matcher_arg_as = [[$for j, \ - [[GMOCK_MATCHER_(tn, $j, __VA_ARGS__) gmock_a$j]]]] -$var matcher_as = [[$for j, [[gmock_a$j]]]] -$var anything_matchers = [[$for j, \ - [[::testing::A<GMOCK_ARG_(tn, $j, __VA_ARGS__)>()]]]] -// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!! -#define GMOCK_METHOD$i[[]]_(tn, constness, ct, Method, ...) \ - static_assert($i == ::testing::internal::Function<__VA_ARGS__>::ArgumentCount, "MOCK_METHOD<N> must match argument count.");\ - GMOCK_RESULT_(tn, __VA_ARGS__) ct Method( \ - $arg_as) constness { \ - GMOCK_MOCKER_($i, constness, Method).SetOwnerAndName(this, #Method); \ - return GMOCK_MOCKER_($i, constness, Method).Invoke($as); \ - } \ - ::testing::MockSpec<__VA_ARGS__> \ - gmock_##Method($matcher_arg_as) constness { \ - GMOCK_MOCKER_($i, constness, Method).RegisterOwner(this); \ - return GMOCK_MOCKER_($i, constness, Method).With($matcher_as); \ - } \ - ::testing::MockSpec<__VA_ARGS__> gmock_##Method( \ - const ::testing::internal::WithoutMatchers&, \ - constness ::testing::internal::Function<__VA_ARGS__>* ) const { \ - return ::testing::internal::AdjustConstness_##constness(this)-> \ - gmock_##Method($anything_matchers); \ - } \ - mutable ::testing::FunctionMocker<__VA_ARGS__> GMOCK_MOCKER_($i, constness, Method) - - -]] -$for i [[ -#define MOCK_METHOD$i(m, ...) GMOCK_METHOD$i[[]]_(, , , m, __VA_ARGS__) - -]] - - -$for i [[ -#define MOCK_CONST_METHOD$i(m, ...) GMOCK_METHOD$i[[]]_(, const, , m, __VA_ARGS__) - -]] - - -$for i [[ -#define MOCK_METHOD$i[[]]_T(m, ...) GMOCK_METHOD$i[[]]_(typename, , , m, __VA_ARGS__) - -]] - - -$for i [[ -#define MOCK_CONST_METHOD$i[[]]_T(m, ...) \ - GMOCK_METHOD$i[[]]_(typename, const, , m, __VA_ARGS__) - -]] - - -$for i [[ -#define MOCK_METHOD$i[[]]_WITH_CALLTYPE(ct, m, ...) \ - GMOCK_METHOD$i[[]]_(, , ct, m, __VA_ARGS__) - -]] - - -$for i [[ -#define MOCK_CONST_METHOD$i[[]]_WITH_CALLTYPE(ct, m, ...) \ - GMOCK_METHOD$i[[]]_(, const, ct, m, __VA_ARGS__) - -]] - - -$for i [[ -#define MOCK_METHOD$i[[]]_T_WITH_CALLTYPE(ct, m, ...) \ - GMOCK_METHOD$i[[]]_(typename, , ct, m, __VA_ARGS__) - -]] - - -$for i [[ -#define MOCK_CONST_METHOD$i[[]]_T_WITH_CALLTYPE(ct, m, ...) \ - GMOCK_METHOD$i[[]]_(typename, const, ct, m, __VA_ARGS__) - -]] - -} // namespace testing - -#endif // GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_FUNCTION_MOCKERS_H_ diff --git a/googlemock/include/gmock/gmock-generated-matchers.h b/googlemock/include/gmock/gmock-generated-matchers.h deleted file mode 100644 index 690a57f1..00000000 --- a/googlemock/include/gmock/gmock-generated-matchers.h +++ /dev/null @@ -1,1097 +0,0 @@ -// This file was GENERATED by command: -// pump.py gmock-generated-matchers.h.pump -// DO NOT EDIT BY HAND!!! - -// Copyright 2008, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Google Mock - a framework for writing C++ mock classes. -// -// This file implements some commonly used variadic matchers. - -// GOOGLETEST_CM0002 DO NOT DELETE - -#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_MATCHERS_H_ -#define GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_MATCHERS_H_ - -#include <iterator> -#include <sstream> -#include <string> -#include <utility> -#include <vector> -#include "gmock/gmock-matchers.h" - -// The MATCHER* family of macros can be used in a namespace scope to -// define custom matchers easily. -// -// Basic Usage -// =========== -// -// The syntax -// -// MATCHER(name, description_string) { statements; } -// -// defines a matcher with the given name that executes the statements, -// which must return a bool to indicate if the match succeeds. Inside -// the statements, you can refer to the value being matched by 'arg', -// and refer to its type by 'arg_type'. -// -// The description string documents what the matcher does, and is used -// to generate the failure message when the match fails. Since a -// MATCHER() is usually defined in a header file shared by multiple -// C++ source files, we require the description to be a C-string -// literal to avoid possible side effects. It can be empty, in which -// case we'll use the sequence of words in the matcher name as the -// description. -// -// For example: -// -// MATCHER(IsEven, "") { return (arg % 2) == 0; } -// -// allows you to write -// -// // Expects mock_foo.Bar(n) to be called where n is even. -// EXPECT_CALL(mock_foo, Bar(IsEven())); -// -// or, -// -// // Verifies that the value of some_expression is even. -// EXPECT_THAT(some_expression, IsEven()); -// -// If the above assertion fails, it will print something like: -// -// Value of: some_expression -// Expected: is even -// Actual: 7 -// -// where the description "is even" is automatically calculated from the -// matcher name IsEven. -// -// Argument Type -// ============= -// -// Note that the type of the value being matched (arg_type) is -// determined by the context in which you use the matcher and is -// supplied to you by the compiler, so you don't need to worry about -// declaring it (nor can you). This allows the matcher to be -// polymorphic. For example, IsEven() can be used to match any type -// where the value of "(arg % 2) == 0" can be implicitly converted to -// a bool. In the "Bar(IsEven())" example above, if method Bar() -// takes an int, 'arg_type' will be int; if it takes an unsigned long, -// 'arg_type' will be unsigned long; and so on. -// -// Parameterizing Matchers -// ======================= -// -// Sometimes you'll want to parameterize the matcher. For that you -// can use another macro: -// -// MATCHER_P(name, param_name, description_string) { statements; } -// -// For example: -// -// MATCHER_P(HasAbsoluteValue, value, "") { return abs(arg) == value; } -// -// will allow you to write: -// -// EXPECT_THAT(Blah("a"), HasAbsoluteValue(n)); -// -// which may lead to this message (assuming n is 10): -// -// Value of: Blah("a") -// Expected: has absolute value 10 -// Actual: -9 -// -// Note that both the matcher description and its parameter are -// printed, making the message human-friendly. -// -// In the matcher definition body, you can write 'foo_type' to -// reference the type of a parameter named 'foo'. For example, in the -// body of MATCHER_P(HasAbsoluteValue, value) above, you can write -// 'value_type' to refer to the type of 'value'. -// -// We also provide MATCHER_P2, MATCHER_P3, ..., up to MATCHER_P10 to -// support multi-parameter matchers. -// -// Describing Parameterized Matchers -// ================================= -// -// The last argument to MATCHER*() is a string-typed expression. The -// expression can reference all of the matcher's parameters and a -// special bool-typed variable named 'negation'. When 'negation' is -// false, the expression should evaluate to the matcher's description; -// otherwise it should evaluate to the description of the negation of -// the matcher. For example, -// -// using testing::PrintToString; -// -// MATCHER_P2(InClosedRange, low, hi, -// std::string(negation ? "is not" : "is") + " in range [" + -// PrintToString(low) + ", " + PrintToString(hi) + "]") { -// return low <= arg && arg <= hi; -// } -// ... -// EXPECT_THAT(3, InClosedRange(4, 6)); -// EXPECT_THAT(3, Not(InClosedRange(2, 4))); -// -// would generate two failures that contain the text: -// -// Expected: is in range [4, 6] -// ... -// Expected: is not in range [2, 4] -// -// If you specify "" as the description, the failure message will -// contain the sequence of words in the matcher name followed by the -// parameter values printed as a tuple. For example, -// -// MATCHER_P2(InClosedRange, low, hi, "") { ... } -// ... -// EXPECT_THAT(3, InClosedRange(4, 6)); -// EXPECT_THAT(3, Not(InClosedRange(2, 4))); -// -// would generate two failures that contain the text: -// -// Expected: in closed range (4, 6) -// ... -// Expected: not (in closed range (2, 4)) -// -// Types of Matcher Parameters -// =========================== -// -// For the purpose of typing, you can view -// -// MATCHER_Pk(Foo, p1, ..., pk, description_string) { ... } -// -// as shorthand for -// -// template <typename p1_type, ..., typename pk_type> -// FooMatcherPk<p1_type, ..., pk_type> -// Foo(p1_type p1, ..., pk_type pk) { ... } -// -// When you write Foo(v1, ..., vk), the compiler infers the types of -// the parameters v1, ..., and vk for you. If you are not happy with -// the result of the type inference, you can specify the types by -// explicitly instantiating the template, as in Foo<long, bool>(5, -// false). As said earlier, you don't get to (or need to) specify -// 'arg_type' as that's determined by the context in which the matcher -// is used. You can assign the result of expression Foo(p1, ..., pk) -// to a variable of type FooMatcherPk<p1_type, ..., pk_type>. This -// can be useful when composing matchers. -// -// While you can instantiate a matcher template with reference types, -// passing the parameters by pointer usually makes your code more -// readable. If, however, you still want to pass a parameter by -// reference, be aware that in the failure message generated by the -// matcher you will see the value of the referenced object but not its -// address. -// -// Explaining Match Results -// ======================== -// -// Sometimes the matcher description alone isn't enough to explain why -// the match has failed or succeeded. For example, when expecting a -// long string, it can be very helpful to also print the diff between -// the expected string and the actual one. To achieve that, you can -// optionally stream additional information to a special variable -// named result_listener, whose type is a pointer to class -// MatchResultListener: -// -// MATCHER_P(EqualsLongString, str, "") { -// if (arg == str) return true; -// -// *result_listener << "the difference: " -/// << DiffStrings(str, arg); -// return false; -// } -// -// Overloading Matchers -// ==================== -// -// You can overload matchers with different numbers of parameters: -// -// MATCHER_P(Blah, a, description_string1) { ... } -// MATCHER_P2(Blah, a, b, description_string2) { ... } -// -// Caveats -// ======= -// -// When defining a new matcher, you should also consider implementing -// MatcherInterface or using MakePolymorphicMatcher(). These -// approaches require more work than the MATCHER* macros, but also -// give you more control on the types of the value being matched and -// the matcher parameters, which may leads to better compiler error -// messages when the matcher is used wrong. They also allow -// overloading matchers based on parameter types (as opposed to just -// based on the number of parameters). -// -// MATCHER*() can only be used in a namespace scope as templates cannot be -// declared inside of a local class. -// -// More Information -// ================ -// -// To learn more about using these macros, please search for 'MATCHER' -// on -// https://github.com/google/googletest/blob/master/googlemock/docs/cook_book.md - -#define MATCHER(name, description)\ - class name##Matcher {\ - public:\ - template <typename arg_type>\ - class gmock_Impl : public ::testing::MatcherInterface<\ - GTEST_REFERENCE_TO_CONST_(arg_type)> {\ - public:\ - gmock_Impl()\ - {}\ - virtual bool MatchAndExplain(\ - GTEST_REFERENCE_TO_CONST_(arg_type) arg,\ - ::testing::MatchResultListener* result_listener) const;\ - virtual void DescribeTo(::std::ostream* gmock_os) const {\ - *gmock_os << FormatDescription(false);\ - }\ - virtual void DescribeNegationTo(::std::ostream* gmock_os) const {\ - *gmock_os << FormatDescription(true);\ - }\ - private:\ - ::std::string FormatDescription(bool negation) const {\ - ::std::string gmock_description = (description);\ - if (!gmock_description.empty()) {\ - return gmock_description;\ - }\ - return ::testing::internal::FormatMatcherDescription(\ - negation, #name, \ - ::testing::internal::UniversalTersePrintTupleFieldsToStrings(\ - ::std::tuple<>()));\ - }\ - };\ - template <typename arg_type>\ - operator ::testing::Matcher<arg_type>() const {\ - return ::testing::Matcher<arg_type>(\ - new gmock_Impl<arg_type>());\ - }\ - name##Matcher() {\ - }\ - private:\ - };\ - inline name##Matcher name() {\ - return name##Matcher();\ - }\ - template <typename arg_type>\ - bool name##Matcher::gmock_Impl<arg_type>::MatchAndExplain(\ - GTEST_REFERENCE_TO_CONST_(arg_type) arg,\ - ::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\ - const - -#define MATCHER_P(name, p0, description)\ - template <typename p0##_type>\ - class name##MatcherP {\ - public:\ - template <typename arg_type>\ - class gmock_Impl : public ::testing::MatcherInterface<\ - GTEST_REFERENCE_TO_CONST_(arg_type)> {\ - public:\ - explicit gmock_Impl(p0##_type gmock_p0)\ - : p0(::std::move(gmock_p0)) {}\ - virtual bool MatchAndExplain(\ - GTEST_REFERENCE_TO_CONST_(arg_type) arg,\ - ::testing::MatchResultListener* result_listener) const;\ - virtual void DescribeTo(::std::ostream* gmock_os) const {\ - *gmock_os << FormatDescription(false);\ - }\ - virtual void DescribeNegationTo(::std::ostream* gmock_os) const {\ - *gmock_os << FormatDescription(true);\ - }\ - p0##_type const p0;\ - private:\ - ::std::string FormatDescription(bool negation) const {\ - ::std::string gmock_description = (description);\ - if (!gmock_description.empty()) {\ - return gmock_description;\ - }\ - return ::testing::internal::FormatMatcherDescription(\ - negation, #name, \ - ::testing::internal::UniversalTersePrintTupleFieldsToStrings(\ - ::std::tuple<p0##_type>(p0)));\ - }\ - };\ - template <typename arg_type>\ - operator ::testing::Matcher<arg_type>() const {\ - return ::testing::Matcher<arg_type>(\ - new gmock_Impl<arg_type>(p0));\ - }\ - explicit name##MatcherP(p0##_type gmock_p0) : p0(::std::move(gmock_p0)) {\ - }\ - p0##_type const p0;\ - private:\ - };\ - template <typename p0##_type>\ - inline name##MatcherP<p0##_type> name(p0##_type p0) {\ - return name##MatcherP<p0##_type>(p0);\ - }\ - template <typename p0##_type>\ - template <typename arg_type>\ - bool name##MatcherP<p0##_type>::gmock_Impl<arg_type>::MatchAndExplain(\ - GTEST_REFERENCE_TO_CONST_(arg_type) arg,\ - ::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\ - const - -#define MATCHER_P2(name, p0, p1, description)\ - template <typename p0##_type, typename p1##_type>\ - class name##MatcherP2 {\ - public:\ - template <typename arg_type>\ - class gmock_Impl : public ::testing::MatcherInterface<\ - GTEST_REFERENCE_TO_CONST_(arg_type)> {\ - public:\ - gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1)\ - : p0(::std::move(gmock_p0)), p1(::std::move(gmock_p1)) {}\ - virtual bool MatchAndExplain(\ - GTEST_REFERENCE_TO_CONST_(arg_type) arg,\ - ::testing::MatchResultListener* result_listener) const;\ - virtual void DescribeTo(::std::ostream* gmock_os) const {\ - *gmock_os << FormatDescription(false);\ - }\ - virtual void DescribeNegationTo(::std::ostream* gmock_os) const {\ - *gmock_os << FormatDescription(true);\ - }\ - p0##_type const p0;\ - p1##_type const p1;\ - private:\ - ::std::string FormatDescription(bool negation) const {\ - ::std::string gmock_description = (description);\ - if (!gmock_description.empty()) {\ - return gmock_description;\ - }\ - return ::testing::internal::FormatMatcherDescription(\ - negation, #name, \ - ::testing::internal::UniversalTersePrintTupleFieldsToStrings(\ - ::std::tuple<p0##_type, p1##_type>(p0, p1)));\ - }\ - };\ - template <typename arg_type>\ - operator ::testing::Matcher<arg_type>() const {\ - return ::testing::Matcher<arg_type>(\ - new gmock_Impl<arg_type>(p0, p1));\ - }\ - name##MatcherP2(p0##_type gmock_p0, \ - p1##_type gmock_p1) : p0(::std::move(gmock_p0)), \ - p1(::std::move(gmock_p1)) {\ - }\ - p0##_type const p0;\ - p1##_type const p1;\ - private:\ - };\ - template <typename p0##_type, typename p1##_type>\ - inline name##MatcherP2<p0##_type, p1##_type> name(p0##_type p0, \ - p1##_type p1) {\ - return name##MatcherP2<p0##_type, p1##_type>(p0, p1);\ - }\ - template <typename p0##_type, typename p1##_type>\ - template <typename arg_type>\ - bool name##MatcherP2<p0##_type, \ - p1##_type>::gmock_Impl<arg_type>::MatchAndExplain(\ - GTEST_REFERENCE_TO_CONST_(arg_type) arg,\ - ::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\ - const - -#define MATCHER_P3(name, p0, p1, p2, description)\ - template <typename p0##_type, typename p1##_type, typename p2##_type>\ - class name##MatcherP3 {\ - public:\ - template <typename arg_type>\ - class gmock_Impl : public ::testing::MatcherInterface<\ - GTEST_REFERENCE_TO_CONST_(arg_type)> {\ - public:\ - gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2)\ - : p0(::std::move(gmock_p0)), p1(::std::move(gmock_p1)), \ - p2(::std::move(gmock_p2)) {}\ - virtual bool MatchAndExplain(\ - GTEST_REFERENCE_TO_CONST_(arg_type) arg,\ - ::testing::MatchResultListener* result_listener) const;\ - virtual void DescribeTo(::std::ostream* gmock_os) const {\ - *gmock_os << FormatDescription(false);\ - }\ - virtual void DescribeNegationTo(::std::ostream* gmock_os) const {\ - *gmock_os << FormatDescription(true);\ - }\ - p0##_type const p0;\ - p1##_type const p1;\ - p2##_type const p2;\ - private:\ - ::std::string FormatDescription(bool negation) const {\ - ::std::string gmock_description = (description);\ - if (!gmock_description.empty()) {\ - return gmock_description;\ - }\ - return ::testing::internal::FormatMatcherDescription(\ - negation, #name, \ - ::testing::internal::UniversalTersePrintTupleFieldsToStrings(\ - ::std::tuple<p0##_type, p1##_type, p2##_type>(p0, p1, p2)));\ - }\ - };\ - template <typename arg_type>\ - operator ::testing::Matcher<arg_type>() const {\ - return ::testing::Matcher<arg_type>(\ - new gmock_Impl<arg_type>(p0, p1, p2));\ - }\ - name##MatcherP3(p0##_type gmock_p0, p1##_type gmock_p1, \ - p2##_type gmock_p2) : p0(::std::move(gmock_p0)), \ - p1(::std::move(gmock_p1)), p2(::std::move(gmock_p2)) {\ - }\ - p0##_type const p0;\ - p1##_type const p1;\ - p2##_type const p2;\ - private:\ - };\ - template <typename p0##_type, typename p1##_type, typename p2##_type>\ - inline name##MatcherP3<p0##_type, p1##_type, p2##_type> name(p0##_type p0, \ - p1##_type p1, p2##_type p2) {\ - return name##MatcherP3<p0##_type, p1##_type, p2##_type>(p0, p1, p2);\ - }\ - template <typename p0##_type, typename p1##_type, typename p2##_type>\ - template <typename arg_type>\ - bool name##MatcherP3<p0##_type, p1##_type, \ - p2##_type>::gmock_Impl<arg_type>::MatchAndExplain(\ - GTEST_REFERENCE_TO_CONST_(arg_type) arg,\ - ::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\ - const - -#define MATCHER_P4(name, p0, p1, p2, p3, description)\ - template <typename p0##_type, typename p1##_type, typename p2##_type, \ - typename p3##_type>\ - class name##MatcherP4 {\ - public:\ - template <typename arg_type>\ - class gmock_Impl : public ::testing::MatcherInterface<\ - GTEST_REFERENCE_TO_CONST_(arg_type)> {\ - public:\ - gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \ - p3##_type gmock_p3)\ - : p0(::std::move(gmock_p0)), p1(::std::move(gmock_p1)), \ - p2(::std::move(gmock_p2)), p3(::std::move(gmock_p3)) {}\ - virtual bool MatchAndExplain(\ - GTEST_REFERENCE_TO_CONST_(arg_type) arg,\ - ::testing::MatchResultListener* result_listener) const;\ - virtual void DescribeTo(::std::ostream* gmock_os) const {\ - *gmock_os << FormatDescription(false);\ - }\ - virtual void DescribeNegationTo(::std::ostream* gmock_os) const {\ - *gmock_os << FormatDescription(true);\ - }\ - p0##_type const p0;\ - p1##_type const p1;\ - p2##_type const p2;\ - p3##_type const p3;\ - private:\ - ::std::string FormatDescription(bool negation) const {\ - ::std::string gmock_description = (description);\ - if (!gmock_description.empty()) {\ - return gmock_description;\ - }\ - return ::testing::internal::FormatMatcherDescription(\ - negation, #name, \ - ::testing::internal::UniversalTersePrintTupleFieldsToStrings(\ - ::std::tuple<p0##_type, p1##_type, p2##_type, p3##_type>(p0, \ - p1, p2, p3)));\ - }\ - };\ - template <typename arg_type>\ - operator ::testing::Matcher<arg_type>() const {\ - return ::testing::Matcher<arg_type>(\ - new gmock_Impl<arg_type>(p0, p1, p2, p3));\ - }\ - name##MatcherP4(p0##_type gmock_p0, p1##_type gmock_p1, \ - p2##_type gmock_p2, p3##_type gmock_p3) : p0(::std::move(gmock_p0)), \ - p1(::std::move(gmock_p1)), p2(::std::move(gmock_p2)), \ - p3(::std::move(gmock_p3)) {\ - }\ - p0##_type const p0;\ - p1##_type const p1;\ - p2##_type const p2;\ - p3##_type const p3;\ - private:\ - };\ - template <typename p0##_type, typename p1##_type, typename p2##_type, \ - typename p3##_type>\ - inline name##MatcherP4<p0##_type, p1##_type, p2##_type, \ - p3##_type> name(p0##_type p0, p1##_type p1, p2##_type p2, \ - p3##_type p3) {\ - return name##MatcherP4<p0##_type, p1##_type, p2##_type, p3##_type>(p0, \ - p1, p2, p3);\ - }\ - template <typename p0##_type, typename p1##_type, typename p2##_type, \ - typename p3##_type>\ - template <typename arg_type>\ - bool name##MatcherP4<p0##_type, p1##_type, p2##_type, \ - p3##_type>::gmock_Impl<arg_type>::MatchAndExplain(\ - GTEST_REFERENCE_TO_CONST_(arg_type) arg,\ - ::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\ - const - -#define MATCHER_P5(name, p0, p1, p2, p3, p4, description)\ - template <typename p0##_type, typename p1##_type, typename p2##_type, \ - typename p3##_type, typename p4##_type>\ - class name##MatcherP5 {\ - public:\ - template <typename arg_type>\ - class gmock_Impl : public ::testing::MatcherInterface<\ - GTEST_REFERENCE_TO_CONST_(arg_type)> {\ - public:\ - gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \ - p3##_type gmock_p3, p4##_type gmock_p4)\ - : p0(::std::move(gmock_p0)), p1(::std::move(gmock_p1)), \ - p2(::std::move(gmock_p2)), p3(::std::move(gmock_p3)), \ - p4(::std::move(gmock_p4)) {}\ - virtual bool MatchAndExplain(\ - GTEST_REFERENCE_TO_CONST_(arg_type) arg,\ - ::testing::MatchResultListener* result_listener) const;\ - virtual void DescribeTo(::std::ostream* gmock_os) const {\ - *gmock_os << FormatDescription(false);\ - }\ - virtual void DescribeNegationTo(::std::ostream* gmock_os) const {\ - *gmock_os << FormatDescription(true);\ - }\ - p0##_type const p0;\ - p1##_type const p1;\ - p2##_type const p2;\ - p3##_type const p3;\ - p4##_type const p4;\ - private:\ - ::std::string FormatDescription(bool negation) const {\ - ::std::string gmock_description = (description);\ - if (!gmock_description.empty()) {\ - return gmock_description;\ - }\ - return ::testing::internal::FormatMatcherDescription(\ - negation, #name, \ - ::testing::internal::UniversalTersePrintTupleFieldsToStrings(\ - ::std::tuple<p0##_type, p1##_type, p2##_type, p3##_type, \ - p4##_type>(p0, p1, p2, p3, p4)));\ - }\ - };\ - template <typename arg_type>\ - operator ::testing::Matcher<arg_type>() const {\ - return ::testing::Matcher<arg_type>(\ - new gmock_Impl<arg_type>(p0, p1, p2, p3, p4));\ - }\ - name##MatcherP5(p0##_type gmock_p0, p1##_type gmock_p1, \ - p2##_type gmock_p2, p3##_type gmock_p3, \ - p4##_type gmock_p4) : p0(::std::move(gmock_p0)), \ - p1(::std::move(gmock_p1)), p2(::std::move(gmock_p2)), \ - p3(::std::move(gmock_p3)), p4(::std::move(gmock_p4)) {\ - }\ - p0##_type const p0;\ - p1##_type const p1;\ - p2##_type const p2;\ - p3##_type const p3;\ - p4##_type const p4;\ - private:\ - };\ - template <typename p0##_type, typename p1##_type, typename p2##_type, \ - typename p3##_type, typename p4##_type>\ - inline name##MatcherP5<p0##_type, p1##_type, p2##_type, p3##_type, \ - p4##_type> name(p0##_type p0, p1##_type p1, p2##_type p2, p3##_type p3, \ - p4##_type p4) {\ - return name##MatcherP5<p0##_type, p1##_type, p2##_type, p3##_type, \ - p4##_type>(p0, p1, p2, p3, p4);\ - }\ - template <typename p0##_type, typename p1##_type, typename p2##_type, \ - typename p3##_type, typename p4##_type>\ - template <typename arg_type>\ - bool name##MatcherP5<p0##_type, p1##_type, p2##_type, p3##_type, \ - p4##_type>::gmock_Impl<arg_type>::MatchAndExplain(\ - GTEST_REFERENCE_TO_CONST_(arg_type) arg,\ - ::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\ - const - -#define MATCHER_P6(name, p0, p1, p2, p3, p4, p5, description)\ - template <typename p0##_type, typename p1##_type, typename p2##_type, \ - typename p3##_type, typename p4##_type, typename p5##_type>\ - class name##MatcherP6 {\ - public:\ - template <typename arg_type>\ - class gmock_Impl : public ::testing::MatcherInterface<\ - GTEST_REFERENCE_TO_CONST_(arg_type)> {\ - public:\ - gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \ - p3##_type gmock_p3, p4##_type gmock_p4, p5##_type gmock_p5)\ - : p0(::std::move(gmock_p0)), p1(::std::move(gmock_p1)), \ - p2(::std::move(gmock_p2)), p3(::std::move(gmock_p3)), \ - p4(::std::move(gmock_p4)), p5(::std::move(gmock_p5)) {}\ - virtual bool MatchAndExplain(\ - GTEST_REFERENCE_TO_CONST_(arg_type) arg,\ - ::testing::MatchResultListener* result_listener) const;\ - virtual void DescribeTo(::std::ostream* gmock_os) const {\ - *gmock_os << FormatDescription(false);\ - }\ - virtual void DescribeNegationTo(::std::ostream* gmock_os) const {\ - *gmock_os << FormatDescription(true);\ - }\ - p0##_type const p0;\ - p1##_type const p1;\ - p2##_type const p2;\ - p3##_type const p3;\ - p4##_type const p4;\ - p5##_type const p5;\ - private:\ - ::std::string FormatDescription(bool negation) const {\ - ::std::string gmock_description = (description);\ - if (!gmock_description.empty()) {\ - return gmock_description;\ - }\ - return ::testing::internal::FormatMatcherDescription(\ - negation, #name, \ - ::testing::internal::UniversalTersePrintTupleFieldsToStrings(\ - ::std::tuple<p0##_type, p1##_type, p2##_type, p3##_type, \ - p4##_type, p5##_type>(p0, p1, p2, p3, p4, p5)));\ - }\ - };\ - template <typename arg_type>\ - operator ::testing::Matcher<arg_type>() const {\ - return ::testing::Matcher<arg_type>(\ - new gmock_Impl<arg_type>(p0, p1, p2, p3, p4, p5));\ - }\ - name##MatcherP6(p0##_type gmock_p0, p1##_type gmock_p1, \ - p2##_type gmock_p2, p3##_type gmock_p3, p4##_type gmock_p4, \ - p5##_type gmock_p5) : p0(::std::move(gmock_p0)), \ - p1(::std::move(gmock_p1)), p2(::std::move(gmock_p2)), \ - p3(::std::move(gmock_p3)), p4(::std::move(gmock_p4)), \ - p5(::std::move(gmock_p5)) {\ - }\ - p0##_type const p0;\ - p1##_type const p1;\ - p2##_type const p2;\ - p3##_type const p3;\ - p4##_type const p4;\ - p5##_type const p5;\ - private:\ - };\ - template <typename p0##_type, typename p1##_type, typename p2##_type, \ - typename p3##_type, typename p4##_type, typename p5##_type>\ - inline name##MatcherP6<p0##_type, p1##_type, p2##_type, p3##_type, \ - p4##_type, p5##_type> name(p0##_type p0, p1##_type p1, p2##_type p2, \ - p3##_type p3, p4##_type p4, p5##_type p5) {\ - return name##MatcherP6<p0##_type, p1##_type, p2##_type, p3##_type, \ - p4##_type, p5##_type>(p0, p1, p2, p3, p4, p5);\ - }\ - template <typename p0##_type, typename p1##_type, typename p2##_type, \ - typename p3##_type, typename p4##_type, typename p5##_type>\ - template <typename arg_type>\ - bool name##MatcherP6<p0##_type, p1##_type, p2##_type, p3##_type, p4##_type, \ - p5##_type>::gmock_Impl<arg_type>::MatchAndExplain(\ - GTEST_REFERENCE_TO_CONST_(arg_type) arg,\ - ::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\ - const - -#define MATCHER_P7(name, p0, p1, p2, p3, p4, p5, p6, description)\ - template <typename p0##_type, typename p1##_type, typename p2##_type, \ - typename p3##_type, typename p4##_type, typename p5##_type, \ - typename p6##_type>\ - class name##MatcherP7 {\ - public:\ - template <typename arg_type>\ - class gmock_Impl : public ::testing::MatcherInterface<\ - GTEST_REFERENCE_TO_CONST_(arg_type)> {\ - public:\ - gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \ - p3##_type gmock_p3, p4##_type gmock_p4, p5##_type gmock_p5, \ - p6##_type gmock_p6)\ - : p0(::std::move(gmock_p0)), p1(::std::move(gmock_p1)), \ - p2(::std::move(gmock_p2)), p3(::std::move(gmock_p3)), \ - p4(::std::move(gmock_p4)), p5(::std::move(gmock_p5)), \ - p6(::std::move(gmock_p6)) {}\ - virtual bool MatchAndExplain(\ - GTEST_REFERENCE_TO_CONST_(arg_type) arg,\ - ::testing::MatchResultListener* result_listener) const;\ - virtual void DescribeTo(::std::ostream* gmock_os) const {\ - *gmock_os << FormatDescription(false);\ - }\ - virtual void DescribeNegationTo(::std::ostream* gmock_os) const {\ - *gmock_os << FormatDescription(true);\ - }\ - p0##_type const p0;\ - p1##_type const p1;\ - p2##_type const p2;\ - p3##_type const p3;\ - p4##_type const p4;\ - p5##_type const p5;\ - p6##_type const p6;\ - private:\ - ::std::string FormatDescription(bool negation) const {\ - ::std::string gmock_description = (description);\ - if (!gmock_description.empty()) {\ - return gmock_description;\ - }\ - return ::testing::internal::FormatMatcherDescription(\ - negation, #name, \ - ::testing::internal::UniversalTersePrintTupleFieldsToStrings(\ - ::std::tuple<p0##_type, p1##_type, p2##_type, p3##_type, \ - p4##_type, p5##_type, p6##_type>(p0, p1, p2, p3, p4, p5, \ - p6)));\ - }\ - };\ - template <typename arg_type>\ - operator ::testing::Matcher<arg_type>() const {\ - return ::testing::Matcher<arg_type>(\ - new gmock_Impl<arg_type>(p0, p1, p2, p3, p4, p5, p6));\ - }\ - name##MatcherP7(p0##_type gmock_p0, p1##_type gmock_p1, \ - p2##_type gmock_p2, p3##_type gmock_p3, p4##_type gmock_p4, \ - p5##_type gmock_p5, p6##_type gmock_p6) : p0(::std::move(gmock_p0)), \ - p1(::std::move(gmock_p1)), p2(::std::move(gmock_p2)), \ - p3(::std::move(gmock_p3)), p4(::std::move(gmock_p4)), \ - p5(::std::move(gmock_p5)), p6(::std::move(gmock_p6)) {\ - }\ - p0##_type const p0;\ - p1##_type const p1;\ - p2##_type const p2;\ - p3##_type const p3;\ - p4##_type const p4;\ - p5##_type const p5;\ - p6##_type const p6;\ - private:\ - };\ - template <typename p0##_type, typename p1##_type, typename p2##_type, \ - typename p3##_type, typename p4##_type, typename p5##_type, \ - typename p6##_type>\ - inline name##MatcherP7<p0##_type, p1##_type, p2##_type, p3##_type, \ - p4##_type, p5##_type, p6##_type> name(p0##_type p0, p1##_type p1, \ - p2##_type p2, p3##_type p3, p4##_type p4, p5##_type p5, \ - p6##_type p6) {\ - return name##MatcherP7<p0##_type, p1##_type, p2##_type, p3##_type, \ - p4##_type, p5##_type, p6##_type>(p0, p1, p2, p3, p4, p5, p6);\ - }\ - template <typename p0##_type, typename p1##_type, typename p2##_type, \ - typename p3##_type, typename p4##_type, typename p5##_type, \ - typename p6##_type>\ - template <typename arg_type>\ - bool name##MatcherP7<p0##_type, p1##_type, p2##_type, p3##_type, p4##_type, \ - p5##_type, p6##_type>::gmock_Impl<arg_type>::MatchAndExplain(\ - GTEST_REFERENCE_TO_CONST_(arg_type) arg,\ - ::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\ - const - -#define MATCHER_P8(name, p0, p1, p2, p3, p4, p5, p6, p7, description)\ - template <typename p0##_type, typename p1##_type, typename p2##_type, \ - typename p3##_type, typename p4##_type, typename p5##_type, \ - typename p6##_type, typename p7##_type>\ - class name##MatcherP8 {\ - public:\ - template <typename arg_type>\ - class gmock_Impl : public ::testing::MatcherInterface<\ - GTEST_REFERENCE_TO_CONST_(arg_type)> {\ - public:\ - gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \ - p3##_type gmock_p3, p4##_type gmock_p4, p5##_type gmock_p5, \ - p6##_type gmock_p6, p7##_type gmock_p7)\ - : p0(::std::move(gmock_p0)), p1(::std::move(gmock_p1)), \ - p2(::std::move(gmock_p2)), p3(::std::move(gmock_p3)), \ - p4(::std::move(gmock_p4)), p5(::std::move(gmock_p5)), \ - p6(::std::move(gmock_p6)), p7(::std::move(gmock_p7)) {}\ - virtual bool MatchAndExplain(\ - GTEST_REFERENCE_TO_CONST_(arg_type) arg,\ - ::testing::MatchResultListener* result_listener) const;\ - virtual void DescribeTo(::std::ostream* gmock_os) const {\ - *gmock_os << FormatDescription(false);\ - }\ - virtual void DescribeNegationTo(::std::ostream* gmock_os) const {\ - *gmock_os << FormatDescription(true);\ - }\ - p0##_type const p0;\ - p1##_type const p1;\ - p2##_type const p2;\ - p3##_type const p3;\ - p4##_type const p4;\ - p5##_type const p5;\ - p6##_type const p6;\ - p7##_type const p7;\ - private:\ - ::std::string FormatDescription(bool negation) const {\ - ::std::string gmock_description = (description);\ - if (!gmock_description.empty()) {\ - return gmock_description;\ - }\ - return ::testing::internal::FormatMatcherDescription(\ - negation, #name, \ - ::testing::internal::UniversalTersePrintTupleFieldsToStrings(\ - ::std::tuple<p0##_type, p1##_type, p2##_type, p3##_type, \ - p4##_type, p5##_type, p6##_type, p7##_type>(p0, p1, p2, \ - p3, p4, p5, p6, p7)));\ - }\ - };\ - template <typename arg_type>\ - operator ::testing::Matcher<arg_type>() const {\ - return ::testing::Matcher<arg_type>(\ - new gmock_Impl<arg_type>(p0, p1, p2, p3, p4, p5, p6, p7));\ - }\ - name##MatcherP8(p0##_type gmock_p0, p1##_type gmock_p1, \ - p2##_type gmock_p2, p3##_type gmock_p3, p4##_type gmock_p4, \ - p5##_type gmock_p5, p6##_type gmock_p6, \ - p7##_type gmock_p7) : p0(::std::move(gmock_p0)), \ - p1(::std::move(gmock_p1)), p2(::std::move(gmock_p2)), \ - p3(::std::move(gmock_p3)), p4(::std::move(gmock_p4)), \ - p5(::std::move(gmock_p5)), p6(::std::move(gmock_p6)), \ - p7(::std::move(gmock_p7)) {\ - }\ - p0##_type const p0;\ - p1##_type const p1;\ - p2##_type const p2;\ - p3##_type const p3;\ - p4##_type const p4;\ - p5##_type const p5;\ - p6##_type const p6;\ - p7##_type const p7;\ - private:\ - };\ - template <typename p0##_type, typename p1##_type, typename p2##_type, \ - typename p3##_type, typename p4##_type, typename p5##_type, \ - typename p6##_type, typename p7##_type>\ - inline name##MatcherP8<p0##_type, p1##_type, p2##_type, p3##_type, \ - p4##_type, p5##_type, p6##_type, p7##_type> name(p0##_type p0, \ - p1##_type p1, p2##_type p2, p3##_type p3, p4##_type p4, p5##_type p5, \ - p6##_type p6, p7##_type p7) {\ - return name##MatcherP8<p0##_type, p1##_type, p2##_type, p3##_type, \ - p4##_type, p5##_type, p6##_type, p7##_type>(p0, p1, p2, p3, p4, p5, \ - p6, p7);\ - }\ - template <typename p0##_type, typename p1##_type, typename p2##_type, \ - typename p3##_type, typename p4##_type, typename p5##_type, \ - typename p6##_type, typename p7##_type>\ - template <typename arg_type>\ - bool name##MatcherP8<p0##_type, p1##_type, p2##_type, p3##_type, p4##_type, \ - p5##_type, p6##_type, \ - p7##_type>::gmock_Impl<arg_type>::MatchAndExplain(\ - GTEST_REFERENCE_TO_CONST_(arg_type) arg,\ - ::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\ - const - -#define MATCHER_P9(name, p0, p1, p2, p3, p4, p5, p6, p7, p8, description)\ - template <typename p0##_type, typename p1##_type, typename p2##_type, \ - typename p3##_type, typename p4##_type, typename p5##_type, \ - typename p6##_type, typename p7##_type, typename p8##_type>\ - class name##MatcherP9 {\ - public:\ - template <typename arg_type>\ - class gmock_Impl : public ::testing::MatcherInterface<\ - GTEST_REFERENCE_TO_CONST_(arg_type)> {\ - public:\ - gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \ - p3##_type gmock_p3, p4##_type gmock_p4, p5##_type gmock_p5, \ - p6##_type gmock_p6, p7##_type gmock_p7, p8##_type gmock_p8)\ - : p0(::std::move(gmock_p0)), p1(::std::move(gmock_p1)), \ - p2(::std::move(gmock_p2)), p3(::std::move(gmock_p3)), \ - p4(::std::move(gmock_p4)), p5(::std::move(gmock_p5)), \ - p6(::std::move(gmock_p6)), p7(::std::move(gmock_p7)), \ - p8(::std::move(gmock_p8)) {}\ - virtual bool MatchAndExplain(\ - GTEST_REFERENCE_TO_CONST_(arg_type) arg,\ - ::testing::MatchResultListener* result_listener) const;\ - virtual void DescribeTo(::std::ostream* gmock_os) const {\ - *gmock_os << FormatDescription(false);\ - }\ - virtual void DescribeNegationTo(::std::ostream* gmock_os) const {\ - *gmock_os << FormatDescription(true);\ - }\ - p0##_type const p0;\ - p1##_type const p1;\ - p2##_type const p2;\ - p3##_type const p3;\ - p4##_type const p4;\ - p5##_type const p5;\ - p6##_type const p6;\ - p7##_type const p7;\ - p8##_type const p8;\ - private:\ - ::std::string FormatDescription(bool negation) const {\ - ::std::string gmock_description = (description);\ - if (!gmock_description.empty()) {\ - return gmock_description;\ - }\ - return ::testing::internal::FormatMatcherDescription(\ - negation, #name, \ - ::testing::internal::UniversalTersePrintTupleFieldsToStrings(\ - ::std::tuple<p0##_type, p1##_type, p2##_type, p3##_type, \ - p4##_type, p5##_type, p6##_type, p7##_type, \ - p8##_type>(p0, p1, p2, p3, p4, p5, p6, p7, p8)));\ - }\ - };\ - template <typename arg_type>\ - operator ::testing::Matcher<arg_type>() const {\ - return ::testing::Matcher<arg_type>(\ - new gmock_Impl<arg_type>(p0, p1, p2, p3, p4, p5, p6, p7, p8));\ - }\ - name##MatcherP9(p0##_type gmock_p0, p1##_type gmock_p1, \ - p2##_type gmock_p2, p3##_type gmock_p3, p4##_type gmock_p4, \ - p5##_type gmock_p5, p6##_type gmock_p6, p7##_type gmock_p7, \ - p8##_type gmock_p8) : p0(::std::move(gmock_p0)), \ - p1(::std::move(gmock_p1)), p2(::std::move(gmock_p2)), \ - p3(::std::move(gmock_p3)), p4(::std::move(gmock_p4)), \ - p5(::std::move(gmock_p5)), p6(::std::move(gmock_p6)), \ - p7(::std::move(gmock_p7)), p8(::std::move(gmock_p8)) {\ - }\ - p0##_type const p0;\ - p1##_type const p1;\ - p2##_type const p2;\ - p3##_type const p3;\ - p4##_type const p4;\ - p5##_type const p5;\ - p6##_type const p6;\ - p7##_type const p7;\ - p8##_type const p8;\ - private:\ - };\ - template <typename p0##_type, typename p1##_type, typename p2##_type, \ - typename p3##_type, typename p4##_type, typename p5##_type, \ - typename p6##_type, typename p7##_type, typename p8##_type>\ - inline name##MatcherP9<p0##_type, p1##_type, p2##_type, p3##_type, \ - p4##_type, p5##_type, p6##_type, p7##_type, \ - p8##_type> name(p0##_type p0, p1##_type p1, p2##_type p2, p3##_type p3, \ - p4##_type p4, p5##_type p5, p6##_type p6, p7##_type p7, \ - p8##_type p8) {\ - return name##MatcherP9<p0##_type, p1##_type, p2##_type, p3##_type, \ - p4##_type, p5##_type, p6##_type, p7##_type, p8##_type>(p0, p1, p2, \ - p3, p4, p5, p6, p7, p8);\ - }\ - template <typename p0##_type, typename p1##_type, typename p2##_type, \ - typename p3##_type, typename p4##_type, typename p5##_type, \ - typename p6##_type, typename p7##_type, typename p8##_type>\ - template <typename arg_type>\ - bool name##MatcherP9<p0##_type, p1##_type, p2##_type, p3##_type, p4##_type, \ - p5##_type, p6##_type, p7##_type, \ - p8##_type>::gmock_Impl<arg_type>::MatchAndExplain(\ - GTEST_REFERENCE_TO_CONST_(arg_type) arg,\ - ::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\ - const - -#define MATCHER_P10(name, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, description)\ - template <typename p0##_type, typename p1##_type, typename p2##_type, \ - typename p3##_type, typename p4##_type, typename p5##_type, \ - typename p6##_type, typename p7##_type, typename p8##_type, \ - typename p9##_type>\ - class name##MatcherP10 {\ - public:\ - template <typename arg_type>\ - class gmock_Impl : public ::testing::MatcherInterface<\ - GTEST_REFERENCE_TO_CONST_(arg_type)> {\ - public:\ - gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \ - p3##_type gmock_p3, p4##_type gmock_p4, p5##_type gmock_p5, \ - p6##_type gmock_p6, p7##_type gmock_p7, p8##_type gmock_p8, \ - p9##_type gmock_p9)\ - : p0(::std::move(gmock_p0)), p1(::std::move(gmock_p1)), \ - p2(::std::move(gmock_p2)), p3(::std::move(gmock_p3)), \ - p4(::std::move(gmock_p4)), p5(::std::move(gmock_p5)), \ - p6(::std::move(gmock_p6)), p7(::std::move(gmock_p7)), \ - p8(::std::move(gmock_p8)), p9(::std::move(gmock_p9)) {}\ - virtual bool MatchAndExplain(\ - GTEST_REFERENCE_TO_CONST_(arg_type) arg,\ - ::testing::MatchResultListener* result_listener) const;\ - virtual void DescribeTo(::std::ostream* gmock_os) const {\ - *gmock_os << FormatDescription(false);\ - }\ - virtual void DescribeNegationTo(::std::ostream* gmock_os) const {\ - *gmock_os << FormatDescription(true);\ - }\ - p0##_type const p0;\ - p1##_type const p1;\ - p2##_type const p2;\ - p3##_type const p3;\ - p4##_type const p4;\ - p5##_type const p5;\ - p6##_type const p6;\ - p7##_type const p7;\ - p8##_type const p8;\ - p9##_type const p9;\ - private:\ - ::std::string FormatDescription(bool negation) const {\ - ::std::string gmock_description = (description);\ - if (!gmock_description.empty()) {\ - return gmock_description;\ - }\ - return ::testing::internal::FormatMatcherDescription(\ - negation, #name, \ - ::testing::internal::UniversalTersePrintTupleFieldsToStrings(\ - ::std::tuple<p0##_type, p1##_type, p2##_type, p3##_type, \ - p4##_type, p5##_type, p6##_type, p7##_type, p8##_type, \ - p9##_type>(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9)));\ - }\ - };\ - template <typename arg_type>\ - operator ::testing::Matcher<arg_type>() const {\ - return ::testing::Matcher<arg_type>(\ - new gmock_Impl<arg_type>(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9));\ - }\ - name##MatcherP10(p0##_type gmock_p0, p1##_type gmock_p1, \ - p2##_type gmock_p2, p3##_type gmock_p3, p4##_type gmock_p4, \ - p5##_type gmock_p5, p6##_type gmock_p6, p7##_type gmock_p7, \ - p8##_type gmock_p8, p9##_type gmock_p9) : p0(::std::move(gmock_p0)), \ - p1(::std::move(gmock_p1)), p2(::std::move(gmock_p2)), \ - p3(::std::move(gmock_p3)), p4(::std::move(gmock_p4)), \ - p5(::std::move(gmock_p5)), p6(::std::move(gmock_p6)), \ - p7(::std::move(gmock_p7)), p8(::std::move(gmock_p8)), \ - p9(::std::move(gmock_p9)) {\ - }\ - p0##_type const p0;\ - p1##_type const p1;\ - p2##_type const p2;\ - p3##_type const p3;\ - p4##_type const p4;\ - p5##_type const p5;\ - p6##_type const p6;\ - p7##_type const p7;\ - p8##_type const p8;\ - p9##_type const p9;\ - private:\ - };\ - template <typename p0##_type, typename p1##_type, typename p2##_type, \ - typename p3##_type, typename p4##_type, typename p5##_type, \ - typename p6##_type, typename p7##_type, typename p8##_type, \ - typename p9##_type>\ - inline name##MatcherP10<p0##_type, p1##_type, p2##_type, p3##_type, \ - p4##_type, p5##_type, p6##_type, p7##_type, p8##_type, \ - p9##_type> name(p0##_type p0, p1##_type p1, p2##_type p2, p3##_type p3, \ - p4##_type p4, p5##_type p5, p6##_type p6, p7##_type p7, p8##_type p8, \ - p9##_type p9) {\ - return name##MatcherP10<p0##_type, p1##_type, p2##_type, p3##_type, \ - p4##_type, p5##_type, p6##_type, p7##_type, p8##_type, p9##_type>(p0, \ - p1, p2, p3, p4, p5, p6, p7, p8, p9);\ - }\ - template <typename p0##_type, typename p1##_type, typename p2##_type, \ - typename p3##_type, typename p4##_type, typename p5##_type, \ - typename p6##_type, typename p7##_type, typename p8##_type, \ - typename p9##_type>\ - template <typename arg_type>\ - bool name##MatcherP10<p0##_type, p1##_type, p2##_type, p3##_type, \ - p4##_type, p5##_type, p6##_type, p7##_type, p8##_type, \ - p9##_type>::gmock_Impl<arg_type>::MatchAndExplain(\ - GTEST_REFERENCE_TO_CONST_(arg_type) arg,\ - ::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\ - const - -#endif // GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_MATCHERS_H_ diff --git a/googlemock/include/gmock/gmock-generated-matchers.h.pump b/googlemock/include/gmock/gmock-generated-matchers.h.pump deleted file mode 100644 index ae90917c..00000000 --- a/googlemock/include/gmock/gmock-generated-matchers.h.pump +++ /dev/null @@ -1,346 +0,0 @@ -$$ -*- mode: c++; -*- -$$ This is a Pump source file. Please use Pump to convert -$$ it to gmock-generated-matchers.h. -$$ -$var n = 10 $$ The maximum arity we support. -$$ }} This line fixes auto-indentation of the following code in Emacs. -// Copyright 2008, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Google Mock - a framework for writing C++ mock classes. -// -// This file implements some commonly used variadic matchers. - -// GOOGLETEST_CM0002 DO NOT DELETE - -#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_MATCHERS_H_ -#define GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_MATCHERS_H_ - -#include <iterator> -#include <sstream> -#include <string> -#include <utility> -#include <vector> -#include "gmock/gmock-matchers.h" - -// The MATCHER* family of macros can be used in a namespace scope to -// define custom matchers easily. -// -// Basic Usage -// =========== -// -// The syntax -// -// MATCHER(name, description_string) { statements; } -// -// defines a matcher with the given name that executes the statements, -// which must return a bool to indicate if the match succeeds. Inside -// the statements, you can refer to the value being matched by 'arg', -// and refer to its type by 'arg_type'. -// -// The description string documents what the matcher does, and is used -// to generate the failure message when the match fails. Since a -// MATCHER() is usually defined in a header file shared by multiple -// C++ source files, we require the description to be a C-string -// literal to avoid possible side effects. It can be empty, in which -// case we'll use the sequence of words in the matcher name as the -// description. -// -// For example: -// -// MATCHER(IsEven, "") { return (arg % 2) == 0; } -// -// allows you to write -// -// // Expects mock_foo.Bar(n) to be called where n is even. -// EXPECT_CALL(mock_foo, Bar(IsEven())); -// -// or, -// -// // Verifies that the value of some_expression is even. -// EXPECT_THAT(some_expression, IsEven()); -// -// If the above assertion fails, it will print something like: -// -// Value of: some_expression -// Expected: is even -// Actual: 7 -// -// where the description "is even" is automatically calculated from the -// matcher name IsEven. -// -// Argument Type -// ============= -// -// Note that the type of the value being matched (arg_type) is -// determined by the context in which you use the matcher and is -// supplied to you by the compiler, so you don't need to worry about -// declaring it (nor can you). This allows the matcher to be -// polymorphic. For example, IsEven() can be used to match any type -// where the value of "(arg % 2) == 0" can be implicitly converted to -// a bool. In the "Bar(IsEven())" example above, if method Bar() -// takes an int, 'arg_type' will be int; if it takes an unsigned long, -// 'arg_type' will be unsigned long; and so on. -// -// Parameterizing Matchers -// ======================= -// -// Sometimes you'll want to parameterize the matcher. For that you -// can use another macro: -// -// MATCHER_P(name, param_name, description_string) { statements; } -// -// For example: -// -// MATCHER_P(HasAbsoluteValue, value, "") { return abs(arg) == value; } -// -// will allow you to write: -// -// EXPECT_THAT(Blah("a"), HasAbsoluteValue(n)); -// -// which may lead to this message (assuming n is 10): -// -// Value of: Blah("a") -// Expected: has absolute value 10 -// Actual: -9 -// -// Note that both the matcher description and its parameter are -// printed, making the message human-friendly. -// -// In the matcher definition body, you can write 'foo_type' to -// reference the type of a parameter named 'foo'. For example, in the -// body of MATCHER_P(HasAbsoluteValue, value) above, you can write -// 'value_type' to refer to the type of 'value'. -// -// We also provide MATCHER_P2, MATCHER_P3, ..., up to MATCHER_P$n to -// support multi-parameter matchers. -// -// Describing Parameterized Matchers -// ================================= -// -// The last argument to MATCHER*() is a string-typed expression. The -// expression can reference all of the matcher's parameters and a -// special bool-typed variable named 'negation'. When 'negation' is -// false, the expression should evaluate to the matcher's description; -// otherwise it should evaluate to the description of the negation of -// the matcher. For example, -// -// using testing::PrintToString; -// -// MATCHER_P2(InClosedRange, low, hi, -// std::string(negation ? "is not" : "is") + " in range [" + -// PrintToString(low) + ", " + PrintToString(hi) + "]") { -// return low <= arg && arg <= hi; -// } -// ... -// EXPECT_THAT(3, InClosedRange(4, 6)); -// EXPECT_THAT(3, Not(InClosedRange(2, 4))); -// -// would generate two failures that contain the text: -// -// Expected: is in range [4, 6] -// ... -// Expected: is not in range [2, 4] -// -// If you specify "" as the description, the failure message will -// contain the sequence of words in the matcher name followed by the -// parameter values printed as a tuple. For example, -// -// MATCHER_P2(InClosedRange, low, hi, "") { ... } -// ... -// EXPECT_THAT(3, InClosedRange(4, 6)); -// EXPECT_THAT(3, Not(InClosedRange(2, 4))); -// -// would generate two failures that contain the text: -// -// Expected: in closed range (4, 6) -// ... -// Expected: not (in closed range (2, 4)) -// -// Types of Matcher Parameters -// =========================== -// -// For the purpose of typing, you can view -// -// MATCHER_Pk(Foo, p1, ..., pk, description_string) { ... } -// -// as shorthand for -// -// template <typename p1_type, ..., typename pk_type> -// FooMatcherPk<p1_type, ..., pk_type> -// Foo(p1_type p1, ..., pk_type pk) { ... } -// -// When you write Foo(v1, ..., vk), the compiler infers the types of -// the parameters v1, ..., and vk for you. If you are not happy with -// the result of the type inference, you can specify the types by -// explicitly instantiating the template, as in Foo<long, bool>(5, -// false). As said earlier, you don't get to (or need to) specify -// 'arg_type' as that's determined by the context in which the matcher -// is used. You can assign the result of expression Foo(p1, ..., pk) -// to a variable of type FooMatcherPk<p1_type, ..., pk_type>. This -// can be useful when composing matchers. -// -// While you can instantiate a matcher template with reference types, -// passing the parameters by pointer usually makes your code more -// readable. If, however, you still want to pass a parameter by -// reference, be aware that in the failure message generated by the -// matcher you will see the value of the referenced object but not its -// address. -// -// Explaining Match Results -// ======================== -// -// Sometimes the matcher description alone isn't enough to explain why -// the match has failed or succeeded. For example, when expecting a -// long string, it can be very helpful to also print the diff between -// the expected string and the actual one. To achieve that, you can -// optionally stream additional information to a special variable -// named result_listener, whose type is a pointer to class -// MatchResultListener: -// -// MATCHER_P(EqualsLongString, str, "") { -// if (arg == str) return true; -// -// *result_listener << "the difference: " -/// << DiffStrings(str, arg); -// return false; -// } -// -// Overloading Matchers -// ==================== -// -// You can overload matchers with different numbers of parameters: -// -// MATCHER_P(Blah, a, description_string1) { ... } -// MATCHER_P2(Blah, a, b, description_string2) { ... } -// -// Caveats -// ======= -// -// When defining a new matcher, you should also consider implementing -// MatcherInterface or using MakePolymorphicMatcher(). These -// approaches require more work than the MATCHER* macros, but also -// give you more control on the types of the value being matched and -// the matcher parameters, which may leads to better compiler error -// messages when the matcher is used wrong. They also allow -// overloading matchers based on parameter types (as opposed to just -// based on the number of parameters). -// -// MATCHER*() can only be used in a namespace scope as templates cannot be -// declared inside of a local class. -// -// More Information -// ================ -// -// To learn more about using these macros, please search for 'MATCHER' -// on -// https://github.com/google/googletest/blob/master/googlemock/docs/cook_book.md - -$range i 0..n -$for i - -[[ -$var macro_name = [[$if i==0 [[MATCHER]] $elif i==1 [[MATCHER_P]] - $else [[MATCHER_P$i]]]] -$var class_name = [[name##Matcher[[$if i==0 [[]] $elif i==1 [[P]] - $else [[P$i]]]]]] -$range j 0..i-1 -$var template = [[$if i==0 [[]] $else [[ - - template <$for j, [[typename p$j##_type]]>\ -]]]] -$var ctor_param_list = [[$for j, [[p$j##_type gmock_p$j]]]] -$var impl_ctor_param_list = [[$for j, [[p$j##_type gmock_p$j]]]] -$var impl_inits = [[$if i==0 [[]] $else [[ : $for j, [[p$j(::std::move(gmock_p$j))]]]]]] -$var inits = [[$if i==0 [[]] $else [[ : $for j, [[p$j(::std::move(gmock_p$j))]]]]]] -$var params = [[$for j, [[p$j]]]] -$var param_types = [[$if i==0 [[]] $else [[<$for j, [[p$j##_type]]>]]]] -$var param_types_and_names = [[$for j, [[p$j##_type p$j]]]] -$var param_field_decls = [[$for j -[[ - - p$j##_type const p$j;\ -]]]] -$var param_field_decls2 = [[$for j -[[ - - p$j##_type const p$j;\ -]]]] - -#define $macro_name(name$for j [[, p$j]], description)\$template - class $class_name {\ - public:\ - template <typename arg_type>\ - class gmock_Impl : public ::testing::MatcherInterface<\ - GTEST_REFERENCE_TO_CONST_(arg_type)> {\ - public:\ - [[$if i==1 [[explicit ]]]]gmock_Impl($impl_ctor_param_list)\ - $impl_inits {}\ - virtual bool MatchAndExplain(\ - GTEST_REFERENCE_TO_CONST_(arg_type) arg,\ - ::testing::MatchResultListener* result_listener) const;\ - virtual void DescribeTo(::std::ostream* gmock_os) const {\ - *gmock_os << FormatDescription(false);\ - }\ - virtual void DescribeNegationTo(::std::ostream* gmock_os) const {\ - *gmock_os << FormatDescription(true);\ - }\$param_field_decls - private:\ - ::std::string FormatDescription(bool negation) const {\ - ::std::string gmock_description = (description);\ - if (!gmock_description.empty()) {\ - return gmock_description;\ - }\ - return ::testing::internal::FormatMatcherDescription(\ - negation, #name, \ - ::testing::internal::UniversalTersePrintTupleFieldsToStrings(\ - ::std::tuple<$for j, [[p$j##_type]]>($for j, [[p$j]])));\ - }\ - };\ - template <typename arg_type>\ - operator ::testing::Matcher<arg_type>() const {\ - return ::testing::Matcher<arg_type>(\ - new gmock_Impl<arg_type>($params));\ - }\ - [[$if i==1 [[explicit ]]]]$class_name($ctor_param_list)$inits {\ - }\$param_field_decls2 - private:\ - };\$template - inline $class_name$param_types name($param_types_and_names) {\ - return $class_name$param_types($params);\ - }\$template - template <typename arg_type>\ - bool $class_name$param_types::gmock_Impl<arg_type>::MatchAndExplain(\ - GTEST_REFERENCE_TO_CONST_(arg_type) arg,\ - ::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\ - const -]] - - -#endif // GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_MATCHERS_H_ diff --git a/googlemock/include/gmock/gmock-matchers.h b/googlemock/include/gmock/gmock-matchers.h index 28e188bb..fe88a7c7 100644 --- a/googlemock/include/gmock/gmock-matchers.h +++ b/googlemock/include/gmock/gmock-matchers.h @@ -30,7 +30,220 @@ // Google Mock - a framework for writing C++ mock classes. // -// This file implements some commonly used argument matchers. More +// The MATCHER* family of macros can be used in a namespace scope to +// define custom matchers easily. +// +// Basic Usage +// =========== +// +// The syntax +// +// MATCHER(name, description_string) { statements; } +// +// defines a matcher with the given name that executes the statements, +// which must return a bool to indicate if the match succeeds. Inside +// the statements, you can refer to the value being matched by 'arg', +// and refer to its type by 'arg_type'. +// +// The description string documents what the matcher does, and is used +// to generate the failure message when the match fails. Since a +// MATCHER() is usually defined in a header file shared by multiple +// C++ source files, we require the description to be a C-string +// literal to avoid possible side effects. It can be empty, in which +// case we'll use the sequence of words in the matcher name as the +// description. +// +// For example: +// +// MATCHER(IsEven, "") { return (arg % 2) == 0; } +// +// allows you to write +// +// // Expects mock_foo.Bar(n) to be called where n is even. +// EXPECT_CALL(mock_foo, Bar(IsEven())); +// +// or, +// +// // Verifies that the value of some_expression is even. +// EXPECT_THAT(some_expression, IsEven()); +// +// If the above assertion fails, it will print something like: +// +// Value of: some_expression +// Expected: is even +// Actual: 7 +// +// where the description "is even" is automatically calculated from the +// matcher name IsEven. +// +// Argument Type +// ============= +// +// Note that the type of the value being matched (arg_type) is +// determined by the context in which you use the matcher and is +// supplied to you by the compiler, so you don't need to worry about +// declaring it (nor can you). This allows the matcher to be +// polymorphic. For example, IsEven() can be used to match any type +// where the value of "(arg % 2) == 0" can be implicitly converted to +// a bool. In the "Bar(IsEven())" example above, if method Bar() +// takes an int, 'arg_type' will be int; if it takes an unsigned long, +// 'arg_type' will be unsigned long; and so on. +// +// Parameterizing Matchers +// ======================= +// +// Sometimes you'll want to parameterize the matcher. For that you +// can use another macro: +// +// MATCHER_P(name, param_name, description_string) { statements; } +// +// For example: +// +// MATCHER_P(HasAbsoluteValue, value, "") { return abs(arg) == value; } +// +// will allow you to write: +// +// EXPECT_THAT(Blah("a"), HasAbsoluteValue(n)); +// +// which may lead to this message (assuming n is 10): +// +// Value of: Blah("a") +// Expected: has absolute value 10 +// Actual: -9 +// +// Note that both the matcher description and its parameter are +// printed, making the message human-friendly. +// +// In the matcher definition body, you can write 'foo_type' to +// reference the type of a parameter named 'foo'. For example, in the +// body of MATCHER_P(HasAbsoluteValue, value) above, you can write +// 'value_type' to refer to the type of 'value'. +// +// We also provide MATCHER_P2, MATCHER_P3, ..., up to MATCHER_P$n to +// support multi-parameter matchers. +// +// Describing Parameterized Matchers +// ================================= +// +// The last argument to MATCHER*() is a string-typed expression. The +// expression can reference all of the matcher's parameters and a +// special bool-typed variable named 'negation'. When 'negation' is +// false, the expression should evaluate to the matcher's description; +// otherwise it should evaluate to the description of the negation of +// the matcher. For example, +// +// using testing::PrintToString; +// +// MATCHER_P2(InClosedRange, low, hi, +// std::string(negation ? "is not" : "is") + " in range [" + +// PrintToString(low) + ", " + PrintToString(hi) + "]") { +// return low <= arg && arg <= hi; +// } +// ... +// EXPECT_THAT(3, InClosedRange(4, 6)); +// EXPECT_THAT(3, Not(InClosedRange(2, 4))); +// +// would generate two failures that contain the text: +// +// Expected: is in range [4, 6] +// ... +// Expected: is not in range [2, 4] +// +// If you specify "" as the description, the failure message will +// contain the sequence of words in the matcher name followed by the +// parameter values printed as a tuple. For example, +// +// MATCHER_P2(InClosedRange, low, hi, "") { ... } +// ... +// EXPECT_THAT(3, InClosedRange(4, 6)); +// EXPECT_THAT(3, Not(InClosedRange(2, 4))); +// +// would generate two failures that contain the text: +// +// Expected: in closed range (4, 6) +// ... +// Expected: not (in closed range (2, 4)) +// +// Types of Matcher Parameters +// =========================== +// +// For the purpose of typing, you can view +// +// MATCHER_Pk(Foo, p1, ..., pk, description_string) { ... } +// +// as shorthand for +// +// template <typename p1_type, ..., typename pk_type> +// FooMatcherPk<p1_type, ..., pk_type> +// Foo(p1_type p1, ..., pk_type pk) { ... } +// +// When you write Foo(v1, ..., vk), the compiler infers the types of +// the parameters v1, ..., and vk for you. If you are not happy with +// the result of the type inference, you can specify the types by +// explicitly instantiating the template, as in Foo<long, bool>(5, +// false). As said earlier, you don't get to (or need to) specify +// 'arg_type' as that's determined by the context in which the matcher +// is used. You can assign the result of expression Foo(p1, ..., pk) +// to a variable of type FooMatcherPk<p1_type, ..., pk_type>. This +// can be useful when composing matchers. +// +// While you can instantiate a matcher template with reference types, +// passing the parameters by pointer usually makes your code more +// readable. If, however, you still want to pass a parameter by +// reference, be aware that in the failure message generated by the +// matcher you will see the value of the referenced object but not its +// address. +// +// Explaining Match Results +// ======================== +// +// Sometimes the matcher description alone isn't enough to explain why +// the match has failed or succeeded. For example, when expecting a +// long string, it can be very helpful to also print the diff between +// the expected string and the actual one. To achieve that, you can +// optionally stream additional information to a special variable +// named result_listener, whose type is a pointer to class +// MatchResultListener: +// +// MATCHER_P(EqualsLongString, str, "") { +// if (arg == str) return true; +// +// *result_listener << "the difference: " +/// << DiffStrings(str, arg); +// return false; +// } +// +// Overloading Matchers +// ==================== +// +// You can overload matchers with different numbers of parameters: +// +// MATCHER_P(Blah, a, description_string1) { ... } +// MATCHER_P2(Blah, a, b, description_string2) { ... } +// +// Caveats +// ======= +// +// When defining a new matcher, you should also consider implementing +// MatcherInterface or using MakePolymorphicMatcher(). These +// approaches require more work than the MATCHER* macros, but also +// give you more control on the types of the value being matched and +// the matcher parameters, which may leads to better compiler error +// messages when the matcher is used wrong. They also allow +// overloading matchers based on parameter types (as opposed to just +// based on the number of parameters). +// +// MATCHER*() can only be used in a namespace scope as templates cannot be +// declared inside of a local class. +// +// More Information +// ================ +// +// To learn more about using these macros, please search for 'MATCHER' +// on +// https://github.com/google/googletest/blob/master/googlemock/docs/cook_book.md +// +// This file also implements some commonly used argument matchers. More // matchers can be defined by the user implementing the // MatcherInterface<T> interface if necessary. // @@ -42,8 +255,8 @@ #ifndef GMOCK_INCLUDE_GMOCK_GMOCK_MATCHERS_H_ #define GMOCK_INCLUDE_GMOCK_GMOCK_MATCHERS_H_ -#include <math.h> #include <algorithm> +#include <cmath> #include <initializer_list> #include <iterator> #include <limits> @@ -54,8 +267,10 @@ #include <type_traits> #include <utility> #include <vector> + #include "gmock/internal/gmock-internal-utils.h" #include "gmock/internal/gmock-port.h" +#include "gmock/internal/gmock-pp.h" #include "gtest/gtest.h" // MSVC warning C5046 is new as of VS2017 version 15.8. @@ -141,7 +356,7 @@ class MatcherCastImpl { template <bool Ignore> static Matcher<T> CastImpl(const M& polymorphic_matcher_or_value, std::true_type /* convertible_to_matcher */, - bool_constant<Ignore>) { + std::integral_constant<bool, Ignore>) { // M is implicitly convertible to Matcher<T>, which means that either // M is a polymorphic matcher or Matcher<T> has an implicit constructor // from M. In both cases using the implicit conversion will produce a @@ -209,7 +424,14 @@ class MatcherCastImpl<T, Matcher<U> > { !std::is_base_of<FromType, ToType>::value, "Can't implicitly convert from <base> to <derived>"); - return source_matcher_.MatchAndExplain(static_cast<U>(x), listener); + // Do the cast to `U` explicitly if necessary. + // Otherwise, let implicit conversions do the trick. + using CastType = + typename std::conditional<std::is_convertible<T&, const U&>::value, + T&, U>::type; + + return source_matcher_.MatchAndExplain(static_cast<CastType>(x), + listener); } void DescribeTo(::std::ostream* os) const override { @@ -235,6 +457,50 @@ class MatcherCastImpl<T, Matcher<T> > { static Matcher<T> Cast(const Matcher<T>& matcher) { return matcher; } }; +// Template specialization for parameterless Matcher. +template <typename Derived> +class MatcherBaseImpl { + public: + MatcherBaseImpl() = default; + + template <typename T> + operator ::testing::Matcher<T>() const { // NOLINT(runtime/explicit) + return ::testing::Matcher<T>(new + typename Derived::template gmock_Impl<T>()); + } +}; + +// Template specialization for Matcher with parameters. +template <template <typename...> class Derived, typename... Ts> +class MatcherBaseImpl<Derived<Ts...>> { + public: + // Mark the constructor explicit for single argument T to avoid implicit + // conversions. + template <typename E = std::enable_if<sizeof...(Ts) == 1>, + typename E::type* = nullptr> + explicit MatcherBaseImpl(Ts... params) + : params_(std::forward<Ts>(params)...) {} + template <typename E = std::enable_if<sizeof...(Ts) != 1>, + typename = typename E::type> + MatcherBaseImpl(Ts... params) // NOLINT + : params_(std::forward<Ts>(params)...) {} + + template <typename F> + operator ::testing::Matcher<F>() const { // NOLINT(runtime/explicit) + return Apply<F>(MakeIndexSequence<sizeof...(Ts)>{}); + } + + private: + template <typename F, std::size_t... tuple_ids> + ::testing::Matcher<F> Apply(IndexSequence<tuple_ids...>) const { + return ::testing::Matcher<F>( + new typename Derived<Ts...>::template gmock_Impl<F>( + std::get<tuple_ids>(params_)...)); + } + + const std::tuple<Ts...> params_; +}; + } // namespace internal // In order to be safe and clear, casting between different matcher @@ -246,56 +512,43 @@ inline Matcher<T> MatcherCast(const M& matcher) { return internal::MatcherCastImpl<T, M>::Cast(matcher); } -// Implements SafeMatcherCast(). -// -// FIXME: The intermediate SafeMatcherCastImpl class was introduced as a -// workaround for a compiler bug, and can now be removed. -template <typename T> -class SafeMatcherCastImpl { - public: - // This overload handles polymorphic matchers and values only since - // monomorphic matchers are handled by the next one. - template <typename M> - static inline Matcher<T> Cast(const M& polymorphic_matcher_or_value) { - return internal::MatcherCastImpl<T, M>::Cast(polymorphic_matcher_or_value); - } - - // This overload handles monomorphic matchers. - // - // In general, if type T can be implicitly converted to type U, we can - // safely convert a Matcher<U> to a Matcher<T> (i.e. Matcher is - // contravariant): just keep a copy of the original Matcher<U>, convert the - // argument from type T to U, and then pass it to the underlying Matcher<U>. - // The only exception is when U is a reference and T is not, as the - // underlying Matcher<U> may be interested in the argument's address, which - // is not preserved in the conversion from T to U. - template <typename U> - static inline Matcher<T> Cast(const Matcher<U>& matcher) { - // Enforce that T can be implicitly converted to U. - GTEST_COMPILE_ASSERT_((std::is_convertible<T, U>::value), - "T must be implicitly convertible to U"); - // Enforce that we are not converting a non-reference type T to a reference - // type U. - GTEST_COMPILE_ASSERT_( - std::is_reference<T>::value || !std::is_reference<U>::value, - cannot_convert_non_reference_arg_to_reference); - // In case both T and U are arithmetic types, enforce that the - // conversion is not lossy. - typedef GTEST_REMOVE_REFERENCE_AND_CONST_(T) RawT; - typedef GTEST_REMOVE_REFERENCE_AND_CONST_(U) RawU; - const bool kTIsOther = GMOCK_KIND_OF_(RawT) == internal::kOther; - const bool kUIsOther = GMOCK_KIND_OF_(RawU) == internal::kOther; - GTEST_COMPILE_ASSERT_( - kTIsOther || kUIsOther || - (internal::LosslessArithmeticConvertible<RawT, RawU>::value), - conversion_of_arithmetic_types_must_be_lossless); - return MatcherCast<T>(matcher); - } -}; - +// This overload handles polymorphic matchers and values only since +// monomorphic matchers are handled by the next one. template <typename T, typename M> -inline Matcher<T> SafeMatcherCast(const M& polymorphic_matcher) { - return SafeMatcherCastImpl<T>::Cast(polymorphic_matcher); +inline Matcher<T> SafeMatcherCast(const M& polymorphic_matcher_or_value) { + return MatcherCast<T>(polymorphic_matcher_or_value); +} + +// This overload handles monomorphic matchers. +// +// In general, if type T can be implicitly converted to type U, we can +// safely convert a Matcher<U> to a Matcher<T> (i.e. Matcher is +// contravariant): just keep a copy of the original Matcher<U>, convert the +// argument from type T to U, and then pass it to the underlying Matcher<U>. +// The only exception is when U is a reference and T is not, as the +// underlying Matcher<U> may be interested in the argument's address, which +// is not preserved in the conversion from T to U. +template <typename T, typename U> +inline Matcher<T> SafeMatcherCast(const Matcher<U>& matcher) { + // Enforce that T can be implicitly converted to U. + static_assert(std::is_convertible<const T&, const U&>::value, + "T must be implicitly convertible to U"); + // Enforce that we are not converting a non-reference type T to a reference + // type U. + GTEST_COMPILE_ASSERT_( + std::is_reference<T>::value || !std::is_reference<U>::value, + cannot_convert_non_reference_arg_to_reference); + // In case both T and U are arithmetic types, enforce that the + // conversion is not lossy. + typedef GTEST_REMOVE_REFERENCE_AND_CONST_(T) RawT; + typedef GTEST_REMOVE_REFERENCE_AND_CONST_(U) RawU; + constexpr bool kTIsOther = GMOCK_KIND_OF_(RawT) == internal::kOther; + constexpr bool kUIsOther = GMOCK_KIND_OF_(RawU) == internal::kOther; + GTEST_COMPILE_ASSERT_( + kTIsOther || kUIsOther || + (internal::LosslessArithmeticConvertible<RawT, RawU>::value), + conversion_of_arithmetic_types_must_be_lossless); + return MatcherCast<T>(matcher); } // A<T>() returns a matcher that matches any value of type T. @@ -660,15 +913,15 @@ class StrEqualityMatcher { bool case_sensitive) : string_(str), expect_eq_(expect_eq), case_sensitive_(case_sensitive) {} -#if GTEST_HAS_ABSL - bool MatchAndExplain(const absl::string_view& s, +#if GTEST_INTERNAL_HAS_STRING_VIEW + bool MatchAndExplain(const internal::StringView& s, MatchResultListener* listener) const { - // This should fail to compile if absl::string_view is used with wide + // This should fail to compile if StringView is used with wide // strings. const StringType& str = std::string(s); return MatchAndExplain(str, listener); } -#endif // GTEST_HAS_ABSL +#endif // GTEST_INTERNAL_HAS_STRING_VIEW // Accepts pointer types, particularly: // const char* @@ -686,11 +939,11 @@ class StrEqualityMatcher { // Matches anything that can convert to StringType. // // This is a template, not just a plain function with const StringType&, - // because absl::string_view has some interfering non-explicit constructors. + // because StringView has some interfering non-explicit constructors. template <typename MatcheeStringType> bool MatchAndExplain(const MatcheeStringType& s, MatchResultListener* /* listener */) const { - const StringType& s2(s); + const StringType s2(s); const bool eq = case_sensitive_ ? s2 == string_ : CaseInsensitiveStringEquals(s2, string_); return expect_eq_ == eq; @@ -730,15 +983,15 @@ class HasSubstrMatcher { explicit HasSubstrMatcher(const StringType& substring) : substring_(substring) {} -#if GTEST_HAS_ABSL - bool MatchAndExplain(const absl::string_view& s, +#if GTEST_INTERNAL_HAS_STRING_VIEW + bool MatchAndExplain(const internal::StringView& s, MatchResultListener* listener) const { - // This should fail to compile if absl::string_view is used with wide + // This should fail to compile if StringView is used with wide // strings. const StringType& str = std::string(s); return MatchAndExplain(str, listener); } -#endif // GTEST_HAS_ABSL +#endif // GTEST_INTERNAL_HAS_STRING_VIEW // Accepts pointer types, particularly: // const char* @@ -753,12 +1006,11 @@ class HasSubstrMatcher { // Matches anything that can convert to StringType. // // This is a template, not just a plain function with const StringType&, - // because absl::string_view has some interfering non-explicit constructors. + // because StringView has some interfering non-explicit constructors. template <typename MatcheeStringType> bool MatchAndExplain(const MatcheeStringType& s, MatchResultListener* /* listener */) const { - const StringType& s2(s); - return s2.find(substring_) != StringType::npos; + return StringType(s).find(substring_) != StringType::npos; } // Describes what this matcher matches. @@ -787,15 +1039,15 @@ class StartsWithMatcher { explicit StartsWithMatcher(const StringType& prefix) : prefix_(prefix) { } -#if GTEST_HAS_ABSL - bool MatchAndExplain(const absl::string_view& s, +#if GTEST_INTERNAL_HAS_STRING_VIEW + bool MatchAndExplain(const internal::StringView& s, MatchResultListener* listener) const { - // This should fail to compile if absl::string_view is used with wide + // This should fail to compile if StringView is used with wide // strings. const StringType& str = std::string(s); return MatchAndExplain(str, listener); } -#endif // GTEST_HAS_ABSL +#endif // GTEST_INTERNAL_HAS_STRING_VIEW // Accepts pointer types, particularly: // const char* @@ -810,7 +1062,7 @@ class StartsWithMatcher { // Matches anything that can convert to StringType. // // This is a template, not just a plain function with const StringType&, - // because absl::string_view has some interfering non-explicit constructors. + // because StringView has some interfering non-explicit constructors. template <typename MatcheeStringType> bool MatchAndExplain(const MatcheeStringType& s, MatchResultListener* /* listener */) const { @@ -843,15 +1095,15 @@ class EndsWithMatcher { public: explicit EndsWithMatcher(const StringType& suffix) : suffix_(suffix) {} -#if GTEST_HAS_ABSL - bool MatchAndExplain(const absl::string_view& s, +#if GTEST_INTERNAL_HAS_STRING_VIEW + bool MatchAndExplain(const internal::StringView& s, MatchResultListener* listener) const { - // This should fail to compile if absl::string_view is used with wide + // This should fail to compile if StringView is used with wide // strings. const StringType& str = std::string(s); return MatchAndExplain(str, listener); } -#endif // GTEST_HAS_ABSL +#endif // GTEST_INTERNAL_HAS_STRING_VIEW // Accepts pointer types, particularly: // const char* @@ -866,7 +1118,7 @@ class EndsWithMatcher { // Matches anything that can convert to StringType. // // This is a template, not just a plain function with const StringType&, - // because absl::string_view has some interfering non-explicit constructors. + // because StringView has some interfering non-explicit constructors. template <typename MatcheeStringType> bool MatchAndExplain(const MatcheeStringType& s, MatchResultListener* /* listener */) const { @@ -1323,7 +1575,7 @@ class PredicateFormatterFromMatcher { << "Expected: "; matcher.DescribeTo(&ss); - // Rerun the matcher to "PrintAndExain" the failure. + // Rerun the matcher to "PrintAndExplain" the failure. StringMatchResultListener listener; if (MatchPrintAndExplain(x, matcher, &listener)) { ss << "\n The matcher failed on the initial attempt; but passed when " @@ -1349,6 +1601,22 @@ MakePredicateFormatterFromMatcher(M matcher) { return PredicateFormatterFromMatcher<M>(std::move(matcher)); } +// Implements the polymorphic IsNan() matcher, which matches any floating type +// value that is Nan. +class IsNanMatcher { + public: + template <typename FloatType> + bool MatchAndExplain(const FloatType& f, + MatchResultListener* /* listener */) const { + return (::std::isnan)(f); + } + + void DescribeTo(::std::ostream* os) const { *os << "is NaN"; } + void DescribeNegationTo(::std::ostream* os) const { + *os << "isn't NaN"; + } +}; + // Implements the polymorphic floating point equality matcher, which matches // two float values using ULP-based approximation or, optionally, a // user-specified epsilon. The template is meant to be instantiated with @@ -1409,7 +1677,7 @@ class FloatingEqMatcher { } const FloatType diff = value - expected_; - if (fabs(diff) <= max_abs_error_) { + if (::std::fabs(diff) <= max_abs_error_) { return true; } @@ -1607,8 +1875,8 @@ class PointeeMatcher { template <typename Pointer> class Impl : public MatcherInterface<Pointer> { public: - typedef typename PointeeOf<typename std::remove_const< - typename std::remove_reference<Pointer>::type>::type>::type Pointee; + typedef typename PointeeOf<GTEST_REMOVE_REFERENCE_AND_CONST_(Pointer)>::type + Pointee; explicit Impl(const InnerMatcher& matcher) : matcher_(MatcherCast<const Pointee&>(matcher)) {} @@ -3011,12 +3279,14 @@ class UnorderedElementsAreMatcherImpl element_printouts->clear(); ::std::vector<char> did_match; size_t num_elements = 0; + DummyMatchResultListener dummy; for (; elem_first != elem_last; ++num_elements, ++elem_first) { if (listener->IsInterested()) { element_printouts->push_back(PrintToString(*elem_first)); } for (size_t irhs = 0; irhs != matchers_.size(); ++irhs) { - did_match.push_back(Matches(matchers_[irhs])(*elem_first)); + did_match.push_back( + matchers_[irhs].MatchAndExplain(*elem_first, &dummy)); } } @@ -3164,6 +3434,8 @@ class BoundSecondMatcher { BoundSecondMatcher(const Tuple2Matcher& tm, const Second& second) : tuple2_matcher_(tm), second_value_(second) {} + BoundSecondMatcher(const BoundSecondMatcher& other) = default; + template <typename T> operator Matcher<T>() const { return MakeMatcher(new Impl<T>(tuple2_matcher_, second_value_)); @@ -3626,6 +3898,11 @@ inline internal::RefMatcher<T&> Ref(T& x) { // NOLINT return internal::RefMatcher<T&>(x); } +// Creates a polymorphic matcher that matches any NaN floating point. +inline PolymorphicMatcher<internal::IsNanMatcher> IsNan() { + return MakePolymorphicMatcher(internal::IsNanMatcher()); +} + // Creates a matcher that matches any double argument approximately // equal to rhs, where two NANs are considered unequal. inline internal::FloatingEqMatcher<double> DoubleEq(double rhs) { @@ -4034,11 +4311,7 @@ template <typename Container> inline PolymorphicMatcher<internal::ContainerEqMatcher< typename std::remove_const<Container>::type>> ContainerEq(const Container& rhs) { - // This following line is for working around a bug in MSVC 8.0, - // which causes Container to be a const type sometimes. - typedef typename std::remove_const<Container>::type RawContainer; - return MakePolymorphicMatcher( - internal::ContainerEqMatcher<RawContainer>(rhs)); + return MakePolymorphicMatcher(internal::ContainerEqMatcher<Container>(rhs)); } // Returns a matcher that matches a container that, when sorted using @@ -4071,12 +4344,8 @@ template <typename TupleMatcher, typename Container> inline internal::PointwiseMatcher<TupleMatcher, typename std::remove_const<Container>::type> Pointwise(const TupleMatcher& tuple_matcher, const Container& rhs) { - // This following line is for working around a bug in MSVC 8.0, - // which causes Container to be a const type sometimes (e.g. when - // rhs is a const int[]).. - typedef typename std::remove_const<Container>::type RawContainer; - return internal::PointwiseMatcher<TupleMatcher, RawContainer>( - tuple_matcher, rhs); + return internal::PointwiseMatcher<TupleMatcher, Container>(tuple_matcher, + rhs); } @@ -4107,14 +4376,9 @@ inline internal::UnorderedElementsAreArrayMatcher< typename std::remove_const<RhsContainer>::type>::type::value_type>> UnorderedPointwise(const Tuple2Matcher& tuple2_matcher, const RhsContainer& rhs_container) { - // This following line is for working around a bug in MSVC 8.0, - // which causes RhsContainer to be a const type sometimes (e.g. when - // rhs_container is a const int[]). - typedef typename std::remove_const<RhsContainer>::type RawRhsContainer; - // RhsView allows the same code to handle RhsContainer being a // STL-style container and it being a native C-style array. - typedef typename internal::StlContainerView<RawRhsContainer> RhsView; + typedef typename internal::StlContainerView<RhsContainer> RhsView; typedef typename RhsView::type RhsStlContainer; typedef typename RhsStlContainer::value_type Second; const RhsStlContainer& rhs_stl_container = @@ -4556,6 +4820,156 @@ PolymorphicMatcher<internal::variant_matcher::VariantMatcher<T> > VariantWith( #define EXPECT_THAT(value, matcher) EXPECT_PRED_FORMAT1(\ ::testing::internal::MakePredicateFormatterFromMatcher(matcher), value) +// MATCHER* macroses itself are listed below. +#define MATCHER(name, description) \ + class name##Matcher \ + : public ::testing::internal::MatcherBaseImpl<name##Matcher> { \ + public: \ + template <typename arg_type> \ + class gmock_Impl : public ::testing::MatcherInterface<const arg_type&> { \ + public: \ + gmock_Impl() {} \ + bool MatchAndExplain( \ + const arg_type& arg, \ + ::testing::MatchResultListener* result_listener) const override; \ + void DescribeTo(::std::ostream* gmock_os) const override { \ + *gmock_os << FormatDescription(false); \ + } \ + void DescribeNegationTo(::std::ostream* gmock_os) const override { \ + *gmock_os << FormatDescription(true); \ + } \ + \ + private: \ + ::std::string FormatDescription(bool negation) const { \ + ::std::string gmock_description = (description); \ + if (!gmock_description.empty()) { \ + return gmock_description; \ + } \ + return ::testing::internal::FormatMatcherDescription(negation, #name, \ + {}); \ + } \ + }; \ + }; \ + GTEST_ATTRIBUTE_UNUSED_ inline name##Matcher name() { return {}; } \ + template <typename arg_type> \ + bool name##Matcher::gmock_Impl<arg_type>::MatchAndExplain( \ + const arg_type& arg, \ + ::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_) \ + const + +#define MATCHER_P(name, p0, description) \ + GMOCK_INTERNAL_MATCHER(name, name##MatcherP, description, (p0)) +#define MATCHER_P2(name, p0, p1, description) \ + GMOCK_INTERNAL_MATCHER(name, name##MatcherP2, description, (p0, p1)) +#define MATCHER_P3(name, p0, p1, p2, description) \ + GMOCK_INTERNAL_MATCHER(name, name##MatcherP3, description, (p0, p1, p2)) +#define MATCHER_P4(name, p0, p1, p2, p3, description) \ + GMOCK_INTERNAL_MATCHER(name, name##MatcherP4, description, (p0, p1, p2, p3)) +#define MATCHER_P5(name, p0, p1, p2, p3, p4, description) \ + GMOCK_INTERNAL_MATCHER(name, name##MatcherP5, description, \ + (p0, p1, p2, p3, p4)) +#define MATCHER_P6(name, p0, p1, p2, p3, p4, p5, description) \ + GMOCK_INTERNAL_MATCHER(name, name##MatcherP6, description, \ + (p0, p1, p2, p3, p4, p5)) +#define MATCHER_P7(name, p0, p1, p2, p3, p4, p5, p6, description) \ + GMOCK_INTERNAL_MATCHER(name, name##MatcherP7, description, \ + (p0, p1, p2, p3, p4, p5, p6)) +#define MATCHER_P8(name, p0, p1, p2, p3, p4, p5, p6, p7, description) \ + GMOCK_INTERNAL_MATCHER(name, name##MatcherP8, description, \ + (p0, p1, p2, p3, p4, p5, p6, p7)) +#define MATCHER_P9(name, p0, p1, p2, p3, p4, p5, p6, p7, p8, description) \ + GMOCK_INTERNAL_MATCHER(name, name##MatcherP9, description, \ + (p0, p1, p2, p3, p4, p5, p6, p7, p8)) +#define MATCHER_P10(name, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, description) \ + GMOCK_INTERNAL_MATCHER(name, name##MatcherP10, description, \ + (p0, p1, p2, p3, p4, p5, p6, p7, p8, p9)) + +#define GMOCK_INTERNAL_MATCHER(name, full_name, description, args) \ + template <GMOCK_INTERNAL_MATCHER_TEMPLATE_PARAMS(args)> \ + class full_name : public ::testing::internal::MatcherBaseImpl< \ + full_name<GMOCK_INTERNAL_MATCHER_TYPE_PARAMS(args)>> { \ + public: \ + using full_name::MatcherBaseImpl::MatcherBaseImpl; \ + template <typename arg_type> \ + class gmock_Impl : public ::testing::MatcherInterface<const arg_type&> { \ + public: \ + explicit gmock_Impl(GMOCK_INTERNAL_MATCHER_FUNCTION_ARGS(args)) \ + : GMOCK_INTERNAL_MATCHER_FORWARD_ARGS(args) {} \ + bool MatchAndExplain( \ + const arg_type& arg, \ + ::testing::MatchResultListener* result_listener) const override; \ + void DescribeTo(::std::ostream* gmock_os) const override { \ + *gmock_os << FormatDescription(false); \ + } \ + void DescribeNegationTo(::std::ostream* gmock_os) const override { \ + *gmock_os << FormatDescription(true); \ + } \ + GMOCK_INTERNAL_MATCHER_MEMBERS(args) \ + \ + private: \ + ::std::string FormatDescription(bool negation) const { \ + ::std::string gmock_description = (description); \ + if (!gmock_description.empty()) { \ + return gmock_description; \ + } \ + return ::testing::internal::FormatMatcherDescription( \ + negation, #name, \ + ::testing::internal::UniversalTersePrintTupleFieldsToStrings( \ + ::std::tuple<GMOCK_INTERNAL_MATCHER_TYPE_PARAMS(args)>( \ + GMOCK_INTERNAL_MATCHER_MEMBERS_USAGE(args)))); \ + } \ + }; \ + }; \ + template <GMOCK_INTERNAL_MATCHER_TEMPLATE_PARAMS(args)> \ + inline full_name<GMOCK_INTERNAL_MATCHER_TYPE_PARAMS(args)> name( \ + GMOCK_INTERNAL_MATCHER_FUNCTION_ARGS(args)) { \ + return full_name<GMOCK_INTERNAL_MATCHER_TYPE_PARAMS(args)>( \ + GMOCK_INTERNAL_MATCHER_ARGS_USAGE(args)); \ + } \ + template <GMOCK_INTERNAL_MATCHER_TEMPLATE_PARAMS(args)> \ + template <typename arg_type> \ + bool full_name<GMOCK_INTERNAL_MATCHER_TYPE_PARAMS(args)>::gmock_Impl< \ + arg_type>::MatchAndExplain(const arg_type& arg, \ + ::testing::MatchResultListener* \ + result_listener GTEST_ATTRIBUTE_UNUSED_) \ + const + +#define GMOCK_INTERNAL_MATCHER_TEMPLATE_PARAMS(args) \ + GMOCK_PP_TAIL( \ + GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_MATCHER_TEMPLATE_PARAM, , args)) +#define GMOCK_INTERNAL_MATCHER_TEMPLATE_PARAM(i_unused, data_unused, arg) \ + , typename arg##_type + +#define GMOCK_INTERNAL_MATCHER_TYPE_PARAMS(args) \ + GMOCK_PP_TAIL(GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_MATCHER_TYPE_PARAM, , args)) +#define GMOCK_INTERNAL_MATCHER_TYPE_PARAM(i_unused, data_unused, arg) \ + , arg##_type + +#define GMOCK_INTERNAL_MATCHER_FUNCTION_ARGS(args) \ + GMOCK_PP_TAIL(dummy_first GMOCK_PP_FOR_EACH( \ + GMOCK_INTERNAL_MATCHER_FUNCTION_ARG, , args)) +#define GMOCK_INTERNAL_MATCHER_FUNCTION_ARG(i, data_unused, arg) \ + , arg##_type gmock_p##i + +#define GMOCK_INTERNAL_MATCHER_FORWARD_ARGS(args) \ + GMOCK_PP_TAIL(GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_MATCHER_FORWARD_ARG, , args)) +#define GMOCK_INTERNAL_MATCHER_FORWARD_ARG(i, data_unused, arg) \ + , arg(::std::forward<arg##_type>(gmock_p##i)) + +#define GMOCK_INTERNAL_MATCHER_MEMBERS(args) \ + GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_MATCHER_MEMBER, , args) +#define GMOCK_INTERNAL_MATCHER_MEMBER(i_unused, data_unused, arg) \ + const arg##_type arg; + +#define GMOCK_INTERNAL_MATCHER_MEMBERS_USAGE(args) \ + GMOCK_PP_TAIL(GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_MATCHER_MEMBER_USAGE, , args)) +#define GMOCK_INTERNAL_MATCHER_MEMBER_USAGE(i_unused, data_unused, arg) , arg + +#define GMOCK_INTERNAL_MATCHER_ARGS_USAGE(args) \ + GMOCK_PP_TAIL(GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_MATCHER_ARG_USAGE, , args)) +#define GMOCK_INTERNAL_MATCHER_ARG_USAGE(i, data_unused, arg_unused) \ + , gmock_p##i + } // namespace testing GTEST_DISABLE_MSC_WARNINGS_POP_() // 4251 5046 diff --git a/googlemock/include/gmock/gmock-more-matchers.h b/googlemock/include/gmock/gmock-more-matchers.h index 1c9a399a..b306dd60 100644 --- a/googlemock/include/gmock/gmock-more-matchers.h +++ b/googlemock/include/gmock/gmock-more-matchers.h @@ -30,7 +30,7 @@ // Google Mock - a framework for writing C++ mock classes. // -// This file implements some matchers that depend on gmock-generated-matchers.h. +// This file implements some matchers that depend on gmock-matchers.h. // // Note that tests are implemented in gmock-matchers_test.cc rather than // gmock-more-matchers-test.cc. @@ -40,7 +40,7 @@ #ifndef GMOCK_INCLUDE_GMOCK_MORE_MATCHERS_H_ #define GMOCK_INCLUDE_GMOCK_MORE_MATCHERS_H_ -#include "gmock/gmock-generated-matchers.h" +#include "gmock/gmock-matchers.h" namespace testing { diff --git a/googlemock/include/gmock/gmock-spec-builders.h b/googlemock/include/gmock/gmock-spec-builders.h index 80c13b55..718c9484 100644 --- a/googlemock/include/gmock/gmock-spec-builders.h +++ b/googlemock/include/gmock/gmock-spec-builders.h @@ -1350,12 +1350,6 @@ class ReferenceOrValueWrapper<T&> { T* value_ptr_; }; -// MSVC warns about using 'this' in base member initializer list, so -// we need to temporarily disable the warning. We have to do it for -// the entire class to suppress the warning, even though it's about -// the constructor only. -GTEST_DISABLE_MSC_WARNINGS_PUSH_(4355) - // C++ treats the void type specially. For example, you cannot define // a void-typed variable or pass a void value to a function. // ActionResultHolder<T> holds a value of type T, where T must be a @@ -1786,8 +1780,6 @@ class FunctionMocker<R(Args...)> final : public UntypedFunctionMockerBase { } }; // class FunctionMocker -GTEST_DISABLE_MSC_WARNINGS_POP_() // 4355 - // Reports an uninteresting call (whose description is in msg) in the // manner specified by 'reaction'. void ReportUninterestingCall(CallReaction reaction, const std::string& msg); diff --git a/googlemock/include/gmock/gmock.h b/googlemock/include/gmock/gmock.h index 99c3d787..3c317b6d 100644 --- a/googlemock/include/gmock/gmock.h +++ b/googlemock/include/gmock/gmock.h @@ -60,8 +60,6 @@ #include "gmock/gmock-cardinalities.h" #include "gmock/gmock-function-mocker.h" #include "gmock/gmock-generated-actions.h" -#include "gmock/gmock-generated-function-mockers.h" -#include "gmock/gmock-generated-matchers.h" #include "gmock/gmock-matchers.h" #include "gmock/gmock-more-actions.h" #include "gmock/gmock-more-matchers.h" diff --git a/googlemock/include/gmock/internal/gmock-internal-utils.h b/googlemock/include/gmock/internal/gmock-internal-utils.h index fdc049c5..66cf857b 100644 --- a/googlemock/include/gmock/internal/gmock-internal-utils.h +++ b/googlemock/include/gmock/internal/gmock-internal-utils.h @@ -136,15 +136,13 @@ GMOCK_DECLARE_KIND_(int, kInteger); GMOCK_DECLARE_KIND_(unsigned int, kInteger); GMOCK_DECLARE_KIND_(long, kInteger); // NOLINT GMOCK_DECLARE_KIND_(unsigned long, kInteger); // NOLINT +GMOCK_DECLARE_KIND_(long long, kInteger); // NOLINT +GMOCK_DECLARE_KIND_(unsigned long long, kInteger); // NOLINT #if GMOCK_WCHAR_T_IS_NATIVE_ GMOCK_DECLARE_KIND_(wchar_t, kInteger); #endif -// Non-standard integer types. -GMOCK_DECLARE_KIND_(Int64, kInteger); -GMOCK_DECLARE_KIND_(UInt64, kInteger); - // All standard floating-point types. GMOCK_DECLARE_KIND_(float, kFloatingPoint); GMOCK_DECLARE_KIND_(double, kFloatingPoint); @@ -157,9 +155,6 @@ GMOCK_DECLARE_KIND_(long double, kFloatingPoint); static_cast< ::testing::internal::TypeKind>( \ ::testing::internal::KindOf<type>::value) -// Evaluates to true if and only if integer type T is signed. -#define GMOCK_IS_SIGNED_(T) (static_cast<T>(-1) < 0) - // LosslessArithmeticConvertibleImpl<kFromKind, From, kToKind, To>::value // is true if and only if arithmetic type From can be losslessly converted to // arithmetic type To. @@ -170,65 +165,30 @@ GMOCK_DECLARE_KIND_(long double, kFloatingPoint); // From, and kToKind is the kind of To; the value is // implementation-defined when the above pre-condition is violated. template <TypeKind kFromKind, typename From, TypeKind kToKind, typename To> -struct LosslessArithmeticConvertibleImpl : public std::false_type {}; - -// Converting bool to bool is lossless. -template <> -struct LosslessArithmeticConvertibleImpl<kBool, bool, kBool, bool> - : public std::true_type {}; - -// Converting bool to any integer type is lossless. -template <typename To> -struct LosslessArithmeticConvertibleImpl<kBool, bool, kInteger, To> - : public std::true_type {}; - -// Converting bool to any floating-point type is lossless. -template <typename To> -struct LosslessArithmeticConvertibleImpl<kBool, bool, kFloatingPoint, To> - : public std::true_type {}; - -// Converting an integer to bool is lossy. -template <typename From> -struct LosslessArithmeticConvertibleImpl<kInteger, From, kBool, bool> - : public std::false_type {}; - -// Converting an integer to another non-bool integer is lossless -// if and only if the target type's range encloses the source type's range. -template <typename From, typename To> -struct LosslessArithmeticConvertibleImpl<kInteger, From, kInteger, To> - : public bool_constant< - // When converting from a smaller size to a larger size, we are - // fine as long as we are not converting from signed to unsigned. - ((sizeof(From) < sizeof(To)) && - (!GMOCK_IS_SIGNED_(From) || GMOCK_IS_SIGNED_(To))) || - // When converting between the same size, the signedness must match. - ((sizeof(From) == sizeof(To)) && - (GMOCK_IS_SIGNED_(From) == GMOCK_IS_SIGNED_(To)))> {}; // NOLINT - -#undef GMOCK_IS_SIGNED_ - -// Converting an integer to a floating-point type may be lossy, since -// the format of a floating-point number is implementation-defined. -template <typename From, typename To> -struct LosslessArithmeticConvertibleImpl<kInteger, From, kFloatingPoint, To> - : public std::false_type {}; - -// Converting a floating-point to bool is lossy. -template <typename From> -struct LosslessArithmeticConvertibleImpl<kFloatingPoint, From, kBool, bool> - : public std::false_type {}; - -// Converting a floating-point to an integer is lossy. -template <typename From, typename To> -struct LosslessArithmeticConvertibleImpl<kFloatingPoint, From, kInteger, To> - : public std::false_type {}; - -// Converting a floating-point to another floating-point is lossless -// if and only if the target type is at least as big as the source type. -template <typename From, typename To> -struct LosslessArithmeticConvertibleImpl< - kFloatingPoint, From, kFloatingPoint, To> - : public bool_constant<sizeof(From) <= sizeof(To)> {}; // NOLINT +using LosslessArithmeticConvertibleImpl = std::integral_constant< + bool, + // clang-format off + // Converting from bool is always lossless + (kFromKind == kBool) ? true + // Converting between any other type kinds will be lossy if the type + // kinds are not the same. + : (kFromKind != kToKind) ? false + : (kFromKind == kInteger && + // Converting between integers of different widths is allowed so long + // as the conversion does not go from signed to unsigned. + (((sizeof(From) < sizeof(To)) && + !(std::is_signed<From>::value && !std::is_signed<To>::value)) || + // Converting between integers of the same width only requires the + // two types to have the same signedness. + ((sizeof(From) == sizeof(To)) && + (std::is_signed<From>::value == std::is_signed<To>::value))) + ) ? true + // Floating point conversions are lossless if and only if `To` is at least + // as wide as `From`. + : (kFromKind == kFloatingPoint && (sizeof(From) <= sizeof(To))) ? true + : false + // clang-format on + >; // LosslessArithmeticConvertible<From, To>::value is true if and only if // arithmetic type From can be losslessly converted to arithmetic type To. @@ -238,9 +198,9 @@ struct LosslessArithmeticConvertibleImpl< // reference) built-in arithmetic types; the value is // implementation-defined when the above pre-condition is violated. template <typename From, typename To> -struct LosslessArithmeticConvertible - : public LosslessArithmeticConvertibleImpl< - GMOCK_KIND_OF_(From), From, GMOCK_KIND_OF_(To), To> {}; // NOLINT +using LosslessArithmeticConvertible = + LosslessArithmeticConvertibleImpl<GMOCK_KIND_OF_(From), From, + GMOCK_KIND_OF_(To), To>; // This interface knows how to report a Google Mock failure (either // non-fatal or fatal). @@ -334,8 +294,6 @@ class WithoutMatchers { // Internal use only: access the singleton instance of WithoutMatchers. GTEST_API_ WithoutMatchers GetWithoutMatchers(); -// Type traits. - // Disable MSVC warnings for infinite recursion, since in this case the // the recursion is unreachable. #ifdef _MSC_VER @@ -492,8 +450,7 @@ struct Function<R(Args...)> { using Result = R; static constexpr size_t ArgumentCount = sizeof...(Args); template <size_t I> - using Arg = ElemFromList<I, typename MakeIndexSequence<sizeof...(Args)>::type, - Args...>; + using Arg = ElemFromList<I, Args...>; using ArgumentTuple = std::tuple<Args...>; using ArgumentMatcherTuple = std::tuple<Matcher<Args>...>; using MakeResultVoid = void(Args...); diff --git a/googlemock/include/gmock/internal/gmock-port.h b/googlemock/include/gmock/internal/gmock-port.h index 063e2929..70872ef3 100644 --- a/googlemock/include/gmock/internal/gmock-port.h +++ b/googlemock/include/gmock/internal/gmock-port.h @@ -42,6 +42,7 @@ #include <assert.h> #include <stdlib.h> +#include <cstdint> #include <iostream> // Most of the utilities needed for porting Google Mock are also @@ -69,8 +70,7 @@ // Macros for declaring flags. # define GMOCK_DECLARE_bool_(name) extern GTEST_API_ bool GMOCK_FLAG(name) -# define GMOCK_DECLARE_int32_(name) \ - extern GTEST_API_ ::testing::internal::Int32 GMOCK_FLAG(name) +# define GMOCK_DECLARE_int32_(name) extern GTEST_API_ int32_t GMOCK_FLAG(name) # define GMOCK_DECLARE_string_(name) \ extern GTEST_API_ ::std::string GMOCK_FLAG(name) @@ -78,7 +78,7 @@ # define GMOCK_DEFINE_bool_(name, default_val, doc) \ GTEST_API_ bool GMOCK_FLAG(name) = (default_val) # define GMOCK_DEFINE_int32_(name, default_val, doc) \ - GTEST_API_ ::testing::internal::Int32 GMOCK_FLAG(name) = (default_val) + GTEST_API_ int32_t GMOCK_FLAG(name) = (default_val) # define GMOCK_DEFINE_string_(name, default_val, doc) \ GTEST_API_ ::std::string GMOCK_FLAG(name) = (default_val) diff --git a/googlemock/include/gmock/internal/gmock-pp.h b/googlemock/include/gmock/internal/gmock-pp.h index 1ab80e1c..d13e75f3 100644 --- a/googlemock/include/gmock/internal/gmock-pp.h +++ b/googlemock/include/gmock/internal/gmock-pp.h @@ -1,19 +1,6 @@ #ifndef THIRD_PARTY_GOOGLETEST_GOOGLEMOCK_INCLUDE_GMOCK_PP_H_ #define THIRD_PARTY_GOOGLETEST_GOOGLEMOCK_INCLUDE_GMOCK_PP_H_ -#undef GMOCK_PP_INTERNAL_USE_MSVC -#if defined(__clang__) -#define GMOCK_PP_INTERNAL_USE_MSVC 0 -#elif defined(_MSC_VER) -// TODO(iserna): Also verify tradional versus comformant preprocessor. -static_assert( - _MSC_VER >= 1900, - "MSVC version not supported. There is support for MSVC 14.0 and above."); -#define GMOCK_PP_INTERNAL_USE_MSVC 1 -#else -#define GMOCK_PP_INTERNAL_USE_MSVC 0 -#endif - // Expands and concatenates the arguments. Constructed macros reevaluate. #define GMOCK_PP_CAT(_1, _2) GMOCK_PP_INTERNAL_CAT(_1, _2) @@ -29,10 +16,6 @@ static_assert( // Returns the only argument. #define GMOCK_PP_IDENTITY(_1) _1 -// MSVC preprocessor collapses __VA_ARGS__ in a single argument, we use a -// CAT-like directive to force correct evaluation. Each macro has its own. -#if GMOCK_PP_INTERNAL_USE_MSVC - // Evaluates to the number of arguments after expansion. // // #define PAIR x, y @@ -43,45 +26,27 @@ static_assert( // GMOCK_PP_NARG(PAIR) => 2 // // Requires: the number of arguments after expansion is at most 15. -#define GMOCK_PP_NARG(...) \ - GMOCK_PP_INTERNAL_NARG_CAT( \ - GMOCK_PP_INTERNAL_INTERNAL_16TH(__VA_ARGS__, 15, 14, 13, 12, 11, 10, 9, \ - 8, 7, 6, 5, 4, 3, 2, 1), ) +#define GMOCK_PP_NARG(...) \ + GMOCK_PP_INTERNAL_16TH( \ + (__VA_ARGS__, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1)) // Returns 1 if the expansion of arguments has an unprotected comma. Otherwise // returns 0. Requires no more than 15 unprotected commas. -#define GMOCK_PP_HAS_COMMA(...) \ - GMOCK_PP_INTERNAL_HAS_COMMA_CAT( \ - GMOCK_PP_INTERNAL_INTERNAL_16TH(__VA_ARGS__, 1, 1, 1, 1, 1, 1, 1, 1, 1, \ - 1, 1, 1, 1, 1, 0), ) +#define GMOCK_PP_HAS_COMMA(...) \ + GMOCK_PP_INTERNAL_16TH( \ + (__VA_ARGS__, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0)) + // Returns the first argument. -#define GMOCK_PP_HEAD(...) \ - GMOCK_PP_INTERNAL_HEAD_CAT(GMOCK_PP_INTERNAL_HEAD(__VA_ARGS__), ) +#define GMOCK_PP_HEAD(...) GMOCK_PP_INTERNAL_HEAD((__VA_ARGS__)) // Returns the tail. A variadic list of all arguments minus the first. Requires // at least one argument. -#define GMOCK_PP_TAIL(...) \ - GMOCK_PP_INTERNAL_TAIL_CAT(GMOCK_PP_INTERNAL_TAIL(__VA_ARGS__), ) +#define GMOCK_PP_TAIL(...) GMOCK_PP_INTERNAL_TAIL((__VA_ARGS__)) // Calls CAT(_Macro, NARG(__VA_ARGS__))(__VA_ARGS__) #define GMOCK_PP_VARIADIC_CALL(_Macro, ...) \ - GMOCK_PP_INTERNAL_VARIADIC_CALL_CAT( \ - GMOCK_PP_CAT(_Macro, GMOCK_PP_NARG(__VA_ARGS__))(__VA_ARGS__), ) - -#else // GMOCK_PP_INTERNAL_USE_MSVC - -#define GMOCK_PP_NARG(...) \ - GMOCK_PP_INTERNAL_INTERNAL_16TH(__VA_ARGS__, 15, 14, 13, 12, 11, 10, 9, 8, \ - 7, 6, 5, 4, 3, 2, 1) -#define GMOCK_PP_HAS_COMMA(...) \ - GMOCK_PP_INTERNAL_INTERNAL_16TH(__VA_ARGS__, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \ - 1, 1, 1, 1, 0) -#define GMOCK_PP_HEAD(...) GMOCK_PP_INTERNAL_HEAD(__VA_ARGS__) -#define GMOCK_PP_TAIL(...) GMOCK_PP_INTERNAL_TAIL(__VA_ARGS__) -#define GMOCK_PP_VARIADIC_CALL(_Macro, ...) \ - GMOCK_PP_CAT(_Macro, GMOCK_PP_NARG(__VA_ARGS__))(__VA_ARGS__) - -#endif // GMOCK_PP_INTERNAL_USE_MSVC + GMOCK_PP_IDENTITY( \ + GMOCK_PP_CAT(_Macro, GMOCK_PP_NARG(__VA_ARGS__))(__VA_ARGS__)) // If the arguments after expansion have no tokens, evaluates to `1`. Otherwise // evaluates to `0`. @@ -121,6 +86,14 @@ static_assert( #define GMOCK_PP_IF(_Cond, _Then, _Else) \ GMOCK_PP_CAT(GMOCK_PP_INTERNAL_IF_, _Cond)(_Then, _Else) +// Similar to GMOCK_PP_IF but takes _Then and _Else in parentheses. +// +// GMOCK_PP_GENERIC_IF(1, (a, b, c), (d, e, f)) => a, b, c +// GMOCK_PP_GENERIC_IF(0, (a, b, c), (d, e, f)) => d, e, f +// +#define GMOCK_PP_GENERIC_IF(_Cond, _Then, _Else) \ + GMOCK_PP_REMOVE_PARENS(GMOCK_PP_IF(_Cond, _Then, _Else)) + // Evaluates to the number of arguments after expansion. Identifies 'empty' as // 0. // @@ -139,10 +112,9 @@ static_assert( // Expands to 1 if the first argument starts with something in parentheses, // otherwise to 0. -#define GMOCK_PP_IS_BEGIN_PARENS(...) \ - GMOCK_PP_INTERNAL_ALTERNATE_HEAD( \ - GMOCK_PP_CAT(GMOCK_PP_INTERNAL_IBP_IS_VARIADIC_R_, \ - GMOCK_PP_INTERNAL_IBP_IS_VARIADIC_C __VA_ARGS__)) +#define GMOCK_PP_IS_BEGIN_PARENS(...) \ + GMOCK_PP_HEAD(GMOCK_PP_CAT(GMOCK_PP_INTERNAL_IBP_IS_VARIADIC_R_, \ + GMOCK_PP_INTERNAL_IBP_IS_VARIADIC_C __VA_ARGS__)) // Expands to 1 is there is only one argument and it is enclosed in parentheses. #define GMOCK_PP_IS_ENCLOSED_PARENS(...) \ @@ -179,10 +151,6 @@ static_assert( #define GMOCK_PP_INTENRAL_EMPTY_TUPLE (, , , , , , , , , , , , , , , ) #define GMOCK_PP_INTERNAL_CAT(_1, _2) _1##_2 #define GMOCK_PP_INTERNAL_STRINGIZE(...) #__VA_ARGS__ -#define GMOCK_PP_INTERNAL_INTERNAL_16TH(_1, _2, _3, _4, _5, _6, _7, _8, _9, \ - _10, _11, _12, _13, _14, _15, _16, \ - ...) \ - _16 #define GMOCK_PP_INTERNAL_CAT_5(_1, _2, _3, _4, _5) _1##_2##_3##_4##_5 #define GMOCK_PP_INTERNAL_IS_EMPTY(_1, _2, _3, _4) \ GMOCK_PP_HAS_COMMA(GMOCK_PP_INTERNAL_CAT_5(GMOCK_PP_INTERNAL_IS_EMPTY_CASE_, \ @@ -190,30 +158,24 @@ static_assert( #define GMOCK_PP_INTERNAL_IS_EMPTY_CASE_0001 , #define GMOCK_PP_INTERNAL_IF_1(_Then, _Else) _Then #define GMOCK_PP_INTERNAL_IF_0(_Then, _Else) _Else -#define GMOCK_PP_INTERNAL_HEAD(_1, ...) _1 -#define GMOCK_PP_INTERNAL_TAIL(_1, ...) __VA_ARGS__ -#if GMOCK_PP_INTERNAL_USE_MSVC -#define GMOCK_PP_INTERNAL_NARG_CAT(_1, _2) GMOCK_PP_INTERNAL_NARG_CAT_I(_1, _2) -#define GMOCK_PP_INTERNAL_HEAD_CAT(_1, _2) GMOCK_PP_INTERNAL_HEAD_CAT_I(_1, _2) -#define GMOCK_PP_INTERNAL_HAS_COMMA_CAT(_1, _2) \ - GMOCK_PP_INTERNAL_HAS_COMMA_CAT_I(_1, _2) -#define GMOCK_PP_INTERNAL_TAIL_CAT(_1, _2) GMOCK_PP_INTERNAL_TAIL_CAT_I(_1, _2) -#define GMOCK_PP_INTERNAL_VARIADIC_CALL_CAT(_1, _2) \ - GMOCK_PP_INTERNAL_VARIADIC_CALL_CAT_I(_1, _2) -#define GMOCK_PP_INTERNAL_NARG_CAT_I(_1, _2) _1##_2 -#define GMOCK_PP_INTERNAL_HEAD_CAT_I(_1, _2) _1##_2 -#define GMOCK_PP_INTERNAL_HAS_COMMA_CAT_I(_1, _2) _1##_2 -#define GMOCK_PP_INTERNAL_TAIL_CAT_I(_1, _2) _1##_2 -#define GMOCK_PP_INTERNAL_VARIADIC_CALL_CAT_I(_1, _2) _1##_2 -#define GMOCK_PP_INTERNAL_ALTERNATE_HEAD(...) \ - GMOCK_PP_INTERNAL_ALTERNATE_HEAD_CAT(GMOCK_PP_HEAD(__VA_ARGS__), ) -#define GMOCK_PP_INTERNAL_ALTERNATE_HEAD_CAT(_1, _2) \ - GMOCK_PP_INTERNAL_ALTERNATE_HEAD_CAT_I(_1, _2) -#define GMOCK_PP_INTERNAL_ALTERNATE_HEAD_CAT_I(_1, _2) _1##_2 -#else // GMOCK_PP_INTERNAL_USE_MSVC -#define GMOCK_PP_INTERNAL_ALTERNATE_HEAD(...) GMOCK_PP_HEAD(__VA_ARGS__) -#endif // GMOCK_PP_INTERNAL_USE_MSVC +// Because of MSVC treating a token with a comma in it as a single token when +// passed to another macro, we need to force it to evaluate it as multiple +// tokens. We do that by using a "IDENTITY(MACRO PARENTHESIZED_ARGS)" macro. We +// define one per possible macro that relies on this behavior. Note "_Args" must +// be parenthesized. +#define GMOCK_PP_INTERNAL_INTERNAL_16TH(_1, _2, _3, _4, _5, _6, _7, _8, _9, \ + _10, _11, _12, _13, _14, _15, _16, \ + ...) \ + _16 +#define GMOCK_PP_INTERNAL_16TH(_Args) \ + GMOCK_PP_IDENTITY(GMOCK_PP_INTERNAL_INTERNAL_16TH _Args) +#define GMOCK_PP_INTERNAL_INTERNAL_HEAD(_1, ...) _1 +#define GMOCK_PP_INTERNAL_HEAD(_Args) \ + GMOCK_PP_IDENTITY(GMOCK_PP_INTERNAL_INTERNAL_HEAD _Args) +#define GMOCK_PP_INTERNAL_INTERNAL_TAIL(_1, ...) __VA_ARGS__ +#define GMOCK_PP_INTERNAL_TAIL(_Args) \ + GMOCK_PP_IDENTITY(GMOCK_PP_INTERNAL_INTERNAL_TAIL _Args) #define GMOCK_PP_INTERNAL_IBP_IS_VARIADIC_C(...) 1 _ #define GMOCK_PP_INTERNAL_IBP_IS_VARIADIC_R_1 1, diff --git a/googlemock/scripts/README.md b/googlemock/scripts/README.md new file mode 100644 index 00000000..a3301e5b --- /dev/null +++ b/googlemock/scripts/README.md @@ -0,0 +1,5 @@ +# Please Note: + +Files in this directory are no longer supported by the maintainers. They +represent mostly historical artifacts and supported by the community only. There +is no guarantee whatsoever that these scripts still work. diff --git a/googlemock/scripts/generator/cpp/ast.py b/googlemock/scripts/generator/cpp/ast.py index f14728b4..b4890a54 100755 --- a/googlemock/scripts/generator/cpp/ast.py +++ b/googlemock/scripts/generator/cpp/ast.py @@ -17,10 +17,7 @@ """Generate an Abstract Syntax Tree (AST) for C++.""" -__author__ = 'nnorwitz@google.com (Neal Norwitz)' - - -# TODO: +# FIXME: # * Tokens should never be exported, need to convert to Nodes # (return types, parameters, etc.) # * Handle static class data for templatized classes @@ -33,11 +30,11 @@ __author__ = 'nnorwitz@google.com (Neal Norwitz)' try: - # Python 3.x - import builtins + # Python 3.x + import builtins except ImportError: - # Python 2.x - import __builtin__ as builtins + # Python 2.x + import __builtin__ as builtins import sys import traceback @@ -48,15 +45,15 @@ from cpp import utils if not hasattr(builtins, 'reversed'): - # Support Python 2.3 and earlier. - def reversed(seq): - for i in range(len(seq)-1, -1, -1): - yield seq[i] + # Support Python 2.3 and earlier. + def reversed(seq): + for i in range(len(seq)-1, -1, -1): + yield seq[i] if not hasattr(builtins, 'next'): - # Support Python 2.5 and earlier. - def next(obj): - return obj.next() + # Support Python 2.5 and earlier. + def next(obj): + return obj.next() VISIBILITY_PUBLIC, VISIBILITY_PROTECTED, VISIBILITY_PRIVATE = range(3) @@ -101,1570 +98,1610 @@ _NAMESPACE_POP = 'ns-pop' # TODO(nnorwitz): use this as a singleton for templated_types, etc # where we don't want to create a new empty dict each time. It is also const. class _NullDict(object): - __contains__ = lambda self: False - keys = values = items = iterkeys = itervalues = iteritems = lambda self: () + __contains__ = lambda self: False + keys = values = items = iterkeys = itervalues = iteritems = lambda self: () # TODO(nnorwitz): move AST nodes into a separate module. class Node(object): - """Base AST node.""" + """Base AST node.""" - def __init__(self, start, end): - self.start = start - self.end = end + def __init__(self, start, end): + self.start = start + self.end = end - def IsDeclaration(self): - """Returns bool if this node is a declaration.""" - return False + def IsDeclaration(self): + """Returns bool if this node is a declaration.""" + return False - def IsDefinition(self): - """Returns bool if this node is a definition.""" - return False + def IsDefinition(self): + """Returns bool if this node is a definition.""" + return False - def IsExportable(self): - """Returns bool if this node exportable from a header file.""" - return False + def IsExportable(self): + """Returns bool if this node exportable from a header file.""" + return False - def Requires(self, node): - """Does this AST node require the definition of the node passed in?""" - return False + def Requires(self, node): + """Does this AST node require the definition of the node passed in?""" + return False - def XXX__str__(self): - return self._StringHelper(self.__class__.__name__, '') + def XXX__str__(self): + return self._StringHelper(self.__class__.__name__, '') - def _StringHelper(self, name, suffix): - if not utils.DEBUG: - return '%s(%s)' % (name, suffix) - return '%s(%d, %d, %s)' % (name, self.start, self.end, suffix) + def _StringHelper(self, name, suffix): + if not utils.DEBUG: + return '%s(%s)' % (name, suffix) + return '%s(%d, %d, %s)' % (name, self.start, self.end, suffix) - def __repr__(self): - return str(self) + def __repr__(self): + return str(self) class Define(Node): - def __init__(self, start, end, name, definition): - Node.__init__(self, start, end) - self.name = name - self.definition = definition + def __init__(self, start, end, name, definition): + Node.__init__(self, start, end) + self.name = name + self.definition = definition - def __str__(self): - value = '%s %s' % (self.name, self.definition) - return self._StringHelper(self.__class__.__name__, value) + def __str__(self): + value = '%s %s' % (self.name, self.definition) + return self._StringHelper(self.__class__.__name__, value) class Include(Node): - def __init__(self, start, end, filename, system): - Node.__init__(self, start, end) - self.filename = filename - self.system = system + def __init__(self, start, end, filename, system): + Node.__init__(self, start, end) + self.filename = filename + self.system = system - def __str__(self): - fmt = '"%s"' - if self.system: - fmt = '<%s>' - return self._StringHelper(self.__class__.__name__, fmt % self.filename) + def __str__(self): + fmt = '"%s"' + if self.system: + fmt = '<%s>' + return self._StringHelper(self.__class__.__name__, fmt % self.filename) class Goto(Node): - def __init__(self, start, end, label): - Node.__init__(self, start, end) - self.label = label + def __init__(self, start, end, label): + Node.__init__(self, start, end) + self.label = label - def __str__(self): - return self._StringHelper(self.__class__.__name__, str(self.label)) + def __str__(self): + return self._StringHelper(self.__class__.__name__, str(self.label)) class Expr(Node): - def __init__(self, start, end, expr): - Node.__init__(self, start, end) - self.expr = expr + def __init__(self, start, end, expr): + Node.__init__(self, start, end) + self.expr = expr - def Requires(self, node): - # TODO(nnorwitz): impl. - return False + def Requires(self, node): + # TODO(nnorwitz): impl. + return False - def __str__(self): - return self._StringHelper(self.__class__.__name__, str(self.expr)) + def __str__(self): + return self._StringHelper(self.__class__.__name__, str(self.expr)) class Return(Expr): - pass + pass class Delete(Expr): - pass + pass class Friend(Expr): - def __init__(self, start, end, expr, namespace): - Expr.__init__(self, start, end, expr) - self.namespace = namespace[:] + def __init__(self, start, end, expr, namespace): + Expr.__init__(self, start, end, expr) + self.namespace = namespace[:] class Using(Node): - def __init__(self, start, end, names): - Node.__init__(self, start, end) - self.names = names + def __init__(self, start, end, names): + Node.__init__(self, start, end) + self.names = names - def __str__(self): - return self._StringHelper(self.__class__.__name__, str(self.names)) + def __str__(self): + return self._StringHelper(self.__class__.__name__, str(self.names)) class Parameter(Node): - def __init__(self, start, end, name, parameter_type, default): - Node.__init__(self, start, end) - self.name = name - self.type = parameter_type - self.default = default + def __init__(self, start, end, name, parameter_type, default): + Node.__init__(self, start, end) + self.name = name + self.type = parameter_type + self.default = default - def Requires(self, node): - # TODO(nnorwitz): handle namespaces, etc. - return self.type.name == node.name + def Requires(self, node): + # TODO(nnorwitz): handle namespaces, etc. + return self.type.name == node.name - def __str__(self): - name = str(self.type) - suffix = '%s %s' % (name, self.name) - if self.default: - suffix += ' = ' + ''.join([d.name for d in self.default]) - return self._StringHelper(self.__class__.__name__, suffix) + def __str__(self): + name = str(self.type) + suffix = '%s %s' % (name, self.name) + if self.default: + suffix += ' = ' + ''.join([d.name for d in self.default]) + return self._StringHelper(self.__class__.__name__, suffix) class _GenericDeclaration(Node): - def __init__(self, start, end, name, namespace): - Node.__init__(self, start, end) - self.name = name - self.namespace = namespace[:] + def __init__(self, start, end, name, namespace): + Node.__init__(self, start, end) + self.name = name + self.namespace = namespace[:] - def FullName(self): - prefix = '' - if self.namespace and self.namespace[-1]: - prefix = '::'.join(self.namespace) + '::' - return prefix + self.name + def FullName(self): + prefix = '' + if self.namespace and self.namespace[-1]: + prefix = '::'.join(self.namespace) + '::' + return prefix + self.name - def _TypeStringHelper(self, suffix): - if self.namespace: - names = [n or '<anonymous>' for n in self.namespace] - suffix += ' in ' + '::'.join(names) - return self._StringHelper(self.__class__.__name__, suffix) + def _TypeStringHelper(self, suffix): + if self.namespace: + names = [n or '<anonymous>' for n in self.namespace] + suffix += ' in ' + '::'.join(names) + return self._StringHelper(self.__class__.__name__, suffix) # TODO(nnorwitz): merge with Parameter in some way? class VariableDeclaration(_GenericDeclaration): - def __init__(self, start, end, name, var_type, initial_value, namespace): - _GenericDeclaration.__init__(self, start, end, name, namespace) - self.type = var_type - self.initial_value = initial_value + def __init__(self, start, end, name, var_type, initial_value, namespace): + _GenericDeclaration.__init__(self, start, end, name, namespace) + self.type = var_type + self.initial_value = initial_value - def Requires(self, node): - # TODO(nnorwitz): handle namespaces, etc. - return self.type.name == node.name + def Requires(self, node): + # TODO(nnorwitz): handle namespaces, etc. + return self.type.name == node.name - def ToString(self): - """Return a string that tries to reconstitute the variable decl.""" - suffix = '%s %s' % (self.type, self.name) - if self.initial_value: - suffix += ' = ' + self.initial_value - return suffix + def ToString(self): + """Return a string that tries to reconstitute the variable decl.""" + suffix = '%s %s' % (self.type, self.name) + if self.initial_value: + suffix += ' = ' + self.initial_value + return suffix - def __str__(self): - return self._StringHelper(self.__class__.__name__, self.ToString()) + def __str__(self): + return self._StringHelper(self.__class__.__name__, self.ToString()) class Typedef(_GenericDeclaration): - def __init__(self, start, end, name, alias, namespace): - _GenericDeclaration.__init__(self, start, end, name, namespace) - self.alias = alias + def __init__(self, start, end, name, alias, namespace): + _GenericDeclaration.__init__(self, start, end, name, namespace) + self.alias = alias - def IsDefinition(self): - return True + def IsDefinition(self): + return True - def IsExportable(self): - return True + def IsExportable(self): + return True - def Requires(self, node): - # TODO(nnorwitz): handle namespaces, etc. - name = node.name - for token in self.alias: - if token is not None and name == token.name: - return True - return False + def Requires(self, node): + # TODO(nnorwitz): handle namespaces, etc. + name = node.name + for token in self.alias: + if token is not None and name == token.name: + return True + return False - def __str__(self): - suffix = '%s, %s' % (self.name, self.alias) - return self._TypeStringHelper(suffix) + def __str__(self): + suffix = '%s, %s' % (self.name, self.alias) + return self._TypeStringHelper(suffix) class _NestedType(_GenericDeclaration): - def __init__(self, start, end, name, fields, namespace): - _GenericDeclaration.__init__(self, start, end, name, namespace) - self.fields = fields + def __init__(self, start, end, name, fields, namespace): + _GenericDeclaration.__init__(self, start, end, name, namespace) + self.fields = fields - def IsDefinition(self): - return True + def IsDefinition(self): + return True - def IsExportable(self): - return True + def IsExportable(self): + return True - def __str__(self): - suffix = '%s, {%s}' % (self.name, self.fields) - return self._TypeStringHelper(suffix) + def __str__(self): + suffix = '%s, {%s}' % (self.name, self.fields) + return self._TypeStringHelper(suffix) class Union(_NestedType): - pass + pass class Enum(_NestedType): - pass + pass class Class(_GenericDeclaration): - def __init__(self, start, end, name, bases, templated_types, body, namespace): - _GenericDeclaration.__init__(self, start, end, name, namespace) - self.bases = bases - self.body = body - self.templated_types = templated_types - - def IsDeclaration(self): - return self.bases is None and self.body is None - - def IsDefinition(self): - return not self.IsDeclaration() - - def IsExportable(self): - return not self.IsDeclaration() - - def Requires(self, node): - # TODO(nnorwitz): handle namespaces, etc. - if self.bases: - for token_list in self.bases: - # TODO(nnorwitz): bases are tokens, do name comparison. - for token in token_list: - if token.name == node.name: - return True - # TODO(nnorwitz): search in body too. - return False - - def __str__(self): - name = self.name - if self.templated_types: - name += '<%s>' % self.templated_types - suffix = '%s, %s, %s' % (name, self.bases, self.body) - return self._TypeStringHelper(suffix) + def __init__(self, start, end, name, bases, templated_types, body, namespace): + _GenericDeclaration.__init__(self, start, end, name, namespace) + self.bases = bases + self.body = body + self.templated_types = templated_types + + def IsDeclaration(self): + return self.bases is None and self.body is None + + def IsDefinition(self): + return not self.IsDeclaration() + + def IsExportable(self): + return not self.IsDeclaration() + + def Requires(self, node): + # TODO(nnorwitz): handle namespaces, etc. + if self.bases: + for token_list in self.bases: + # TODO(nnorwitz): bases are tokens, do name comparision. + for token in token_list: + if token.name == node.name: + return True + # TODO(nnorwitz): search in body too. + return False + + def __str__(self): + name = self.name + if self.templated_types: + name += '<%s>' % self.templated_types + suffix = '%s, %s, %s' % (name, self.bases, self.body) + return self._TypeStringHelper(suffix) class Struct(Class): - pass + pass class Function(_GenericDeclaration): - def __init__(self, start, end, name, return_type, parameters, - modifiers, templated_types, body, namespace): - _GenericDeclaration.__init__(self, start, end, name, namespace) - converter = TypeConverter(namespace) - self.return_type = converter.CreateReturnType(return_type) - self.parameters = converter.ToParameters(parameters) - self.modifiers = modifiers - self.body = body - self.templated_types = templated_types - - def IsDeclaration(self): - return self.body is None - - def IsDefinition(self): - return self.body is not None - - def IsExportable(self): - if self.return_type and 'static' in self.return_type.modifiers: - return False - return None not in self.namespace - - def Requires(self, node): - if self.parameters: - # TODO(nnorwitz): parameters are tokens, do name comparison. - for p in self.parameters: - if p.name == node.name: - return True - # TODO(nnorwitz): search in body too. - return False - - def __str__(self): - # TODO(nnorwitz): add templated_types. - suffix = ('%s %s(%s), 0x%02x, %s' % - (self.return_type, self.name, self.parameters, - self.modifiers, self.body)) - return self._TypeStringHelper(suffix) + def __init__(self, start, end, name, return_type, parameters, + modifiers, templated_types, body, namespace): + _GenericDeclaration.__init__(self, start, end, name, namespace) + converter = TypeConverter(namespace) + self.return_type = converter.CreateReturnType(return_type) + self.parameters = converter.ToParameters(parameters) + self.modifiers = modifiers + self.body = body + self.templated_types = templated_types + + def IsDeclaration(self): + return self.body is None + + def IsDefinition(self): + return self.body is not None + + def IsExportable(self): + if self.return_type and 'static' in self.return_type.modifiers: + return False + return None not in self.namespace + + def Requires(self, node): + if self.parameters: + # TODO(nnorwitz): parameters are tokens, do name comparision. + for p in self.parameters: + if p.name == node.name: + return True + # TODO(nnorwitz): search in body too. + return False + + def __str__(self): + # TODO(nnorwitz): add templated_types. + suffix = ('%s %s(%s), 0x%02x, %s' % + (self.return_type, self.name, self.parameters, + self.modifiers, self.body)) + return self._TypeStringHelper(suffix) class Method(Function): - def __init__(self, start, end, name, in_class, return_type, parameters, - modifiers, templated_types, body, namespace): - Function.__init__(self, start, end, name, return_type, parameters, - modifiers, templated_types, body, namespace) - # TODO(nnorwitz): in_class could also be a namespace which can - # mess up finding functions properly. - self.in_class = in_class + def __init__(self, start, end, name, in_class, return_type, parameters, + modifiers, templated_types, body, namespace): + Function.__init__(self, start, end, name, return_type, parameters, + modifiers, templated_types, body, namespace) + # TODO(nnorwitz): in_class could also be a namespace which can + # mess up finding functions properly. + self.in_class = in_class class Type(_GenericDeclaration): - """Type used for any variable (eg class, primitive, struct, etc).""" + """Type used for any variable (eg class, primitive, struct, etc).""" - def __init__(self, start, end, name, templated_types, modifiers, - reference, pointer, array): - """ + def __init__(self, start, end, name, templated_types, modifiers, + reference, pointer, array): + """ Args: name: str name of main type templated_types: [Class (Type?)] template type info between <> modifiers: [str] type modifiers (keywords) eg, const, mutable, etc. reference, pointer, array: bools """ - _GenericDeclaration.__init__(self, start, end, name, []) - self.templated_types = templated_types - if not name and modifiers: - self.name = modifiers.pop() - self.modifiers = modifiers - self.reference = reference - self.pointer = pointer - self.array = array - - def __str__(self): - prefix = '' - if self.modifiers: - prefix = ' '.join(self.modifiers) + ' ' - name = str(self.name) - if self.templated_types: - name += '<%s>' % self.templated_types - suffix = prefix + name - if self.reference: - suffix += '&' - if self.pointer: - suffix += '*' - if self.array: - suffix += '[]' - return self._TypeStringHelper(suffix) - - # By definition, Is* are always False. A Type can only exist in - # some sort of variable declaration, parameter, or return value. - def IsDeclaration(self): - return False - - def IsDefinition(self): - return False - - def IsExportable(self): - return False + _GenericDeclaration.__init__(self, start, end, name, []) + self.templated_types = templated_types + if not name and modifiers: + self.name = modifiers.pop() + self.modifiers = modifiers + self.reference = reference + self.pointer = pointer + self.array = array + + def __str__(self): + prefix = '' + if self.modifiers: + prefix = ' '.join(self.modifiers) + ' ' + name = str(self.name) + if self.templated_types: + name += '<%s>' % self.templated_types + suffix = prefix + name + if self.reference: + suffix += '&' + if self.pointer: + suffix += '*' + if self.array: + suffix += '[]' + return self._TypeStringHelper(suffix) + + # By definition, Is* are always False. A Type can only exist in + # some sort of variable declaration, parameter, or return value. + def IsDeclaration(self): + return False + + def IsDefinition(self): + return False + + def IsExportable(self): + return False class TypeConverter(object): - def __init__(self, namespace_stack): - self.namespace_stack = namespace_stack - - def _GetTemplateEnd(self, tokens, start): - count = 1 - end = start - while 1: - token = tokens[end] - end += 1 - if token.name == '<': - count += 1 - elif token.name == '>': - count -= 1 - if count == 0: - break - return tokens[start:end-1], end - - def ToType(self, tokens): - """Convert [Token,...] to [Class(...), ] useful for base classes. + def __init__(self, namespace_stack): + self.namespace_stack = namespace_stack + + def _GetTemplateEnd(self, tokens, start): + count = 1 + end = start + while 1: + token = tokens[end] + end += 1 + if token.name == '<': + count += 1 + elif token.name == '>': + count -= 1 + if count == 0: + break + return tokens[start:end-1], end + + def ToType(self, tokens): + """Convert [Token,...] to [Class(...), ] useful for base classes. For example, code like class Foo : public Bar<x, y> { ... }; the "Bar<x, y>" portion gets converted to an AST. Returns: [Class(...), ...] """ - result = [] - name_tokens = [] + result = [] + name_tokens = [] + reference = pointer = array = False + + def AddType(templated_types): + # Partition tokens into name and modifier tokens. + names = [] + modifiers = [] + for t in name_tokens: + if keywords.IsKeyword(t.name): + modifiers.append(t.name) + else: + names.append(t.name) + name = ''.join(names) + if name_tokens: + result.append(Type(name_tokens[0].start, name_tokens[-1].end, + name, templated_types, modifiers, + reference, pointer, array)) + del name_tokens[:] + + i = 0 + end = len(tokens) + while i < end: + token = tokens[i] + if token.name == '<': + new_tokens, new_end = self._GetTemplateEnd(tokens, i+1) + AddType(self.ToType(new_tokens)) + # If there is a comma after the template, we need to consume + # that here otherwise it becomes part of the name. + i = new_end reference = pointer = array = False - - def AddType(templated_types): - # Partition tokens into name and modifier tokens. - names = [] - modifiers = [] - for t in name_tokens: - if keywords.IsKeyword(t.name): - modifiers.append(t.name) - else: - names.append(t.name) - name = ''.join(names) - if name_tokens: - result.append(Type(name_tokens[0].start, name_tokens[-1].end, - name, templated_types, modifiers, - reference, pointer, array)) - del name_tokens[:] - - i = 0 - end = len(tokens) - while i < end: - token = tokens[i] - if token.name == '<': - new_tokens, new_end = self._GetTemplateEnd(tokens, i+1) - AddType(self.ToType(new_tokens)) - # If there is a comma after the template, we need to consume - # that here otherwise it becomes part of the name. - i = new_end - reference = pointer = array = False - elif token.name == ',': - AddType([]) - reference = pointer = array = False - elif token.name == '*': - pointer = True - elif token.name == '&': - reference = True - elif token.name == '[': - pointer = True - elif token.name == ']': - pass - else: - name_tokens.append(token) - i += 1 - - if name_tokens: - # No '<' in the tokens, just a simple name and no template. - AddType([]) - return result - - def DeclarationToParts(self, parts, needs_name_removed): - name = None - default = [] - if needs_name_removed: - # Handle default (initial) values properly. - for i, t in enumerate(parts): - if t.name == '=': - default = parts[i+1:] - name = parts[i-1].name - if name == ']' and parts[i-2].name == '[': - name = parts[i-3].name - i -= 1 - parts = parts[:i-1] - break - else: - if parts[-1].token_type == tokenize.NAME: - name = parts.pop().name - else: - # TODO(nnorwitz): this is a hack that happens for code like - # Register(Foo<T>); where it thinks this is a function call - # but it's actually a declaration. - name = '???' - modifiers = [] - type_name = [] - other_tokens = [] - templated_types = [] - i = 0 - end = len(parts) - while i < end: - p = parts[i] - if keywords.IsKeyword(p.name): - modifiers.append(p.name) - elif p.name == '<': - templated_tokens, new_end = self._GetTemplateEnd(parts, i+1) - templated_types = self.ToType(templated_tokens) - i = new_end - 1 - # Don't add a spurious :: to data members being initialized. - next_index = i + 1 - if next_index < end and parts[next_index].name == '::': - i += 1 - elif p.name in ('[', ']', '='): - # These are handled elsewhere. - other_tokens.append(p) - elif p.name not in ('*', '&', '>'): - # Ensure that names have a space between them. - if (type_name and type_name[-1].token_type == tokenize.NAME and - p.token_type == tokenize.NAME): - type_name.append(tokenize.Token(tokenize.SYNTAX, ' ', 0, 0)) - type_name.append(p) - else: - other_tokens.append(p) - i += 1 - type_name = ''.join([t.name for t in type_name]) - return name, type_name, templated_types, modifiers, default, other_tokens - - def ToParameters(self, tokens): - if not tokens: - return [] - - result = [] + elif token.name == ',': + AddType([]) + reference = pointer = array = False + elif token.name == '*': + pointer = True + elif token.name == '&': + reference = True + elif token.name == '[': + pointer = True + elif token.name == ']': + pass + else: + name_tokens.append(token) + i += 1 + + if name_tokens: + # No '<' in the tokens, just a simple name and no template. + AddType([]) + return result + + def DeclarationToParts(self, parts, needs_name_removed): + name = None + default = [] + if needs_name_removed: + # Handle default (initial) values properly. + for i, t in enumerate(parts): + if t.name == '=': + default = parts[i+1:] + name = parts[i-1].name + if name == ']' and parts[i-2].name == '[': + name = parts[i-3].name + i -= 1 + parts = parts[:i-1] + break + else: + if parts[-1].token_type == tokenize.NAME: + name = parts.pop().name + else: + # TODO(nnorwitz): this is a hack that happens for code like + # Register(Foo<T>); where it thinks this is a function call + # but it's actually a declaration. + name = '???' + modifiers = [] + type_name = [] + other_tokens = [] + templated_types = [] + i = 0 + end = len(parts) + while i < end: + p = parts[i] + if keywords.IsKeyword(p.name): + modifiers.append(p.name) + elif p.name == '<': + templated_tokens, new_end = self._GetTemplateEnd(parts, i+1) + templated_types = self.ToType(templated_tokens) + i = new_end - 1 + # Don't add a spurious :: to data members being initialized. + next_index = i + 1 + if next_index < end and parts[next_index].name == '::': + i += 1 + elif p.name in ('[', ']', '='): + # These are handled elsewhere. + other_tokens.append(p) + elif p.name not in ('*', '&', '>'): + # Ensure that names have a space between them. + if (type_name and type_name[-1].token_type == tokenize.NAME and + p.token_type == tokenize.NAME): + type_name.append(tokenize.Token(tokenize.SYNTAX, ' ', 0, 0)) + type_name.append(p) + else: + other_tokens.append(p) + i += 1 + type_name = ''.join([t.name for t in type_name]) + return name, type_name, templated_types, modifiers, default, other_tokens + + def ToParameters(self, tokens): + if not tokens: + return [] + + result = [] + name = type_name = '' + type_modifiers = [] + pointer = reference = array = False + first_token = None + default = [] + + def AddParameter(end): + if default: + del default[0] # Remove flag. + parts = self.DeclarationToParts(type_modifiers, True) + (name, type_name, templated_types, modifiers, + unused_default, unused_other_tokens) = parts + parameter_type = Type(first_token.start, first_token.end, + type_name, templated_types, modifiers, + reference, pointer, array) + p = Parameter(first_token.start, end, name, + parameter_type, default) + result.append(p) + + template_count = 0 + brace_count = 0 + for s in tokens: + if not first_token: + first_token = s + + # Check for braces before templates, as we can have unmatched '<>' + # inside default arguments. + if s.name == '{': + brace_count += 1 + elif s.name == '}': + brace_count -= 1 + if brace_count > 0: + type_modifiers.append(s) + continue + + if s.name == '<': + template_count += 1 + elif s.name == '>': + template_count -= 1 + if template_count > 0: + type_modifiers.append(s) + continue + + if s.name == ',': + AddParameter(s.start) name = type_name = '' type_modifiers = [] pointer = reference = array = False first_token = None default = [] - - def AddParameter(end): - if default: - del default[0] # Remove flag. - parts = self.DeclarationToParts(type_modifiers, True) - (name, type_name, templated_types, modifiers, - unused_default, unused_other_tokens) = parts - parameter_type = Type(first_token.start, first_token.end, - type_name, templated_types, modifiers, - reference, pointer, array) - p = Parameter(first_token.start, end, name, - parameter_type, default) - result.append(p) - - template_count = 0 - for s in tokens: - if not first_token: - first_token = s - if s.name == '<': - template_count += 1 - elif s.name == '>': - template_count -= 1 - if template_count > 0: - type_modifiers.append(s) - continue - - if s.name == ',': - AddParameter(s.start) - name = type_name = '' - type_modifiers = [] - pointer = reference = array = False - first_token = None - default = [] - elif s.name == '*': - pointer = True - elif s.name == '&': - reference = True - elif s.name == '[': - array = True - elif s.name == ']': - pass # Just don't add to type_modifiers. - elif s.name == '=': - # Got a default value. Add any value (None) as a flag. - default.append(None) - elif default: - default.append(s) - else: - type_modifiers.append(s) - AddParameter(tokens[-1].end) - return result - - def CreateReturnType(self, return_type_seq): - if not return_type_seq: - return None - start = return_type_seq[0].start - end = return_type_seq[-1].end - _, name, templated_types, modifiers, default, other_tokens = \ - self.DeclarationToParts(return_type_seq, False) - names = [n.name for n in other_tokens] - reference = '&' in names - pointer = '*' in names - array = '[' in names - return Type(start, end, name, templated_types, modifiers, - reference, pointer, array) - - def GetTemplateIndices(self, names): - # names is a list of strings. - start = names.index('<') - end = len(names) - 1 - while end > 0: - if names[end] == '>': - break - end -= 1 - return start, end+1 + elif s.name == '*': + pointer = True + elif s.name == '&': + reference = True + elif s.name == '[': + array = True + elif s.name == ']': + pass # Just don't add to type_modifiers. + elif s.name == '=': + # Got a default value. Add any value (None) as a flag. + default.append(None) + elif default: + default.append(s) + else: + type_modifiers.append(s) + AddParameter(tokens[-1].end) + return result + + def CreateReturnType(self, return_type_seq): + if not return_type_seq: + return None + start = return_type_seq[0].start + end = return_type_seq[-1].end + _, name, templated_types, modifiers, default, other_tokens = \ + self.DeclarationToParts(return_type_seq, False) + names = [n.name for n in other_tokens] + reference = '&' in names + pointer = '*' in names + array = '[' in names + return Type(start, end, name, templated_types, modifiers, + reference, pointer, array) + + def GetTemplateIndices(self, names): + # names is a list of strings. + start = names.index('<') + end = len(names) - 1 + while end > 0: + if names[end] == '>': + break + end -= 1 + return start, end+1 class AstBuilder(object): - def __init__(self, token_stream, filename, in_class='', visibility=None, - namespace_stack=[]): - self.tokens = token_stream - self.filename = filename - # TODO(nnorwitz): use a better data structure (deque) for the queue. - # Switching directions of the "queue" improved perf by about 25%. - # Using a deque should be even better since we access from both sides. - self.token_queue = [] - self.namespace_stack = namespace_stack[:] - self.in_class = in_class - if in_class is None: - self.in_class_name_only = None - else: - self.in_class_name_only = in_class.split('::')[-1] - self.visibility = visibility - self.in_function = False - self.current_token = None - # Keep the state whether we are currently handling a typedef or not. - self._handling_typedef = False - - self.converter = TypeConverter(self.namespace_stack) - - def HandleError(self, msg, token): - printable_queue = list(reversed(self.token_queue[-20:])) - sys.stderr.write('Got %s in %s @ %s %s\n' % - (msg, self.filename, token, printable_queue)) - - def Generate(self): - while 1: - token = self._GetNextToken() - if not token: - break - - # Get the next token. - self.current_token = token - - # Dispatch on the next token type. - if token.token_type == _INTERNAL_TOKEN: - if token.name == _NAMESPACE_POP: - self.namespace_stack.pop() - continue - - try: - result = self._GenerateOne(token) - if result is not None: - yield result - except: - self.HandleError('exception', token) - raise - - def _CreateVariable(self, pos_token, name, type_name, type_modifiers, - ref_pointer_name_seq, templated_types, value=None): - reference = '&' in ref_pointer_name_seq - pointer = '*' in ref_pointer_name_seq - array = '[' in ref_pointer_name_seq - var_type = Type(pos_token.start, pos_token.end, type_name, - templated_types, type_modifiers, - reference, pointer, array) - return VariableDeclaration(pos_token.start, pos_token.end, - name, var_type, value, self.namespace_stack) - - def _GenerateOne(self, token): - if token.token_type == tokenize.NAME: - if (keywords.IsKeyword(token.name) and - not keywords.IsBuiltinType(token.name)): - method = getattr(self, 'handle_' + token.name) - return method() - elif token.name == self.in_class_name_only: - # The token name is the same as the class, must be a ctor if - # there is a paren. Otherwise, it's the return type. - # Peek ahead to get the next token to figure out which. - next = self._GetNextToken() - self._AddBackToken(next) - if next.token_type == tokenize.SYNTAX and next.name == '(': - return self._GetMethod([token], FUNCTION_CTOR, None, True) - # Fall through--handle like any other method. - - # Handle data or function declaration/definition. - syntax = tokenize.SYNTAX - temp_tokens, last_token = \ - self._GetVarTokensUpTo(syntax, '(', ';', '{', '[') - temp_tokens.insert(0, token) - if last_token.name == '(': - # If there is an assignment before the paren, - # this is an expression, not a method. - expr = bool([e for e in temp_tokens if e.name == '=']) - if expr: - new_temp = self._GetTokensUpTo(tokenize.SYNTAX, ';') - temp_tokens.append(last_token) - temp_tokens.extend(new_temp) - last_token = tokenize.Token(tokenize.SYNTAX, ';', 0, 0) - - if last_token.name == '[': - # Handle array, this isn't a method, unless it's an operator. - # TODO(nnorwitz): keep the size somewhere. - # unused_size = self._GetTokensUpTo(tokenize.SYNTAX, ']') - temp_tokens.append(last_token) - if temp_tokens[-2].name == 'operator': - temp_tokens.append(self._GetNextToken()) - else: - temp_tokens2, last_token = \ - self._GetVarTokensUpTo(tokenize.SYNTAX, ';') - temp_tokens.extend(temp_tokens2) - - if last_token.name == ';': - # Handle data, this isn't a method. - parts = self.converter.DeclarationToParts(temp_tokens, True) - (name, type_name, templated_types, modifiers, default, - unused_other_tokens) = parts - - t0 = temp_tokens[0] - names = [t.name for t in temp_tokens] - if templated_types: - start, end = self.converter.GetTemplateIndices(names) - names = names[:start] + names[end:] - default = ''.join([t.name for t in default]) - return self._CreateVariable(t0, name, type_name, modifiers, - names, templated_types, default) - if last_token.name == '{': - self._AddBackTokens(temp_tokens[1:]) - self._AddBackToken(last_token) - method_name = temp_tokens[0].name - method = getattr(self, 'handle_' + method_name, None) - if not method: - # Must be declaring a variable. - # TODO(nnorwitz): handle the declaration. - return None - return method() - return self._GetMethod(temp_tokens, 0, None, False) - elif token.token_type == tokenize.SYNTAX: - if token.name == '~' and self.in_class: - # Must be a dtor (probably not in method body). - token = self._GetNextToken() - # self.in_class can contain A::Name, but the dtor will only - # be Name. Make sure to compare against the right value. - if (token.token_type == tokenize.NAME and - token.name == self.in_class_name_only): - return self._GetMethod([token], FUNCTION_DTOR, None, True) - # TODO(nnorwitz): handle a lot more syntax. - elif token.token_type == tokenize.PREPROCESSOR: - # TODO(nnorwitz): handle more preprocessor directives. - # token starts with a #, so remove it and strip whitespace. - name = token.name[1:].lstrip() - if name.startswith('include'): - # Remove "include". - name = name[7:].strip() - assert name - # Handle #include \<newline> "header-on-second-line.h". - if name.startswith('\\'): - name = name[1:].strip() - assert name[0] in '<"', token - assert name[-1] in '>"', token - system = name[0] == '<' - filename = name[1:-1] - return Include(token.start, token.end, filename, system) - if name.startswith('define'): - # Remove "define". - name = name[6:].strip() - assert name - value = '' - for i, c in enumerate(name): - if c.isspace(): - value = name[i:].lstrip() - name = name[:i] - break - return Define(token.start, token.end, name, value) - if name.startswith('if') and name[2:3].isspace(): - condition = name[3:].strip() - if condition.startswith('0') or condition.startswith('(0)'): - self._SkipIf0Blocks() - return None - - def _GetTokensUpTo(self, expected_token_type, expected_token): - return self._GetVarTokensUpTo(expected_token_type, expected_token)[0] - - def _GetVarTokensUpTo(self, expected_token_type, *expected_tokens): - last_token = self._GetNextToken() - tokens = [] - while (last_token.token_type != expected_token_type or - last_token.name not in expected_tokens): - tokens.append(last_token) - last_token = self._GetNextToken() - return tokens, last_token - - # TODO(nnorwitz): remove _IgnoreUpTo() it shouldn't be necessary. - def _IgnoreUpTo(self, token_type, token): - unused_tokens = self._GetTokensUpTo(token_type, token) - - def _SkipIf0Blocks(self): - count = 1 - while 1: - token = self._GetNextToken() - if token.token_type != tokenize.PREPROCESSOR: - continue - - name = token.name[1:].lstrip() - if name.startswith('endif'): - count -= 1 - if count == 0: - break - elif name.startswith('if'): - count += 1 - - def _GetMatchingChar(self, open_paren, close_paren, GetNextToken=None): - if GetNextToken is None: - GetNextToken = self._GetNextToken - # Assumes the current token is open_paren and we will consume - # and return up to the close_paren. - count = 1 - token = GetNextToken() - while 1: - if token.token_type == tokenize.SYNTAX: - if token.name == open_paren: - count += 1 - elif token.name == close_paren: - count -= 1 - if count == 0: - break - yield token - token = GetNextToken() - yield token - - def _GetParameters(self): - return self._GetMatchingChar('(', ')') - - def GetScope(self): - return self._GetMatchingChar('{', '}') - - def _GetNextToken(self): - if self.token_queue: - return self.token_queue.pop() - return next(self.tokens) - - def _AddBackToken(self, token): - if token.whence == tokenize.WHENCE_STREAM: - token.whence = tokenize.WHENCE_QUEUE - self.token_queue.insert(0, token) + def __init__(self, token_stream, filename, in_class='', visibility=None, + namespace_stack=[]): + self.tokens = token_stream + self.filename = filename + # TODO(nnorwitz): use a better data structure (deque) for the queue. + # Switching directions of the "queue" improved perf by about 25%. + # Using a deque should be even better since we access from both sides. + self.token_queue = [] + self.namespace_stack = namespace_stack[:] + self.in_class = in_class + if in_class is None: + self.in_class_name_only = None + else: + self.in_class_name_only = in_class.split('::')[-1] + self.visibility = visibility + self.in_function = False + self.current_token = None + # Keep the state whether we are currently handling a typedef or not. + self._handling_typedef = False + + self.converter = TypeConverter(self.namespace_stack) + + def HandleError(self, msg, token): + printable_queue = list(reversed(self.token_queue[-20:])) + sys.stderr.write('Got %s in %s @ %s %s\n' % + (msg, self.filename, token, printable_queue)) + + def Generate(self): + while 1: + token = self._GetNextToken() + if not token: + break + + # Get the next token. + self.current_token = token + + # Dispatch on the next token type. + if token.token_type == _INTERNAL_TOKEN: + if token.name == _NAMESPACE_POP: + self.namespace_stack.pop() + continue + + try: + result = self._GenerateOne(token) + if result is not None: + yield result + except: + self.HandleError('exception', token) + raise + + def _CreateVariable(self, pos_token, name, type_name, type_modifiers, + ref_pointer_name_seq, templated_types, value=None): + reference = '&' in ref_pointer_name_seq + pointer = '*' in ref_pointer_name_seq + array = '[' in ref_pointer_name_seq + var_type = Type(pos_token.start, pos_token.end, type_name, + templated_types, type_modifiers, + reference, pointer, array) + return VariableDeclaration(pos_token.start, pos_token.end, + name, var_type, value, self.namespace_stack) + + def _GenerateOne(self, token): + if token.token_type == tokenize.NAME: + if (keywords.IsKeyword(token.name) and + not keywords.IsBuiltinType(token.name)): + if token.name == 'enum': + # Pop the next token and only put it back if it's not + # 'class'. This allows us to support the two-token + # 'enum class' keyword as if it were simply 'enum'. + next = self._GetNextToken() + if next.name != 'class': + self._AddBackToken(next) + + method = getattr(self, 'handle_' + token.name) + return method() + elif token.name == self.in_class_name_only: + # The token name is the same as the class, must be a ctor if + # there is a paren. Otherwise, it's the return type. + # Peek ahead to get the next token to figure out which. + next = self._GetNextToken() + self._AddBackToken(next) + if next.token_type == tokenize.SYNTAX and next.name == '(': + return self._GetMethod([token], FUNCTION_CTOR, None, True) + # Fall through--handle like any other method. + + # Handle data or function declaration/definition. + syntax = tokenize.SYNTAX + temp_tokens, last_token = \ + self._GetVarTokensUpToIgnoringTemplates(syntax, + '(', ';', '{', '[') + temp_tokens.insert(0, token) + if last_token.name == '(': + # If there is an assignment before the paren, + # this is an expression, not a method. + expr = bool([e for e in temp_tokens if e.name == '=']) + if expr: + new_temp = self._GetTokensUpTo(tokenize.SYNTAX, ';') + temp_tokens.append(last_token) + temp_tokens.extend(new_temp) + last_token = tokenize.Token(tokenize.SYNTAX, ';', 0, 0) + + if last_token.name == '[': + # Handle array, this isn't a method, unless it's an operator. + # TODO(nnorwitz): keep the size somewhere. + # unused_size = self._GetTokensUpTo(tokenize.SYNTAX, ']') + temp_tokens.append(last_token) + if temp_tokens[-2].name == 'operator': + temp_tokens.append(self._GetNextToken()) else: - assert token.whence == tokenize.WHENCE_QUEUE, token - self.token_queue.append(token) - - def _AddBackTokens(self, tokens): - if tokens: - if tokens[-1].whence == tokenize.WHENCE_STREAM: - for token in tokens: - token.whence = tokenize.WHENCE_QUEUE - self.token_queue[:0] = reversed(tokens) - else: - assert tokens[-1].whence == tokenize.WHENCE_QUEUE, tokens - self.token_queue.extend(reversed(tokens)) - - def GetName(self, seq=None): - """Returns ([tokens], next_token_info).""" - GetNextToken = self._GetNextToken - if seq is not None: - it = iter(seq) - GetNextToken = lambda: next(it) - next_token = GetNextToken() - tokens = [] - last_token_was_name = False - while (next_token.token_type == tokenize.NAME or - (next_token.token_type == tokenize.SYNTAX and - next_token.name in ('::', '<'))): - # Two NAMEs in a row means the identifier should terminate. - # It's probably some sort of variable declaration. - if last_token_was_name and next_token.token_type == tokenize.NAME: - break - last_token_was_name = next_token.token_type == tokenize.NAME - tokens.append(next_token) - # Handle templated names. - if next_token.name == '<': - tokens.extend(self._GetMatchingChar('<', '>', GetNextToken)) - last_token_was_name = True - next_token = GetNextToken() - return tokens, next_token - - def GetMethod(self, modifiers, templated_types): - return_type_and_name = self._GetTokensUpTo(tokenize.SYNTAX, '(') - assert len(return_type_and_name) >= 1 - return self._GetMethod(return_type_and_name, modifiers, templated_types, - False) - - def _GetMethod(self, return_type_and_name, modifiers, templated_types, - get_paren): - template_portion = None - if get_paren: - token = self._GetNextToken() - assert token.token_type == tokenize.SYNTAX, token - if token.name == '<': - # Handle templatized dtors. - template_portion = [token] - template_portion.extend(self._GetMatchingChar('<', '>')) - token = self._GetNextToken() - assert token.token_type == tokenize.SYNTAX, token - assert token.name == '(', token - - name = return_type_and_name.pop() - # Handle templatized ctors. - if name.name == '>': - index = 1 - while return_type_and_name[index].name != '<': - index += 1 - template_portion = return_type_and_name[index:] + [name] - del return_type_and_name[index:] - name = return_type_and_name.pop() - elif name.name == ']': - rt = return_type_and_name - assert rt[-1].name == '[', return_type_and_name - assert rt[-2].name == 'operator', return_type_and_name - name_seq = return_type_and_name[-2:] - del return_type_and_name[-2:] - name = tokenize.Token(tokenize.NAME, 'operator[]', - name_seq[0].start, name.end) - # Get the open paren so _GetParameters() below works. - unused_open_paren = self._GetNextToken() - - # TODO(nnorwitz): store template_portion. - return_type = return_type_and_name - indices = name - if return_type: - indices = return_type[0] - - # Force ctor for templatized ctors. - if name.name == self.in_class and not modifiers: - modifiers |= FUNCTION_CTOR - parameters = list(self._GetParameters()) - del parameters[-1] # Remove trailing ')'. - - # Handling operator() is especially weird. - if name.name == 'operator' and not parameters: - token = self._GetNextToken() - assert token.name == '(', token - parameters = list(self._GetParameters()) - del parameters[-1] # Remove trailing ')'. - + temp_tokens2, last_token = \ + self._GetVarTokensUpTo(tokenize.SYNTAX, ';') + temp_tokens.extend(temp_tokens2) + + if last_token.name == ';': + # Handle data, this isn't a method. + parts = self.converter.DeclarationToParts(temp_tokens, True) + (name, type_name, templated_types, modifiers, default, + unused_other_tokens) = parts + + t0 = temp_tokens[0] + names = [t.name for t in temp_tokens] + if templated_types: + start, end = self.converter.GetTemplateIndices(names) + names = names[:start] + names[end:] + default = ''.join([t.name for t in default]) + return self._CreateVariable(t0, name, type_name, modifiers, + names, templated_types, default) + if last_token.name == '{': + self._AddBackTokens(temp_tokens[1:]) + self._AddBackToken(last_token) + method_name = temp_tokens[0].name + method = getattr(self, 'handle_' + method_name, None) + if not method: + # Must be declaring a variable. + # TODO(nnorwitz): handle the declaration. + return None + return method() + return self._GetMethod(temp_tokens, 0, None, False) + elif token.token_type == tokenize.SYNTAX: + if token.name == '~' and self.in_class: + # Must be a dtor (probably not in method body). + token = self._GetNextToken() + # self.in_class can contain A::Name, but the dtor will only + # be Name. Make sure to compare against the right value. + if (token.token_type == tokenize.NAME and + token.name == self.in_class_name_only): + return self._GetMethod([token], FUNCTION_DTOR, None, True) + # TODO(nnorwitz): handle a lot more syntax. + elif token.token_type == tokenize.PREPROCESSOR: + # TODO(nnorwitz): handle more preprocessor directives. + # token starts with a #, so remove it and strip whitespace. + name = token.name[1:].lstrip() + if name.startswith('include'): + # Remove "include". + name = name[7:].strip() + assert name + # Handle #include \<newline> "header-on-second-line.h". + if name.startswith('\\'): + name = name[1:].strip() + assert name[0] in '<"', token + assert name[-1] in '>"', token + system = name[0] == '<' + filename = name[1:-1] + return Include(token.start, token.end, filename, system) + if name.startswith('define'): + # Remove "define". + name = name[6:].strip() + assert name + value = '' + for i, c in enumerate(name): + if c.isspace(): + value = name[i:].lstrip() + name = name[:i] + break + return Define(token.start, token.end, name, value) + if name.startswith('if') and name[2:3].isspace(): + condition = name[3:].strip() + if condition.startswith('0') or condition.startswith('(0)'): + self._SkipIf0Blocks() + return None + + def _GetTokensUpTo(self, expected_token_type, expected_token): + return self._GetVarTokensUpTo(expected_token_type, expected_token)[0] + + def _GetVarTokensUpTo(self, expected_token_type, *expected_tokens): + last_token = self._GetNextToken() + tokens = [] + while (last_token.token_type != expected_token_type or + last_token.name not in expected_tokens): + tokens.append(last_token) + last_token = self._GetNextToken() + return tokens, last_token + + # Same as _GetVarTokensUpTo, but skips over '<...>' which could contain an + # expected token. + def _GetVarTokensUpToIgnoringTemplates(self, expected_token_type, + *expected_tokens): + last_token = self._GetNextToken() + tokens = [] + nesting = 0 + while (nesting > 0 or + last_token.token_type != expected_token_type or + last_token.name not in expected_tokens): + tokens.append(last_token) + last_token = self._GetNextToken() + if last_token.name == '<': + nesting += 1 + elif last_token.name == '>': + nesting -= 1 + return tokens, last_token + + # TODO(nnorwitz): remove _IgnoreUpTo() it shouldn't be necesary. + def _IgnoreUpTo(self, token_type, token): + unused_tokens = self._GetTokensUpTo(token_type, token) + + def _SkipIf0Blocks(self): + count = 1 + while 1: + token = self._GetNextToken() + if token.token_type != tokenize.PREPROCESSOR: + continue + + name = token.name[1:].lstrip() + if name.startswith('endif'): + count -= 1 + if count == 0: + break + elif name.startswith('if'): + count += 1 + + def _GetMatchingChar(self, open_paren, close_paren, GetNextToken=None): + if GetNextToken is None: + GetNextToken = self._GetNextToken + # Assumes the current token is open_paren and we will consume + # and return up to the close_paren. + count = 1 + token = GetNextToken() + while 1: + if token.token_type == tokenize.SYNTAX: + if token.name == open_paren: + count += 1 + elif token.name == close_paren: + count -= 1 + if count == 0: + break + yield token + token = GetNextToken() + yield token + + def _GetParameters(self): + return self._GetMatchingChar('(', ')') + + def GetScope(self): + return self._GetMatchingChar('{', '}') + + def _GetNextToken(self): + if self.token_queue: + return self.token_queue.pop() + try: + return next(self.tokens) + except StopIteration: + return + + def _AddBackToken(self, token): + if token.whence == tokenize.WHENCE_STREAM: + token.whence = tokenize.WHENCE_QUEUE + self.token_queue.insert(0, token) + else: + assert token.whence == tokenize.WHENCE_QUEUE, token + self.token_queue.append(token) + + def _AddBackTokens(self, tokens): + if tokens: + if tokens[-1].whence == tokenize.WHENCE_STREAM: + for token in tokens: + token.whence = tokenize.WHENCE_QUEUE + self.token_queue[:0] = reversed(tokens) + else: + assert tokens[-1].whence == tokenize.WHENCE_QUEUE, tokens + self.token_queue.extend(reversed(tokens)) + + def GetName(self, seq=None): + """Returns ([tokens], next_token_info).""" + GetNextToken = self._GetNextToken + if seq is not None: + it = iter(seq) + GetNextToken = lambda: next(it) + next_token = GetNextToken() + tokens = [] + last_token_was_name = False + while (next_token.token_type == tokenize.NAME or + (next_token.token_type == tokenize.SYNTAX and + next_token.name in ('::', '<'))): + # Two NAMEs in a row means the identifier should terminate. + # It's probably some sort of variable declaration. + if last_token_was_name and next_token.token_type == tokenize.NAME: + break + last_token_was_name = next_token.token_type == tokenize.NAME + tokens.append(next_token) + # Handle templated names. + if next_token.name == '<': + tokens.extend(self._GetMatchingChar('<', '>', GetNextToken)) + last_token_was_name = True + next_token = GetNextToken() + return tokens, next_token + + def GetMethod(self, modifiers, templated_types): + return_type_and_name = self._GetTokensUpTo(tokenize.SYNTAX, '(') + assert len(return_type_and_name) >= 1 + return self._GetMethod(return_type_and_name, modifiers, templated_types, + False) + + def _GetMethod(self, return_type_and_name, modifiers, templated_types, + get_paren): + template_portion = None + if get_paren: + token = self._GetNextToken() + assert token.token_type == tokenize.SYNTAX, token + if token.name == '<': + # Handle templatized dtors. + template_portion = [token] + template_portion.extend(self._GetMatchingChar('<', '>')) + token = self._GetNextToken() + assert token.token_type == tokenize.SYNTAX, token + assert token.name == '(', token + + name = return_type_and_name.pop() + # Handle templatized ctors. + if name.name == '>': + index = 1 + while return_type_and_name[index].name != '<': + index += 1 + template_portion = return_type_and_name[index:] + [name] + del return_type_and_name[index:] + name = return_type_and_name.pop() + elif name.name == ']': + rt = return_type_and_name + assert rt[-1].name == '[', return_type_and_name + assert rt[-2].name == 'operator', return_type_and_name + name_seq = return_type_and_name[-2:] + del return_type_and_name[-2:] + name = tokenize.Token(tokenize.NAME, 'operator[]', + name_seq[0].start, name.end) + # Get the open paren so _GetParameters() below works. + unused_open_paren = self._GetNextToken() + + # TODO(nnorwitz): store template_portion. + return_type = return_type_and_name + indices = name + if return_type: + indices = return_type[0] + + # Force ctor for templatized ctors. + if name.name == self.in_class and not modifiers: + modifiers |= FUNCTION_CTOR + parameters = list(self._GetParameters()) + del parameters[-1] # Remove trailing ')'. + + # Handling operator() is especially weird. + if name.name == 'operator' and not parameters: + token = self._GetNextToken() + assert token.name == '(', token + parameters = list(self._GetParameters()) + del parameters[-1] # Remove trailing ')'. + + token = self._GetNextToken() + while token.token_type == tokenize.NAME: + modifier_token = token + token = self._GetNextToken() + if modifier_token.name == 'const': + modifiers |= FUNCTION_CONST + elif modifier_token.name == '__attribute__': + # TODO(nnorwitz): handle more __attribute__ details. + modifiers |= FUNCTION_ATTRIBUTE + assert token.name == '(', token + # Consume everything between the (parens). + unused_tokens = list(self._GetMatchingChar('(', ')')) + token = self._GetNextToken() + elif modifier_token.name == 'throw': + modifiers |= FUNCTION_THROW + assert token.name == '(', token + # Consume everything between the (parens). + unused_tokens = list(self._GetMatchingChar('(', ')')) + token = self._GetNextToken() + elif modifier_token.name == 'override': + modifiers |= FUNCTION_OVERRIDE + elif modifier_token.name == modifier_token.name.upper(): + # HACK(nnorwitz): assume that all upper-case names + # are some macro we aren't expanding. + modifiers |= FUNCTION_UNKNOWN_ANNOTATION + else: + self.HandleError('unexpected token', modifier_token) + + assert token.token_type == tokenize.SYNTAX, token + # Handle ctor initializers. + if token.name == ':': + # TODO(nnorwitz): anything else to handle for initializer list? + while token.name != ';' and token.name != '{': token = self._GetNextToken() - while token.token_type == tokenize.NAME: - modifier_token = token - token = self._GetNextToken() - if modifier_token.name == 'const': - modifiers |= FUNCTION_CONST - elif modifier_token.name == '__attribute__': - # TODO(nnorwitz): handle more __attribute__ details. - modifiers |= FUNCTION_ATTRIBUTE - assert token.name == '(', token - # Consume everything between the (parens). - unused_tokens = list(self._GetMatchingChar('(', ')')) - token = self._GetNextToken() - elif modifier_token.name == 'throw': - modifiers |= FUNCTION_THROW - assert token.name == '(', token - # Consume everything between the (parens). - unused_tokens = list(self._GetMatchingChar('(', ')')) - token = self._GetNextToken() - elif modifier_token.name == 'override': - modifiers |= FUNCTION_OVERRIDE - elif modifier_token.name == modifier_token.name.upper(): - # HACK(nnorwitz): assume that all upper-case names - # are some macro we aren't expanding. - modifiers |= FUNCTION_UNKNOWN_ANNOTATION - else: - self.HandleError('unexpected token', modifier_token) + # Handle pointer to functions that are really data but look + # like method declarations. + if token.name == '(': + if parameters[0].name == '*': + # name contains the return type. + name = parameters.pop() + # parameters contains the name of the data. + modifiers = [p.name for p in parameters] + # Already at the ( to open the parameter list. + function_parameters = list(self._GetMatchingChar('(', ')')) + del function_parameters[-1] # Remove trailing ')'. + # TODO(nnorwitz): store the function_parameters. + token = self._GetNextToken() assert token.token_type == tokenize.SYNTAX, token - # Handle ctor initializers. - if token.name == ':': - # TODO(nnorwitz): anything else to handle for initializer list? - while token.name != ';' and token.name != '{': - token = self._GetNextToken() - - # Handle pointer to functions that are really data but look - # like method declarations. - if token.name == '(': - if parameters[0].name == '*': - # name contains the return type. - name = parameters.pop() - # parameters contains the name of the data. - modifiers = [p.name for p in parameters] - # Already at the ( to open the parameter list. - function_parameters = list(self._GetMatchingChar('(', ')')) - del function_parameters[-1] # Remove trailing ')'. - # TODO(nnorwitz): store the function_parameters. - token = self._GetNextToken() - assert token.token_type == tokenize.SYNTAX, token - assert token.name == ';', token - return self._CreateVariable(indices, name.name, indices.name, - modifiers, '', None) - # At this point, we got something like: - # return_type (type::*name_)(params); - # This is a data member called name_ that is a function pointer. - # With this code: void (sq_type::*field_)(string&); - # We get: name=void return_type=[] parameters=sq_type ... field_ - # TODO(nnorwitz): is return_type always empty? - # TODO(nnorwitz): this isn't even close to being correct. - # Just put in something so we don't crash and can move on. - real_name = parameters[-1] - modifiers = [p.name for p in self._GetParameters()] - del modifiers[-1] # Remove trailing ')'. - return self._CreateVariable(indices, real_name.name, indices.name, - modifiers, '', None) - - if token.name == '{': - body = list(self.GetScope()) - del body[-1] # Remove trailing '}'. - else: - body = None - if token.name == '=': - token = self._GetNextToken() - - if token.name == 'default' or token.name == 'delete': - # Ignore explicitly defaulted and deleted special members - # in C++11. - token = self._GetNextToken() - else: - # Handle pure-virtual declarations. - assert token.token_type == tokenize.CONSTANT, token - assert token.name == '0', token - modifiers |= FUNCTION_PURE_VIRTUAL - token = self._GetNextToken() - - if token.name == '[': - # TODO(nnorwitz): store tokens and improve parsing. - # template <typename T, size_t N> char (&ASH(T (&seq)[N]))[N]; - tokens = list(self._GetMatchingChar('[', ']')) - token = self._GetNextToken() - - assert token.name == ';', (token, return_type_and_name, parameters) - - # Looks like we got a method, not a function. - if len(return_type) > 2 and return_type[-1].name == '::': - return_type, in_class = \ - self._GetReturnTypeAndClassName(return_type) - return Method(indices.start, indices.end, name.name, in_class, - return_type, parameters, modifiers, templated_types, - body, self.namespace_stack) - return Function(indices.start, indices.end, name.name, return_type, - parameters, modifiers, templated_types, body, - self.namespace_stack) - - def _GetReturnTypeAndClassName(self, token_seq): - # Splitting the return type from the class name in a method - # can be tricky. For example, Return::Type::Is::Hard::To::Find(). - # Where is the return type and where is the class name? - # The heuristic used is to pull the last name as the class name. - # This includes all the templated type info. - # TODO(nnorwitz): if there is only One name like in the - # example above, punt and assume the last bit is the class name. - - # Ignore a :: prefix, if exists so we can find the first real name. - i = 0 - if token_seq[0].name == '::': - i = 1 - # Ignore a :: suffix, if exists. - end = len(token_seq) - 1 - if token_seq[end-1].name == '::': - end -= 1 - - # Make a copy of the sequence so we can append a sentinel - # value. This is required for GetName will has to have some - # terminating condition beyond the last name. - seq_copy = token_seq[i:end] - seq_copy.append(tokenize.Token(tokenize.SYNTAX, '', 0, 0)) - names = [] - while i < end: - # Iterate through the sequence parsing out each name. - new_name, next = self.GetName(seq_copy[i:]) - assert new_name, 'Got empty new_name, next=%s' % next - # We got a pointer or ref. Add it to the name. - if next and next.token_type == tokenize.SYNTAX: - new_name.append(next) - names.append(new_name) - i += len(new_name) - - # Now that we have the names, it's time to undo what we did. - - # Remove the sentinel value. - names[-1].pop() - # Flatten the token sequence for the return type. - return_type = [e for seq in names[:-1] for e in seq] - # The class name is the last name. - class_name = names[-1] - return return_type, class_name - - def handle_bool(self): - pass - - def handle_char(self): - pass + assert token.name == ';', token + return self._CreateVariable(indices, name.name, indices.name, + modifiers, '', None) + # At this point, we got something like: + # return_type (type::*name_)(params); + # This is a data member called name_ that is a function pointer. + # With this code: void (sq_type::*field_)(string&); + # We get: name=void return_type=[] parameters=sq_type ... field_ + # TODO(nnorwitz): is return_type always empty? + # TODO(nnorwitz): this isn't even close to being correct. + # Just put in something so we don't crash and can move on. + real_name = parameters[-1] + modifiers = [p.name for p in self._GetParameters()] + del modifiers[-1] # Remove trailing ')'. + return self._CreateVariable(indices, real_name.name, indices.name, + modifiers, '', None) + + if token.name == '{': + body = list(self.GetScope()) + del body[-1] # Remove trailing '}'. + else: + body = None + if token.name == '=': + token = self._GetNextToken() - def handle_int(self): - pass + if token.name == 'default' or token.name == 'delete': + # Ignore explicitly defaulted and deleted special members + # in C++11. + token = self._GetNextToken() + else: + # Handle pure-virtual declarations. + assert token.token_type == tokenize.CONSTANT, token + assert token.name == '0', token + modifiers |= FUNCTION_PURE_VIRTUAL + token = self._GetNextToken() + + if token.name == '[': + # TODO(nnorwitz): store tokens and improve parsing. + # template <typename T, size_t N> char (&ASH(T (&seq)[N]))[N]; + tokens = list(self._GetMatchingChar('[', ']')) + token = self._GetNextToken() - def handle_long(self): - pass + assert token.name == ';', (token, return_type_and_name, parameters) + + # Looks like we got a method, not a function. + if len(return_type) > 2 and return_type[-1].name == '::': + return_type, in_class = \ + self._GetReturnTypeAndClassName(return_type) + return Method(indices.start, indices.end, name.name, in_class, + return_type, parameters, modifiers, templated_types, + body, self.namespace_stack) + return Function(indices.start, indices.end, name.name, return_type, + parameters, modifiers, templated_types, body, + self.namespace_stack) + + def _GetReturnTypeAndClassName(self, token_seq): + # Splitting the return type from the class name in a method + # can be tricky. For example, Return::Type::Is::Hard::To::Find(). + # Where is the return type and where is the class name? + # The heuristic used is to pull the last name as the class name. + # This includes all the templated type info. + # TODO(nnorwitz): if there is only One name like in the + # example above, punt and assume the last bit is the class name. + + # Ignore a :: prefix, if exists so we can find the first real name. + i = 0 + if token_seq[0].name == '::': + i = 1 + # Ignore a :: suffix, if exists. + end = len(token_seq) - 1 + if token_seq[end-1].name == '::': + end -= 1 + + # Make a copy of the sequence so we can append a sentinel + # value. This is required for GetName will has to have some + # terminating condition beyond the last name. + seq_copy = token_seq[i:end] + seq_copy.append(tokenize.Token(tokenize.SYNTAX, '', 0, 0)) + names = [] + while i < end: + # Iterate through the sequence parsing out each name. + new_name, next = self.GetName(seq_copy[i:]) + assert new_name, 'Got empty new_name, next=%s' % next + # We got a pointer or ref. Add it to the name. + if next and next.token_type == tokenize.SYNTAX: + new_name.append(next) + names.append(new_name) + i += len(new_name) + + # Now that we have the names, it's time to undo what we did. + + # Remove the sentinel value. + names[-1].pop() + # Flatten the token sequence for the return type. + return_type = [e for seq in names[:-1] for e in seq] + # The class name is the last name. + class_name = names[-1] + return return_type, class_name + + def handle_bool(self): + pass - def handle_short(self): - pass + def handle_char(self): + pass - def handle_double(self): - pass + def handle_int(self): + pass - def handle_float(self): - pass + def handle_long(self): + pass - def handle_void(self): - pass + def handle_short(self): + pass - def handle_wchar_t(self): - pass + def handle_double(self): + pass - def handle_unsigned(self): - pass + def handle_float(self): + pass - def handle_signed(self): - pass + def handle_void(self): + pass - def _GetNestedType(self, ctor): - name = None - name_tokens, token = self.GetName() - if name_tokens: - name = ''.join([t.name for t in name_tokens]) - - # Handle forward declarations. - if token.token_type == tokenize.SYNTAX and token.name == ';': - return ctor(token.start, token.end, name, None, - self.namespace_stack) - - if token.token_type == tokenize.NAME and self._handling_typedef: - self._AddBackToken(token) - return ctor(token.start, token.end, name, None, - self.namespace_stack) - - # Must be the type declaration. - fields = list(self._GetMatchingChar('{', '}')) - del fields[-1] # Remove trailing '}'. - if token.token_type == tokenize.SYNTAX and token.name == '{': - next = self._GetNextToken() - new_type = ctor(token.start, token.end, name, fields, - self.namespace_stack) - # A name means this is an anonymous type and the name - # is the variable declaration. - if next.token_type != tokenize.NAME: - return new_type - name = new_type - token = next - - # Must be variable declaration using the type prefixed with keyword. - assert token.token_type == tokenize.NAME, token - return self._CreateVariable(token, token.name, name, [], '', None) - - def handle_struct(self): - # Special case the handling typedef/aliasing of structs here. - # It would be a pain to handle in the class code. - name_tokens, var_token = self.GetName() - if name_tokens: - next_token = self._GetNextToken() - is_syntax = (var_token.token_type == tokenize.SYNTAX and - var_token.name[0] in '*&') - is_variable = (var_token.token_type == tokenize.NAME and - next_token.name == ';') - variable = var_token - if is_syntax and not is_variable: - variable = next_token - temp = self._GetNextToken() - if temp.token_type == tokenize.SYNTAX and temp.name == '(': - # Handle methods declared to return a struct. - t0 = name_tokens[0] - struct = tokenize.Token(tokenize.NAME, 'struct', - t0.start-7, t0.start-2) - type_and_name = [struct] - type_and_name.extend(name_tokens) - type_and_name.extend((var_token, next_token)) - return self._GetMethod(type_and_name, 0, None, False) - assert temp.name == ';', (temp, name_tokens, var_token) - if is_syntax or (is_variable and not self._handling_typedef): - modifiers = ['struct'] - type_name = ''.join([t.name for t in name_tokens]) - position = name_tokens[0] - return self._CreateVariable(position, variable.name, type_name, - modifiers, var_token.name, None) - name_tokens.extend((var_token, next_token)) - self._AddBackTokens(name_tokens) - else: - self._AddBackToken(var_token) - return self._GetClass(Struct, VISIBILITY_PUBLIC, None) + def handle_wchar_t(self): + pass - def handle_union(self): - return self._GetNestedType(Union) + def handle_unsigned(self): + pass - def handle_enum(self): - token = self._GetNextToken() - if not (token.token_type == tokenize.NAME and token.name == 'class'): - self._AddBackToken(token) - return self._GetNestedType(Enum) + def handle_signed(self): + pass - def handle_auto(self): - # TODO(nnorwitz): warn about using auto? Probably not since it - # will be reclaimed and useful for C++0x. - pass + def _GetNestedType(self, ctor): + name = None + name_tokens, token = self.GetName() + if name_tokens: + name = ''.join([t.name for t in name_tokens]) + + # Handle forward declarations. + if token.token_type == tokenize.SYNTAX and token.name == ';': + return ctor(token.start, token.end, name, None, + self.namespace_stack) + + if token.token_type == tokenize.NAME and self._handling_typedef: + self._AddBackToken(token) + return ctor(token.start, token.end, name, None, + self.namespace_stack) + + # Must be the type declaration. + fields = list(self._GetMatchingChar('{', '}')) + del fields[-1] # Remove trailing '}'. + if token.token_type == tokenize.SYNTAX and token.name == '{': + next = self._GetNextToken() + new_type = ctor(token.start, token.end, name, fields, + self.namespace_stack) + # A name means this is an anonymous type and the name + # is the variable declaration. + if next.token_type != tokenize.NAME: + return new_type + name = new_type + token = next + + # Must be variable declaration using the type prefixed with keyword. + assert token.token_type == tokenize.NAME, token + return self._CreateVariable(token, token.name, name, [], '', None) + + def handle_struct(self): + # Special case the handling typedef/aliasing of structs here. + # It would be a pain to handle in the class code. + name_tokens, var_token = self.GetName() + if name_tokens: + next_token = self._GetNextToken() + is_syntax = (var_token.token_type == tokenize.SYNTAX and + var_token.name[0] in '*&') + is_variable = (var_token.token_type == tokenize.NAME and + next_token.name == ';') + variable = var_token + if is_syntax and not is_variable: + variable = next_token + temp = self._GetNextToken() + if temp.token_type == tokenize.SYNTAX and temp.name == '(': + # Handle methods declared to return a struct. + t0 = name_tokens[0] + struct = tokenize.Token(tokenize.NAME, 'struct', + t0.start-7, t0.start-2) + type_and_name = [struct] + type_and_name.extend(name_tokens) + type_and_name.extend((var_token, next_token)) + return self._GetMethod(type_and_name, 0, None, False) + assert temp.name == ';', (temp, name_tokens, var_token) + if is_syntax or (is_variable and not self._handling_typedef): + modifiers = ['struct'] + type_name = ''.join([t.name for t in name_tokens]) + position = name_tokens[0] + return self._CreateVariable(position, variable.name, type_name, + modifiers, var_token.name, None) + name_tokens.extend((var_token, next_token)) + self._AddBackTokens(name_tokens) + else: + self._AddBackToken(var_token) + return self._GetClass(Struct, VISIBILITY_PUBLIC, None) + + def handle_union(self): + return self._GetNestedType(Union) + + def handle_enum(self): + return self._GetNestedType(Enum) + + def handle_auto(self): + # TODO(nnorwitz): warn about using auto? Probably not since it + # will be reclaimed and useful for C++0x. + pass - def handle_register(self): - pass + def handle_register(self): + pass - def handle_const(self): - pass + def handle_const(self): + pass - def handle_inline(self): - pass + def handle_inline(self): + pass - def handle_extern(self): - pass + def handle_extern(self): + pass - def handle_static(self): - pass + def handle_static(self): + pass - def handle_virtual(self): - # What follows must be a method. - token = token2 = self._GetNextToken() - if token.name == 'inline': - # HACK(nnorwitz): handle inline dtors by ignoring 'inline'. - token2 = self._GetNextToken() - if token2.token_type == tokenize.SYNTAX and token2.name == '~': - return self.GetMethod(FUNCTION_VIRTUAL + FUNCTION_DTOR, None) - assert token.token_type == tokenize.NAME or token.name == '::', token - return_type_and_name = self._GetTokensUpTo(tokenize.SYNTAX, '(') # ) - return_type_and_name.insert(0, token) - if token2 is not token: - return_type_and_name.insert(1, token2) - return self._GetMethod(return_type_and_name, FUNCTION_VIRTUAL, - None, False) - - def handle_volatile(self): - pass + def handle_virtual(self): + # What follows must be a method. + token = token2 = self._GetNextToken() + if token.name == 'inline': + # HACK(nnorwitz): handle inline dtors by ignoring 'inline'. + token2 = self._GetNextToken() + if token2.token_type == tokenize.SYNTAX and token2.name == '~': + return self.GetMethod(FUNCTION_VIRTUAL + FUNCTION_DTOR, None) + assert token.token_type == tokenize.NAME or token.name == '::', token + return_type_and_name, _ = self._GetVarTokensUpToIgnoringTemplates( + tokenize.SYNTAX, '(') # ) + return_type_and_name.insert(0, token) + if token2 is not token: + return_type_and_name.insert(1, token2) + return self._GetMethod(return_type_and_name, FUNCTION_VIRTUAL, + None, False) + + def handle_volatile(self): + pass - def handle_mutable(self): - pass + def handle_mutable(self): + pass - def handle_public(self): - assert self.in_class - self.visibility = VISIBILITY_PUBLIC + def handle_public(self): + assert self.in_class + self.visibility = VISIBILITY_PUBLIC - def handle_protected(self): - assert self.in_class - self.visibility = VISIBILITY_PROTECTED + def handle_protected(self): + assert self.in_class + self.visibility = VISIBILITY_PROTECTED - def handle_private(self): - assert self.in_class - self.visibility = VISIBILITY_PRIVATE + def handle_private(self): + assert self.in_class + self.visibility = VISIBILITY_PRIVATE - def handle_friend(self): - tokens = self._GetTokensUpTo(tokenize.SYNTAX, ';') - assert tokens - t0 = tokens[0] - return Friend(t0.start, t0.end, tokens, self.namespace_stack) + def handle_friend(self): + tokens = self._GetTokensUpTo(tokenize.SYNTAX, ';') + assert tokens + t0 = tokens[0] + return Friend(t0.start, t0.end, tokens, self.namespace_stack) - def handle_static_cast(self): - pass + def handle_static_cast(self): + pass - def handle_const_cast(self): - pass + def handle_const_cast(self): + pass - def handle_dynamic_cast(self): - pass + def handle_dynamic_cast(self): + pass - def handle_reinterpret_cast(self): - pass + def handle_reinterpret_cast(self): + pass - def handle_new(self): - pass + def handle_new(self): + pass - def handle_delete(self): - tokens = self._GetTokensUpTo(tokenize.SYNTAX, ';') - assert tokens - return Delete(tokens[0].start, tokens[0].end, tokens) + def handle_delete(self): + tokens = self._GetTokensUpTo(tokenize.SYNTAX, ';') + assert tokens + return Delete(tokens[0].start, tokens[0].end, tokens) - def handle_typedef(self): - token = self._GetNextToken() - if (token.token_type == tokenize.NAME and + def handle_typedef(self): + token = self._GetNextToken() + if (token.token_type == tokenize.NAME and keywords.IsKeyword(token.name)): - # Token must be struct/enum/union/class. - method = getattr(self, 'handle_' + token.name) - self._handling_typedef = True - tokens = [method()] - self._handling_typedef = False + # Token must be struct/enum/union/class. + method = getattr(self, 'handle_' + token.name) + self._handling_typedef = True + tokens = [method()] + self._handling_typedef = False + else: + tokens = [token] + + # Get the remainder of the typedef up to the semi-colon. + tokens.extend(self._GetTokensUpTo(tokenize.SYNTAX, ';')) + + # TODO(nnorwitz): clean all this up. + assert tokens + name = tokens.pop() + indices = name + if tokens: + indices = tokens[0] + if not indices: + indices = token + if name.name == ')': + # HACK(nnorwitz): Handle pointers to functions "properly". + if (len(tokens) >= 4 and + tokens[1].name == '(' and tokens[2].name == '*'): + tokens.append(name) + name = tokens[3] + elif name.name == ']': + # HACK(nnorwitz): Handle arrays properly. + if len(tokens) >= 2: + tokens.append(name) + name = tokens[1] + new_type = tokens + if tokens and isinstance(tokens[0], tokenize.Token): + new_type = self.converter.ToType(tokens)[0] + return Typedef(indices.start, indices.end, name.name, + new_type, self.namespace_stack) + + def handle_typeid(self): + pass # Not needed yet. + + def handle_typename(self): + pass # Not needed yet. + + def _GetTemplatedTypes(self): + result = {} + tokens = list(self._GetMatchingChar('<', '>')) + len_tokens = len(tokens) - 1 # Ignore trailing '>'. + i = 0 + while i < len_tokens: + key = tokens[i].name + i += 1 + if keywords.IsKeyword(key) or key == ',': + continue + type_name = default = None + if i < len_tokens: + i += 1 + if tokens[i-1].name == '=': + assert i < len_tokens, '%s %s' % (i, tokens) + default, unused_next_token = self.GetName(tokens[i:]) + i += len(default) else: - tokens = [token] - - # Get the remainder of the typedef up to the semi-colon. - tokens.extend(self._GetTokensUpTo(tokenize.SYNTAX, ';')) - - # TODO(nnorwitz): clean all this up. - assert tokens - name = tokens.pop() - indices = name - if tokens: - indices = tokens[0] - if not indices: - indices = token - if name.name == ')': - # HACK(nnorwitz): Handle pointers to functions "properly". - if (len(tokens) >= 4 and - tokens[1].name == '(' and tokens[2].name == '*'): - tokens.append(name) - name = tokens[3] - elif name.name == ']': - # HACK(nnorwitz): Handle arrays properly. - if len(tokens) >= 2: - tokens.append(name) - name = tokens[1] - new_type = tokens - if tokens and isinstance(tokens[0], tokenize.Token): - new_type = self.converter.ToType(tokens)[0] - return Typedef(indices.start, indices.end, name.name, - new_type, self.namespace_stack) - - def handle_typeid(self): - pass # Not needed yet. - - def handle_typename(self): - pass # Not needed yet. - - def _GetTemplatedTypes(self): - result = {} - tokens = list(self._GetMatchingChar('<', '>')) - len_tokens = len(tokens) - 1 # Ignore trailing '>'. - i = 0 - while i < len_tokens: - key = tokens[i].name - i += 1 - if keywords.IsKeyword(key) or key == ',': - continue - type_name = default = None - if i < len_tokens: - i += 1 - if tokens[i-1].name == '=': - assert i < len_tokens, '%s %s' % (i, tokens) - default, unused_next_token = self.GetName(tokens[i:]) - i += len(default) - else: - if tokens[i-1].name != ',': - # We got something like: Type variable. - # Re-adjust the key (variable) and type_name (Type). - key = tokens[i-1].name - type_name = tokens[i-2] - - result[key] = (type_name, default) - return result - - def handle_template(self): - token = self._GetNextToken() - assert token.token_type == tokenize.SYNTAX, token - assert token.name == '<', token - templated_types = self._GetTemplatedTypes() - # TODO(nnorwitz): for now, just ignore the template params. - token = self._GetNextToken() - if token.token_type == tokenize.NAME: - if token.name == 'class': - return self._GetClass(Class, VISIBILITY_PRIVATE, templated_types) - elif token.name == 'struct': - return self._GetClass(Struct, VISIBILITY_PUBLIC, templated_types) - elif token.name == 'friend': - return self.handle_friend() + if tokens[i-1].name != ',': + # We got something like: Type variable. + # Re-adjust the key (variable) and type_name (Type). + key = tokens[i-1].name + type_name = tokens[i-2] + + result[key] = (type_name, default) + return result + + def handle_template(self): + token = self._GetNextToken() + assert token.token_type == tokenize.SYNTAX, token + assert token.name == '<', token + templated_types = self._GetTemplatedTypes() + # TODO(nnorwitz): for now, just ignore the template params. + token = self._GetNextToken() + if token.token_type == tokenize.NAME: + if token.name == 'class': + return self._GetClass(Class, VISIBILITY_PRIVATE, templated_types) + elif token.name == 'struct': + return self._GetClass(Struct, VISIBILITY_PUBLIC, templated_types) + elif token.name == 'friend': + return self.handle_friend() + self._AddBackToken(token) + tokens, last = self._GetVarTokensUpTo(tokenize.SYNTAX, '(', ';') + tokens.append(last) + self._AddBackTokens(tokens) + if last.name == '(': + return self.GetMethod(FUNCTION_NONE, templated_types) + # Must be a variable definition. + return None + + def handle_true(self): + pass # Nothing to do. + + def handle_false(self): + pass # Nothing to do. + + def handle_asm(self): + pass # Not needed yet. + + def handle_class(self): + return self._GetClass(Class, VISIBILITY_PRIVATE, None) + + def _GetBases(self): + # Get base classes. + bases = [] + while 1: + token = self._GetNextToken() + assert token.token_type == tokenize.NAME, token + # TODO(nnorwitz): store kind of inheritance...maybe. + if token.name not in ('public', 'protected', 'private'): + # If inheritance type is not specified, it is private. + # Just put the token back so we can form a name. + # TODO(nnorwitz): it would be good to warn about this. self._AddBackToken(token) - tokens, last = self._GetVarTokensUpTo(tokenize.SYNTAX, '(', ';') - tokens.append(last) - self._AddBackTokens(tokens) - if last.name == '(': - return self.GetMethod(FUNCTION_NONE, templated_types) - # Must be a variable definition. - return None - - def handle_true(self): - pass # Nothing to do. - - def handle_false(self): - pass # Nothing to do. - - def handle_asm(self): - pass # Not needed yet. - - def handle_class(self): - return self._GetClass(Class, VISIBILITY_PRIVATE, None) - - def _GetBases(self): - # Get base classes. - bases = [] - while 1: - token = self._GetNextToken() - assert token.token_type == tokenize.NAME, token - # TODO(nnorwitz): store kind of inheritance...maybe. - if token.name not in ('public', 'protected', 'private'): - # If inheritance type is not specified, it is private. - # Just put the token back so we can form a name. - # TODO(nnorwitz): it would be good to warn about this. - self._AddBackToken(token) - else: - # Check for virtual inheritance. - token = self._GetNextToken() - if token.name != 'virtual': - self._AddBackToken(token) - else: - # TODO(nnorwitz): store that we got virtual for this base. - pass - base, next_token = self.GetName() - bases_ast = self.converter.ToType(base) - assert len(bases_ast) == 1, bases_ast - bases.append(bases_ast[0]) - assert next_token.token_type == tokenize.SYNTAX, next_token - if next_token.name == '{': - token = next_token - break - # Support multiple inheritance. - assert next_token.name == ',', next_token - return bases, token - - def _GetClass(self, class_type, visibility, templated_types): - class_name = None - class_token = self._GetNextToken() - if class_token.token_type != tokenize.NAME: - assert class_token.token_type == tokenize.SYNTAX, class_token - token = class_token + else: + # Check for virtual inheritance. + token = self._GetNextToken() + if token.name != 'virtual': + self._AddBackToken(token) else: - # Skip any macro (e.g. storage class specifiers) after the - # 'class' keyword. - next_token = self._GetNextToken() - if next_token.token_type == tokenize.NAME: - self._AddBackToken(next_token) - else: - self._AddBackTokens([class_token, next_token]) - name_tokens, token = self.GetName() - class_name = ''.join([t.name for t in name_tokens]) - bases = None - if token.token_type == tokenize.SYNTAX: - if token.name == ';': - # Forward declaration. - return class_type(class_token.start, class_token.end, - class_name, None, templated_types, None, - self.namespace_stack) - if token.name in '*&': - # Inline forward declaration. Could be method or data. - name_token = self._GetNextToken() - next_token = self._GetNextToken() - if next_token.name == ';': - # Handle data - modifiers = ['class'] - return self._CreateVariable(class_token, name_token.name, - class_name, - modifiers, token.name, None) - else: - # Assume this is a method. - tokens = (class_token, token, name_token, next_token) - self._AddBackTokens(tokens) - return self.GetMethod(FUNCTION_NONE, None) - if token.name == ':': - bases, token = self._GetBases() - - body = None - if token.token_type == tokenize.SYNTAX and token.name == '{': - assert token.token_type == tokenize.SYNTAX, token - assert token.name == '{', token - - ast = AstBuilder(self.GetScope(), self.filename, class_name, - visibility, self.namespace_stack) - body = list(ast.Generate()) - - if not self._handling_typedef: - token = self._GetNextToken() - if token.token_type != tokenize.NAME: - assert token.token_type == tokenize.SYNTAX, token - assert token.name == ';', token - else: - new_class = class_type(class_token.start, class_token.end, - class_name, bases, None, - body, self.namespace_stack) - - modifiers = [] - return self._CreateVariable(class_token, - token.name, new_class, - modifiers, token.name, None) + # TODO(nnorwitz): store that we got virtual for this base. + pass + base, next_token = self.GetName() + bases_ast = self.converter.ToType(base) + assert len(bases_ast) == 1, bases_ast + bases.append(bases_ast[0]) + assert next_token.token_type == tokenize.SYNTAX, next_token + if next_token.name == '{': + token = next_token + break + # Support multiple inheritance. + assert next_token.name == ',', next_token + return bases, token + + def _GetClass(self, class_type, visibility, templated_types): + class_name = None + class_token = self._GetNextToken() + if class_token.token_type != tokenize.NAME: + assert class_token.token_type == tokenize.SYNTAX, class_token + token = class_token + else: + # Skip any macro (e.g. storage class specifiers) after the + # 'class' keyword. + next_token = self._GetNextToken() + if next_token.token_type == tokenize.NAME: + self._AddBackToken(next_token) + else: + self._AddBackTokens([class_token, next_token]) + name_tokens, token = self.GetName() + class_name = ''.join([t.name for t in name_tokens]) + bases = None + if token.token_type == tokenize.SYNTAX: + if token.name == ';': + # Forward declaration. + return class_type(class_token.start, class_token.end, + class_name, None, templated_types, None, + self.namespace_stack) + if token.name in '*&': + # Inline forward declaration. Could be method or data. + name_token = self._GetNextToken() + next_token = self._GetNextToken() + if next_token.name == ';': + # Handle data + modifiers = ['class'] + return self._CreateVariable(class_token, name_token.name, + class_name, + modifiers, token.name, None) else: - if not self._handling_typedef: - self.HandleError('non-typedef token', token) - self._AddBackToken(token) - - return class_type(class_token.start, class_token.end, class_name, - bases, templated_types, body, self.namespace_stack) - - def handle_namespace(self): + # Assume this is a method. + tokens = (class_token, token, name_token, next_token) + self._AddBackTokens(tokens) + return self.GetMethod(FUNCTION_NONE, None) + if token.name == ':': + bases, token = self._GetBases() + + body = None + if token.token_type == tokenize.SYNTAX and token.name == '{': + assert token.token_type == tokenize.SYNTAX, token + assert token.name == '{', token + + ast = AstBuilder(self.GetScope(), self.filename, class_name, + visibility, self.namespace_stack) + body = list(ast.Generate()) + + if not self._handling_typedef: token = self._GetNextToken() - # Support anonymous namespaces. - name = None - if token.token_type == tokenize.NAME: - name = token.name - token = self._GetNextToken() - self.namespace_stack.append(name) - assert token.token_type == tokenize.SYNTAX, token - # Create an internal token that denotes when the namespace is complete. - internal_token = tokenize.Token(_INTERNAL_TOKEN, _NAMESPACE_POP, - None, None) - internal_token.whence = token.whence - if token.name == '=': - # TODO(nnorwitz): handle aliasing namespaces. - name, next_token = self.GetName() - assert next_token.name == ';', next_token - self._AddBackToken(internal_token) + if token.token_type != tokenize.NAME: + assert token.token_type == tokenize.SYNTAX, token + assert token.name == ';', token else: - assert token.name == '{', token - tokens = list(self.GetScope()) - # Replace the trailing } with the internal namespace pop token. - tokens[-1] = internal_token - # Handle namespace with nothing in it. - self._AddBackTokens(tokens) - return None - - def handle_using(self): - tokens = self._GetTokensUpTo(tokenize.SYNTAX, ';') - assert tokens - return Using(tokens[0].start, tokens[0].end, tokens) - - def handle_explicit(self): - assert self.in_class - # Nothing much to do. - # TODO(nnorwitz): maybe verify the method name == class name. - # This must be a ctor. - return self.GetMethod(FUNCTION_CTOR, None) - - def handle_this(self): - pass # Nothing to do. - - def handle_operator(self): - # Pull off the next token(s?) and make that part of the method name. - pass + new_class = class_type(class_token.start, class_token.end, + class_name, bases, None, + body, self.namespace_stack) + + modifiers = [] + return self._CreateVariable(class_token, + token.name, new_class, + modifiers, token.name, None) + else: + if not self._handling_typedef: + self.HandleError('non-typedef token', token) + self._AddBackToken(token) + + return class_type(class_token.start, class_token.end, class_name, + bases, templated_types, body, self.namespace_stack) + + def handle_namespace(self): + token = self._GetNextToken() + # Support anonymous namespaces. + name = None + if token.token_type == tokenize.NAME: + name = token.name + token = self._GetNextToken() + self.namespace_stack.append(name) + assert token.token_type == tokenize.SYNTAX, token + # Create an internal token that denotes when the namespace is complete. + internal_token = tokenize.Token(_INTERNAL_TOKEN, _NAMESPACE_POP, + None, None) + internal_token.whence = token.whence + if token.name == '=': + # TODO(nnorwitz): handle aliasing namespaces. + name, next_token = self.GetName() + assert next_token.name == ';', next_token + self._AddBackToken(internal_token) + else: + assert token.name == '{', token + tokens = list(self.GetScope()) + # Replace the trailing } with the internal namespace pop token. + tokens[-1] = internal_token + # Handle namespace with nothing in it. + self._AddBackTokens(tokens) + return None + + def handle_using(self): + tokens = self._GetTokensUpTo(tokenize.SYNTAX, ';') + assert tokens + return Using(tokens[0].start, tokens[0].end, tokens) + + def handle_explicit(self): + assert self.in_class + # Nothing much to do. + # TODO(nnorwitz): maybe verify the method name == class name. + # This must be a ctor. + return self.GetMethod(FUNCTION_CTOR, None) + + def handle_this(self): + pass # Nothing to do. + + def handle_operator(self): + # Pull off the next token(s?) and make that part of the method name. + pass - def handle_sizeof(self): - pass + def handle_sizeof(self): + pass - def handle_case(self): - pass + def handle_case(self): + pass - def handle_switch(self): - pass + def handle_switch(self): + pass - def handle_default(self): - token = self._GetNextToken() - assert token.token_type == tokenize.SYNTAX - assert token.name == ':' + def handle_default(self): + token = self._GetNextToken() + assert token.token_type == tokenize.SYNTAX + assert token.name == ':' - def handle_if(self): - pass + def handle_if(self): + pass - def handle_else(self): - pass + def handle_else(self): + pass - def handle_return(self): - tokens = self._GetTokensUpTo(tokenize.SYNTAX, ';') - if not tokens: - return Return(self.current_token.start, self.current_token.end, None) - return Return(tokens[0].start, tokens[0].end, tokens) + def handle_return(self): + tokens = self._GetTokensUpTo(tokenize.SYNTAX, ';') + if not tokens: + return Return(self.current_token.start, self.current_token.end, None) + return Return(tokens[0].start, tokens[0].end, tokens) - def handle_goto(self): - tokens = self._GetTokensUpTo(tokenize.SYNTAX, ';') - assert len(tokens) == 1, str(tokens) - return Goto(tokens[0].start, tokens[0].end, tokens[0].name) + def handle_goto(self): + tokens = self._GetTokensUpTo(tokenize.SYNTAX, ';') + assert len(tokens) == 1, str(tokens) + return Goto(tokens[0].start, tokens[0].end, tokens[0].name) - def handle_try(self): - pass # Not needed yet. + def handle_try(self): + pass # Not needed yet. - def handle_catch(self): - pass # Not needed yet. + def handle_catch(self): + pass # Not needed yet. - def handle_throw(self): - pass # Not needed yet. + def handle_throw(self): + pass # Not needed yet. - def handle_while(self): - pass + def handle_while(self): + pass - def handle_do(self): - pass + def handle_do(self): + pass - def handle_for(self): - pass + def handle_for(self): + pass - def handle_break(self): - self._IgnoreUpTo(tokenize.SYNTAX, ';') + def handle_break(self): + self._IgnoreUpTo(tokenize.SYNTAX, ';') - def handle_continue(self): - self._IgnoreUpTo(tokenize.SYNTAX, ';') + def handle_continue(self): + self._IgnoreUpTo(tokenize.SYNTAX, ';') def BuilderFromSource(source, filename): - """Utility method that returns an AstBuilder from source code. + """Utility method that returns an AstBuilder from source code. Args: source: 'C++ source code' @@ -1673,64 +1710,64 @@ def BuilderFromSource(source, filename): Returns: AstBuilder """ - return AstBuilder(tokenize.GetTokens(source), filename) + return AstBuilder(tokenize.GetTokens(source), filename) def PrintIndentifiers(filename, should_print): - """Prints all identifiers for a C++ source file. + """Prints all identifiers for a C++ source file. Args: filename: 'file1' should_print: predicate with signature: bool Function(token) """ - source = utils.ReadFile(filename, False) - if source is None: - sys.stderr.write('Unable to find: %s\n' % filename) - return - - #print('Processing %s' % actual_filename) - builder = BuilderFromSource(source, filename) - try: - for node in builder.Generate(): - if should_print(node): - print(node.name) - except KeyboardInterrupt: - return - except: - pass + source = utils.ReadFile(filename, False) + if source is None: + sys.stderr.write('Unable to find: %s\n' % filename) + return + + #print('Processing %s' % actual_filename) + builder = BuilderFromSource(source, filename) + try: + for node in builder.Generate(): + if should_print(node): + print(node.name) + except KeyboardInterrupt: + return + except: + pass def PrintAllIndentifiers(filenames, should_print): - """Prints all identifiers for each C++ source file in filenames. + """Prints all identifiers for each C++ source file in filenames. Args: filenames: ['file1', 'file2', ...] should_print: predicate with signature: bool Function(token) """ - for path in filenames: - PrintIndentifiers(path, should_print) + for path in filenames: + PrintIndentifiers(path, should_print) def main(argv): - for filename in argv[1:]: - source = utils.ReadFile(filename) - if source is None: - continue - - print('Processing %s' % filename) - builder = BuilderFromSource(source, filename) - try: - entire_ast = filter(None, builder.Generate()) - except KeyboardInterrupt: - return - except: - # Already printed a warning, print the traceback and continue. - traceback.print_exc() - else: - if utils.DEBUG: - for ast in entire_ast: - print(ast) + for filename in argv[1:]: + source = utils.ReadFile(filename) + if source is None: + continue + + print('Processing %s' % filename) + builder = BuilderFromSource(source, filename) + try: + entire_ast = filter(None, builder.Generate()) + except KeyboardInterrupt: + return + except: + # Already printed a warning, print the traceback and continue. + traceback.print_exc() + else: + if utils.DEBUG: + for ast in entire_ast: + print(ast) if __name__ == '__main__': - main(sys.argv) + main(sys.argv) diff --git a/googlemock/scripts/generator/cpp/gmock_class.py b/googlemock/scripts/generator/cpp/gmock_class.py index f9966cbb..488cc153 100755 --- a/googlemock/scripts/generator/cpp/gmock_class.py +++ b/googlemock/scripts/generator/cpp/gmock_class.py @@ -26,9 +26,6 @@ Usage: Output is sent to stdout. """ -__author__ = 'nnorwitz@google.com (Neal Norwitz)' - - import os import re import sys @@ -41,6 +38,7 @@ try: _dummy = set except NameError: import sets + set = sets.Set _VERSION = (1, 0, 1) # The version of this script. @@ -48,79 +46,99 @@ _VERSION = (1, 0, 1) # The version of this script. _INDENT = 2 +def _RenderType(ast_type): + """Renders the potentially recursively templated type into a string. + + Args: + ast_type: The AST of the type. + + Returns: + Rendered string of the type. + """ + # Add modifiers like 'const'. + modifiers = '' + if ast_type.modifiers: + modifiers = ' '.join(ast_type.modifiers) + ' ' + return_type = modifiers + ast_type.name + if ast_type.templated_types: + # Collect template args. + template_args = [] + for arg in ast_type.templated_types: + rendered_arg = _RenderType(arg) + template_args.append(rendered_arg) + return_type += '<' + ', '.join(template_args) + '>' + if ast_type.pointer: + return_type += '*' + if ast_type.reference: + return_type += '&' + return return_type + + +def _GenerateArg(source): + """Strips out comments, default arguments, and redundant spaces from a single argument. + + Args: + source: A string for a single argument. + + Returns: + Rendered string of the argument. + """ + # Remove end of line comments before eliminating newlines. + arg = re.sub(r'//.*', '', source) + + # Remove c-style comments. + arg = re.sub(r'/\*.*\*/', '', arg) + + # Remove default arguments. + arg = re.sub(r'=.*', '', arg) + + # Collapse spaces and newlines into a single space. + arg = re.sub(r'\s+', ' ', arg) + return arg.strip() + + +def _EscapeForMacro(s): + """Escapes a string for use as an argument to a C++ macro.""" + paren_count = 0 + for c in s: + if c == '(': + paren_count += 1 + elif c == ')': + paren_count -= 1 + elif c == ',' and paren_count == 0: + return '(' + s + ')' + return s + + def _GenerateMethods(output_lines, source, class_node): - function_type = (ast.FUNCTION_VIRTUAL | ast.FUNCTION_PURE_VIRTUAL | - ast.FUNCTION_OVERRIDE) + function_type = ( + ast.FUNCTION_VIRTUAL | ast.FUNCTION_PURE_VIRTUAL | ast.FUNCTION_OVERRIDE) ctor_or_dtor = ast.FUNCTION_CTOR | ast.FUNCTION_DTOR indent = ' ' * _INDENT for node in class_node.body: # We only care about virtual functions. - if (isinstance(node, ast.Function) and - node.modifiers & function_type and + if (isinstance(node, ast.Function) and node.modifiers & function_type and not node.modifiers & ctor_or_dtor): # Pick out all the elements we need from the original function. - const = '' + modifiers = 'override' if node.modifiers & ast.FUNCTION_CONST: - const = 'CONST_' + modifiers = 'const, ' + modifiers + return_type = 'void' if node.return_type: - # Add modifiers like 'const'. - modifiers = '' - if node.return_type.modifiers: - modifiers = ' '.join(node.return_type.modifiers) + ' ' - return_type = modifiers + node.return_type.name - template_args = [arg.name for arg in node.return_type.templated_types] - if template_args: - return_type += '<' + ', '.join(template_args) + '>' - if len(template_args) > 1: - for line in [ - '// The following line won\'t really compile, as the return', - '// type has multiple template arguments. To fix it, use a', - '// typedef for the return type.']: - output_lines.append(indent + line) - if node.return_type.pointer: - return_type += '*' - if node.return_type.reference: - return_type += '&' - num_parameters = len(node.parameters) - if len(node.parameters) == 1: - first_param = node.parameters[0] - if source[first_param.start:first_param.end].strip() == 'void': - # We must treat T(void) as a function with no parameters. - num_parameters = 0 - tmpl = '' - if class_node.templated_types: - tmpl = '_T' - mock_method_macro = 'MOCK_%sMETHOD%d%s' % (const, num_parameters, tmpl) - - args = '' - if node.parameters: - # Due to the parser limitations, it is impossible to keep comments - # while stripping the default parameters. When defaults are - # present, we choose to strip them and comments (and produce - # compilable code). - # TODO(nnorwitz@google.com): Investigate whether it is possible to - # preserve parameter name when reconstructing parameter text from - # the AST. - if len([param for param in node.parameters if param.default]) > 0: - args = ', '.join(param.type.name for param in node.parameters) - else: - # Get the full text of the parameters from the start - # of the first parameter to the end of the last parameter. - start = node.parameters[0].start - end = node.parameters[-1].end - # Remove // comments. - args_strings = re.sub(r'//.*', '', source[start:end]) - # Condense multiple spaces and eliminate newlines putting the - # parameters together on a single line. Ensure there is a - # space in an argument which is split by a newline without - # intervening whitespace, e.g.: int\nBar - args = re.sub(' +', ' ', args_strings.replace('\n', ' ')) + return_type = _EscapeForMacro(_RenderType(node.return_type)) + + args = [] + for p in node.parameters: + arg = _GenerateArg(source[p.start:p.end]) + args.append(_EscapeForMacro(arg)) # Create the mock method definition. - output_lines.extend(['%s%s(%s,' % (indent, mock_method_macro, node.name), - '%s%s(%s));' % (indent*3, return_type, args)]) + output_lines.extend([ + '%sMOCK_METHOD(%s, %s, (%s), (%s));' % + (indent, return_type, node.name, ', '.join(args), modifiers) + ]) def _GenerateMocks(filename, source, ast_list, desired_class_names): @@ -171,7 +189,7 @@ def _GenerateMocks(filename, source, ast_list, desired_class_names): # Close the namespace. if class_node.namespace: - for i in range(len(class_node.namespace)-1, -1, -1): + for i in range(len(class_node.namespace) - 1, -1, -1): lines.append('} // namespace %s' % class_node.namespace[i]) lines.append('') # Add an extra newline. diff --git a/googlemock/scripts/generator/cpp/gmock_class_test.py b/googlemock/scripts/generator/cpp/gmock_class_test.py index c53e6000..74655692 100755 --- a/googlemock/scripts/generator/cpp/gmock_class_test.py +++ b/googlemock/scripts/generator/cpp/gmock_class_test.py @@ -17,9 +17,6 @@ """Tests for gmock.scripts.generator.cpp.gmock_class.""" -__author__ = 'nnorwitz@google.com (Neal Norwitz)' - - import os import sys import unittest @@ -34,7 +31,8 @@ from cpp import gmock_class class TestCase(unittest.TestCase): """Helper class that adds assert methods.""" - def StripLeadingWhitespace(self, lines): + @staticmethod + def StripLeadingWhitespace(lines): """Strip leading whitespace in each line in 'lines'.""" return '\n'.join([s.lstrip() for s in lines.split('\n')]) @@ -45,7 +43,8 @@ class TestCase(unittest.TestCase): class GenerateMethodsTest(TestCase): - def GenerateMethodSource(self, cpp_source): + @staticmethod + def GenerateMethodSource(cpp_source): """Convert C++ source to Google Mock output source lines.""" method_source_lines = [] # <test> is a pseudo-filename, it is not read or written. @@ -62,7 +61,7 @@ class Foo { }; """ self.assertEqualIgnoreLeadingWhitespace( - 'MOCK_METHOD0(Bar,\nint());', + 'MOCK_METHOD(int, Bar, (), (override));', self.GenerateMethodSource(source)) def testSimpleConstructorsAndDestructor(self): @@ -79,7 +78,7 @@ class Foo { """ # The constructors and destructor should be ignored. self.assertEqualIgnoreLeadingWhitespace( - 'MOCK_METHOD0(Bar,\nint());', + 'MOCK_METHOD(int, Bar, (), (override));', self.GenerateMethodSource(source)) def testVirtualDestructor(self): @@ -92,7 +91,7 @@ class Foo { """ # The destructor should be ignored. self.assertEqualIgnoreLeadingWhitespace( - 'MOCK_METHOD0(Bar,\nint());', + 'MOCK_METHOD(int, Bar, (), (override));', self.GenerateMethodSource(source)) def testExplicitlyDefaultedConstructorsAndDestructor(self): @@ -108,7 +107,7 @@ class Foo { """ # The constructors and destructor should be ignored. self.assertEqualIgnoreLeadingWhitespace( - 'MOCK_METHOD0(Bar,\nint());', + 'MOCK_METHOD(int, Bar, (), (override));', self.GenerateMethodSource(source)) def testExplicitlyDeletedConstructorsAndDestructor(self): @@ -124,7 +123,7 @@ class Foo { """ # The constructors and destructor should be ignored. self.assertEqualIgnoreLeadingWhitespace( - 'MOCK_METHOD0(Bar,\nint());', + 'MOCK_METHOD(int, Bar, (), (override));', self.GenerateMethodSource(source)) def testSimpleOverrideMethod(self): @@ -135,7 +134,7 @@ class Foo { }; """ self.assertEqualIgnoreLeadingWhitespace( - 'MOCK_METHOD0(Bar,\nint());', + 'MOCK_METHOD(int, Bar, (), (override));', self.GenerateMethodSource(source)) def testSimpleConstMethod(self): @@ -146,7 +145,7 @@ class Foo { }; """ self.assertEqualIgnoreLeadingWhitespace( - 'MOCK_CONST_METHOD1(Bar,\nvoid(bool flag));', + 'MOCK_METHOD(void, Bar, (bool flag), (const, override));', self.GenerateMethodSource(source)) def testExplicitVoid(self): @@ -157,7 +156,7 @@ class Foo { }; """ self.assertEqualIgnoreLeadingWhitespace( - 'MOCK_METHOD0(Bar,\nint(void));', + 'MOCK_METHOD(int, Bar, (void), (override));', self.GenerateMethodSource(source)) def testStrangeNewlineInParameter(self): @@ -169,7 +168,7 @@ a) = 0; }; """ self.assertEqualIgnoreLeadingWhitespace( - 'MOCK_METHOD1(Bar,\nvoid(int a));', + 'MOCK_METHOD(void, Bar, (int a), (override));', self.GenerateMethodSource(source)) def testDefaultParameters(self): @@ -180,18 +179,58 @@ class Foo { }; """ self.assertEqualIgnoreLeadingWhitespace( - 'MOCK_METHOD2(Bar,\nvoid(int, char));', + 'MOCK_METHOD(void, Bar, (int a, char c), (override));', self.GenerateMethodSource(source)) def testMultipleDefaultParameters(self): source = """ class Foo { public: - virtual void Bar(int a = 42, char c = 'x') = 0; + virtual void Bar( + int a = 42, + char c = 'x', + const int* const p = nullptr, + const std::string& s = "42", + char tab[] = {'4','2'}, + int const *& rp = aDefaultPointer) = 0; +}; +""" + self.assertEqualIgnoreLeadingWhitespace( + 'MOCK_METHOD(void, Bar, ' + '(int a, char c, const int* const p, const std::string& s, char tab[], int const *& rp), ' + '(override));', self.GenerateMethodSource(source)) + + def testMultipleSingleLineDefaultParameters(self): + source = """ +class Foo { + public: + virtual void Bar(int a = 42, int b = 43, int c = 44) = 0; +}; +""" + self.assertEqualIgnoreLeadingWhitespace( + 'MOCK_METHOD(void, Bar, (int a, int b, int c), (override));', + self.GenerateMethodSource(source)) + + def testConstDefaultParameter(self): + source = """ +class Test { + public: + virtual bool Bar(const int test_arg = 42) = 0; +}; +""" + self.assertEqualIgnoreLeadingWhitespace( + 'MOCK_METHOD(bool, Bar, (const int test_arg), (override));', + self.GenerateMethodSource(source)) + + def testConstRefDefaultParameter(self): + source = """ +class Test { + public: + virtual bool Bar(const std::string& test_arg = "42" ) = 0; }; """ self.assertEqualIgnoreLeadingWhitespace( - 'MOCK_METHOD2(Bar,\nvoid(int, char));', + 'MOCK_METHOD(bool, Bar, (const std::string& test_arg), (override));', self.GenerateMethodSource(source)) def testRemovesCommentsWhenDefaultsArePresent(self): @@ -203,7 +242,7 @@ class Foo { }; """ self.assertEqualIgnoreLeadingWhitespace( - 'MOCK_METHOD2(Bar,\nvoid(int, char));', + 'MOCK_METHOD(void, Bar, (int a, char c), (override));', self.GenerateMethodSource(source)) def testDoubleSlashCommentsInParameterListAreRemoved(self): @@ -216,7 +255,7 @@ class Foo { }; """ self.assertEqualIgnoreLeadingWhitespace( - 'MOCK_CONST_METHOD2(Bar,\nvoid(int a, int b));', + 'MOCK_METHOD(void, Bar, (int a, int b), (const, override));', self.GenerateMethodSource(source)) def testCStyleCommentsInParameterListAreNotRemoved(self): @@ -230,7 +269,7 @@ class Foo { }; """ self.assertEqualIgnoreLeadingWhitespace( - 'MOCK_METHOD2(Bar,\nconst string&(int /* keeper */, int b));', + 'MOCK_METHOD(const string&, Bar, (int, int b), (override));', self.GenerateMethodSource(source)) def testArgsOfTemplateTypes(self): @@ -240,8 +279,7 @@ class Foo { virtual int Bar(const vector<int>& v, map<int, string>* output); };""" self.assertEqualIgnoreLeadingWhitespace( - 'MOCK_METHOD2(Bar,\n' - 'int(const vector<int>& v, map<int, string>* output));', + 'MOCK_METHOD(int, Bar, (const vector<int>& v, (map<int, string>* output)), (override));', self.GenerateMethodSource(source)) def testReturnTypeWithOneTemplateArg(self): @@ -251,7 +289,7 @@ class Foo { virtual vector<int>* Bar(int n); };""" self.assertEqualIgnoreLeadingWhitespace( - 'MOCK_METHOD1(Bar,\nvector<int>*(int n));', + 'MOCK_METHOD(vector<int>*, Bar, (int n), (override));', self.GenerateMethodSource(source)) def testReturnTypeWithManyTemplateArgs(self): @@ -260,13 +298,8 @@ class Foo { public: virtual map<int, string> Bar(); };""" - # Comparing the comment text is brittle - we'll think of something - # better in case this gets annoying, but for now let's keep it simple. self.assertEqualIgnoreLeadingWhitespace( - '// The following line won\'t really compile, as the return\n' - '// type has multiple template arguments. To fix it, use a\n' - '// typedef for the return type.\n' - 'MOCK_METHOD0(Bar,\nmap<int, string>());', + 'MOCK_METHOD((map<int, string>), Bar, (), (override));', self.GenerateMethodSource(source)) def testSimpleMethodInTemplatedClass(self): @@ -278,7 +311,7 @@ class Foo { }; """ self.assertEqualIgnoreLeadingWhitespace( - 'MOCK_METHOD0_T(Bar,\nint());', + 'MOCK_METHOD(int, Bar, (), (override));', self.GenerateMethodSource(source)) def testPointerArgWithoutNames(self): @@ -288,7 +321,7 @@ class Foo { }; """ self.assertEqualIgnoreLeadingWhitespace( - 'MOCK_METHOD1(Bar,\nint(C*));', + 'MOCK_METHOD(int, Bar, (C*), (override));', self.GenerateMethodSource(source)) def testReferenceArgWithoutNames(self): @@ -298,7 +331,7 @@ class Foo { }; """ self.assertEqualIgnoreLeadingWhitespace( - 'MOCK_METHOD1(Bar,\nint(C&));', + 'MOCK_METHOD(int, Bar, (C&), (override));', self.GenerateMethodSource(source)) def testArrayArgWithoutNames(self): @@ -308,13 +341,14 @@ class Foo { }; """ self.assertEqualIgnoreLeadingWhitespace( - 'MOCK_METHOD1(Bar,\nint(C[]));', + 'MOCK_METHOD(int, Bar, (C[]), (override));', self.GenerateMethodSource(source)) class GenerateMocksTest(TestCase): - def GenerateMocks(self, cpp_source): + @staticmethod + def GenerateMocks(cpp_source): """Convert C++ source to complete Google Mock output source.""" # <test> is a pseudo-filename, it is not read or written. filename = '<test>' @@ -343,15 +377,14 @@ namespace Baz { class MockTest : public Test { public: -MOCK_METHOD0(Foo, -void()); +MOCK_METHOD(void, Foo, (), (override)); }; } // namespace Baz } // namespace Foo """ - self.assertEqualIgnoreLeadingWhitespace( - expected, self.GenerateMocks(source)) + self.assertEqualIgnoreLeadingWhitespace(expected, + self.GenerateMocks(source)) def testClassWithStorageSpecifierMacro(self): source = """ @@ -363,12 +396,11 @@ class STORAGE_SPECIFIER Test { expected = """\ class MockTest : public Test { public: -MOCK_METHOD0(Foo, -void()); +MOCK_METHOD(void, Foo, (), (override)); }; """ - self.assertEqualIgnoreLeadingWhitespace( - expected, self.GenerateMocks(source)) + self.assertEqualIgnoreLeadingWhitespace(expected, + self.GenerateMocks(source)) def testTemplatedForwardDeclaration(self): source = """ @@ -381,12 +413,11 @@ class Test { expected = """\ class MockTest : public Test { public: -MOCK_METHOD0(Foo, -void()); +MOCK_METHOD(void, Foo, (), (override)); }; """ - self.assertEqualIgnoreLeadingWhitespace( - expected, self.GenerateMocks(source)) + self.assertEqualIgnoreLeadingWhitespace(expected, + self.GenerateMocks(source)) def testTemplatedClass(self): source = """ @@ -400,12 +431,11 @@ class Test { template <typename T0, typename T1> class MockTest : public Test<T0, T1> { public: -MOCK_METHOD0_T(Foo, -void()); +MOCK_METHOD(void, Foo, (), (override)); }; """ - self.assertEqualIgnoreLeadingWhitespace( - expected, self.GenerateMocks(source)) + self.assertEqualIgnoreLeadingWhitespace(expected, + self.GenerateMocks(source)) def testTemplateInATemplateTypedef(self): source = """ @@ -418,12 +448,11 @@ class Test { expected = """\ class MockTest : public Test { public: -MOCK_METHOD1(Bar, -void(const FooType& test_arg)); +MOCK_METHOD(void, Bar, (const FooType& test_arg), (override)); }; """ - self.assertEqualIgnoreLeadingWhitespace( - expected, self.GenerateMocks(source)) + self.assertEqualIgnoreLeadingWhitespace(expected, + self.GenerateMocks(source)) def testTemplateInATemplateTypedefWithComma(self): source = """ @@ -437,30 +466,87 @@ class Test { expected = """\ class MockTest : public Test { public: -MOCK_METHOD1(Bar, -void(const FooType& test_arg)); +MOCK_METHOD(void, Bar, (const FooType& test_arg), (override)); }; """ - self.assertEqualIgnoreLeadingWhitespace( - expected, self.GenerateMocks(source)) + self.assertEqualIgnoreLeadingWhitespace(expected, + self.GenerateMocks(source)) - def testEnumClass(self): + def testParenthesizedCommaInArg(self): source = """ class Test { public: - enum class Baz { BAZINGA }; - virtual void Bar(const FooType& test_arg); + virtual void Bar(std::function<void(int, int)> f); }; """ expected = """\ class MockTest : public Test { public: -MOCK_METHOD1(Bar, -void(const FooType& test_arg)); +MOCK_METHOD(void, Bar, (std::function<void(int, int)> f), (override)); }; """ - self.assertEqualIgnoreLeadingWhitespace( - expected, self.GenerateMocks(source)) + self.assertEqualIgnoreLeadingWhitespace(expected, + self.GenerateMocks(source)) + + def testEnumType(self): + source = """ +class Test { + public: + enum Bar { + BAZ, QUX, QUUX, QUUUX + }; + virtual void Foo(); +}; +""" + expected = """\ +class MockTest : public Test { +public: +MOCK_METHOD(void, Foo, (), (override)); +}; +""" + self.assertEqualIgnoreLeadingWhitespace(expected, + self.GenerateMocks(source)) + + def testEnumClassType(self): + source = """ +class Test { + public: + enum class Bar { + BAZ, QUX, QUUX, QUUUX + }; + virtual void Foo(); +}; +""" + expected = """\ +class MockTest : public Test { +public: +MOCK_METHOD(void, Foo, (), (override)); +}; +""" + self.assertEqualIgnoreLeadingWhitespace(expected, + self.GenerateMocks(source)) + + def testStdFunction(self): + source = """ +class Test { + public: + Test(std::function<int(std::string)> foo) : foo_(foo) {} + + virtual std::function<int(std::string)> foo(); + + private: + std::function<int(std::string)> foo_; +}; +""" + expected = """\ +class MockTest : public Test { +public: +MOCK_METHOD(std::function<int (std::string)>, foo, (), (override)); +}; +""" + self.assertEqualIgnoreLeadingWhitespace(expected, + self.GenerateMocks(source)) + if __name__ == '__main__': unittest.main() diff --git a/googlemock/scripts/generator/cpp/keywords.py b/googlemock/scripts/generator/cpp/keywords.py index f694450e..e4282714 100755 --- a/googlemock/scripts/generator/cpp/keywords.py +++ b/googlemock/scripts/generator/cpp/keywords.py @@ -17,9 +17,6 @@ """C++ keywords and helper utilities for determining keywords.""" -__author__ = 'nnorwitz@google.com (Neal Norwitz)' - - try: # Python 3.x import builtins diff --git a/googlemock/scripts/generator/cpp/tokenize.py b/googlemock/scripts/generator/cpp/tokenize.py index 359d5562..a75edcb1 100755 --- a/googlemock/scripts/generator/cpp/tokenize.py +++ b/googlemock/scripts/generator/cpp/tokenize.py @@ -17,9 +17,6 @@ """Tokenize C++ source code.""" -__author__ = 'nnorwitz@google.com (Neal Norwitz)' - - try: # Python 3.x import builtins diff --git a/googlemock/scripts/generator/cpp/utils.py b/googlemock/scripts/generator/cpp/utils.py index eab36eec..6f5fc097 100755 --- a/googlemock/scripts/generator/cpp/utils.py +++ b/googlemock/scripts/generator/cpp/utils.py @@ -17,12 +17,8 @@ """Generic utilities for C++ parsing.""" -__author__ = 'nnorwitz@google.com (Neal Norwitz)' - - import sys - # Set to True to see the start/end token indices. DEBUG = True diff --git a/googlemock/scripts/generator/gmock_gen.py b/googlemock/scripts/generator/gmock_gen.py index 8cc0d135..9d528a56 100755 --- a/googlemock/scripts/generator/gmock_gen.py +++ b/googlemock/scripts/generator/gmock_gen.py @@ -16,7 +16,6 @@ """Driver for starting up Google Mock class generator.""" -__author__ = 'nnorwitz@google.com (Neal Norwitz)' import os import sys diff --git a/googlemock/scripts/gmock-config.in b/googlemock/scripts/gmock-config.in deleted file mode 100755 index 2baefe94..00000000 --- a/googlemock/scripts/gmock-config.in +++ /dev/null @@ -1,303 +0,0 @@ -#!/bin/sh - -# These variables are automatically filled in by the configure script. -name="@PACKAGE_TARNAME@" -version="@PACKAGE_VERSION@" - -show_usage() -{ - echo "Usage: gmock-config [OPTIONS...]" -} - -show_help() -{ - show_usage - cat <<\EOF - -The `gmock-config' script provides access to the necessary compile and linking -flags to connect with Google C++ Mocking Framework, both in a build prior to -installation, and on the system proper after installation. The installation -overrides may be issued in combination with any other queries, but will only -affect installation queries if called on a built but not installed gmock. The -installation queries may not be issued with any other types of queries, and -only one installation query may be made at a time. The version queries and -compiler flag queries may be combined as desired but not mixed. Different -version queries are always combined with logical "and" semantics, and only the -last of any particular query is used while all previous ones ignored. All -versions must be specified as a sequence of numbers separated by periods. -Compiler flag queries output the union of the sets of flags when combined. - - Examples: - gmock-config --min-version=1.0 || echo "Insufficient Google Mock version." - - g++ $(gmock-config --cppflags --cxxflags) -o foo.o -c foo.cpp - g++ $(gmock-config --ldflags --libs) -o foo foo.o - - # When using a built but not installed Google Mock: - g++ $(../../my_gmock_build/scripts/gmock-config ...) ... - - # When using an installed Google Mock, but with installation overrides: - export GMOCK_PREFIX="/opt" - g++ $(gmock-config --libdir="/opt/lib64" ...) ... - - Help: - --usage brief usage information - --help display this help message - - Installation Overrides: - --prefix=<dir> overrides the installation prefix - --exec-prefix=<dir> overrides the executable installation prefix - --libdir=<dir> overrides the library installation prefix - --includedir=<dir> overrides the header file installation prefix - - Installation Queries: - --prefix installation prefix - --exec-prefix executable installation prefix - --libdir library installation directory - --includedir header file installation directory - --version the version of the Google Mock installation - - Version Queries: - --min-version=VERSION return 0 if the version is at least VERSION - --exact-version=VERSION return 0 if the version is exactly VERSION - --max-version=VERSION return 0 if the version is at most VERSION - - Compilation Flag Queries: - --cppflags compile flags specific to the C-like preprocessors - --cxxflags compile flags appropriate for C++ programs - --ldflags linker flags - --libs libraries for linking - -EOF -} - -# This function bounds our version with a min and a max. It uses some clever -# POSIX-compliant variable expansion to portably do all the work in the shell -# and avoid any dependency on a particular "sed" or "awk" implementation. -# Notable is that it will only ever compare the first 3 components of versions. -# Further components will be cleanly stripped off. All versions must be -# unadorned, so "v1.0" will *not* work. The minimum version must be in $1, and -# the max in $2. TODO(chandlerc@google.com): If this ever breaks, we should -# investigate expanding this via autom4te from AS_VERSION_COMPARE rather than -# continuing to maintain our own shell version. -check_versions() -{ - major_version=${version%%.*} - minor_version="0" - point_version="0" - if test "${version#*.}" != "${version}"; then - minor_version=${version#*.} - minor_version=${minor_version%%.*} - fi - if test "${version#*.*.}" != "${version}"; then - point_version=${version#*.*.} - point_version=${point_version%%.*} - fi - - min_version="$1" - min_major_version=${min_version%%.*} - min_minor_version="0" - min_point_version="0" - if test "${min_version#*.}" != "${min_version}"; then - min_minor_version=${min_version#*.} - min_minor_version=${min_minor_version%%.*} - fi - if test "${min_version#*.*.}" != "${min_version}"; then - min_point_version=${min_version#*.*.} - min_point_version=${min_point_version%%.*} - fi - - max_version="$2" - max_major_version=${max_version%%.*} - max_minor_version="0" - max_point_version="0" - if test "${max_version#*.}" != "${max_version}"; then - max_minor_version=${max_version#*.} - max_minor_version=${max_minor_version%%.*} - fi - if test "${max_version#*.*.}" != "${max_version}"; then - max_point_version=${max_version#*.*.} - max_point_version=${max_point_version%%.*} - fi - - test $(($major_version)) -lt $(($min_major_version)) && exit 1 - if test $(($major_version)) -eq $(($min_major_version)); then - test $(($minor_version)) -lt $(($min_minor_version)) && exit 1 - if test $(($minor_version)) -eq $(($min_minor_version)); then - test $(($point_version)) -lt $(($min_point_version)) && exit 1 - fi - fi - - test $(($major_version)) -gt $(($max_major_version)) && exit 1 - if test $(($major_version)) -eq $(($max_major_version)); then - test $(($minor_version)) -gt $(($max_minor_version)) && exit 1 - if test $(($minor_version)) -eq $(($max_minor_version)); then - test $(($point_version)) -gt $(($max_point_version)) && exit 1 - fi - fi - - exit 0 -} - -# Show the usage line when no arguments are specified. -if test $# -eq 0; then - show_usage - exit 1 -fi - -while test $# -gt 0; do - case $1 in - --usage) show_usage; exit 0;; - --help) show_help; exit 0;; - - # Installation overrides - --prefix=*) GMOCK_PREFIX=${1#--prefix=};; - --exec-prefix=*) GMOCK_EXEC_PREFIX=${1#--exec-prefix=};; - --libdir=*) GMOCK_LIBDIR=${1#--libdir=};; - --includedir=*) GMOCK_INCLUDEDIR=${1#--includedir=};; - - # Installation queries - --prefix|--exec-prefix|--libdir|--includedir|--version) - if test -n "${do_query}"; then - show_usage - exit 1 - fi - do_query=${1#--} - ;; - - # Version checking - --min-version=*) - do_check_versions=yes - min_version=${1#--min-version=} - ;; - --max-version=*) - do_check_versions=yes - max_version=${1#--max-version=} - ;; - --exact-version=*) - do_check_versions=yes - exact_version=${1#--exact-version=} - ;; - - # Compiler flag output - --cppflags) echo_cppflags=yes;; - --cxxflags) echo_cxxflags=yes;; - --ldflags) echo_ldflags=yes;; - --libs) echo_libs=yes;; - - # Everything else is an error - *) show_usage; exit 1;; - esac - shift -done - -# These have defaults filled in by the configure script but can also be -# overridden by environment variables or command line parameters. -prefix="${GMOCK_PREFIX:-@prefix@}" -exec_prefix="${GMOCK_EXEC_PREFIX:-@exec_prefix@}" -libdir="${GMOCK_LIBDIR:-@libdir@}" -includedir="${GMOCK_INCLUDEDIR:-@includedir@}" - -# We try and detect if our binary is not located at its installed location. If -# it's not, we provide variables pointing to the source and build tree rather -# than to the install tree. We also locate Google Test using the configured -# gtest-config script rather than searching the PATH and our bindir for one. -# This allows building against a just-built gmock rather than an installed -# gmock. -bindir="@bindir@" -this_relative_bindir=`dirname $0` -this_bindir=`cd ${this_relative_bindir}; pwd -P` -if test "${this_bindir}" = "${this_bindir%${bindir}}"; then - # The path to the script doesn't end in the bindir sequence from Autoconf, - # assume that we are in a build tree. - build_dir=`dirname ${this_bindir}` - src_dir=`cd ${this_bindir}/@top_srcdir@; pwd -P` - - # TODO(chandlerc@google.com): This is a dangerous dependency on libtool, we - # should work to remove it, and/or remove libtool altogether, replacing it - # with direct references to the library and a link path. - gmock_libs="${build_dir}/lib/libgmock.la" - gmock_ldflags="" - - # We provide hooks to include from either the source or build dir, where the - # build dir is always preferred. This will potentially allow us to write - # build rules for generated headers and have them automatically be preferred - # over provided versions. - gmock_cppflags="-I${build_dir}/include -I${src_dir}/include" - gmock_cxxflags="" - - # Directly invoke the gtest-config script used during the build process. - gtest_config="@GTEST_CONFIG@" -else - # We're using an installed gmock, although it may be staged under some - # prefix. Assume (as our own libraries do) that we can resolve the prefix, - # and are present in the dynamic link paths. - gmock_ldflags="-L${libdir}" - gmock_libs="-l${name}" - gmock_cppflags="-I${includedir}" - gmock_cxxflags="" - - # We also prefer any gtest-config script installed in our prefix. Lacking - # one, we look in the PATH for one. - gtest_config="${bindir}/gtest-config" - if test ! -x "${gtest_config}"; then - gtest_config=`which gtest-config` - fi -fi - -# Ensure that we have located a Google Test to link against. -if ! test -x "${gtest_config}"; then - echo "Unable to locate Google Test, check your Google Mock configuration" \ - "and installation" >&2 - exit 1 -elif ! "${gtest_config}" "--exact-version=@GTEST_VERSION@"; then - echo "The Google Test found is not the same version as Google Mock was " \ - "built against" >&2 - exit 1 -fi - -# Add the necessary Google Test bits into the various flag variables -gmock_cppflags="${gmock_cppflags} `${gtest_config} --cppflags`" -gmock_cxxflags="${gmock_cxxflags} `${gtest_config} --cxxflags`" -gmock_ldflags="${gmock_ldflags} `${gtest_config} --ldflags`" -gmock_libs="${gmock_libs} `${gtest_config} --libs`" - -# Do an installation query if requested. -if test -n "$do_query"; then - case $do_query in - prefix) echo $prefix; exit 0;; - exec-prefix) echo $exec_prefix; exit 0;; - libdir) echo $libdir; exit 0;; - includedir) echo $includedir; exit 0;; - version) echo $version; exit 0;; - *) show_usage; exit 1;; - esac -fi - -# Do a version check if requested. -if test "$do_check_versions" = "yes"; then - # Make sure we didn't receive a bad combination of parameters. - test "$echo_cppflags" = "yes" && show_usage && exit 1 - test "$echo_cxxflags" = "yes" && show_usage && exit 1 - test "$echo_ldflags" = "yes" && show_usage && exit 1 - test "$echo_libs" = "yes" && show_usage && exit 1 - - if test "$exact_version" != ""; then - check_versions $exact_version $exact_version - # unreachable - else - check_versions ${min_version:-0.0.0} ${max_version:-9999.9999.9999} - # unreachable - fi -fi - -# Do the output in the correct order so that these can be used in-line of -# a compiler invocation. -output="" -test "$echo_cppflags" = "yes" && output="$output $gmock_cppflags" -test "$echo_cxxflags" = "yes" && output="$output $gmock_cxxflags" -test "$echo_ldflags" = "yes" && output="$output $gmock_ldflags" -test "$echo_libs" = "yes" && output="$output $gmock_libs" -echo $output - -exit 0 diff --git a/googlemock/scripts/gmock_doctor.py b/googlemock/scripts/gmock_doctor.py deleted file mode 100755 index 74992bc7..00000000 --- a/googlemock/scripts/gmock_doctor.py +++ /dev/null @@ -1,640 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2008, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -"""Converts compiler's errors in code using Google Mock to plain English.""" - -__author__ = 'wan@google.com (Zhanyong Wan)' - -import re -import sys - -_VERSION = '1.0.3' - -_EMAIL = 'googlemock@googlegroups.com' - -_COMMON_GMOCK_SYMBOLS = [ - # Matchers - '_', - 'A', - 'AddressSatisfies', - 'AllOf', - 'An', - 'AnyOf', - 'ContainerEq', - 'Contains', - 'ContainsRegex', - 'DoubleEq', - 'ElementsAre', - 'ElementsAreArray', - 'EndsWith', - 'Eq', - 'Field', - 'FloatEq', - 'Ge', - 'Gt', - 'HasSubstr', - 'IsInitializedProto', - 'Le', - 'Lt', - 'MatcherCast', - 'Matches', - 'MatchesRegex', - 'NanSensitiveDoubleEq', - 'NanSensitiveFloatEq', - 'Ne', - 'Not', - 'NotNull', - 'Pointee', - 'Property', - 'Ref', - 'ResultOf', - 'SafeMatcherCast', - 'StartsWith', - 'StrCaseEq', - 'StrCaseNe', - 'StrEq', - 'StrNe', - 'Truly', - 'TypedEq', - 'Value', - - # Actions - 'Assign', - 'ByRef', - 'DeleteArg', - 'DoAll', - 'DoDefault', - 'IgnoreResult', - 'Invoke', - 'InvokeArgument', - 'InvokeWithoutArgs', - 'Return', - 'ReturnNew', - 'ReturnNull', - 'ReturnRef', - 'SaveArg', - 'SetArgReferee', - 'SetArgPointee', - 'SetArgumentPointee', - 'SetArrayArgument', - 'SetErrnoAndReturn', - 'Throw', - 'WithArg', - 'WithArgs', - 'WithoutArgs', - - # Cardinalities - 'AnyNumber', - 'AtLeast', - 'AtMost', - 'Between', - 'Exactly', - - # Sequences - 'InSequence', - 'Sequence', - - # Misc - 'DefaultValue', - 'Mock', - ] - -# Regex for matching source file path and line number in the compiler's errors. -_GCC_FILE_LINE_RE = r'(?P<file>.*):(?P<line>\d+):(\d+:)?\s+' -_CLANG_FILE_LINE_RE = r'(?P<file>.*):(?P<line>\d+):(?P<column>\d+):\s+' -_CLANG_NON_GMOCK_FILE_LINE_RE = ( - r'(?P<file>.*[/\\^](?!gmock-)[^/\\]+):(?P<line>\d+):(?P<column>\d+):\s+') - - -def _FindAllMatches(regex, s): - """Generates all matches of regex in string s.""" - - r = re.compile(regex) - return r.finditer(s) - - -def _GenericDiagnoser(short_name, long_name, diagnoses, msg): - """Diagnoses the given disease by pattern matching. - - Can provide different diagnoses for different patterns. - - Args: - short_name: Short name of the disease. - long_name: Long name of the disease. - diagnoses: A list of pairs (regex, pattern for formatting the diagnosis - for matching regex). - msg: Compiler's error messages. - Yields: - Tuples of the form - (short name of disease, long name of disease, diagnosis). - """ - for regex, diagnosis in diagnoses: - if re.search(regex, msg): - diagnosis = '%(file)s:%(line)s:' + diagnosis - for m in _FindAllMatches(regex, msg): - yield (short_name, long_name, diagnosis % m.groupdict()) - - -def _NeedToReturnReferenceDiagnoser(msg): - """Diagnoses the NRR disease, given the error messages by the compiler.""" - - gcc_regex = (r'In member function \'testing::internal::ReturnAction<R>.*\n' - + _GCC_FILE_LINE_RE + r'instantiated from here\n' - r'.*gmock-actions\.h.*error: creating array with negative size') - clang_regex = (r'error:.*array.*negative.*\r?\n' - r'(.*\n)*?' + - _CLANG_NON_GMOCK_FILE_LINE_RE + - r'note: in instantiation of function template specialization ' - r'\'testing::internal::ReturnAction<(?P<type>.*)>' - r'::operator Action<.*>\' requested here') - clang11_re = (r'use_ReturnRef_instead_of_Return_to_return_a_reference.*' - r'(.*\n)*?' + _CLANG_NON_GMOCK_FILE_LINE_RE) - - diagnosis = """ -You are using a Return() action in a function that returns a reference to -%(type)s. Please use ReturnRef() instead.""" - return _GenericDiagnoser('NRR', 'Need to Return Reference', - [(clang_regex, diagnosis), - (clang11_re, diagnosis % {'type': 'a type'}), - (gcc_regex, diagnosis % {'type': 'a type'})], - msg) - - -def _NeedToReturnSomethingDiagnoser(msg): - """Diagnoses the NRS disease, given the error messages by the compiler.""" - - gcc_regex = (_GCC_FILE_LINE_RE + r'(instantiated from here\n.' - r'*gmock.*actions\.h.*error: void value not ignored)' - r'|(error: control reaches end of non-void function)') - clang_regex1 = (_CLANG_FILE_LINE_RE + - r'error: cannot initialize return object ' - r'of type \'Result\' \(aka \'(?P<return_type>.*)\'\) ' - r'with an rvalue of type \'void\'') - clang_regex2 = (_CLANG_FILE_LINE_RE + - r'error: cannot initialize return object ' - r'of type \'(?P<return_type>.*)\' ' - r'with an rvalue of type \'void\'') - diagnosis = """ -You are using an action that returns void, but it needs to return -%(return_type)s. Please tell it *what* to return. Perhaps you can use -the pattern DoAll(some_action, Return(some_value))?""" - return _GenericDiagnoser( - 'NRS', - 'Need to Return Something', - [(gcc_regex, diagnosis % {'return_type': '*something*'}), - (clang_regex1, diagnosis), - (clang_regex2, diagnosis)], - msg) - - -def _NeedToReturnNothingDiagnoser(msg): - """Diagnoses the NRN disease, given the error messages by the compiler.""" - - gcc_regex = (_GCC_FILE_LINE_RE + r'instantiated from here\n' - r'.*gmock-actions\.h.*error: instantiation of ' - r'\'testing::internal::ReturnAction<R>::Impl<F>::value_\' ' - r'as type \'void\'') - clang_regex1 = (r'error: field has incomplete type ' - r'\'Result\' \(aka \'void\'\)(\r)?\n' - r'(.*\n)*?' + - _CLANG_NON_GMOCK_FILE_LINE_RE + r'note: in instantiation ' - r'of function template specialization ' - r'\'testing::internal::ReturnAction<(?P<return_type>.*)>' - r'::operator Action<void \(.*\)>\' requested here') - clang_regex2 = (r'error: field has incomplete type ' - r'\'Result\' \(aka \'void\'\)(\r)?\n' - r'(.*\n)*?' + - _CLANG_NON_GMOCK_FILE_LINE_RE + r'note: in instantiation ' - r'of function template specialization ' - r'\'testing::internal::DoBothAction<.*>' - r'::operator Action<(?P<return_type>.*) \(.*\)>\' ' - r'requested here') - diagnosis = """ -You are using an action that returns %(return_type)s, but it needs to return -void. Please use a void-returning action instead. - -All actions but the last in DoAll(...) must return void. Perhaps you need -to re-arrange the order of actions in a DoAll(), if you are using one?""" - return _GenericDiagnoser( - 'NRN', - 'Need to Return Nothing', - [(gcc_regex, diagnosis % {'return_type': '*something*'}), - (clang_regex1, diagnosis), - (clang_regex2, diagnosis)], - msg) - - -def _IncompleteByReferenceArgumentDiagnoser(msg): - """Diagnoses the IBRA disease, given the error messages by the compiler.""" - - gcc_regex = (_GCC_FILE_LINE_RE + r'instantiated from here\n' - r'.*gtest-printers\.h.*error: invalid application of ' - r'\'sizeof\' to incomplete type \'(?P<type>.*)\'') - - clang_regex = (r'.*gtest-printers\.h.*error: invalid application of ' - r'\'sizeof\' to an incomplete type ' - r'\'(?P<type>.*)( const)?\'\r?\n' - r'(.*\n)*?' + - _CLANG_NON_GMOCK_FILE_LINE_RE + - r'note: in instantiation of member function ' - r'\'testing::internal2::TypeWithoutFormatter<.*>::' - r'PrintValue\' requested here') - diagnosis = """ -In order to mock this function, Google Mock needs to see the definition -of type "%(type)s" - declaration alone is not enough. Either #include -the header that defines it, or change the argument to be passed -by pointer.""" - - return _GenericDiagnoser('IBRA', 'Incomplete By-Reference Argument Type', - [(gcc_regex, diagnosis), - (clang_regex, diagnosis)], - msg) - - -def _OverloadedFunctionMatcherDiagnoser(msg): - """Diagnoses the OFM disease, given the error messages by the compiler.""" - - gcc_regex = (_GCC_FILE_LINE_RE + r'error: no matching function for ' - r'call to \'Truly\(<unresolved overloaded function type>\)') - clang_regex = (_CLANG_FILE_LINE_RE + r'error: no matching function for ' - r'call to \'Truly') - diagnosis = """ -The argument you gave to Truly() is an overloaded function. Please tell -your compiler which overloaded version you want to use. - -For example, if you want to use the version whose signature is - bool Foo(int n); -you should write - Truly(static_cast<bool (*)(int n)>(Foo))""" - return _GenericDiagnoser('OFM', 'Overloaded Function Matcher', - [(gcc_regex, diagnosis), - (clang_regex, diagnosis)], - msg) - - -def _OverloadedFunctionActionDiagnoser(msg): - """Diagnoses the OFA disease, given the error messages by the compiler.""" - - gcc_regex = (_GCC_FILE_LINE_RE + r'error: no matching function for call to ' - r'\'Invoke\(<unresolved overloaded function type>') - clang_regex = (_CLANG_FILE_LINE_RE + r'error: no matching ' - r'function for call to \'Invoke\'\r?\n' - r'(.*\n)*?' - r'.*\bgmock-generated-actions\.h:\d+:\d+:\s+' - r'note: candidate template ignored:\s+' - r'couldn\'t infer template argument \'FunctionImpl\'') - diagnosis = """ -Function you are passing to Invoke is overloaded. Please tell your compiler -which overloaded version you want to use. - -For example, if you want to use the version whose signature is - bool MyFunction(int n, double x); -you should write something like - Invoke(static_cast<bool (*)(int n, double x)>(MyFunction))""" - return _GenericDiagnoser('OFA', 'Overloaded Function Action', - [(gcc_regex, diagnosis), - (clang_regex, diagnosis)], - msg) - - -def _OverloadedMethodActionDiagnoser(msg): - """Diagnoses the OMA disease, given the error messages by the compiler.""" - - gcc_regex = (_GCC_FILE_LINE_RE + r'error: no matching function for ' - r'call to \'Invoke\(.+, <unresolved overloaded function ' - r'type>\)') - clang_regex = (_CLANG_FILE_LINE_RE + r'error: no matching function ' - r'for call to \'Invoke\'\r?\n' - r'(.*\n)*?' - r'.*\bgmock-generated-actions\.h:\d+:\d+: ' - r'note: candidate function template not viable: ' - r'requires .*, but 2 (arguments )?were provided') - diagnosis = """ -The second argument you gave to Invoke() is an overloaded method. Please -tell your compiler which overloaded version you want to use. - -For example, if you want to use the version whose signature is - class Foo { - ... - bool Bar(int n, double x); - }; -you should write something like - Invoke(foo, static_cast<bool (Foo::*)(int n, double x)>(&Foo::Bar))""" - return _GenericDiagnoser('OMA', 'Overloaded Method Action', - [(gcc_regex, diagnosis), - (clang_regex, diagnosis)], - msg) - - -def _MockObjectPointerDiagnoser(msg): - """Diagnoses the MOP disease, given the error messages by the compiler.""" - - gcc_regex = (_GCC_FILE_LINE_RE + r'error: request for member ' - r'\'gmock_(?P<method>.+)\' in \'(?P<mock_object>.+)\', ' - r'which is of non-class type \'(.*::)*(?P<class_name>.+)\*\'') - clang_regex = (_CLANG_FILE_LINE_RE + r'error: member reference type ' - r'\'(?P<class_name>.*?) *\' is a pointer; ' - r'(did you mean|maybe you meant) to use \'->\'\?') - diagnosis = """ -The first argument to ON_CALL() and EXPECT_CALL() must be a mock *object*, -not a *pointer* to it. Please write '*(%(mock_object)s)' instead of -'%(mock_object)s' as your first argument. - -For example, given the mock class: - - class %(class_name)s : public ... { - ... - MOCK_METHOD0(%(method)s, ...); - }; - -and the following mock instance: - - %(class_name)s* mock_ptr = ... - -you should use the EXPECT_CALL like this: - - EXPECT_CALL(*mock_ptr, %(method)s(...));""" - - return _GenericDiagnoser( - 'MOP', - 'Mock Object Pointer', - [(gcc_regex, diagnosis), - (clang_regex, diagnosis % {'mock_object': 'mock_object', - 'method': 'method', - 'class_name': '%(class_name)s'})], - msg) - - -def _NeedToUseSymbolDiagnoser(msg): - """Diagnoses the NUS disease, given the error messages by the compiler.""" - - gcc_regex = (_GCC_FILE_LINE_RE + r'error: \'(?P<symbol>.+)\' ' - r'(was not declared in this scope|has not been declared)') - clang_regex = (_CLANG_FILE_LINE_RE + - r'error: (use of undeclared identifier|unknown type name|' - r'no template named) \'(?P<symbol>[^\']+)\'') - diagnosis = """ -'%(symbol)s' is defined by Google Mock in the testing namespace. -Did you forget to write - using testing::%(symbol)s; -?""" - for m in (list(_FindAllMatches(gcc_regex, msg)) + - list(_FindAllMatches(clang_regex, msg))): - symbol = m.groupdict()['symbol'] - if symbol in _COMMON_GMOCK_SYMBOLS: - yield ('NUS', 'Need to Use Symbol', diagnosis % m.groupdict()) - - -def _NeedToUseReturnNullDiagnoser(msg): - """Diagnoses the NRNULL disease, given the error messages by the compiler.""" - - gcc_regex = ('instantiated from \'testing::internal::ReturnAction<R>' - '::operator testing::Action<Func>\(\) const.*\n' + - _GCC_FILE_LINE_RE + r'instantiated from here\n' - r'.*error: no matching function for call to \'ImplicitCast_\(' - r'(:?long )?int&\)') - clang_regex = (r'\bgmock-actions.h:.* error: no matching function for ' - r'call to \'ImplicitCast_\'\r?\n' - r'(.*\n)*?' + - _CLANG_NON_GMOCK_FILE_LINE_RE + r'note: in instantiation ' - r'of function template specialization ' - r'\'testing::internal::ReturnAction<(int|long)>::operator ' - r'Action<(?P<type>.*)\(\)>\' requested here') - diagnosis = """ -You are probably calling Return(NULL) and the compiler isn't sure how to turn -NULL into %(type)s. Use ReturnNull() instead. -Note: the line number may be off; please fix all instances of Return(NULL).""" - return _GenericDiagnoser( - 'NRNULL', 'Need to use ReturnNull', - [(clang_regex, diagnosis), - (gcc_regex, diagnosis % {'type': 'the right type'})], - msg) - - -def _TypeInTemplatedBaseDiagnoser(msg): - """Diagnoses the TTB disease, given the error messages by the compiler.""" - - # This version works when the type is used as the mock function's return - # type. - gcc_4_3_1_regex_type_in_retval = ( - r'In member function \'int .*\n' + _GCC_FILE_LINE_RE + - r'error: a function call cannot appear in a constant-expression') - gcc_4_4_0_regex_type_in_retval = ( - r'error: a function call cannot appear in a constant-expression' - + _GCC_FILE_LINE_RE + r'error: template argument 1 is invalid\n') - # This version works when the type is used as the mock function's sole - # parameter type. - gcc_regex_type_of_sole_param = ( - _GCC_FILE_LINE_RE + - r'error: \'(?P<type>.+)\' was not declared in this scope\n' - r'.*error: template argument 1 is invalid\n') - # This version works when the type is used as a parameter of a mock - # function that has multiple parameters. - gcc_regex_type_of_a_param = ( - r'error: expected `;\' before \'::\' token\n' - + _GCC_FILE_LINE_RE + - r'error: \'(?P<type>.+)\' was not declared in this scope\n' - r'.*error: template argument 1 is invalid\n' - r'.*error: \'.+\' was not declared in this scope') - clang_regex_type_of_retval_or_sole_param = ( - _CLANG_FILE_LINE_RE + - r'error: use of undeclared identifier \'(?P<type>.*)\'\n' - r'(.*\n)*?' - r'(?P=file):(?P=line):\d+: error: ' - r'non-friend class member \'Result\' cannot have a qualified name' - ) - clang_regex_type_of_a_param = ( - _CLANG_FILE_LINE_RE + - r'error: C\+\+ requires a type specifier for all declarations\n' - r'(.*\n)*?' - r'(?P=file):(?P=line):(?P=column): error: ' - r'C\+\+ requires a type specifier for all declarations' - ) - clang_regex_unknown_type = ( - _CLANG_FILE_LINE_RE + - r'error: unknown type name \'(?P<type>[^\']+)\'' - ) - - diagnosis = """ -In a mock class template, types or typedefs defined in the base class -template are *not* automatically visible. This is how C++ works. Before -you can use a type or typedef named %(type)s defined in base class Base<T>, you -need to make it visible. One way to do it is: - - typedef typename Base<T>::%(type)s %(type)s;""" - - for diag in _GenericDiagnoser( - 'TTB', 'Type in Template Base', - [(gcc_4_3_1_regex_type_in_retval, diagnosis % {'type': 'Foo'}), - (gcc_4_4_0_regex_type_in_retval, diagnosis % {'type': 'Foo'}), - (gcc_regex_type_of_sole_param, diagnosis), - (gcc_regex_type_of_a_param, diagnosis), - (clang_regex_type_of_retval_or_sole_param, diagnosis), - (clang_regex_type_of_a_param, diagnosis % {'type': 'Foo'})], - msg): - yield diag - # Avoid overlap with the NUS pattern. - for m in _FindAllMatches(clang_regex_unknown_type, msg): - type_ = m.groupdict()['type'] - if type_ not in _COMMON_GMOCK_SYMBOLS: - yield ('TTB', 'Type in Template Base', diagnosis % m.groupdict()) - - -def _WrongMockMethodMacroDiagnoser(msg): - """Diagnoses the WMM disease, given the error messages by the compiler.""" - - gcc_regex = (_GCC_FILE_LINE_RE + - r'.*this_method_does_not_take_(?P<wrong_args>\d+)_argument.*\n' - r'.*\n' - r'.*candidates are.*FunctionMocker<[^>]+A(?P<args>\d+)\)>') - clang_regex = (_CLANG_NON_GMOCK_FILE_LINE_RE + - r'error:.*array.*negative.*r?\n' - r'(.*\n)*?' - r'(?P=file):(?P=line):(?P=column): error: too few arguments ' - r'to function call, expected (?P<args>\d+), ' - r'have (?P<wrong_args>\d+)') - clang11_re = (_CLANG_NON_GMOCK_FILE_LINE_RE + - r'.*this_method_does_not_take_' - r'(?P<wrong_args>\d+)_argument.*') - diagnosis = """ -You are using MOCK_METHOD%(wrong_args)s to define a mock method that has -%(args)s arguments. Use MOCK_METHOD%(args)s (or MOCK_CONST_METHOD%(args)s, -MOCK_METHOD%(args)s_T, MOCK_CONST_METHOD%(args)s_T as appropriate) instead.""" - return _GenericDiagnoser('WMM', 'Wrong MOCK_METHODn Macro', - [(gcc_regex, diagnosis), - (clang11_re, diagnosis % {'wrong_args': 'm', - 'args': 'n'}), - (clang_regex, diagnosis)], - msg) - - -def _WrongParenPositionDiagnoser(msg): - """Diagnoses the WPP disease, given the error messages by the compiler.""" - - gcc_regex = (_GCC_FILE_LINE_RE + - r'error:.*testing::internal::MockSpec<.* has no member named \'' - r'(?P<method>\w+)\'') - clang_regex = (_CLANG_NON_GMOCK_FILE_LINE_RE + - r'error: no member named \'(?P<method>\w+)\' in ' - r'\'testing::internal::MockSpec<.*>\'') - diagnosis = """ -The closing parenthesis of ON_CALL or EXPECT_CALL should be *before* -".%(method)s". For example, you should write: - EXPECT_CALL(my_mock, Foo(_)).%(method)s(...); -instead of: - EXPECT_CALL(my_mock, Foo(_).%(method)s(...));""" - return _GenericDiagnoser('WPP', 'Wrong Parenthesis Position', - [(gcc_regex, diagnosis), - (clang_regex, diagnosis)], - msg) - - -_DIAGNOSERS = [ - _IncompleteByReferenceArgumentDiagnoser, - _MockObjectPointerDiagnoser, - _NeedToReturnNothingDiagnoser, - _NeedToReturnReferenceDiagnoser, - _NeedToReturnSomethingDiagnoser, - _NeedToUseReturnNullDiagnoser, - _NeedToUseSymbolDiagnoser, - _OverloadedFunctionActionDiagnoser, - _OverloadedFunctionMatcherDiagnoser, - _OverloadedMethodActionDiagnoser, - _TypeInTemplatedBaseDiagnoser, - _WrongMockMethodMacroDiagnoser, - _WrongParenPositionDiagnoser, - ] - - -def Diagnose(msg): - """Generates all possible diagnoses given the compiler error message.""" - - msg = re.sub(r'\x1b\[[^m]*m', '', msg) # Strips all color formatting. - # Assuming the string is using the UTF-8 encoding, replaces the left and - # the right single quote characters with apostrophes. - msg = re.sub(r'(\xe2\x80\x98|\xe2\x80\x99)', "'", msg) - - diagnoses = [] - for diagnoser in _DIAGNOSERS: - for diag in diagnoser(msg): - diagnosis = '[%s - %s]\n%s' % diag - if not diagnosis in diagnoses: - diagnoses.append(diagnosis) - return diagnoses - - -def main(): - print ('Google Mock Doctor v%s - ' - 'diagnoses problems in code using Google Mock.' % _VERSION) - - if sys.stdin.isatty(): - print ('Please copy and paste the compiler errors here. Press c-D when ' - 'you are done:') - else: - print ('Waiting for compiler errors on stdin . . .') - - msg = sys.stdin.read().strip() - diagnoses = Diagnose(msg) - count = len(diagnoses) - if not count: - print (""" -Your compiler complained: -8<------------------------------------------------------------ -%s ------------------------------------------------------------->8 - -Uh-oh, I'm not smart enough to figure out what the problem is. :-( -However... -If you send your source code and the compiler's error messages to -%s, you can be helped and I can get smarter -- -win-win for us!""" % (msg, _EMAIL)) - else: - print ('------------------------------------------------------------') - print ('Your code appears to have the following',) - if count > 1: - print ('%s diseases:' % (count,)) - else: - print ('disease:') - i = 0 - for d in diagnoses: - i += 1 - if count > 1: - print ('\n#%s:' % (i,)) - print (d) - print (""" -How did I do? If you think I'm wrong or unhelpful, please send your -source code and the compiler's error messages to %s. -Then you can be helped and I can get smarter -- I promise I won't be upset!""" % - _EMAIL) - - -if __name__ == '__main__': - main() diff --git a/googlemock/scripts/pump.py b/googlemock/scripts/pump.py new file mode 100755 index 00000000..5523a19d --- /dev/null +++ b/googlemock/scripts/pump.py @@ -0,0 +1,856 @@ +#!/usr/bin/env python +# +# Copyright 2008, Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +"""pump v0.2.0 - Pretty Useful for Meta Programming. + +A tool for preprocessor meta programming. Useful for generating +repetitive boilerplate code. Especially useful for writing C++ +classes, functions, macros, and templates that need to work with +various number of arguments. + +USAGE: + pump.py SOURCE_FILE + +EXAMPLES: + pump.py foo.cc.pump + Converts foo.cc.pump to foo.cc. + +GRAMMAR: + CODE ::= ATOMIC_CODE* + ATOMIC_CODE ::= $var ID = EXPRESSION + | $var ID = [[ CODE ]] + | $range ID EXPRESSION..EXPRESSION + | $for ID SEPARATOR [[ CODE ]] + | $($) + | $ID + | $(EXPRESSION) + | $if EXPRESSION [[ CODE ]] ELSE_BRANCH + | [[ CODE ]] + | RAW_CODE + SEPARATOR ::= RAW_CODE | EMPTY + ELSE_BRANCH ::= $else [[ CODE ]] + | $elif EXPRESSION [[ CODE ]] ELSE_BRANCH + | EMPTY + EXPRESSION has Python syntax. +""" + +from __future__ import print_function + +import io +import os +import re +import sys + + +TOKEN_TABLE = [ + (re.compile(r'\$var\s+'), '$var'), + (re.compile(r'\$elif\s+'), '$elif'), + (re.compile(r'\$else\s+'), '$else'), + (re.compile(r'\$for\s+'), '$for'), + (re.compile(r'\$if\s+'), '$if'), + (re.compile(r'\$range\s+'), '$range'), + (re.compile(r'\$[_A-Za-z]\w*'), '$id'), + (re.compile(r'\$\(\$\)'), '$($)'), + (re.compile(r'\$'), '$'), + (re.compile(r'\[\[\n?'), '[['), + (re.compile(r'\]\]\n?'), ']]'), + ] + + +class Cursor: + """Represents a position (line and column) in a text file.""" + + def __init__(self, line=-1, column=-1): + self.line = line + self.column = column + + def __eq__(self, rhs): + return self.line == rhs.line and self.column == rhs.column + + def __ne__(self, rhs): + return not self == rhs + + def __lt__(self, rhs): + return self.line < rhs.line or ( + self.line == rhs.line and self.column < rhs.column) + + def __le__(self, rhs): + return self < rhs or self == rhs + + def __gt__(self, rhs): + return rhs < self + + def __ge__(self, rhs): + return rhs <= self + + def __str__(self): + if self == Eof(): + return 'EOF' + else: + return '%s(%s)' % (self.line + 1, self.column) + + def __add__(self, offset): + return Cursor(self.line, self.column + offset) + + def __sub__(self, offset): + return Cursor(self.line, self.column - offset) + + def Clone(self): + """Returns a copy of self.""" + + return Cursor(self.line, self.column) + + +# Special cursor to indicate the end-of-file. +def Eof(): + """Returns the special cursor to denote the end-of-file.""" + return Cursor(-1, -1) + + +class Token: + """Represents a token in a Pump source file.""" + + def __init__(self, start=None, end=None, value=None, token_type=None): + if start is None: + self.start = Eof() + else: + self.start = start + if end is None: + self.end = Eof() + else: + self.end = end + self.value = value + self.token_type = token_type + + def __str__(self): + return 'Token @%s: \'%s\' type=%s' % ( + self.start, self.value, self.token_type) + + def Clone(self): + """Returns a copy of self.""" + + return Token(self.start.Clone(), self.end.Clone(), self.value, + self.token_type) + + +def StartsWith(lines, pos, string): + """Returns True iff the given position in lines starts with 'string'.""" + + return lines[pos.line][pos.column:].startswith(string) + + +def FindFirstInLine(line, token_table): + best_match_start = -1 + for (regex, token_type) in token_table: + m = regex.search(line) + if m: + # We found regex in lines + if best_match_start < 0 or m.start() < best_match_start: + best_match_start = m.start() + best_match_length = m.end() - m.start() + best_match_token_type = token_type + + if best_match_start < 0: + return None + + return (best_match_start, best_match_length, best_match_token_type) + + +def FindFirst(lines, token_table, cursor): + """Finds the first occurrence of any string in strings in lines.""" + + start = cursor.Clone() + cur_line_number = cursor.line + for line in lines[start.line:]: + if cur_line_number == start.line: + line = line[start.column:] + m = FindFirstInLine(line, token_table) + if m: + # We found a regex in line. + (start_column, length, token_type) = m + if cur_line_number == start.line: + start_column += start.column + found_start = Cursor(cur_line_number, start_column) + found_end = found_start + length + return MakeToken(lines, found_start, found_end, token_type) + cur_line_number += 1 + # We failed to find str in lines + return None + + +def SubString(lines, start, end): + """Returns a substring in lines.""" + + if end == Eof(): + end = Cursor(len(lines) - 1, len(lines[-1])) + + if start >= end: + return '' + + if start.line == end.line: + return lines[start.line][start.column:end.column] + + result_lines = ([lines[start.line][start.column:]] + + lines[start.line + 1:end.line] + + [lines[end.line][:end.column]]) + return ''.join(result_lines) + + +def StripMetaComments(str): + """Strip meta comments from each line in the given string.""" + + # First, completely remove lines containing nothing but a meta + # comment, including the trailing \n. + str = re.sub(r'^\s*\$\$.*\n', '', str) + + # Then, remove meta comments from contentful lines. + return re.sub(r'\s*\$\$.*', '', str) + + +def MakeToken(lines, start, end, token_type): + """Creates a new instance of Token.""" + + return Token(start, end, SubString(lines, start, end), token_type) + + +def ParseToken(lines, pos, regex, token_type): + line = lines[pos.line][pos.column:] + m = regex.search(line) + if m and not m.start(): + return MakeToken(lines, pos, pos + m.end(), token_type) + else: + print('ERROR: %s expected at %s.' % (token_type, pos)) + sys.exit(1) + + +ID_REGEX = re.compile(r'[_A-Za-z]\w*') +EQ_REGEX = re.compile(r'=') +REST_OF_LINE_REGEX = re.compile(r'.*?(?=$|\$\$)') +OPTIONAL_WHITE_SPACES_REGEX = re.compile(r'\s*') +WHITE_SPACE_REGEX = re.compile(r'\s') +DOT_DOT_REGEX = re.compile(r'\.\.') + + +def Skip(lines, pos, regex): + line = lines[pos.line][pos.column:] + m = re.search(regex, line) + if m and not m.start(): + return pos + m.end() + else: + return pos + + +def SkipUntil(lines, pos, regex, token_type): + line = lines[pos.line][pos.column:] + m = re.search(regex, line) + if m: + return pos + m.start() + else: + print ('ERROR: %s expected on line %s after column %s.' % + (token_type, pos.line + 1, pos.column)) + sys.exit(1) + + +def ParseExpTokenInParens(lines, pos): + def ParseInParens(pos): + pos = Skip(lines, pos, OPTIONAL_WHITE_SPACES_REGEX) + pos = Skip(lines, pos, r'\(') + pos = Parse(pos) + pos = Skip(lines, pos, r'\)') + return pos + + def Parse(pos): + pos = SkipUntil(lines, pos, r'\(|\)', ')') + if SubString(lines, pos, pos + 1) == '(': + pos = Parse(pos + 1) + pos = Skip(lines, pos, r'\)') + return Parse(pos) + else: + return pos + + start = pos.Clone() + pos = ParseInParens(pos) + return MakeToken(lines, start, pos, 'exp') + + +def RStripNewLineFromToken(token): + if token.value.endswith('\n'): + return Token(token.start, token.end, token.value[:-1], token.token_type) + else: + return token + + +def TokenizeLines(lines, pos): + while True: + found = FindFirst(lines, TOKEN_TABLE, pos) + if not found: + yield MakeToken(lines, pos, Eof(), 'code') + return + + if found.start == pos: + prev_token = None + prev_token_rstripped = None + else: + prev_token = MakeToken(lines, pos, found.start, 'code') + prev_token_rstripped = RStripNewLineFromToken(prev_token) + + if found.token_type == '$var': + if prev_token_rstripped: + yield prev_token_rstripped + yield found + id_token = ParseToken(lines, found.end, ID_REGEX, 'id') + yield id_token + pos = Skip(lines, id_token.end, OPTIONAL_WHITE_SPACES_REGEX) + + eq_token = ParseToken(lines, pos, EQ_REGEX, '=') + yield eq_token + pos = Skip(lines, eq_token.end, r'\s*') + + if SubString(lines, pos, pos + 2) != '[[': + exp_token = ParseToken(lines, pos, REST_OF_LINE_REGEX, 'exp') + yield exp_token + pos = Cursor(exp_token.end.line + 1, 0) + elif found.token_type == '$for': + if prev_token_rstripped: + yield prev_token_rstripped + yield found + id_token = ParseToken(lines, found.end, ID_REGEX, 'id') + yield id_token + pos = Skip(lines, id_token.end, WHITE_SPACE_REGEX) + elif found.token_type == '$range': + if prev_token_rstripped: + yield prev_token_rstripped + yield found + id_token = ParseToken(lines, found.end, ID_REGEX, 'id') + yield id_token + pos = Skip(lines, id_token.end, OPTIONAL_WHITE_SPACES_REGEX) + + dots_pos = SkipUntil(lines, pos, DOT_DOT_REGEX, '..') + yield MakeToken(lines, pos, dots_pos, 'exp') + yield MakeToken(lines, dots_pos, dots_pos + 2, '..') + pos = dots_pos + 2 + new_pos = Cursor(pos.line + 1, 0) + yield MakeToken(lines, pos, new_pos, 'exp') + pos = new_pos + elif found.token_type == '$': + if prev_token: + yield prev_token + yield found + exp_token = ParseExpTokenInParens(lines, found.end) + yield exp_token + pos = exp_token.end + elif (found.token_type == ']]' or found.token_type == '$if' or + found.token_type == '$elif' or found.token_type == '$else'): + if prev_token_rstripped: + yield prev_token_rstripped + yield found + pos = found.end + else: + if prev_token: + yield prev_token + yield found + pos = found.end + + +def Tokenize(s): + """A generator that yields the tokens in the given string.""" + if s != '': + lines = s.splitlines(True) + for token in TokenizeLines(lines, Cursor(0, 0)): + yield token + + +class CodeNode: + def __init__(self, atomic_code_list=None): + self.atomic_code = atomic_code_list + + +class VarNode: + def __init__(self, identifier=None, atomic_code=None): + self.identifier = identifier + self.atomic_code = atomic_code + + +class RangeNode: + def __init__(self, identifier=None, exp1=None, exp2=None): + self.identifier = identifier + self.exp1 = exp1 + self.exp2 = exp2 + + +class ForNode: + def __init__(self, identifier=None, sep=None, code=None): + self.identifier = identifier + self.sep = sep + self.code = code + + +class ElseNode: + def __init__(self, else_branch=None): + self.else_branch = else_branch + + +class IfNode: + def __init__(self, exp=None, then_branch=None, else_branch=None): + self.exp = exp + self.then_branch = then_branch + self.else_branch = else_branch + + +class RawCodeNode: + def __init__(self, token=None): + self.raw_code = token + + +class LiteralDollarNode: + def __init__(self, token): + self.token = token + + +class ExpNode: + def __init__(self, token, python_exp): + self.token = token + self.python_exp = python_exp + + +def PopFront(a_list): + head = a_list[0] + a_list[:1] = [] + return head + + +def PushFront(a_list, elem): + a_list[:0] = [elem] + + +def PopToken(a_list, token_type=None): + token = PopFront(a_list) + if token_type is not None and token.token_type != token_type: + print('ERROR: %s expected at %s' % (token_type, token.start)) + print('ERROR: %s found instead' % (token,)) + sys.exit(1) + + return token + + +def PeekToken(a_list): + if not a_list: + return None + + return a_list[0] + + +def ParseExpNode(token): + python_exp = re.sub(r'([_A-Za-z]\w*)', r'self.GetValue("\1")', token.value) + return ExpNode(token, python_exp) + + +def ParseElseNode(tokens): + def Pop(token_type=None): + return PopToken(tokens, token_type) + + next = PeekToken(tokens) + if not next: + return None + if next.token_type == '$else': + Pop('$else') + Pop('[[') + code_node = ParseCodeNode(tokens) + Pop(']]') + return code_node + elif next.token_type == '$elif': + Pop('$elif') + exp = Pop('code') + Pop('[[') + code_node = ParseCodeNode(tokens) + Pop(']]') + inner_else_node = ParseElseNode(tokens) + return CodeNode([IfNode(ParseExpNode(exp), code_node, inner_else_node)]) + elif not next.value.strip(): + Pop('code') + return ParseElseNode(tokens) + else: + return None + + +def ParseAtomicCodeNode(tokens): + def Pop(token_type=None): + return PopToken(tokens, token_type) + + head = PopFront(tokens) + t = head.token_type + if t == 'code': + return RawCodeNode(head) + elif t == '$var': + id_token = Pop('id') + Pop('=') + next = PeekToken(tokens) + if next.token_type == 'exp': + exp_token = Pop() + return VarNode(id_token, ParseExpNode(exp_token)) + Pop('[[') + code_node = ParseCodeNode(tokens) + Pop(']]') + return VarNode(id_token, code_node) + elif t == '$for': + id_token = Pop('id') + next_token = PeekToken(tokens) + if next_token.token_type == 'code': + sep_token = next_token + Pop('code') + else: + sep_token = None + Pop('[[') + code_node = ParseCodeNode(tokens) + Pop(']]') + return ForNode(id_token, sep_token, code_node) + elif t == '$if': + exp_token = Pop('code') + Pop('[[') + code_node = ParseCodeNode(tokens) + Pop(']]') + else_node = ParseElseNode(tokens) + return IfNode(ParseExpNode(exp_token), code_node, else_node) + elif t == '$range': + id_token = Pop('id') + exp1_token = Pop('exp') + Pop('..') + exp2_token = Pop('exp') + return RangeNode(id_token, ParseExpNode(exp1_token), + ParseExpNode(exp2_token)) + elif t == '$id': + return ParseExpNode(Token(head.start + 1, head.end, head.value[1:], 'id')) + elif t == '$($)': + return LiteralDollarNode(head) + elif t == '$': + exp_token = Pop('exp') + return ParseExpNode(exp_token) + elif t == '[[': + code_node = ParseCodeNode(tokens) + Pop(']]') + return code_node + else: + PushFront(tokens, head) + return None + + +def ParseCodeNode(tokens): + atomic_code_list = [] + while True: + if not tokens: + break + atomic_code_node = ParseAtomicCodeNode(tokens) + if atomic_code_node: + atomic_code_list.append(atomic_code_node) + else: + break + return CodeNode(atomic_code_list) + + +def ParseToAST(pump_src_text): + """Convert the given Pump source text into an AST.""" + tokens = list(Tokenize(pump_src_text)) + code_node = ParseCodeNode(tokens) + return code_node + + +class Env: + def __init__(self): + self.variables = [] + self.ranges = [] + + def Clone(self): + clone = Env() + clone.variables = self.variables[:] + clone.ranges = self.ranges[:] + return clone + + def PushVariable(self, var, value): + # If value looks like an int, store it as an int. + try: + int_value = int(value) + if ('%s' % int_value) == value: + value = int_value + except Exception: + pass + self.variables[:0] = [(var, value)] + + def PopVariable(self): + self.variables[:1] = [] + + def PushRange(self, var, lower, upper): + self.ranges[:0] = [(var, lower, upper)] + + def PopRange(self): + self.ranges[:1] = [] + + def GetValue(self, identifier): + for (var, value) in self.variables: + if identifier == var: + return value + + print('ERROR: meta variable %s is undefined.' % (identifier,)) + sys.exit(1) + + def EvalExp(self, exp): + try: + result = eval(exp.python_exp) + except Exception as e: # pylint: disable=broad-except + print('ERROR: caught exception %s: %s' % (e.__class__.__name__, e)) + print('ERROR: failed to evaluate meta expression %s at %s' % + (exp.python_exp, exp.token.start)) + sys.exit(1) + return result + + def GetRange(self, identifier): + for (var, lower, upper) in self.ranges: + if identifier == var: + return (lower, upper) + + print('ERROR: range %s is undefined.' % (identifier,)) + sys.exit(1) + + +class Output: + def __init__(self): + self.string = '' + + def GetLastLine(self): + index = self.string.rfind('\n') + if index < 0: + return '' + + return self.string[index + 1:] + + def Append(self, s): + self.string += s + + +def RunAtomicCode(env, node, output): + if isinstance(node, VarNode): + identifier = node.identifier.value.strip() + result = Output() + RunAtomicCode(env.Clone(), node.atomic_code, result) + value = result.string + env.PushVariable(identifier, value) + elif isinstance(node, RangeNode): + identifier = node.identifier.value.strip() + lower = int(env.EvalExp(node.exp1)) + upper = int(env.EvalExp(node.exp2)) + env.PushRange(identifier, lower, upper) + elif isinstance(node, ForNode): + identifier = node.identifier.value.strip() + if node.sep is None: + sep = '' + else: + sep = node.sep.value + (lower, upper) = env.GetRange(identifier) + for i in range(lower, upper + 1): + new_env = env.Clone() + new_env.PushVariable(identifier, i) + RunCode(new_env, node.code, output) + if i != upper: + output.Append(sep) + elif isinstance(node, RawCodeNode): + output.Append(node.raw_code.value) + elif isinstance(node, IfNode): + cond = env.EvalExp(node.exp) + if cond: + RunCode(env.Clone(), node.then_branch, output) + elif node.else_branch is not None: + RunCode(env.Clone(), node.else_branch, output) + elif isinstance(node, ExpNode): + value = env.EvalExp(node) + output.Append('%s' % (value,)) + elif isinstance(node, LiteralDollarNode): + output.Append('$') + elif isinstance(node, CodeNode): + RunCode(env.Clone(), node, output) + else: + print('BAD') + print(node) + sys.exit(1) + + +def RunCode(env, code_node, output): + for atomic_code in code_node.atomic_code: + RunAtomicCode(env, atomic_code, output) + + +def IsSingleLineComment(cur_line): + return '//' in cur_line + + +def IsInPreprocessorDirective(prev_lines, cur_line): + if cur_line.lstrip().startswith('#'): + return True + return prev_lines and prev_lines[-1].endswith('\\') + + +def WrapComment(line, output): + loc = line.find('//') + before_comment = line[:loc].rstrip() + if before_comment == '': + indent = loc + else: + output.append(before_comment) + indent = len(before_comment) - len(before_comment.lstrip()) + prefix = indent*' ' + '// ' + max_len = 80 - len(prefix) + comment = line[loc + 2:].strip() + segs = [seg for seg in re.split(r'(\w+\W*)', comment) if seg != ''] + cur_line = '' + for seg in segs: + if len((cur_line + seg).rstrip()) < max_len: + cur_line += seg + else: + if cur_line.strip() != '': + output.append(prefix + cur_line.rstrip()) + cur_line = seg.lstrip() + if cur_line.strip() != '': + output.append(prefix + cur_line.strip()) + + +def WrapCode(line, line_concat, output): + indent = len(line) - len(line.lstrip()) + prefix = indent*' ' # Prefix of the current line + max_len = 80 - indent - len(line_concat) # Maximum length of the current line + new_prefix = prefix + 4*' ' # Prefix of a continuation line + new_max_len = max_len - 4 # Maximum length of a continuation line + # Prefers to wrap a line after a ',' or ';'. + segs = [seg for seg in re.split(r'([^,;]+[,;]?)', line.strip()) if seg != ''] + cur_line = '' # The current line without leading spaces. + for seg in segs: + # If the line is still too long, wrap at a space. + while cur_line == '' and len(seg.strip()) > max_len: + seg = seg.lstrip() + split_at = seg.rfind(' ', 0, max_len) + output.append(prefix + seg[:split_at].strip() + line_concat) + seg = seg[split_at + 1:] + prefix = new_prefix + max_len = new_max_len + + if len((cur_line + seg).rstrip()) < max_len: + cur_line = (cur_line + seg).lstrip() + else: + output.append(prefix + cur_line.rstrip() + line_concat) + prefix = new_prefix + max_len = new_max_len + cur_line = seg.lstrip() + if cur_line.strip() != '': + output.append(prefix + cur_line.strip()) + + +def WrapPreprocessorDirective(line, output): + WrapCode(line, ' \\', output) + + +def WrapPlainCode(line, output): + WrapCode(line, '', output) + + +def IsMultiLineIWYUPragma(line): + return re.search(r'/\* IWYU pragma: ', line) + + +def IsHeaderGuardIncludeOrOneLineIWYUPragma(line): + return (re.match(r'^#(ifndef|define|endif\s*//)\s*[\w_]+\s*$', line) or + re.match(r'^#include\s', line) or + # Don't break IWYU pragmas, either; that causes iwyu.py problems. + re.search(r'// IWYU pragma: ', line)) + + +def WrapLongLine(line, output): + line = line.rstrip() + if len(line) <= 80: + output.append(line) + elif IsSingleLineComment(line): + if IsHeaderGuardIncludeOrOneLineIWYUPragma(line): + # The style guide made an exception to allow long header guard lines, + # includes and IWYU pragmas. + output.append(line) + else: + WrapComment(line, output) + elif IsInPreprocessorDirective(output, line): + if IsHeaderGuardIncludeOrOneLineIWYUPragma(line): + # The style guide made an exception to allow long header guard lines, + # includes and IWYU pragmas. + output.append(line) + else: + WrapPreprocessorDirective(line, output) + elif IsMultiLineIWYUPragma(line): + output.append(line) + else: + WrapPlainCode(line, output) + + +def BeautifyCode(string): + lines = string.splitlines() + output = [] + for line in lines: + WrapLongLine(line, output) + output2 = [line.rstrip() for line in output] + return '\n'.join(output2) + '\n' + + +def ConvertFromPumpSource(src_text): + """Return the text generated from the given Pump source text.""" + ast = ParseToAST(StripMetaComments(src_text)) + output = Output() + RunCode(Env(), ast, output) + return BeautifyCode(output.string) + + +def main(argv): + if len(argv) == 1: + print(__doc__) + sys.exit(1) + + file_path = argv[-1] + output_str = ConvertFromPumpSource(io.open(file_path, 'r').read()) + if file_path.endswith('.pump'): + output_file_path = file_path[:-5] + else: + output_file_path = '-' + if output_file_path == '-': + print(output_str,) + else: + output_file = io.open(output_file_path, 'w') + output_file.write(u'// This file was GENERATED by command:\n') + output_file.write(u'// %s %s\n' % + (os.path.basename(__file__), os.path.basename(file_path))) + output_file.write(u'// DO NOT EDIT BY HAND!!!\n\n') + output_file.write(output_str) + output_file.close() + + +if __name__ == '__main__': + main(sys.argv) diff --git a/googlemock/scripts/upload.py b/googlemock/scripts/upload.py deleted file mode 100755 index 95239dc2..00000000 --- a/googlemock/scripts/upload.py +++ /dev/null @@ -1,1387 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2007 Google Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Tool for uploading diffs from a version control system to the codereview app. - -Usage summary: upload.py [options] [-- diff_options] - -Diff options are passed to the diff command of the underlying system. - -Supported version control systems: - Git - Mercurial - Subversion - -It is important for Git/Mercurial users to specify a tree/node/branch to diff -against by using the '--rev' option. -""" -# This code is derived from appcfg.py in the App Engine SDK (open source), -# and from ASPN recipe #146306. - -import cookielib -import getpass -import logging -import md5 -import mimetypes -import optparse -import os -import re -import socket -import subprocess -import sys -import urllib -import urllib2 -import urlparse - -try: - import readline -except ImportError: - pass - -# The logging verbosity: -# 0: Errors only. -# 1: Status messages. -# 2: Info logs. -# 3: Debug logs. -verbosity = 1 - -# Max size of patch or base file. -MAX_UPLOAD_SIZE = 900 * 1024 - - -def GetEmail(prompt): - """Prompts the user for their email address and returns it. - - The last used email address is saved to a file and offered up as a suggestion - to the user. If the user presses enter without typing in anything the last - used email address is used. If the user enters a new address, it is saved - for next time we prompt. - - """ - last_email_file_name = os.path.expanduser("~/.last_codereview_email_address") - last_email = "" - if os.path.exists(last_email_file_name): - try: - last_email_file = open(last_email_file_name, "r") - last_email = last_email_file.readline().strip("\n") - last_email_file.close() - prompt += " [%s]" % last_email - except IOError, e: - pass - email = raw_input(prompt + ": ").strip() - if email: - try: - last_email_file = open(last_email_file_name, "w") - last_email_file.write(email) - last_email_file.close() - except IOError, e: - pass - else: - email = last_email - return email - - -def StatusUpdate(msg): - """Print a status message to stdout. - - If 'verbosity' is greater than 0, print the message. - - Args: - msg: The string to print. - """ - if verbosity > 0: - print msg - - -def ErrorExit(msg): - """Print an error message to stderr and exit.""" - print >>sys.stderr, msg - sys.exit(1) - - -class ClientLoginError(urllib2.HTTPError): - """Raised to indicate there was an error authenticating with ClientLogin.""" - - def __init__(self, url, code, msg, headers, args): - urllib2.HTTPError.__init__(self, url, code, msg, headers, None) - self.args = args - self.reason = args["Error"] - - -class AbstractRpcServer(object): - """Provides a common interface for a simple RPC server.""" - - def __init__(self, host, auth_function, host_override=None, extra_headers={}, - save_cookies=False): - """Creates a new HttpRpcServer. - - Args: - host: The host to send requests to. - auth_function: A function that takes no arguments and returns an - (email, password) tuple when called. Will be called if authentication - is required. - host_override: The host header to send to the server (defaults to host). - extra_headers: A dict of extra headers to append to every request. - save_cookies: If True, save the authentication cookies to local disk. - If False, use an in-memory cookiejar instead. Subclasses must - implement this functionality. Defaults to False. - """ - self.host = host - self.host_override = host_override - self.auth_function = auth_function - self.authenticated = False - self.extra_headers = extra_headers - self.save_cookies = save_cookies - self.opener = self._GetOpener() - if self.host_override: - logging.info("Server: %s; Host: %s", self.host, self.host_override) - else: - logging.info("Server: %s", self.host) - - def _GetOpener(self): - """Returns an OpenerDirector for making HTTP requests. - - Returns: - A urllib2.OpenerDirector object. - """ - raise NotImplementedError() - - def _CreateRequest(self, url, data=None): - """Creates a new urllib request.""" - logging.debug("Creating request for: '%s' with payload:\n%s", url, data) - req = urllib2.Request(url, data=data) - if self.host_override: - req.add_header("Host", self.host_override) - for key, value in self.extra_headers.iteritems(): - req.add_header(key, value) - return req - - def _GetAuthToken(self, email, password): - """Uses ClientLogin to authenticate the user, returning an auth token. - - Args: - email: The user's email address - password: The user's password - - Raises: - ClientLoginError: If there was an error authenticating with ClientLogin. - HTTPError: If there was some other form of HTTP error. - - Returns: - The authentication token returned by ClientLogin. - """ - account_type = "GOOGLE" - if self.host.endswith(".google.com"): - # Needed for use inside Google. - account_type = "HOSTED" - req = self._CreateRequest( - url="https://www.google.com/accounts/ClientLogin", - data=urllib.urlencode({ - "Email": email, - "Passwd": password, - "service": "ah", - "source": "rietveld-codereview-upload", - "accountType": account_type, - }), - ) - try: - response = self.opener.open(req) - response_body = response.read() - response_dict = dict(x.split("=") - for x in response_body.split("\n") if x) - return response_dict["Auth"] - except urllib2.HTTPError, e: - if e.code == 403: - body = e.read() - response_dict = dict(x.split("=", 1) for x in body.split("\n") if x) - raise ClientLoginError(req.get_full_url(), e.code, e.msg, - e.headers, response_dict) - else: - raise - - def _GetAuthCookie(self, auth_token): - """Fetches authentication cookies for an authentication token. - - Args: - auth_token: The authentication token returned by ClientLogin. - - Raises: - HTTPError: If there was an error fetching the authentication cookies. - """ - # This is a dummy value to allow us to identify when we're successful. - continue_location = "http://localhost/" - args = {"continue": continue_location, "auth": auth_token} - req = self._CreateRequest("http://%s/_ah/login?%s" % - (self.host, urllib.urlencode(args))) - try: - response = self.opener.open(req) - except urllib2.HTTPError, e: - response = e - if (response.code != 302 or - response.info()["location"] != continue_location): - raise urllib2.HTTPError(req.get_full_url(), response.code, response.msg, - response.headers, response.fp) - self.authenticated = True - - def _Authenticate(self): - """Authenticates the user. - - The authentication process works as follows: - 1) We get a username and password from the user - 2) We use ClientLogin to obtain an AUTH token for the user - (see https://developers.google.com/identity/protocols/AuthForInstalledApps). - 3) We pass the auth token to /_ah/login on the server to obtain an - authentication cookie. If login was successful, it tries to redirect - us to the URL we provided. - - If we attempt to access the upload API without first obtaining an - authentication cookie, it returns a 401 response and directs us to - authenticate ourselves with ClientLogin. - """ - for i in range(3): - credentials = self.auth_function() - try: - auth_token = self._GetAuthToken(credentials[0], credentials[1]) - except ClientLoginError, e: - if e.reason == "BadAuthentication": - print >>sys.stderr, "Invalid username or password." - continue - if e.reason == "CaptchaRequired": - print >>sys.stderr, ( - "Please go to\n" - "https://www.google.com/accounts/DisplayUnlockCaptcha\n" - "and verify you are a human. Then try again.") - break - if e.reason == "NotVerified": - print >>sys.stderr, "Account not verified." - break - if e.reason == "TermsNotAgreed": - print >>sys.stderr, "User has not agreed to TOS." - break - if e.reason == "AccountDeleted": - print >>sys.stderr, "The user account has been deleted." - break - if e.reason == "AccountDisabled": - print >>sys.stderr, "The user account has been disabled." - break - if e.reason == "ServiceDisabled": - print >>sys.stderr, ("The user's access to the service has been " - "disabled.") - break - if e.reason == "ServiceUnavailable": - print >>sys.stderr, "The service is not available; try again later." - break - raise - self._GetAuthCookie(auth_token) - return - - def Send(self, request_path, payload=None, - content_type="application/octet-stream", - timeout=None, - **kwargs): - """Sends an RPC and returns the response. - - Args: - request_path: The path to send the request to, eg /api/appversion/create. - payload: The body of the request, or None to send an empty request. - content_type: The Content-Type header to use. - timeout: timeout in seconds; default None i.e. no timeout. - (Note: for large requests on OS X, the timeout doesn't work right.) - kwargs: Any keyword arguments are converted into query string parameters. - - Returns: - The response body, as a string. - """ - # TODO: Don't require authentication. Let the server say - # whether it is necessary. - if not self.authenticated: - self._Authenticate() - - old_timeout = socket.getdefaulttimeout() - socket.setdefaulttimeout(timeout) - try: - tries = 0 - while True: - tries += 1 - args = dict(kwargs) - url = "http://%s%s" % (self.host, request_path) - if args: - url += "?" + urllib.urlencode(args) - req = self._CreateRequest(url=url, data=payload) - req.add_header("Content-Type", content_type) - try: - f = self.opener.open(req) - response = f.read() - f.close() - return response - except urllib2.HTTPError, e: - if tries > 3: - raise - elif e.code == 401: - self._Authenticate() -## elif e.code >= 500 and e.code < 600: -## # Server Error - try again. -## continue - else: - raise - finally: - socket.setdefaulttimeout(old_timeout) - - -class HttpRpcServer(AbstractRpcServer): - """Provides a simplified RPC-style interface for HTTP requests.""" - - def _Authenticate(self): - """Save the cookie jar after authentication.""" - super(HttpRpcServer, self)._Authenticate() - if self.save_cookies: - StatusUpdate("Saving authentication cookies to %s" % self.cookie_file) - self.cookie_jar.save() - - def _GetOpener(self): - """Returns an OpenerDirector that supports cookies and ignores redirects. - - Returns: - A urllib2.OpenerDirector object. - """ - opener = urllib2.OpenerDirector() - opener.add_handler(urllib2.ProxyHandler()) - opener.add_handler(urllib2.UnknownHandler()) - opener.add_handler(urllib2.HTTPHandler()) - opener.add_handler(urllib2.HTTPDefaultErrorHandler()) - opener.add_handler(urllib2.HTTPSHandler()) - opener.add_handler(urllib2.HTTPErrorProcessor()) - if self.save_cookies: - self.cookie_file = os.path.expanduser("~/.codereview_upload_cookies") - self.cookie_jar = cookielib.MozillaCookieJar(self.cookie_file) - if os.path.exists(self.cookie_file): - try: - self.cookie_jar.load() - self.authenticated = True - StatusUpdate("Loaded authentication cookies from %s" % - self.cookie_file) - except (cookielib.LoadError, IOError): - # Failed to load cookies - just ignore them. - pass - else: - # Create an empty cookie file with mode 600 - fd = os.open(self.cookie_file, os.O_CREAT, 0600) - os.close(fd) - # Always chmod the cookie file - os.chmod(self.cookie_file, 0600) - else: - # Don't save cookies across runs of update.py. - self.cookie_jar = cookielib.CookieJar() - opener.add_handler(urllib2.HTTPCookieProcessor(self.cookie_jar)) - return opener - - -parser = optparse.OptionParser(usage="%prog [options] [-- diff_options]") -parser.add_option("-y", "--assume_yes", action="store_true", - dest="assume_yes", default=False, - help="Assume that the answer to yes/no questions is 'yes'.") -# Logging -group = parser.add_option_group("Logging options") -group.add_option("-q", "--quiet", action="store_const", const=0, - dest="verbose", help="Print errors only.") -group.add_option("-v", "--verbose", action="store_const", const=2, - dest="verbose", default=1, - help="Print info level logs (default).") -group.add_option("--noisy", action="store_const", const=3, - dest="verbose", help="Print all logs.") -# Review server -group = parser.add_option_group("Review server options") -group.add_option("-s", "--server", action="store", dest="server", - default="codereview.appspot.com", - metavar="SERVER", - help=("The server to upload to. The format is host[:port]. " - "Defaults to 'codereview.appspot.com'.")) -group.add_option("-e", "--email", action="store", dest="email", - metavar="EMAIL", default=None, - help="The username to use. Will prompt if omitted.") -group.add_option("-H", "--host", action="store", dest="host", - metavar="HOST", default=None, - help="Overrides the Host header sent with all RPCs.") -group.add_option("--no_cookies", action="store_false", - dest="save_cookies", default=True, - help="Do not save authentication cookies to local disk.") -# Issue -group = parser.add_option_group("Issue options") -group.add_option("-d", "--description", action="store", dest="description", - metavar="DESCRIPTION", default=None, - help="Optional description when creating an issue.") -group.add_option("-f", "--description_file", action="store", - dest="description_file", metavar="DESCRIPTION_FILE", - default=None, - help="Optional path of a file that contains " - "the description when creating an issue.") -group.add_option("-r", "--reviewers", action="store", dest="reviewers", - metavar="REVIEWERS", default=None, - help="Add reviewers (comma separated email addresses).") -group.add_option("--cc", action="store", dest="cc", - metavar="CC", default=None, - help="Add CC (comma separated email addresses).") -# Upload options -group = parser.add_option_group("Patch options") -group.add_option("-m", "--message", action="store", dest="message", - metavar="MESSAGE", default=None, - help="A message to identify the patch. " - "Will prompt if omitted.") -group.add_option("-i", "--issue", type="int", action="store", - metavar="ISSUE", default=None, - help="Issue number to which to add. Defaults to new issue.") -group.add_option("--download_base", action="store_true", - dest="download_base", default=False, - help="Base files will be downloaded by the server " - "(side-by-side diffs may not work on files with CRs).") -group.add_option("--rev", action="store", dest="revision", - metavar="REV", default=None, - help="Branch/tree/revision to diff against (used by DVCS).") -group.add_option("--send_mail", action="store_true", - dest="send_mail", default=False, - help="Send notification email to reviewers.") - - -def GetRpcServer(options): - """Returns an instance of an AbstractRpcServer. - - Returns: - A new AbstractRpcServer, on which RPC calls can be made. - """ - - rpc_server_class = HttpRpcServer - - def GetUserCredentials(): - """Prompts the user for a username and password.""" - email = options.email - if email is None: - email = GetEmail("Email (login for uploading to %s)" % options.server) - password = getpass.getpass("Password for %s: " % email) - return (email, password) - - # If this is the dev_appserver, use fake authentication. - host = (options.host or options.server).lower() - if host == "localhost" or host.startswith("localhost:"): - email = options.email - if email is None: - email = "test@example.com" - logging.info("Using debug user %s. Override with --email" % email) - server = rpc_server_class( - options.server, - lambda: (email, "password"), - host_override=options.host, - extra_headers={"Cookie": - 'dev_appserver_login="%s:False"' % email}, - save_cookies=options.save_cookies) - # Don't try to talk to ClientLogin. - server.authenticated = True - return server - - return rpc_server_class(options.server, GetUserCredentials, - host_override=options.host, - save_cookies=options.save_cookies) - - -def EncodeMultipartFormData(fields, files): - """Encode form fields for multipart/form-data. - - Args: - fields: A sequence of (name, value) elements for regular form fields. - files: A sequence of (name, filename, value) elements for data to be - uploaded as files. - Returns: - (content_type, body) ready for httplib.HTTP instance. - - Source: - https://web.archive.org/web/20160116052001/code.activestate.com/recipes/146306 - """ - BOUNDARY = '-M-A-G-I-C---B-O-U-N-D-A-R-Y-' - CRLF = '\r\n' - lines = [] - for (key, value) in fields: - lines.append('--' + BOUNDARY) - lines.append('Content-Disposition: form-data; name="%s"' % key) - lines.append('') - lines.append(value) - for (key, filename, value) in files: - lines.append('--' + BOUNDARY) - lines.append('Content-Disposition: form-data; name="%s"; filename="%s"' % - (key, filename)) - lines.append('Content-Type: %s' % GetContentType(filename)) - lines.append('') - lines.append(value) - lines.append('--' + BOUNDARY + '--') - lines.append('') - body = CRLF.join(lines) - content_type = 'multipart/form-data; boundary=%s' % BOUNDARY - return content_type, body - - -def GetContentType(filename): - """Helper to guess the content-type from the filename.""" - return mimetypes.guess_type(filename)[0] or 'application/octet-stream' - - -# Use a shell for subcommands on Windows to get a PATH search. -use_shell = sys.platform.startswith("win") - -def RunShellWithReturnCode(command, print_output=False, - universal_newlines=True): - """Executes a command and returns the output from stdout and the return code. - - Args: - command: Command to execute. - print_output: If True, the output is printed to stdout. - If False, both stdout and stderr are ignored. - universal_newlines: Use universal_newlines flag (default: True). - - Returns: - Tuple (output, return code) - """ - logging.info("Running %s", command) - p = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, - shell=use_shell, universal_newlines=universal_newlines) - if print_output: - output_array = [] - while True: - line = p.stdout.readline() - if not line: - break - print line.strip("\n") - output_array.append(line) - output = "".join(output_array) - else: - output = p.stdout.read() - p.wait() - errout = p.stderr.read() - if print_output and errout: - print >>sys.stderr, errout - p.stdout.close() - p.stderr.close() - return output, p.returncode - - -def RunShell(command, silent_ok=False, universal_newlines=True, - print_output=False): - data, retcode = RunShellWithReturnCode(command, print_output, - universal_newlines) - if retcode: - ErrorExit("Got error status from %s:\n%s" % (command, data)) - if not silent_ok and not data: - ErrorExit("No output from %s" % command) - return data - - -class VersionControlSystem(object): - """Abstract base class providing an interface to the VCS.""" - - def __init__(self, options): - """Constructor. - - Args: - options: Command line options. - """ - self.options = options - - def GenerateDiff(self, args): - """Return the current diff as a string. - - Args: - args: Extra arguments to pass to the diff command. - """ - raise NotImplementedError( - "abstract method -- subclass %s must override" % self.__class__) - - def GetUnknownFiles(self): - """Return a list of files unknown to the VCS.""" - raise NotImplementedError( - "abstract method -- subclass %s must override" % self.__class__) - - def CheckForUnknownFiles(self): - """Show an "are you sure?" prompt if there are unknown files.""" - unknown_files = self.GetUnknownFiles() - if unknown_files: - print "The following files are not added to version control:" - for line in unknown_files: - print line - prompt = "Are you sure to continue?(y/N) " - answer = raw_input(prompt).strip() - if answer != "y": - ErrorExit("User aborted") - - def GetBaseFile(self, filename): - """Get the content of the upstream version of a file. - - Returns: - A tuple (base_content, new_content, is_binary, status) - base_content: The contents of the base file. - new_content: For text files, this is empty. For binary files, this is - the contents of the new file, since the diff output won't contain - information to reconstruct the current file. - is_binary: True iff the file is binary. - status: The status of the file. - """ - - raise NotImplementedError( - "abstract method -- subclass %s must override" % self.__class__) - - - def GetBaseFiles(self, diff): - """Helper that calls GetBase file for each file in the patch. - - Returns: - A dictionary that maps from filename to GetBaseFile's tuple. Filenames - are retrieved based on lines that start with "Index:" or - "Property changes on:". - """ - files = {} - for line in diff.splitlines(True): - if line.startswith('Index:') or line.startswith('Property changes on:'): - unused, filename = line.split(':', 1) - # On Windows if a file has property changes its filename uses '\' - # instead of '/'. - filename = filename.strip().replace('\\', '/') - files[filename] = self.GetBaseFile(filename) - return files - - - def UploadBaseFiles(self, issue, rpc_server, patch_list, patchset, options, - files): - """Uploads the base files (and if necessary, the current ones as well).""" - - def UploadFile(filename, file_id, content, is_binary, status, is_base): - """Uploads a file to the server.""" - file_too_large = False - if is_base: - type = "base" - else: - type = "current" - if len(content) > MAX_UPLOAD_SIZE: - print ("Not uploading the %s file for %s because it's too large." % - (type, filename)) - file_too_large = True - content = "" - checksum = md5.new(content).hexdigest() - if options.verbose > 0 and not file_too_large: - print "Uploading %s file for %s" % (type, filename) - url = "/%d/upload_content/%d/%d" % (int(issue), int(patchset), file_id) - form_fields = [("filename", filename), - ("status", status), - ("checksum", checksum), - ("is_binary", str(is_binary)), - ("is_current", str(not is_base)), - ] - if file_too_large: - form_fields.append(("file_too_large", "1")) - if options.email: - form_fields.append(("user", options.email)) - ctype, body = EncodeMultipartFormData(form_fields, - [("data", filename, content)]) - response_body = rpc_server.Send(url, body, - content_type=ctype) - if not response_body.startswith("OK"): - StatusUpdate(" --> %s" % response_body) - sys.exit(1) - - patches = dict() - [patches.setdefault(v, k) for k, v in patch_list] - for filename in patches.keys(): - base_content, new_content, is_binary, status = files[filename] - file_id_str = patches.get(filename) - if file_id_str.find("nobase") != -1: - base_content = None - file_id_str = file_id_str[file_id_str.rfind("_") + 1:] - file_id = int(file_id_str) - if base_content != None: - UploadFile(filename, file_id, base_content, is_binary, status, True) - if new_content != None: - UploadFile(filename, file_id, new_content, is_binary, status, False) - - def IsImage(self, filename): - """Returns true if the filename has an image extension.""" - mimetype = mimetypes.guess_type(filename)[0] - if not mimetype: - return False - return mimetype.startswith("image/") - - -class SubversionVCS(VersionControlSystem): - """Implementation of the VersionControlSystem interface for Subversion.""" - - def __init__(self, options): - super(SubversionVCS, self).__init__(options) - if self.options.revision: - match = re.match(r"(\d+)(:(\d+))?", self.options.revision) - if not match: - ErrorExit("Invalid Subversion revision %s." % self.options.revision) - self.rev_start = match.group(1) - self.rev_end = match.group(3) - else: - self.rev_start = self.rev_end = None - # Cache output from "svn list -r REVNO dirname". - # Keys: dirname, Values: 2-tuple (ouput for start rev and end rev). - self.svnls_cache = {} - # SVN base URL is required to fetch files deleted in an older revision. - # Result is cached to not guess it over and over again in GetBaseFile(). - required = self.options.download_base or self.options.revision is not None - self.svn_base = self._GuessBase(required) - - def GuessBase(self, required): - """Wrapper for _GuessBase.""" - return self.svn_base - - def _GuessBase(self, required): - """Returns the SVN base URL. - - Args: - required: If true, exits if the url can't be guessed, otherwise None is - returned. - """ - info = RunShell(["svn", "info"]) - for line in info.splitlines(): - words = line.split() - if len(words) == 2 and words[0] == "URL:": - url = words[1] - scheme, netloc, path, params, query, fragment = urlparse.urlparse(url) - username, netloc = urllib.splituser(netloc) - if username: - logging.info("Removed username from base URL") - if netloc.endswith("svn.python.org"): - if netloc == "svn.python.org": - if path.startswith("/projects/"): - path = path[9:] - elif netloc != "pythondev@svn.python.org": - ErrorExit("Unrecognized Python URL: %s" % url) - base = "http://svn.python.org/view/*checkout*%s/" % path - logging.info("Guessed Python base = %s", base) - elif netloc.endswith("svn.collab.net"): - if path.startswith("/repos/"): - path = path[6:] - base = "http://svn.collab.net/viewvc/*checkout*%s/" % path - logging.info("Guessed CollabNet base = %s", base) - elif netloc.endswith(".googlecode.com"): - path = path + "/" - base = urlparse.urlunparse(("http", netloc, path, params, - query, fragment)) - logging.info("Guessed Google Code base = %s", base) - else: - path = path + "/" - base = urlparse.urlunparse((scheme, netloc, path, params, - query, fragment)) - logging.info("Guessed base = %s", base) - return base - if required: - ErrorExit("Can't find URL in output from svn info") - return None - - def GenerateDiff(self, args): - cmd = ["svn", "diff"] - if self.options.revision: - cmd += ["-r", self.options.revision] - cmd.extend(args) - data = RunShell(cmd) - count = 0 - for line in data.splitlines(): - if line.startswith("Index:") or line.startswith("Property changes on:"): - count += 1 - logging.info(line) - if not count: - ErrorExit("No valid patches found in output from svn diff") - return data - - def _CollapseKeywords(self, content, keyword_str): - """Collapses SVN keywords.""" - # svn cat translates keywords but svn diff doesn't. As a result of this - # behavior patching.PatchChunks() fails with a chunk mismatch error. - # This part was originally written by the Review Board development team - # who had the same problem (https://reviews.reviewboard.org/r/276/). - # Mapping of keywords to known aliases - svn_keywords = { - # Standard keywords - 'Date': ['Date', 'LastChangedDate'], - 'Revision': ['Revision', 'LastChangedRevision', 'Rev'], - 'Author': ['Author', 'LastChangedBy'], - 'HeadURL': ['HeadURL', 'URL'], - 'Id': ['Id'], - - # Aliases - 'LastChangedDate': ['LastChangedDate', 'Date'], - 'LastChangedRevision': ['LastChangedRevision', 'Rev', 'Revision'], - 'LastChangedBy': ['LastChangedBy', 'Author'], - 'URL': ['URL', 'HeadURL'], - } - - def repl(m): - if m.group(2): - return "$%s::%s$" % (m.group(1), " " * len(m.group(3))) - return "$%s$" % m.group(1) - keywords = [keyword - for name in keyword_str.split(" ") - for keyword in svn_keywords.get(name, [])] - return re.sub(r"\$(%s):(:?)([^\$]+)\$" % '|'.join(keywords), repl, content) - - def GetUnknownFiles(self): - status = RunShell(["svn", "status", "--ignore-externals"], silent_ok=True) - unknown_files = [] - for line in status.split("\n"): - if line and line[0] == "?": - unknown_files.append(line) - return unknown_files - - def ReadFile(self, filename): - """Returns the contents of a file.""" - file = open(filename, 'rb') - result = "" - try: - result = file.read() - finally: - file.close() - return result - - def GetStatus(self, filename): - """Returns the status of a file.""" - if not self.options.revision: - status = RunShell(["svn", "status", "--ignore-externals", filename]) - if not status: - ErrorExit("svn status returned no output for %s" % filename) - status_lines = status.splitlines() - # If file is in a cl, the output will begin with - # "\n--- Changelist 'cl_name':\n". See - # https://web.archive.org/web/20090918234815/svn.collab.net/repos/svn/trunk/notes/changelist-design.txt - if (len(status_lines) == 3 and - not status_lines[0] and - status_lines[1].startswith("--- Changelist")): - status = status_lines[2] - else: - status = status_lines[0] - # If we have a revision to diff against we need to run "svn list" - # for the old and the new revision and compare the results to get - # the correct status for a file. - else: - dirname, relfilename = os.path.split(filename) - if dirname not in self.svnls_cache: - cmd = ["svn", "list", "-r", self.rev_start, dirname or "."] - out, returncode = RunShellWithReturnCode(cmd) - if returncode: - ErrorExit("Failed to get status for %s." % filename) - old_files = out.splitlines() - args = ["svn", "list"] - if self.rev_end: - args += ["-r", self.rev_end] - cmd = args + [dirname or "."] - out, returncode = RunShellWithReturnCode(cmd) - if returncode: - ErrorExit("Failed to run command %s" % cmd) - self.svnls_cache[dirname] = (old_files, out.splitlines()) - old_files, new_files = self.svnls_cache[dirname] - if relfilename in old_files and relfilename not in new_files: - status = "D " - elif relfilename in old_files and relfilename in new_files: - status = "M " - else: - status = "A " - return status - - def GetBaseFile(self, filename): - status = self.GetStatus(filename) - base_content = None - new_content = None - - # If a file is copied its status will be "A +", which signifies - # "addition-with-history". See "svn st" for more information. We need to - # upload the original file or else diff parsing will fail if the file was - # edited. - if status[0] == "A" and status[3] != "+": - # We'll need to upload the new content if we're adding a binary file - # since diff's output won't contain it. - mimetype = RunShell(["svn", "propget", "svn:mime-type", filename], - silent_ok=True) - base_content = "" - is_binary = mimetype and not mimetype.startswith("text/") - if is_binary and self.IsImage(filename): - new_content = self.ReadFile(filename) - elif (status[0] in ("M", "D", "R") or - (status[0] == "A" and status[3] == "+") or # Copied file. - (status[0] == " " and status[1] == "M")): # Property change. - args = [] - if self.options.revision: - url = "%s/%s@%s" % (self.svn_base, filename, self.rev_start) - else: - # Don't change filename, it's needed later. - url = filename - args += ["-r", "BASE"] - cmd = ["svn"] + args + ["propget", "svn:mime-type", url] - mimetype, returncode = RunShellWithReturnCode(cmd) - if returncode: - # File does not exist in the requested revision. - # Reset mimetype, it contains an error message. - mimetype = "" - get_base = False - is_binary = mimetype and not mimetype.startswith("text/") - if status[0] == " ": - # Empty base content just to force an upload. - base_content = "" - elif is_binary: - if self.IsImage(filename): - get_base = True - if status[0] == "M": - if not self.rev_end: - new_content = self.ReadFile(filename) - else: - url = "%s/%s@%s" % (self.svn_base, filename, self.rev_end) - new_content = RunShell(["svn", "cat", url], - universal_newlines=True, silent_ok=True) - else: - base_content = "" - else: - get_base = True - - if get_base: - if is_binary: - universal_newlines = False - else: - universal_newlines = True - if self.rev_start: - # "svn cat -r REV delete_file.txt" doesn't work. cat requires - # the full URL with "@REV" appended instead of using "-r" option. - url = "%s/%s@%s" % (self.svn_base, filename, self.rev_start) - base_content = RunShell(["svn", "cat", url], - universal_newlines=universal_newlines, - silent_ok=True) - else: - base_content = RunShell(["svn", "cat", filename], - universal_newlines=universal_newlines, - silent_ok=True) - if not is_binary: - args = [] - if self.rev_start: - url = "%s/%s@%s" % (self.svn_base, filename, self.rev_start) - else: - url = filename - args += ["-r", "BASE"] - cmd = ["svn"] + args + ["propget", "svn:keywords", url] - keywords, returncode = RunShellWithReturnCode(cmd) - if keywords and not returncode: - base_content = self._CollapseKeywords(base_content, keywords) - else: - StatusUpdate("svn status returned unexpected output: %s" % status) - sys.exit(1) - return base_content, new_content, is_binary, status[0:5] - - -class GitVCS(VersionControlSystem): - """Implementation of the VersionControlSystem interface for Git.""" - - def __init__(self, options): - super(GitVCS, self).__init__(options) - # Map of filename -> hash of base file. - self.base_hashes = {} - - def GenerateDiff(self, extra_args): - # This is more complicated than svn's GenerateDiff because we must convert - # the diff output to include an svn-style "Index:" line as well as record - # the hashes of the base files, so we can upload them along with our diff. - if self.options.revision: - extra_args = [self.options.revision] + extra_args - gitdiff = RunShell(["git", "diff", "--full-index"] + extra_args) - svndiff = [] - filecount = 0 - filename = None - for line in gitdiff.splitlines(): - match = re.match(r"diff --git a/(.*) b/.*$", line) - if match: - filecount += 1 - filename = match.group(1) - svndiff.append("Index: %s\n" % filename) - else: - # The "index" line in a git diff looks like this (long hashes elided): - # index 82c0d44..b2cee3f 100755 - # We want to save the left hash, as that identifies the base file. - match = re.match(r"index (\w+)\.\.", line) - if match: - self.base_hashes[filename] = match.group(1) - svndiff.append(line + "\n") - if not filecount: - ErrorExit("No valid patches found in output from git diff") - return "".join(svndiff) - - def GetUnknownFiles(self): - status = RunShell(["git", "ls-files", "--exclude-standard", "--others"], - silent_ok=True) - return status.splitlines() - - def GetBaseFile(self, filename): - hash = self.base_hashes[filename] - base_content = None - new_content = None - is_binary = False - if hash == "0" * 40: # All-zero hash indicates no base file. - status = "A" - base_content = "" - else: - status = "M" - base_content, returncode = RunShellWithReturnCode(["git", "show", hash]) - if returncode: - ErrorExit("Got error status from 'git show %s'" % hash) - return (base_content, new_content, is_binary, status) - - -class MercurialVCS(VersionControlSystem): - """Implementation of the VersionControlSystem interface for Mercurial.""" - - def __init__(self, options, repo_dir): - super(MercurialVCS, self).__init__(options) - # Absolute path to repository (we can be in a subdir) - self.repo_dir = os.path.normpath(repo_dir) - # Compute the subdir - cwd = os.path.normpath(os.getcwd()) - assert cwd.startswith(self.repo_dir) - self.subdir = cwd[len(self.repo_dir):].lstrip(r"\/") - if self.options.revision: - self.base_rev = self.options.revision - else: - self.base_rev = RunShell(["hg", "parent", "-q"]).split(':')[1].strip() - - def _GetRelPath(self, filename): - """Get relative path of a file according to the current directory, - given its logical path in the repo.""" - assert filename.startswith(self.subdir), filename - return filename[len(self.subdir):].lstrip(r"\/") - - def GenerateDiff(self, extra_args): - # If no file specified, restrict to the current subdir - extra_args = extra_args or ["."] - cmd = ["hg", "diff", "--git", "-r", self.base_rev] + extra_args - data = RunShell(cmd, silent_ok=True) - svndiff = [] - filecount = 0 - for line in data.splitlines(): - m = re.match("diff --git a/(\S+) b/(\S+)", line) - if m: - # Modify line to make it look like as it comes from svn diff. - # With this modification no changes on the server side are required - # to make upload.py work with Mercurial repos. - # NOTE: for proper handling of moved/copied files, we have to use - # the second filename. - filename = m.group(2) - svndiff.append("Index: %s" % filename) - svndiff.append("=" * 67) - filecount += 1 - logging.info(line) - else: - svndiff.append(line) - if not filecount: - ErrorExit("No valid patches found in output from hg diff") - return "\n".join(svndiff) + "\n" - - def GetUnknownFiles(self): - """Return a list of files unknown to the VCS.""" - args = [] - status = RunShell(["hg", "status", "--rev", self.base_rev, "-u", "."], - silent_ok=True) - unknown_files = [] - for line in status.splitlines(): - st, fn = line.split(" ", 1) - if st == "?": - unknown_files.append(fn) - return unknown_files - - def GetBaseFile(self, filename): - # "hg status" and "hg cat" both take a path relative to the current subdir - # rather than to the repo root, but "hg diff" has given us the full path - # to the repo root. - base_content = "" - new_content = None - is_binary = False - oldrelpath = relpath = self._GetRelPath(filename) - # "hg status -C" returns two lines for moved/copied files, one otherwise - out = RunShell(["hg", "status", "-C", "--rev", self.base_rev, relpath]) - out = out.splitlines() - # HACK: strip error message about missing file/directory if it isn't in - # the working copy - if out[0].startswith('%s: ' % relpath): - out = out[1:] - if len(out) > 1: - # Moved/copied => considered as modified, use old filename to - # retrieve base contents - oldrelpath = out[1].strip() - status = "M" - else: - status, _ = out[0].split(' ', 1) - if status != "A": - base_content = RunShell(["hg", "cat", "-r", self.base_rev, oldrelpath], - silent_ok=True) - is_binary = "\0" in base_content # Mercurial's heuristic - if status != "R": - new_content = open(relpath, "rb").read() - is_binary = is_binary or "\0" in new_content - if is_binary and base_content: - # Fetch again without converting newlines - base_content = RunShell(["hg", "cat", "-r", self.base_rev, oldrelpath], - silent_ok=True, universal_newlines=False) - if not is_binary or not self.IsImage(relpath): - new_content = None - return base_content, new_content, is_binary, status - - -# NOTE: The SplitPatch function is duplicated in engine.py, keep them in sync. -def SplitPatch(data): - """Splits a patch into separate pieces for each file. - - Args: - data: A string containing the output of svn diff. - - Returns: - A list of 2-tuple (filename, text) where text is the svn diff output - pertaining to filename. - """ - patches = [] - filename = None - diff = [] - for line in data.splitlines(True): - new_filename = None - if line.startswith('Index:'): - unused, new_filename = line.split(':', 1) - new_filename = new_filename.strip() - elif line.startswith('Property changes on:'): - unused, temp_filename = line.split(':', 1) - # When a file is modified, paths use '/' between directories, however - # when a property is modified '\' is used on Windows. Make them the same - # otherwise the file shows up twice. - temp_filename = temp_filename.strip().replace('\\', '/') - if temp_filename != filename: - # File has property changes but no modifications, create a new diff. - new_filename = temp_filename - if new_filename: - if filename and diff: - patches.append((filename, ''.join(diff))) - filename = new_filename - diff = [line] - continue - if diff is not None: - diff.append(line) - if filename and diff: - patches.append((filename, ''.join(diff))) - return patches - - -def UploadSeparatePatches(issue, rpc_server, patchset, data, options): - """Uploads a separate patch for each file in the diff output. - - Returns a list of [patch_key, filename] for each file. - """ - patches = SplitPatch(data) - rv = [] - for patch in patches: - if len(patch[1]) > MAX_UPLOAD_SIZE: - print ("Not uploading the patch for " + patch[0] + - " because the file is too large.") - continue - form_fields = [("filename", patch[0])] - if not options.download_base: - form_fields.append(("content_upload", "1")) - files = [("data", "data.diff", patch[1])] - ctype, body = EncodeMultipartFormData(form_fields, files) - url = "/%d/upload_patch/%d" % (int(issue), int(patchset)) - print "Uploading patch for " + patch[0] - response_body = rpc_server.Send(url, body, content_type=ctype) - lines = response_body.splitlines() - if not lines or lines[0] != "OK": - StatusUpdate(" --> %s" % response_body) - sys.exit(1) - rv.append([lines[1], patch[0]]) - return rv - - -def GuessVCS(options): - """Helper to guess the version control system. - - This examines the current directory, guesses which VersionControlSystem - we're using, and returns an instance of the appropriate class. Exit with an - error if we can't figure it out. - - Returns: - A VersionControlSystem instance. Exits if the VCS can't be guessed. - """ - # Mercurial has a command to get the base directory of a repository - # Try running it, but don't die if we don't have hg installed. - # NOTE: we try Mercurial first as it can sit on top of an SVN working copy. - try: - out, returncode = RunShellWithReturnCode(["hg", "root"]) - if returncode == 0: - return MercurialVCS(options, out.strip()) - except OSError, (errno, message): - if errno != 2: # ENOENT -- they don't have hg installed. - raise - - # Subversion has a .svn in all working directories. - if os.path.isdir('.svn'): - logging.info("Guessed VCS = Subversion") - return SubversionVCS(options) - - # Git has a command to test if you're in a git tree. - # Try running it, but don't die if we don't have git installed. - try: - out, returncode = RunShellWithReturnCode(["git", "rev-parse", - "--is-inside-work-tree"]) - if returncode == 0: - return GitVCS(options) - except OSError, (errno, message): - if errno != 2: # ENOENT -- they don't have git installed. - raise - - ErrorExit(("Could not guess version control system. " - "Are you in a working copy directory?")) - - -def RealMain(argv, data=None): - """The real main function. - - Args: - argv: Command line arguments. - data: Diff contents. If None (default) the diff is generated by - the VersionControlSystem implementation returned by GuessVCS(). - - Returns: - A 2-tuple (issue id, patchset id). - The patchset id is None if the base files are not uploaded by this - script (applies only to SVN checkouts). - """ - logging.basicConfig(format=("%(asctime).19s %(levelname)s %(filename)s:" - "%(lineno)s %(message)s ")) - os.environ['LC_ALL'] = 'C' - options, args = parser.parse_args(argv[1:]) - global verbosity - verbosity = options.verbose - if verbosity >= 3: - logging.getLogger().setLevel(logging.DEBUG) - elif verbosity >= 2: - logging.getLogger().setLevel(logging.INFO) - vcs = GuessVCS(options) - if isinstance(vcs, SubversionVCS): - # base field is only allowed for Subversion. - # Note: Fetching base files may become deprecated in future releases. - base = vcs.GuessBase(options.download_base) - else: - base = None - if not base and options.download_base: - options.download_base = True - logging.info("Enabled upload of base file") - if not options.assume_yes: - vcs.CheckForUnknownFiles() - if data is None: - data = vcs.GenerateDiff(args) - files = vcs.GetBaseFiles(data) - if verbosity >= 1: - print "Upload server:", options.server, "(change with -s/--server)" - if options.issue: - prompt = "Message describing this patch set: " - else: - prompt = "New issue subject: " - message = options.message or raw_input(prompt).strip() - if not message: - ErrorExit("A non-empty message is required") - rpc_server = GetRpcServer(options) - form_fields = [("subject", message)] - if base: - form_fields.append(("base", base)) - if options.issue: - form_fields.append(("issue", str(options.issue))) - if options.email: - form_fields.append(("user", options.email)) - if options.reviewers: - for reviewer in options.reviewers.split(','): - if "@" in reviewer and not reviewer.split("@")[1].count(".") == 1: - ErrorExit("Invalid email address: %s" % reviewer) - form_fields.append(("reviewers", options.reviewers)) - if options.cc: - for cc in options.cc.split(','): - if "@" in cc and not cc.split("@")[1].count(".") == 1: - ErrorExit("Invalid email address: %s" % cc) - form_fields.append(("cc", options.cc)) - description = options.description - if options.description_file: - if options.description: - ErrorExit("Can't specify description and description_file") - file = open(options.description_file, 'r') - description = file.read() - file.close() - if description: - form_fields.append(("description", description)) - # Send a hash of all the base file so the server can determine if a copy - # already exists in an earlier patchset. - base_hashes = "" - for file, info in files.iteritems(): - if not info[0] is None: - checksum = md5.new(info[0]).hexdigest() - if base_hashes: - base_hashes += "|" - base_hashes += checksum + ":" + file - form_fields.append(("base_hashes", base_hashes)) - # If we're uploading base files, don't send the email before the uploads, so - # that it contains the file status. - if options.send_mail and options.download_base: - form_fields.append(("send_mail", "1")) - if not options.download_base: - form_fields.append(("content_upload", "1")) - if len(data) > MAX_UPLOAD_SIZE: - print "Patch is large, so uploading file patches separately." - uploaded_diff_file = [] - form_fields.append(("separate_patches", "1")) - else: - uploaded_diff_file = [("data", "data.diff", data)] - ctype, body = EncodeMultipartFormData(form_fields, uploaded_diff_file) - response_body = rpc_server.Send("/upload", body, content_type=ctype) - patchset = None - if not options.download_base or not uploaded_diff_file: - lines = response_body.splitlines() - if len(lines) >= 2: - msg = lines[0] - patchset = lines[1].strip() - patches = [x.split(" ", 1) for x in lines[2:]] - else: - msg = response_body - else: - msg = response_body - StatusUpdate(msg) - if not response_body.startswith("Issue created.") and \ - not response_body.startswith("Issue updated."): - sys.exit(0) - issue = msg[msg.rfind("/")+1:] - - if not uploaded_diff_file: - result = UploadSeparatePatches(issue, rpc_server, patchset, data, options) - if not options.download_base: - patches = result - - if not options.download_base: - vcs.UploadBaseFiles(issue, rpc_server, patches, patchset, options, files) - if options.send_mail: - rpc_server.Send("/" + issue + "/mail", payload="") - return issue, patchset - - -def main(): - try: - RealMain(sys.argv) - except KeyboardInterrupt: - print - StatusUpdate("Interrupted.") - sys.exit(1) - - -if __name__ == "__main__": - main() diff --git a/googlemock/scripts/upload_gmock.py b/googlemock/scripts/upload_gmock.py deleted file mode 100755 index 5dc484b3..00000000 --- a/googlemock/scripts/upload_gmock.py +++ /dev/null @@ -1,78 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2009, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -"""upload_gmock.py v0.1.0 -- uploads a Google Mock patch for review. - -This simple wrapper passes all command line flags and ---cc=googlemock@googlegroups.com to upload.py. - -USAGE: upload_gmock.py [options for upload.py] -""" - -__author__ = 'wan@google.com (Zhanyong Wan)' - -import os -import sys - -CC_FLAG = '--cc=' -GMOCK_GROUP = 'googlemock@googlegroups.com' - - -def main(): - # Finds the path to upload.py, assuming it is in the same directory - # as this file. - my_dir = os.path.dirname(os.path.abspath(__file__)) - upload_py_path = os.path.join(my_dir, 'upload.py') - - # Adds Google Mock discussion group to the cc line if it's not there - # already. - upload_py_argv = [upload_py_path] - found_cc_flag = False - for arg in sys.argv[1:]: - if arg.startswith(CC_FLAG): - found_cc_flag = True - cc_line = arg[len(CC_FLAG):] - cc_list = [addr for addr in cc_line.split(',') if addr] - if GMOCK_GROUP not in cc_list: - cc_list.append(GMOCK_GROUP) - upload_py_argv.append(CC_FLAG + ','.join(cc_list)) - else: - upload_py_argv.append(arg) - - if not found_cc_flag: - upload_py_argv.append(CC_FLAG + GMOCK_GROUP) - - # Invokes upload.py with the modified command line flags. - os.execv(upload_py_path, upload_py_argv) - - -if __name__ == '__main__': - main() diff --git a/googlemock/src/gmock-matchers.cc b/googlemock/src/gmock-matchers.cc index 4a3f7af2..4f73e0a6 100644 --- a/googlemock/src/gmock-matchers.cc +++ b/googlemock/src/gmock-matchers.cc @@ -34,7 +34,6 @@ // utilities for defining matchers. #include "gmock/gmock-matchers.h" -#include "gmock/gmock-generated-matchers.h" #include <string.h> #include <iostream> diff --git a/googlemock/src/gmock-spec-builders.cc b/googlemock/src/gmock-spec-builders.cc index f9d34345..81ea9894 100644 --- a/googlemock/src/gmock-spec-builders.cc +++ b/googlemock/src/gmock-spec-builders.cc @@ -36,14 +36,17 @@ #include "gmock/gmock-spec-builders.h" #include <stdlib.h> + #include <iostream> // NOLINT #include <map> #include <memory> #include <set> #include <string> #include <vector> + #include "gmock/gmock.h" #include "gtest/gtest.h" +#include "gtest/internal/gtest-port.h" #if GTEST_OS_CYGWIN || GTEST_OS_LINUX || GTEST_OS_MAC # include <unistd.h> // NOLINT @@ -70,7 +73,8 @@ GTEST_API_ void LogWithLocation(testing::internal::LogSeverity severity, const char* file, int line, const std::string& message) { ::std::ostringstream s; - s << file << ":" << line << ": " << message << ::std::endl; + s << internal::FormatFileLocation(file, line) << " " << message + << ::std::endl; Log(severity, s.str(), 0); } diff --git a/googlemock/src/gmock_main.cc b/googlemock/src/gmock_main.cc index 98611b93..18c500f6 100644 --- a/googlemock/src/gmock_main.cc +++ b/googlemock/src/gmock_main.cc @@ -32,7 +32,10 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" -#ifdef ARDUINO +#if GTEST_OS_ESP8266 || GTEST_OS_ESP32 +#if GTEST_OS_ESP8266 +extern "C" { +#endif void setup() { // Since Google Mock depends on Google Test, InitGoogleMock() is // also responsible for initializing Google Test. Therefore there's @@ -40,6 +43,10 @@ void setup() { testing::InitGoogleMock(); } void loop() { RUN_ALL_TESTS(); } +#if GTEST_OS_ESP8266 +} +#endif + #else // MS C++ compiler/linker has a bug on Windows (not on Windows CE), which diff --git a/googlemock/test/gmock-actions_test.cc b/googlemock/test/gmock-actions_test.cc index f63c8c5a..d1229ac9 100644 --- a/googlemock/test/gmock-actions_test.cc +++ b/googlemock/test/gmock-actions_test.cc @@ -46,6 +46,7 @@ #include <iterator> #include <memory> #include <string> +#include <type_traits> #include "gmock/gmock.h" #include "gmock/internal/gmock-port.h" #include "gtest/gtest.h" @@ -73,13 +74,12 @@ using testing::Return; using testing::ReturnNull; using testing::ReturnRef; using testing::ReturnRefOfCopy; +using testing::ReturnRoundRobin; using testing::SetArgPointee; using testing::SetArgumentPointee; using testing::Unused; using testing::WithArgs; using testing::internal::BuiltInDefaultValue; -using testing::internal::Int64; -using testing::internal::UInt64; #if !GTEST_OS_WINDOWS_MOBILE using testing::SetErrnoAndReturn; @@ -121,8 +121,9 @@ TEST(BuiltInDefaultValueTest, IsZeroForNumericTypes) { EXPECT_EQ(0U, BuiltInDefaultValue<unsigned long>::Get()); // NOLINT EXPECT_EQ(0, BuiltInDefaultValue<signed long>::Get()); // NOLINT EXPECT_EQ(0, BuiltInDefaultValue<long>::Get()); // NOLINT - EXPECT_EQ(0U, BuiltInDefaultValue<UInt64>::Get()); - EXPECT_EQ(0, BuiltInDefaultValue<Int64>::Get()); + EXPECT_EQ(0U, BuiltInDefaultValue<unsigned long long>::Get()); // NOLINT + EXPECT_EQ(0, BuiltInDefaultValue<signed long long>::Get()); // NOLINT + EXPECT_EQ(0, BuiltInDefaultValue<long long>::Get()); // NOLINT EXPECT_EQ(0, BuiltInDefaultValue<float>::Get()); EXPECT_EQ(0, BuiltInDefaultValue<double>::Get()); } @@ -145,8 +146,9 @@ TEST(BuiltInDefaultValueTest, ExistsForNumericTypes) { EXPECT_TRUE(BuiltInDefaultValue<unsigned long>::Exists()); // NOLINT EXPECT_TRUE(BuiltInDefaultValue<signed long>::Exists()); // NOLINT EXPECT_TRUE(BuiltInDefaultValue<long>::Exists()); // NOLINT - EXPECT_TRUE(BuiltInDefaultValue<UInt64>::Exists()); - EXPECT_TRUE(BuiltInDefaultValue<Int64>::Exists()); + EXPECT_TRUE(BuiltInDefaultValue<unsigned long long>::Exists()); // NOLINT + EXPECT_TRUE(BuiltInDefaultValue<signed long long>::Exists()); // NOLINT + EXPECT_TRUE(BuiltInDefaultValue<long long>::Exists()); // NOLINT EXPECT_TRUE(BuiltInDefaultValue<float>::Exists()); EXPECT_TRUE(BuiltInDefaultValue<double>::Exists()); } @@ -646,6 +648,41 @@ TEST(ReturnRefTest, IsCovariant) { EXPECT_EQ(&derived, &a.Perform(std::make_tuple())); } +template <typename T, typename = decltype(ReturnRef(std::declval<T&&>()))> +bool CanCallReturnRef(T&&) { return true; } +bool CanCallReturnRef(Unused) { return false; } + +// Tests that ReturnRef(v) is working with non-temporaries (T&) +TEST(ReturnRefTest, WorksForNonTemporary) { + int scalar_value = 123; + EXPECT_TRUE(CanCallReturnRef(scalar_value)); + + std::string non_scalar_value("ABC"); + EXPECT_TRUE(CanCallReturnRef(non_scalar_value)); + + const int const_scalar_value{321}; + EXPECT_TRUE(CanCallReturnRef(const_scalar_value)); + + const std::string const_non_scalar_value("CBA"); + EXPECT_TRUE(CanCallReturnRef(const_non_scalar_value)); +} + +// Tests that ReturnRef(v) is not working with temporaries (T&&) +TEST(ReturnRefTest, DoesNotWorkForTemporary) { + auto scalar_value = []() -> int { return 123; }; + EXPECT_FALSE(CanCallReturnRef(scalar_value())); + + auto non_scalar_value = []() -> std::string { return "ABC"; }; + EXPECT_FALSE(CanCallReturnRef(non_scalar_value())); + + // cannot use here callable returning "const scalar type", + // because such const for scalar return type is ignored + EXPECT_FALSE(CanCallReturnRef(static_cast<const int>(321))); + + auto const_non_scalar_value = []() -> const std::string { return "CBA"; }; + EXPECT_FALSE(CanCallReturnRef(const_non_scalar_value())); +} + // Tests that ReturnRefOfCopy(v) works for reference types. TEST(ReturnRefOfCopyTest, WorksForReference) { int n = 42; @@ -670,6 +707,31 @@ TEST(ReturnRefOfCopyTest, IsCovariant) { EXPECT_NE(&derived, &a.Perform(std::make_tuple())); } +// Tests that ReturnRoundRobin(v) works with initializer lists +TEST(ReturnRoundRobinTest, WorksForInitList) { + Action<int()> ret = ReturnRoundRobin({1, 2, 3}); + + EXPECT_EQ(1, ret.Perform(std::make_tuple())); + EXPECT_EQ(2, ret.Perform(std::make_tuple())); + EXPECT_EQ(3, ret.Perform(std::make_tuple())); + EXPECT_EQ(1, ret.Perform(std::make_tuple())); + EXPECT_EQ(2, ret.Perform(std::make_tuple())); + EXPECT_EQ(3, ret.Perform(std::make_tuple())); +} + +// Tests that ReturnRoundRobin(v) works with vectors +TEST(ReturnRoundRobinTest, WorksForVector) { + std::vector<double> v = {4.4, 5.5, 6.6}; + Action<double()> ret = ReturnRoundRobin(v); + + EXPECT_EQ(4.4, ret.Perform(std::make_tuple())); + EXPECT_EQ(5.5, ret.Perform(std::make_tuple())); + EXPECT_EQ(6.6, ret.Perform(std::make_tuple())); + EXPECT_EQ(4.4, ret.Perform(std::make_tuple())); + EXPECT_EQ(5.5, ret.Perform(std::make_tuple())); + EXPECT_EQ(6.6, ret.Perform(std::make_tuple())); +} + // Tests that DoDefault() does the default action for the mock method. class MockClass { @@ -1408,8 +1470,19 @@ TEST(FunctorActionTest, TypeConversion) { EXPECT_EQ(1, s2.Perform(std::make_tuple("hello"))); // Also between the lambda and the action itself. - const Action<bool(std::string)> x = [](Unused) { return 42; }; - EXPECT_TRUE(x.Perform(std::make_tuple("hello"))); + const Action<bool(std::string)> x1 = [](Unused) { return 42; }; + const Action<bool(std::string)> x2 = [] { return 42; }; + EXPECT_TRUE(x1.Perform(std::make_tuple("hello"))); + EXPECT_TRUE(x2.Perform(std::make_tuple("hello"))); + + // Ensure decay occurs where required. + std::function<int()> f = [] { return 7; }; + Action<int(int)> d = f; + f = nullptr; + EXPECT_EQ(7, d.Perform(std::make_tuple(1))); + + // Ensure creation of an empty action succeeds. + Action<void(int)>(nullptr); } TEST(FunctorActionTest, UnusedArguments) { diff --git a/googlemock/test/gmock-function-mocker_test.cc b/googlemock/test/gmock-function-mocker_test.cc index fbc5d5b2..019e3cb9 100644 --- a/googlemock/test/gmock-function-mocker_test.cc +++ b/googlemock/test/gmock-function-mocker_test.cc @@ -31,7 +31,7 @@ // Google Mock - a framework for writing C++ mock classes. // // This file tests the function mocker classes. -#include "gmock/gmock-generated-function-mockers.h" +#include "gmock/gmock-function-mocker.h" #if GTEST_OS_WINDOWS // MSDN says the header file to be included for STDMETHOD is BaseTyps.h but @@ -42,6 +42,8 @@ #include <map> #include <string> +#include <type_traits> + #include "gmock/gmock.h" #include "gtest/gtest.h" @@ -101,6 +103,10 @@ class FooInterface { virtual int TypeWithComma(const std::map<int, std::string>& a_map) = 0; virtual int TypeWithTemplatedCopyCtor(const TemplatedCopyable<int>&) = 0; + virtual int (*ReturnsFunctionPointer1(int))(bool) = 0; + using fn_ptr = int (*)(bool); + virtual fn_ptr ReturnsFunctionPointer2(int) = 0; + #if GTEST_OS_WINDOWS STDMETHOD_(int, CTNullary)() = 0; STDMETHOD_(bool, CTUnary)(int x) = 0; @@ -159,6 +165,9 @@ class MockFoo : public FooInterface { MOCK_METHOD(int, TypeWithTemplatedCopyCtor, (const TemplatedCopyable<int>&)); // NOLINT + MOCK_METHOD(int (*)(bool), ReturnsFunctionPointer1, (int), ()); + MOCK_METHOD(fn_ptr, ReturnsFunctionPointer2, (int), ()); + #if GTEST_OS_WINDOWS MOCK_METHOD(int, CTNullary, (), (Calltype(STDMETHODCALLTYPE))); MOCK_METHOD(bool, CTUnary, (int), (Calltype(STDMETHODCALLTYPE))); @@ -174,182 +183,238 @@ class MockFoo : public FooInterface { private: GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFoo); }; + +class LegacyMockFoo : public FooInterface { + public: + LegacyMockFoo() {} + + // Makes sure that a mock function parameter can be named. + MOCK_METHOD1(VoidReturning, void(int n)); // NOLINT + + MOCK_METHOD0(Nullary, int()); // NOLINT + + // Makes sure that a mock function parameter can be unnamed. + MOCK_METHOD1(Unary, bool(int)); // NOLINT + MOCK_METHOD2(Binary, long(short, int)); // NOLINT + MOCK_METHOD10(Decimal, int(bool, char, short, int, long, float, // NOLINT + double, unsigned, char*, const std::string& str)); + + MOCK_METHOD1(TakesNonConstReference, bool(int&)); // NOLINT + MOCK_METHOD1(TakesConstReference, std::string(const int&)); + MOCK_METHOD1(TakesConst, bool(const int)); // NOLINT + + // Tests that the function return type can contain unprotected comma. + MOCK_METHOD0(ReturnTypeWithComma, std::map<int, std::string>()); + MOCK_CONST_METHOD1(ReturnTypeWithComma, + std::map<int, std::string>(int)); // NOLINT + + MOCK_METHOD0(OverloadedOnArgumentNumber, int()); // NOLINT + MOCK_METHOD1(OverloadedOnArgumentNumber, int(int)); // NOLINT + + MOCK_METHOD1(OverloadedOnArgumentType, int(int)); // NOLINT + MOCK_METHOD1(OverloadedOnArgumentType, char(char)); // NOLINT + + MOCK_METHOD0(OverloadedOnConstness, int()); // NOLINT + MOCK_CONST_METHOD0(OverloadedOnConstness, char()); // NOLINT + + MOCK_METHOD1(TypeWithHole, int(int (*)())); // NOLINT + MOCK_METHOD1(TypeWithComma, + int(const std::map<int, std::string>&)); // NOLINT + MOCK_METHOD1(TypeWithTemplatedCopyCtor, + int(const TemplatedCopyable<int>&)); // NOLINT + + MOCK_METHOD1(ReturnsFunctionPointer1, int (*(int))(bool)); + MOCK_METHOD1(ReturnsFunctionPointer2, fn_ptr(int)); + +#if GTEST_OS_WINDOWS + MOCK_METHOD0_WITH_CALLTYPE(STDMETHODCALLTYPE, CTNullary, int()); + MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, CTUnary, bool(int)); // NOLINT + MOCK_METHOD10_WITH_CALLTYPE(STDMETHODCALLTYPE, CTDecimal, + int(bool b, char c, short d, int e, // NOLINT + long f, float g, double h, // NOLINT + unsigned i, char* j, const std::string& k)); + MOCK_CONST_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, CTConst, + char(int)); // NOLINT + + // Tests that the function return type can contain unprotected comma. + MOCK_METHOD0_WITH_CALLTYPE(STDMETHODCALLTYPE, CTReturnTypeWithComma, + std::map<int, std::string>()); +#endif // GTEST_OS_WINDOWS + + private: + GTEST_DISALLOW_COPY_AND_ASSIGN_(LegacyMockFoo); +}; + #ifdef _MSC_VER # pragma warning(pop) #endif -class MockMethodFunctionMockerTest : public testing::Test { +template <class T> +class FunctionMockerTest : public testing::Test { protected: - MockMethodFunctionMockerTest() : foo_(&mock_foo_) {} + FunctionMockerTest() : foo_(&mock_foo_) {} FooInterface* const foo_; - MockFoo mock_foo_; + T mock_foo_; }; +using FunctionMockerTestTypes = ::testing::Types<MockFoo, LegacyMockFoo>; +TYPED_TEST_SUITE(FunctionMockerTest, FunctionMockerTestTypes); // Tests mocking a void-returning function. -TEST_F(MockMethodFunctionMockerTest, MocksVoidFunction) { - EXPECT_CALL(mock_foo_, VoidReturning(Lt(100))); - foo_->VoidReturning(0); +TYPED_TEST(FunctionMockerTest, MocksVoidFunction) { + EXPECT_CALL(this->mock_foo_, VoidReturning(Lt(100))); + this->foo_->VoidReturning(0); } // Tests mocking a nullary function. -TEST_F(MockMethodFunctionMockerTest, MocksNullaryFunction) { - EXPECT_CALL(mock_foo_, Nullary()) +TYPED_TEST(FunctionMockerTest, MocksNullaryFunction) { + EXPECT_CALL(this->mock_foo_, Nullary()) .WillOnce(DoDefault()) .WillOnce(Return(1)); - EXPECT_EQ(0, foo_->Nullary()); - EXPECT_EQ(1, foo_->Nullary()); + EXPECT_EQ(0, this->foo_->Nullary()); + EXPECT_EQ(1, this->foo_->Nullary()); } // Tests mocking a unary function. -TEST_F(MockMethodFunctionMockerTest, MocksUnaryFunction) { - EXPECT_CALL(mock_foo_, Unary(Eq(2))) - .Times(2) - .WillOnce(Return(true)); +TYPED_TEST(FunctionMockerTest, MocksUnaryFunction) { + EXPECT_CALL(this->mock_foo_, Unary(Eq(2))).Times(2).WillOnce(Return(true)); - EXPECT_TRUE(foo_->Unary(2)); - EXPECT_FALSE(foo_->Unary(2)); + EXPECT_TRUE(this->foo_->Unary(2)); + EXPECT_FALSE(this->foo_->Unary(2)); } // Tests mocking a binary function. -TEST_F(MockMethodFunctionMockerTest, MocksBinaryFunction) { - EXPECT_CALL(mock_foo_, Binary(2, _)) - .WillOnce(Return(3)); +TYPED_TEST(FunctionMockerTest, MocksBinaryFunction) { + EXPECT_CALL(this->mock_foo_, Binary(2, _)).WillOnce(Return(3)); - EXPECT_EQ(3, foo_->Binary(2, 1)); + EXPECT_EQ(3, this->foo_->Binary(2, 1)); } // Tests mocking a decimal function. -TEST_F(MockMethodFunctionMockerTest, MocksDecimalFunction) { - EXPECT_CALL(mock_foo_, Decimal(true, 'a', 0, 0, 1L, A<float>(), - Lt(100), 5U, NULL, "hi")) +TYPED_TEST(FunctionMockerTest, MocksDecimalFunction) { + EXPECT_CALL(this->mock_foo_, + Decimal(true, 'a', 0, 0, 1L, A<float>(), Lt(100), 5U, NULL, "hi")) .WillOnce(Return(5)); - EXPECT_EQ(5, foo_->Decimal(true, 'a', 0, 0, 1, 0, 0, 5, nullptr, "hi")); + EXPECT_EQ(5, this->foo_->Decimal(true, 'a', 0, 0, 1, 0, 0, 5, nullptr, "hi")); } // Tests mocking a function that takes a non-const reference. -TEST_F(MockMethodFunctionMockerTest, - MocksFunctionWithNonConstReferenceArgument) { +TYPED_TEST(FunctionMockerTest, MocksFunctionWithNonConstReferenceArgument) { int a = 0; - EXPECT_CALL(mock_foo_, TakesNonConstReference(Ref(a))) + EXPECT_CALL(this->mock_foo_, TakesNonConstReference(Ref(a))) .WillOnce(Return(true)); - EXPECT_TRUE(foo_->TakesNonConstReference(a)); + EXPECT_TRUE(this->foo_->TakesNonConstReference(a)); } // Tests mocking a function that takes a const reference. -TEST_F(MockMethodFunctionMockerTest, MocksFunctionWithConstReferenceArgument) { +TYPED_TEST(FunctionMockerTest, MocksFunctionWithConstReferenceArgument) { int a = 0; - EXPECT_CALL(mock_foo_, TakesConstReference(Ref(a))) + EXPECT_CALL(this->mock_foo_, TakesConstReference(Ref(a))) .WillOnce(Return("Hello")); - EXPECT_EQ("Hello", foo_->TakesConstReference(a)); + EXPECT_EQ("Hello", this->foo_->TakesConstReference(a)); } // Tests mocking a function that takes a const variable. -TEST_F(MockMethodFunctionMockerTest, MocksFunctionWithConstArgument) { - EXPECT_CALL(mock_foo_, TakesConst(Lt(10))) - .WillOnce(DoDefault()); +TYPED_TEST(FunctionMockerTest, MocksFunctionWithConstArgument) { + EXPECT_CALL(this->mock_foo_, TakesConst(Lt(10))).WillOnce(DoDefault()); - EXPECT_FALSE(foo_->TakesConst(5)); + EXPECT_FALSE(this->foo_->TakesConst(5)); } // Tests mocking functions overloaded on the number of arguments. -TEST_F(MockMethodFunctionMockerTest, MocksFunctionsOverloadedOnArgumentNumber) { - EXPECT_CALL(mock_foo_, OverloadedOnArgumentNumber()) +TYPED_TEST(FunctionMockerTest, MocksFunctionsOverloadedOnArgumentNumber) { + EXPECT_CALL(this->mock_foo_, OverloadedOnArgumentNumber()) .WillOnce(Return(1)); - EXPECT_CALL(mock_foo_, OverloadedOnArgumentNumber(_)) + EXPECT_CALL(this->mock_foo_, OverloadedOnArgumentNumber(_)) .WillOnce(Return(2)); - EXPECT_EQ(2, foo_->OverloadedOnArgumentNumber(1)); - EXPECT_EQ(1, foo_->OverloadedOnArgumentNumber()); + EXPECT_EQ(2, this->foo_->OverloadedOnArgumentNumber(1)); + EXPECT_EQ(1, this->foo_->OverloadedOnArgumentNumber()); } // Tests mocking functions overloaded on the types of argument. -TEST_F(MockMethodFunctionMockerTest, MocksFunctionsOverloadedOnArgumentType) { - EXPECT_CALL(mock_foo_, OverloadedOnArgumentType(An<int>())) +TYPED_TEST(FunctionMockerTest, MocksFunctionsOverloadedOnArgumentType) { + EXPECT_CALL(this->mock_foo_, OverloadedOnArgumentType(An<int>())) .WillOnce(Return(1)); - EXPECT_CALL(mock_foo_, OverloadedOnArgumentType(TypedEq<char>('a'))) + EXPECT_CALL(this->mock_foo_, OverloadedOnArgumentType(TypedEq<char>('a'))) .WillOnce(Return('b')); - EXPECT_EQ(1, foo_->OverloadedOnArgumentType(0)); - EXPECT_EQ('b', foo_->OverloadedOnArgumentType('a')); + EXPECT_EQ(1, this->foo_->OverloadedOnArgumentType(0)); + EXPECT_EQ('b', this->foo_->OverloadedOnArgumentType('a')); } // Tests mocking functions overloaded on the const-ness of this object. -TEST_F(MockMethodFunctionMockerTest, - MocksFunctionsOverloadedOnConstnessOfThis) { - EXPECT_CALL(mock_foo_, OverloadedOnConstness()); - EXPECT_CALL(Const(mock_foo_), OverloadedOnConstness()) +TYPED_TEST(FunctionMockerTest, MocksFunctionsOverloadedOnConstnessOfThis) { + EXPECT_CALL(this->mock_foo_, OverloadedOnConstness()); + EXPECT_CALL(Const(this->mock_foo_), OverloadedOnConstness()) .WillOnce(Return('a')); - EXPECT_EQ(0, foo_->OverloadedOnConstness()); - EXPECT_EQ('a', Const(*foo_).OverloadedOnConstness()); + EXPECT_EQ(0, this->foo_->OverloadedOnConstness()); + EXPECT_EQ('a', Const(*this->foo_).OverloadedOnConstness()); } -TEST_F(MockMethodFunctionMockerTest, MocksReturnTypeWithComma) { +TYPED_TEST(FunctionMockerTest, MocksReturnTypeWithComma) { const std::map<int, std::string> a_map; - EXPECT_CALL(mock_foo_, ReturnTypeWithComma()) - .WillOnce(Return(a_map)); - EXPECT_CALL(mock_foo_, ReturnTypeWithComma(42)) - .WillOnce(Return(a_map)); + EXPECT_CALL(this->mock_foo_, ReturnTypeWithComma()).WillOnce(Return(a_map)); + EXPECT_CALL(this->mock_foo_, ReturnTypeWithComma(42)).WillOnce(Return(a_map)); - EXPECT_EQ(a_map, mock_foo_.ReturnTypeWithComma()); - EXPECT_EQ(a_map, mock_foo_.ReturnTypeWithComma(42)); + EXPECT_EQ(a_map, this->mock_foo_.ReturnTypeWithComma()); + EXPECT_EQ(a_map, this->mock_foo_.ReturnTypeWithComma(42)); } -TEST_F(MockMethodFunctionMockerTest, MocksTypeWithTemplatedCopyCtor) { - EXPECT_CALL(mock_foo_, TypeWithTemplatedCopyCtor(_)).WillOnce(Return(true)); - EXPECT_TRUE(foo_->TypeWithTemplatedCopyCtor(TemplatedCopyable<int>())); +TYPED_TEST(FunctionMockerTest, MocksTypeWithTemplatedCopyCtor) { + EXPECT_CALL(this->mock_foo_, TypeWithTemplatedCopyCtor(_)) + .WillOnce(Return(true)); + EXPECT_TRUE(this->foo_->TypeWithTemplatedCopyCtor(TemplatedCopyable<int>())); } #if GTEST_OS_WINDOWS // Tests mocking a nullary function with calltype. -TEST_F(MockMethodFunctionMockerTest, MocksNullaryFunctionWithCallType) { - EXPECT_CALL(mock_foo_, CTNullary()) +TYPED_TEST(FunctionMockerTest, MocksNullaryFunctionWithCallType) { + EXPECT_CALL(this->mock_foo_, CTNullary()) .WillOnce(Return(-1)) .WillOnce(Return(0)); - EXPECT_EQ(-1, foo_->CTNullary()); - EXPECT_EQ(0, foo_->CTNullary()); + EXPECT_EQ(-1, this->foo_->CTNullary()); + EXPECT_EQ(0, this->foo_->CTNullary()); } // Tests mocking a unary function with calltype. -TEST_F(MockMethodFunctionMockerTest, MocksUnaryFunctionWithCallType) { - EXPECT_CALL(mock_foo_, CTUnary(Eq(2))) +TYPED_TEST(FunctionMockerTest, MocksUnaryFunctionWithCallType) { + EXPECT_CALL(this->mock_foo_, CTUnary(Eq(2))) .Times(2) .WillOnce(Return(true)) .WillOnce(Return(false)); - EXPECT_TRUE(foo_->CTUnary(2)); - EXPECT_FALSE(foo_->CTUnary(2)); + EXPECT_TRUE(this->foo_->CTUnary(2)); + EXPECT_FALSE(this->foo_->CTUnary(2)); } // Tests mocking a decimal function with calltype. -TEST_F(MockMethodFunctionMockerTest, MocksDecimalFunctionWithCallType) { - EXPECT_CALL(mock_foo_, CTDecimal(true, 'a', 0, 0, 1L, A<float>(), - Lt(100), 5U, NULL, "hi")) +TYPED_TEST(FunctionMockerTest, MocksDecimalFunctionWithCallType) { + EXPECT_CALL(this->mock_foo_, CTDecimal(true, 'a', 0, 0, 1L, A<float>(), + Lt(100), 5U, NULL, "hi")) .WillOnce(Return(10)); - EXPECT_EQ(10, foo_->CTDecimal(true, 'a', 0, 0, 1, 0, 0, 5, NULL, "hi")); + EXPECT_EQ(10, this->foo_->CTDecimal(true, 'a', 0, 0, 1, 0, 0, 5, NULL, "hi")); } // Tests mocking functions overloaded on the const-ness of this object. -TEST_F(MockMethodFunctionMockerTest, MocksFunctionsConstFunctionWithCallType) { - EXPECT_CALL(Const(mock_foo_), CTConst(_)) - .WillOnce(Return('a')); +TYPED_TEST(FunctionMockerTest, MocksFunctionsConstFunctionWithCallType) { + EXPECT_CALL(Const(this->mock_foo_), CTConst(_)).WillOnce(Return('a')); - EXPECT_EQ('a', Const(*foo_).CTConst(0)); + EXPECT_EQ('a', Const(*this->foo_).CTConst(0)); } -TEST_F(MockMethodFunctionMockerTest, MocksReturnTypeWithCommaAndCallType) { +TYPED_TEST(FunctionMockerTest, MocksReturnTypeWithCommaAndCallType) { const std::map<int, std::string> a_map; - EXPECT_CALL(mock_foo_, CTReturnTypeWithComma()) - .WillOnce(Return(a_map)); + EXPECT_CALL(this->mock_foo_, CTReturnTypeWithComma()).WillOnce(Return(a_map)); - EXPECT_EQ(a_map, mock_foo_.CTReturnTypeWithComma()); + EXPECT_EQ(a_map, this->mock_foo_.CTReturnTypeWithComma()); } #endif // GTEST_OS_WINDOWS @@ -364,20 +429,33 @@ class MockB { GTEST_DISALLOW_COPY_AND_ASSIGN_(MockB); }; +class LegacyMockB { + public: + LegacyMockB() {} + + MOCK_METHOD0(DoB, void()); + + private: + GTEST_DISALLOW_COPY_AND_ASSIGN_(LegacyMockB); +}; + +template <typename T> +class ExpectCallTest : public ::testing::Test {}; +using ExpectCallTestTypes = ::testing::Types<MockB, LegacyMockB>; +TYPED_TEST_SUITE(ExpectCallTest, ExpectCallTestTypes); + // Tests that functions with no EXPECT_CALL() rules can be called any // number of times. -TEST(MockMethodExpectCallTest, UnmentionedFunctionCanBeCalledAnyNumberOfTimes) { - { - MockB b; - } +TYPED_TEST(ExpectCallTest, UnmentionedFunctionCanBeCalledAnyNumberOfTimes) { + { TypeParam b; } { - MockB b; + TypeParam b; b.DoB(); } { - MockB b; + TypeParam b; b.DoB(); b.DoB(); } @@ -416,9 +494,33 @@ class MockStack : public StackInterface<T> { GTEST_DISALLOW_COPY_AND_ASSIGN_(MockStack); }; +template <typename T> +class LegacyMockStack : public StackInterface<T> { + public: + LegacyMockStack() {} + + MOCK_METHOD1_T(Push, void(const T& elem)); + MOCK_METHOD0_T(Pop, void()); + MOCK_CONST_METHOD0_T(GetSize, int()); // NOLINT + MOCK_CONST_METHOD0_T(GetTop, const T&()); + + // Tests that the function return type can contain unprotected comma. + MOCK_METHOD0_T(ReturnTypeWithComma, std::map<int, int>()); + MOCK_CONST_METHOD1_T(ReturnTypeWithComma, std::map<int, int>(int)); // NOLINT + + private: + GTEST_DISALLOW_COPY_AND_ASSIGN_(LegacyMockStack); +}; + +template <typename T> +class TemplateMockTest : public ::testing::Test {}; +using TemplateMockTestTypes = + ::testing::Types<MockStack<int>, LegacyMockStack<int>>; +TYPED_TEST_SUITE(TemplateMockTest, TemplateMockTestTypes); + // Tests that template mock works. -TEST(MockMethodTemplateMockTest, Works) { - MockStack<int> mock; +TYPED_TEST(TemplateMockTest, Works) { + TypeParam mock; EXPECT_CALL(mock, GetSize()) .WillOnce(Return(0)) @@ -439,8 +541,8 @@ TEST(MockMethodTemplateMockTest, Works) { EXPECT_EQ(0, mock.GetSize()); } -TEST(MockMethodTemplateMockTest, MethodWithCommaInReturnTypeWorks) { - MockStack<int> mock; +TYPED_TEST(TemplateMockTest, MethodWithCommaInReturnTypeWorks) { + TypeParam mock; const std::map<int, int> a_map; EXPECT_CALL(mock, ReturnTypeWithComma()) @@ -484,9 +586,31 @@ class MockStackWithCallType : public StackInterfaceWithCallType<T> { GTEST_DISALLOW_COPY_AND_ASSIGN_(MockStackWithCallType); }; +template <typename T> +class LegacyMockStackWithCallType : public StackInterfaceWithCallType<T> { + public: + LegacyMockStackWithCallType() {} + + MOCK_METHOD1_T_WITH_CALLTYPE(STDMETHODCALLTYPE, Push, void(const T& elem)); + MOCK_METHOD0_T_WITH_CALLTYPE(STDMETHODCALLTYPE, Pop, void()); + MOCK_CONST_METHOD0_T_WITH_CALLTYPE(STDMETHODCALLTYPE, GetSize, int()); + MOCK_CONST_METHOD0_T_WITH_CALLTYPE(STDMETHODCALLTYPE, GetTop, const T&()); + + private: + GTEST_DISALLOW_COPY_AND_ASSIGN_(LegacyMockStackWithCallType); +}; + +template <typename T> +class TemplateMockTestWithCallType : public ::testing::Test {}; +using TemplateMockTestWithCallTypeTypes = + ::testing::Types<MockStackWithCallType<int>, + LegacyMockStackWithCallType<int>>; +TYPED_TEST_SUITE(TemplateMockTestWithCallType, + TemplateMockTestWithCallTypeTypes); + // Tests that template mock with calltype works. -TEST(MockMethodTemplateMockTestWithCallType, Works) { - MockStackWithCallType<int> mock; +TYPED_TEST(TemplateMockTestWithCallType, Works) { + TypeParam mock; EXPECT_CALL(mock, GetSize()) .WillOnce(Return(0)) @@ -513,6 +637,11 @@ TEST(MockMethodTemplateMockTestWithCallType, Works) { MOCK_METHOD(int, Overloaded, (int), (const)); \ MOCK_METHOD(bool, Overloaded, (bool f, int n)) +#define LEGACY_MY_MOCK_METHODS1_ \ + MOCK_METHOD0(Overloaded, void()); \ + MOCK_CONST_METHOD1(Overloaded, int(int n)); \ + MOCK_METHOD2(Overloaded, bool(bool f, int n)) + class MockOverloadedOnArgNumber { public: MockOverloadedOnArgNumber() {} @@ -523,8 +652,25 @@ class MockOverloadedOnArgNumber { GTEST_DISALLOW_COPY_AND_ASSIGN_(MockOverloadedOnArgNumber); }; -TEST(MockMethodOverloadedMockMethodTest, CanOverloadOnArgNumberInMacroBody) { - MockOverloadedOnArgNumber mock; +class LegacyMockOverloadedOnArgNumber { + public: + LegacyMockOverloadedOnArgNumber() {} + + LEGACY_MY_MOCK_METHODS1_; + + private: + GTEST_DISALLOW_COPY_AND_ASSIGN_(LegacyMockOverloadedOnArgNumber); +}; + +template <typename T> +class OverloadedMockMethodTest : public ::testing::Test {}; +using OverloadedMockMethodTestTypes = + ::testing::Types<MockOverloadedOnArgNumber, + LegacyMockOverloadedOnArgNumber>; +TYPED_TEST_SUITE(OverloadedMockMethodTest, OverloadedMockMethodTestTypes); + +TYPED_TEST(OverloadedMockMethodTest, CanOverloadOnArgNumberInMacroBody) { + TypeParam mock; EXPECT_CALL(mock, Overloaded()); EXPECT_CALL(mock, Overloaded(1)).WillOnce(Return(2)); EXPECT_CALL(mock, Overloaded(true, 1)).WillOnce(Return(true)); @@ -649,11 +795,62 @@ struct MockMethodSizes4 { MOCK_METHOD(void, func, (int, int, int, int)); }; +struct LegacyMockMethodSizes0 { + MOCK_METHOD0(func, void()); +}; +struct LegacyMockMethodSizes1 { + MOCK_METHOD1(func, void(int)); +}; +struct LegacyMockMethodSizes2 { + MOCK_METHOD2(func, void(int, int)); +}; +struct LegacyMockMethodSizes3 { + MOCK_METHOD3(func, void(int, int, int)); +}; +struct LegacyMockMethodSizes4 { + MOCK_METHOD4(func, void(int, int, int, int)); +}; + + TEST(MockMethodMockFunctionTest, MockMethodSizeOverhead) { EXPECT_EQ(sizeof(MockMethodSizes0), sizeof(MockMethodSizes1)); EXPECT_EQ(sizeof(MockMethodSizes0), sizeof(MockMethodSizes2)); EXPECT_EQ(sizeof(MockMethodSizes0), sizeof(MockMethodSizes3)); EXPECT_EQ(sizeof(MockMethodSizes0), sizeof(MockMethodSizes4)); + + EXPECT_EQ(sizeof(LegacyMockMethodSizes0), sizeof(LegacyMockMethodSizes1)); + EXPECT_EQ(sizeof(LegacyMockMethodSizes0), sizeof(LegacyMockMethodSizes2)); + EXPECT_EQ(sizeof(LegacyMockMethodSizes0), sizeof(LegacyMockMethodSizes3)); + EXPECT_EQ(sizeof(LegacyMockMethodSizes0), sizeof(LegacyMockMethodSizes4)); + + EXPECT_EQ(sizeof(LegacyMockMethodSizes0), sizeof(MockMethodSizes0)); +} + +void hasTwoParams(int, int); +void MaybeThrows(); +void DoesntThrow() noexcept; +struct MockMethodNoexceptSpecifier { + MOCK_METHOD(void, func1, (), (noexcept)); + MOCK_METHOD(void, func2, (), (noexcept(true))); + MOCK_METHOD(void, func3, (), (noexcept(false))); + MOCK_METHOD(void, func4, (), (noexcept(noexcept(MaybeThrows())))); + MOCK_METHOD(void, func5, (), (noexcept(noexcept(DoesntThrow())))); + MOCK_METHOD(void, func6, (), (noexcept(noexcept(DoesntThrow())), const)); + MOCK_METHOD(void, func7, (), (const, noexcept(noexcept(DoesntThrow())))); + // Put commas in the noexcept expression + MOCK_METHOD(void, func8, (), (noexcept(noexcept(hasTwoParams(1, 2))), const)); +}; + +TEST(MockMethodMockFunctionTest, NoexceptSpecifierPreserved) { + EXPECT_TRUE(noexcept(std::declval<MockMethodNoexceptSpecifier>().func1())); + EXPECT_TRUE(noexcept(std::declval<MockMethodNoexceptSpecifier>().func2())); + EXPECT_FALSE(noexcept(std::declval<MockMethodNoexceptSpecifier>().func3())); + EXPECT_FALSE(noexcept(std::declval<MockMethodNoexceptSpecifier>().func4())); + EXPECT_TRUE(noexcept(std::declval<MockMethodNoexceptSpecifier>().func5())); + EXPECT_TRUE(noexcept(std::declval<MockMethodNoexceptSpecifier>().func6())); + EXPECT_TRUE(noexcept(std::declval<MockMethodNoexceptSpecifier>().func7())); + EXPECT_EQ(noexcept(std::declval<MockMethodNoexceptSpecifier>().func8()), + noexcept(hasTwoParams(1, 2))); } } // namespace gmock_function_mocker_test diff --git a/googlemock/test/gmock-generated-function-mockers_test.cc b/googlemock/test/gmock-generated-function-mockers_test.cc deleted file mode 100644 index dff3a9f0..00000000 --- a/googlemock/test/gmock-generated-function-mockers_test.cc +++ /dev/null @@ -1,659 +0,0 @@ -// Copyright 2007, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - -// Google Mock - a framework for writing C++ mock classes. -// -// This file tests the function mocker classes. - -#include "gmock/gmock-generated-function-mockers.h" - -#if GTEST_OS_WINDOWS -// MSDN says the header file to be included for STDMETHOD is BaseTyps.h but -// we are getting compiler errors if we use basetyps.h, hence including -// objbase.h for definition of STDMETHOD. -# include <objbase.h> -#endif // GTEST_OS_WINDOWS - -#include <map> -#include <string> -#include "gmock/gmock.h" -#include "gtest/gtest.h" - -namespace testing { -namespace gmock_generated_function_mockers_test { - -using testing::_; -using testing::A; -using testing::An; -using testing::AnyNumber; -using testing::Const; -using testing::DoDefault; -using testing::Eq; -using testing::Lt; -using testing::MockFunction; -using testing::Ref; -using testing::Return; -using testing::ReturnRef; -using testing::TypedEq; - -template<typename T> -class TemplatedCopyable { - public: - TemplatedCopyable() {} - - template <typename U> - TemplatedCopyable(const U& other) {} // NOLINT -}; - -class FooInterface { - public: - virtual ~FooInterface() {} - - virtual void VoidReturning(int x) = 0; - - virtual int Nullary() = 0; - virtual bool Unary(int x) = 0; - virtual long Binary(short x, int y) = 0; // NOLINT - virtual int Decimal(bool b, char c, short d, int e, long f, // NOLINT - float g, double h, unsigned i, char* j, - const std::string& k) = 0; - - virtual bool TakesNonConstReference(int& n) = 0; // NOLINT - virtual std::string TakesConstReference(const int& n) = 0; - virtual bool TakesConst(const int x) = 0; - - virtual int OverloadedOnArgumentNumber() = 0; - virtual int OverloadedOnArgumentNumber(int n) = 0; - - virtual int OverloadedOnArgumentType(int n) = 0; - virtual char OverloadedOnArgumentType(char c) = 0; - - virtual int OverloadedOnConstness() = 0; - virtual char OverloadedOnConstness() const = 0; - - virtual int TypeWithHole(int (*func)()) = 0; - virtual int TypeWithComma(const std::map<int, std::string>& a_map) = 0; - virtual int TypeWithTemplatedCopyCtor( - const TemplatedCopyable<int>& a_vector) = 0; - -#if GTEST_OS_WINDOWS - STDMETHOD_(int, CTNullary)() = 0; - STDMETHOD_(bool, CTUnary)(int x) = 0; - STDMETHOD_(int, CTDecimal) - (bool b, char c, short d, int e, long f, // NOLINT - float g, double h, unsigned i, char* j, const std::string& k) = 0; - STDMETHOD_(char, CTConst)(int x) const = 0; -#endif // GTEST_OS_WINDOWS -}; - -// Const qualifiers on arguments were once (incorrectly) considered -// significant in determining whether two virtual functions had the same -// signature. This was fixed in Visual Studio 2008. However, the compiler -// still emits a warning that alerts about this change in behavior. -#ifdef _MSC_VER -# pragma warning(push) -# pragma warning(disable : 4373) -#endif -class MockFoo : public FooInterface { - public: - MockFoo() {} - - // Makes sure that a mock function parameter can be named. - MOCK_METHOD1(VoidReturning, void(int n)); // NOLINT - - MOCK_METHOD0(Nullary, int()); // NOLINT - - // Makes sure that a mock function parameter can be unnamed. - MOCK_METHOD1(Unary, bool(int)); // NOLINT - MOCK_METHOD2(Binary, long(short, int)); // NOLINT - MOCK_METHOD10(Decimal, int(bool, char, short, int, long, float, // NOLINT - double, unsigned, char*, const std::string& str)); - - MOCK_METHOD1(TakesNonConstReference, bool(int&)); // NOLINT - MOCK_METHOD1(TakesConstReference, std::string(const int&)); - MOCK_METHOD1(TakesConst, bool(const int)); // NOLINT - - // Tests that the function return type can contain unprotected comma. - MOCK_METHOD0(ReturnTypeWithComma, std::map<int, std::string>()); - MOCK_CONST_METHOD1(ReturnTypeWithComma, - std::map<int, std::string>(int)); // NOLINT - - MOCK_METHOD0(OverloadedOnArgumentNumber, int()); // NOLINT - MOCK_METHOD1(OverloadedOnArgumentNumber, int(int)); // NOLINT - - MOCK_METHOD1(OverloadedOnArgumentType, int(int)); // NOLINT - MOCK_METHOD1(OverloadedOnArgumentType, char(char)); // NOLINT - - MOCK_METHOD0(OverloadedOnConstness, int()); // NOLINT - MOCK_CONST_METHOD0(OverloadedOnConstness, char()); // NOLINT - - MOCK_METHOD1(TypeWithHole, int(int (*)())); // NOLINT - MOCK_METHOD1(TypeWithComma, - int(const std::map<int, std::string>&)); // NOLINT - MOCK_METHOD1(TypeWithTemplatedCopyCtor, - int(const TemplatedCopyable<int>&)); // NOLINT - -#if GTEST_OS_WINDOWS - MOCK_METHOD0_WITH_CALLTYPE(STDMETHODCALLTYPE, CTNullary, int()); - MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, CTUnary, bool(int)); - MOCK_METHOD10_WITH_CALLTYPE(STDMETHODCALLTYPE, CTDecimal, - int(bool b, char c, short d, int e, long f, - float g, double h, unsigned i, char* j, - const std::string& k)); - MOCK_CONST_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, CTConst, char(int)); - - // Tests that the function return type can contain unprotected comma. - MOCK_METHOD0_WITH_CALLTYPE(STDMETHODCALLTYPE, CTReturnTypeWithComma, - std::map<int, std::string>()); -#endif // GTEST_OS_WINDOWS - - private: - GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFoo); -}; -#ifdef _MSC_VER -# pragma warning(pop) -#endif - -class FunctionMockerTest : public testing::Test { - protected: - FunctionMockerTest() : foo_(&mock_foo_) {} - - FooInterface* const foo_; - MockFoo mock_foo_; -}; - -// Tests mocking a void-returning function. -TEST_F(FunctionMockerTest, MocksVoidFunction) { - EXPECT_CALL(mock_foo_, VoidReturning(Lt(100))); - foo_->VoidReturning(0); -} - -// Tests mocking a nullary function. -TEST_F(FunctionMockerTest, MocksNullaryFunction) { - EXPECT_CALL(mock_foo_, Nullary()) - .WillOnce(DoDefault()) - .WillOnce(Return(1)); - - EXPECT_EQ(0, foo_->Nullary()); - EXPECT_EQ(1, foo_->Nullary()); -} - -// Tests mocking a unary function. -TEST_F(FunctionMockerTest, MocksUnaryFunction) { - EXPECT_CALL(mock_foo_, Unary(Eq(2))) - .Times(2) - .WillOnce(Return(true)); - - EXPECT_TRUE(foo_->Unary(2)); - EXPECT_FALSE(foo_->Unary(2)); -} - -// Tests mocking a binary function. -TEST_F(FunctionMockerTest, MocksBinaryFunction) { - EXPECT_CALL(mock_foo_, Binary(2, _)) - .WillOnce(Return(3)); - - EXPECT_EQ(3, foo_->Binary(2, 1)); -} - -// Tests mocking a decimal function. -TEST_F(FunctionMockerTest, MocksDecimalFunction) { - EXPECT_CALL(mock_foo_, Decimal(true, 'a', 0, 0, 1L, A<float>(), Lt(100), 5U, - nullptr, "hi")) - .WillOnce(Return(5)); - - EXPECT_EQ(5, foo_->Decimal(true, 'a', 0, 0, 1, 0, 0, 5, nullptr, "hi")); -} - -// Tests mocking a function that takes a non-const reference. -TEST_F(FunctionMockerTest, MocksFunctionWithNonConstReferenceArgument) { - int a = 0; - EXPECT_CALL(mock_foo_, TakesNonConstReference(Ref(a))) - .WillOnce(Return(true)); - - EXPECT_TRUE(foo_->TakesNonConstReference(a)); -} - -// Tests mocking a function that takes a const reference. -TEST_F(FunctionMockerTest, MocksFunctionWithConstReferenceArgument) { - int a = 0; - EXPECT_CALL(mock_foo_, TakesConstReference(Ref(a))) - .WillOnce(Return("Hello")); - - EXPECT_EQ("Hello", foo_->TakesConstReference(a)); -} - -// Tests mocking a function that takes a const variable. -TEST_F(FunctionMockerTest, MocksFunctionWithConstArgument) { - EXPECT_CALL(mock_foo_, TakesConst(Lt(10))) - .WillOnce(DoDefault()); - - EXPECT_FALSE(foo_->TakesConst(5)); -} - -// Tests mocking functions overloaded on the number of arguments. -TEST_F(FunctionMockerTest, MocksFunctionsOverloadedOnArgumentNumber) { - EXPECT_CALL(mock_foo_, OverloadedOnArgumentNumber()) - .WillOnce(Return(1)); - EXPECT_CALL(mock_foo_, OverloadedOnArgumentNumber(_)) - .WillOnce(Return(2)); - - EXPECT_EQ(2, foo_->OverloadedOnArgumentNumber(1)); - EXPECT_EQ(1, foo_->OverloadedOnArgumentNumber()); -} - -// Tests mocking functions overloaded on the types of argument. -TEST_F(FunctionMockerTest, MocksFunctionsOverloadedOnArgumentType) { - EXPECT_CALL(mock_foo_, OverloadedOnArgumentType(An<int>())) - .WillOnce(Return(1)); - EXPECT_CALL(mock_foo_, OverloadedOnArgumentType(TypedEq<char>('a'))) - .WillOnce(Return('b')); - - EXPECT_EQ(1, foo_->OverloadedOnArgumentType(0)); - EXPECT_EQ('b', foo_->OverloadedOnArgumentType('a')); -} - -// Tests mocking functions overloaded on the const-ness of this object. -TEST_F(FunctionMockerTest, MocksFunctionsOverloadedOnConstnessOfThis) { - EXPECT_CALL(mock_foo_, OverloadedOnConstness()); - EXPECT_CALL(Const(mock_foo_), OverloadedOnConstness()) - .WillOnce(Return('a')); - - EXPECT_EQ(0, foo_->OverloadedOnConstness()); - EXPECT_EQ('a', Const(*foo_).OverloadedOnConstness()); -} - -TEST_F(FunctionMockerTest, MocksReturnTypeWithComma) { - const std::map<int, std::string> a_map; - EXPECT_CALL(mock_foo_, ReturnTypeWithComma()) - .WillOnce(Return(a_map)); - EXPECT_CALL(mock_foo_, ReturnTypeWithComma(42)) - .WillOnce(Return(a_map)); - - EXPECT_EQ(a_map, mock_foo_.ReturnTypeWithComma()); - EXPECT_EQ(a_map, mock_foo_.ReturnTypeWithComma(42)); -} - -TEST_F(FunctionMockerTest, MocksTypeWithTemplatedCopyCtor) { - EXPECT_CALL(mock_foo_, TypeWithTemplatedCopyCtor(_)).WillOnce(Return(true)); - EXPECT_TRUE(foo_->TypeWithTemplatedCopyCtor(TemplatedCopyable<int>())); -} - -#if GTEST_OS_WINDOWS -// Tests mocking a nullary function with calltype. -TEST_F(FunctionMockerTest, MocksNullaryFunctionWithCallType) { - EXPECT_CALL(mock_foo_, CTNullary()) - .WillOnce(Return(-1)) - .WillOnce(Return(0)); - - EXPECT_EQ(-1, foo_->CTNullary()); - EXPECT_EQ(0, foo_->CTNullary()); -} - -// Tests mocking a unary function with calltype. -TEST_F(FunctionMockerTest, MocksUnaryFunctionWithCallType) { - EXPECT_CALL(mock_foo_, CTUnary(Eq(2))) - .Times(2) - .WillOnce(Return(true)) - .WillOnce(Return(false)); - - EXPECT_TRUE(foo_->CTUnary(2)); - EXPECT_FALSE(foo_->CTUnary(2)); -} - -// Tests mocking a decimal function with calltype. -TEST_F(FunctionMockerTest, MocksDecimalFunctionWithCallType) { - EXPECT_CALL(mock_foo_, CTDecimal(true, 'a', 0, 0, 1L, A<float>(), Lt(100), 5U, - nullptr, "hi")) - .WillOnce(Return(10)); - - EXPECT_EQ(10, foo_->CTDecimal(true, 'a', 0, 0, 1, 0, 0, 5, nullptr, "hi")); -} - -// Tests mocking functions overloaded on the const-ness of this object. -TEST_F(FunctionMockerTest, MocksFunctionsConstFunctionWithCallType) { - EXPECT_CALL(Const(mock_foo_), CTConst(_)) - .WillOnce(Return('a')); - - EXPECT_EQ('a', Const(*foo_).CTConst(0)); -} - -TEST_F(FunctionMockerTest, MocksReturnTypeWithCommaAndCallType) { - const std::map<int, std::string> a_map; - EXPECT_CALL(mock_foo_, CTReturnTypeWithComma()) - .WillOnce(Return(a_map)); - - EXPECT_EQ(a_map, mock_foo_.CTReturnTypeWithComma()); -} - -#endif // GTEST_OS_WINDOWS - -class MockB { - public: - MockB() {} - - MOCK_METHOD0(DoB, void()); - - private: - GTEST_DISALLOW_COPY_AND_ASSIGN_(MockB); -}; - -// Tests that functions with no EXPECT_CALL() ruls can be called any -// number of times. -TEST(ExpectCallTest, UnmentionedFunctionCanBeCalledAnyNumberOfTimes) { - { - MockB b; - } - - { - MockB b; - b.DoB(); - } - - { - MockB b; - b.DoB(); - b.DoB(); - } -} - -// Tests mocking template interfaces. - -template <typename T> -class StackInterface { - public: - virtual ~StackInterface() {} - - // Template parameter appears in function parameter. - virtual void Push(const T& value) = 0; - virtual void Pop() = 0; - virtual int GetSize() const = 0; - // Template parameter appears in function return type. - virtual const T& GetTop() const = 0; -}; - -template <typename T> -class MockStack : public StackInterface<T> { - public: - MockStack() {} - - MOCK_METHOD1_T(Push, void(const T& elem)); - MOCK_METHOD0_T(Pop, void()); - MOCK_CONST_METHOD0_T(GetSize, int()); // NOLINT - MOCK_CONST_METHOD0_T(GetTop, const T&()); - - // Tests that the function return type can contain unprotected comma. - MOCK_METHOD0_T(ReturnTypeWithComma, std::map<int, int>()); - MOCK_CONST_METHOD1_T(ReturnTypeWithComma, std::map<int, int>(int)); // NOLINT - - private: - GTEST_DISALLOW_COPY_AND_ASSIGN_(MockStack); -}; - -// Tests that template mock works. -TEST(TemplateMockTest, Works) { - MockStack<int> mock; - - EXPECT_CALL(mock, GetSize()) - .WillOnce(Return(0)) - .WillOnce(Return(1)) - .WillOnce(Return(0)); - EXPECT_CALL(mock, Push(_)); - int n = 5; - EXPECT_CALL(mock, GetTop()) - .WillOnce(ReturnRef(n)); - EXPECT_CALL(mock, Pop()) - .Times(AnyNumber()); - - EXPECT_EQ(0, mock.GetSize()); - mock.Push(5); - EXPECT_EQ(1, mock.GetSize()); - EXPECT_EQ(5, mock.GetTop()); - mock.Pop(); - EXPECT_EQ(0, mock.GetSize()); -} - -TEST(TemplateMockTest, MethodWithCommaInReturnTypeWorks) { - MockStack<int> mock; - - const std::map<int, int> a_map; - EXPECT_CALL(mock, ReturnTypeWithComma()) - .WillOnce(Return(a_map)); - EXPECT_CALL(mock, ReturnTypeWithComma(1)) - .WillOnce(Return(a_map)); - - EXPECT_EQ(a_map, mock.ReturnTypeWithComma()); - EXPECT_EQ(a_map, mock.ReturnTypeWithComma(1)); -} - -#if GTEST_OS_WINDOWS -// Tests mocking template interfaces with calltype. - -template <typename T> -class StackInterfaceWithCallType { - public: - virtual ~StackInterfaceWithCallType() {} - - // Template parameter appears in function parameter. - STDMETHOD_(void, Push)(const T& value) = 0; - STDMETHOD_(void, Pop)() = 0; - STDMETHOD_(int, GetSize)() const = 0; - // Template parameter appears in function return type. - STDMETHOD_(const T&, GetTop)() const = 0; -}; - -template <typename T> -class MockStackWithCallType : public StackInterfaceWithCallType<T> { - public: - MockStackWithCallType() {} - - MOCK_METHOD1_T_WITH_CALLTYPE(STDMETHODCALLTYPE, Push, void(const T& elem)); - MOCK_METHOD0_T_WITH_CALLTYPE(STDMETHODCALLTYPE, Pop, void()); - MOCK_CONST_METHOD0_T_WITH_CALLTYPE(STDMETHODCALLTYPE, GetSize, int()); - MOCK_CONST_METHOD0_T_WITH_CALLTYPE(STDMETHODCALLTYPE, GetTop, const T&()); - - private: - GTEST_DISALLOW_COPY_AND_ASSIGN_(MockStackWithCallType); -}; - -// Tests that template mock with calltype works. -TEST(TemplateMockTestWithCallType, Works) { - MockStackWithCallType<int> mock; - - EXPECT_CALL(mock, GetSize()) - .WillOnce(Return(0)) - .WillOnce(Return(1)) - .WillOnce(Return(0)); - EXPECT_CALL(mock, Push(_)); - int n = 5; - EXPECT_CALL(mock, GetTop()) - .WillOnce(ReturnRef(n)); - EXPECT_CALL(mock, Pop()) - .Times(AnyNumber()); - - EXPECT_EQ(0, mock.GetSize()); - mock.Push(5); - EXPECT_EQ(1, mock.GetSize()); - EXPECT_EQ(5, mock.GetTop()); - mock.Pop(); - EXPECT_EQ(0, mock.GetSize()); -} -#endif // GTEST_OS_WINDOWS - -#define MY_MOCK_METHODS1_ \ - MOCK_METHOD0(Overloaded, void()); \ - MOCK_CONST_METHOD1(Overloaded, int(int n)); \ - MOCK_METHOD2(Overloaded, bool(bool f, int n)) - -class MockOverloadedOnArgNumber { - public: - MockOverloadedOnArgNumber() {} - - MY_MOCK_METHODS1_; - - private: - GTEST_DISALLOW_COPY_AND_ASSIGN_(MockOverloadedOnArgNumber); -}; - -TEST(OverloadedMockMethodTest, CanOverloadOnArgNumberInMacroBody) { - MockOverloadedOnArgNumber mock; - EXPECT_CALL(mock, Overloaded()); - EXPECT_CALL(mock, Overloaded(1)).WillOnce(Return(2)); - EXPECT_CALL(mock, Overloaded(true, 1)).WillOnce(Return(true)); - - mock.Overloaded(); - EXPECT_EQ(2, mock.Overloaded(1)); - EXPECT_TRUE(mock.Overloaded(true, 1)); -} - -#define MY_MOCK_METHODS2_ \ - MOCK_CONST_METHOD1(Overloaded, int(int n)); \ - MOCK_METHOD1(Overloaded, int(int n)) - -class MockOverloadedOnConstness { - public: - MockOverloadedOnConstness() {} - - MY_MOCK_METHODS2_; - - private: - GTEST_DISALLOW_COPY_AND_ASSIGN_(MockOverloadedOnConstness); -}; - -TEST(OverloadedMockMethodTest, CanOverloadOnConstnessInMacroBody) { - MockOverloadedOnConstness mock; - const MockOverloadedOnConstness* const_mock = &mock; - EXPECT_CALL(mock, Overloaded(1)).WillOnce(Return(2)); - EXPECT_CALL(*const_mock, Overloaded(1)).WillOnce(Return(3)); - - EXPECT_EQ(2, mock.Overloaded(1)); - EXPECT_EQ(3, const_mock->Overloaded(1)); -} - -TEST(MockFunctionTest, WorksForVoidNullary) { - MockFunction<void()> foo; - EXPECT_CALL(foo, Call()); - foo.Call(); -} - -TEST(MockFunctionTest, WorksForNonVoidNullary) { - MockFunction<int()> foo; - EXPECT_CALL(foo, Call()) - .WillOnce(Return(1)) - .WillOnce(Return(2)); - EXPECT_EQ(1, foo.Call()); - EXPECT_EQ(2, foo.Call()); -} - -TEST(MockFunctionTest, WorksForVoidUnary) { - MockFunction<void(int)> foo; - EXPECT_CALL(foo, Call(1)); - foo.Call(1); -} - -TEST(MockFunctionTest, WorksForNonVoidBinary) { - MockFunction<int(bool, int)> foo; - EXPECT_CALL(foo, Call(false, 42)) - .WillOnce(Return(1)) - .WillOnce(Return(2)); - EXPECT_CALL(foo, Call(true, Ge(100))) - .WillOnce(Return(3)); - EXPECT_EQ(1, foo.Call(false, 42)); - EXPECT_EQ(2, foo.Call(false, 42)); - EXPECT_EQ(3, foo.Call(true, 120)); -} - -TEST(MockFunctionTest, WorksFor10Arguments) { - MockFunction<int(bool a0, char a1, int a2, int a3, int a4, - int a5, int a6, char a7, int a8, bool a9)> foo; - EXPECT_CALL(foo, Call(_, 'a', _, _, _, _, _, _, _, _)) - .WillOnce(Return(1)) - .WillOnce(Return(2)); - EXPECT_EQ(1, foo.Call(false, 'a', 0, 0, 0, 0, 0, 'b', 0, true)); - EXPECT_EQ(2, foo.Call(true, 'a', 0, 0, 0, 0, 0, 'b', 1, false)); -} - -TEST(MockFunctionTest, AsStdFunction) { - MockFunction<int(int)> foo; - auto call = [](const std::function<int(int)> &f, int i) { - return f(i); - }; - EXPECT_CALL(foo, Call(1)).WillOnce(Return(-1)); - EXPECT_CALL(foo, Call(2)).WillOnce(Return(-2)); - EXPECT_EQ(-1, call(foo.AsStdFunction(), 1)); - EXPECT_EQ(-2, call(foo.AsStdFunction(), 2)); -} - -TEST(MockFunctionTest, AsStdFunctionReturnsReference) { - MockFunction<int&()> foo; - int value = 1; - EXPECT_CALL(foo, Call()).WillOnce(ReturnRef(value)); - int& ref = foo.AsStdFunction()(); - EXPECT_EQ(1, ref); - value = 2; - EXPECT_EQ(2, ref); -} - -TEST(MockFunctionTest, AsStdFunctionWithReferenceParameter) { - MockFunction<int(int &)> foo; - auto call = [](const std::function<int(int& )> &f, int &i) { - return f(i); - }; - int i = 42; - EXPECT_CALL(foo, Call(i)).WillOnce(Return(-1)); - EXPECT_EQ(-1, call(foo.AsStdFunction(), i)); -} - - -struct MockMethodSizes0 { - MOCK_METHOD0(func, void()); -}; -struct MockMethodSizes1 { - MOCK_METHOD1(func, void(int)); -}; -struct MockMethodSizes2 { - MOCK_METHOD2(func, void(int, int)); -}; -struct MockMethodSizes3 { - MOCK_METHOD3(func, void(int, int, int)); -}; -struct MockMethodSizes4 { - MOCK_METHOD4(func, void(int, int, int, int)); -}; - -TEST(MockFunctionTest, MockMethodSizeOverhead) { - EXPECT_EQ(sizeof(MockMethodSizes0), sizeof(MockMethodSizes1)); - EXPECT_EQ(sizeof(MockMethodSizes0), sizeof(MockMethodSizes2)); - EXPECT_EQ(sizeof(MockMethodSizes0), sizeof(MockMethodSizes3)); - EXPECT_EQ(sizeof(MockMethodSizes0), sizeof(MockMethodSizes4)); -} - -} // namespace gmock_generated_function_mockers_test -} // namespace testing diff --git a/googlemock/test/gmock-generated-matchers_test.cc b/googlemock/test/gmock-generated-matchers_test.cc index 6c4b3000..26c41f68 100644 --- a/googlemock/test/gmock-generated-matchers_test.cc +++ b/googlemock/test/gmock-generated-matchers_test.cc @@ -39,8 +39,10 @@ # pragma warning(disable:4100) #endif -#include "gmock/gmock-generated-matchers.h" +#include "gmock/gmock-matchers.h" +#include <array> +#include <iterator> #include <list> #include <map> #include <memory> @@ -51,8 +53,8 @@ #include <vector> #include "gmock/gmock.h" -#include "gtest/gtest.h" #include "gtest/gtest-spi.h" +#include "gtest/gtest.h" namespace { @@ -195,7 +197,7 @@ TEST(ElementsAreTest, ExplainsNonTrivialMatch) { ElementsAre(GreaterThan(1), 0, GreaterThan(2)); const int a[] = { 10, 0, 100 }; - vector<int> test_vector(a, a + GTEST_ARRAY_SIZE_(a)); + vector<int> test_vector(std::begin(a), std::end(a)); EXPECT_EQ("whose element #0 matches, which is 9 more than 1,\n" "and whose element #2 matches, which is 98 more than 2", Explain(m, test_vector)); @@ -280,7 +282,7 @@ TEST(ElementsAreTest, MatchesThreeElementsMixedMatchers) { TEST(ElementsAreTest, MatchesTenElementVector) { const int a[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; - vector<int> test_vector(a, a + GTEST_ARRAY_SIZE_(a)); + vector<int> test_vector(std::begin(a), std::end(a)); EXPECT_THAT(test_vector, // The element list can contain values and/or matchers @@ -317,13 +319,10 @@ TEST(ElementsAreTest, DoesNotMatchWrongOrder) { } TEST(ElementsAreTest, WorksForNestedContainer) { - const char* strings[] = { - "Hi", - "world" - }; + constexpr std::array<const char*, 2> strings = {{"Hi", "world"}}; vector<list<char> > nested; - for (size_t i = 0; i < GTEST_ARRAY_SIZE_(strings); i++) { + for (size_t i = 0; i < strings.size(); i++) { nested.push_back(list<char>(strings[i], strings[i] + strlen(strings[i]))); } @@ -335,7 +334,7 @@ TEST(ElementsAreTest, WorksForNestedContainer) { TEST(ElementsAreTest, WorksWithByRefElementMatchers) { int a[] = { 0, 1, 2 }; - vector<int> v(a, a + GTEST_ARRAY_SIZE_(a)); + vector<int> v(std::begin(a), std::end(a)); EXPECT_THAT(v, ElementsAre(Ref(v[0]), Ref(v[1]), Ref(v[2]))); EXPECT_THAT(v, Not(ElementsAre(Ref(v[0]), Ref(v[1]), Ref(a[2])))); @@ -343,7 +342,7 @@ TEST(ElementsAreTest, WorksWithByRefElementMatchers) { TEST(ElementsAreTest, WorksWithContainerPointerUsingPointee) { int a[] = { 0, 1, 2 }; - vector<int> v(a, a + GTEST_ARRAY_SIZE_(a)); + vector<int> v(std::begin(a), std::end(a)); EXPECT_THAT(&v, Pointee(ElementsAre(0, 1, _))); EXPECT_THAT(&v, Not(Pointee(ElementsAre(0, _, 3)))); @@ -393,13 +392,6 @@ TEST(ElementsAreTest, AcceptsStringLiteral) { EXPECT_THAT(array, Not(ElementsAre("hi", "one", "too"))); } -#ifndef _MSC_VER - -// The following test passes a value of type const char[] to a -// function template that expects const T&. Some versions of MSVC -// generates a compiler error C2665 for that. We believe it's a bug -// in MSVC. Therefore this test is #if-ed out for MSVC. - // Declared here with the size unknown. Defined AFTER the following test. extern const char kHi[]; @@ -416,8 +408,6 @@ TEST(ElementsAreTest, AcceptsArrayWithUnknownSize) { const char kHi[] = "hi"; -#endif // _MSC_VER - TEST(ElementsAreTest, MakesCopyOfArguments) { int x = 1; int y = 2; @@ -440,7 +430,7 @@ TEST(ElementsAreTest, MakesCopyOfArguments) { TEST(ElementsAreArrayTest, CanBeCreatedWithValueArray) { const int a[] = { 1, 2, 3 }; - vector<int> test_vector(a, a + GTEST_ARRAY_SIZE_(a)); + vector<int> test_vector(std::begin(a), std::end(a)); EXPECT_THAT(test_vector, ElementsAreArray(a)); test_vector[2] = 0; @@ -448,20 +438,20 @@ TEST(ElementsAreArrayTest, CanBeCreatedWithValueArray) { } TEST(ElementsAreArrayTest, CanBeCreatedWithArraySize) { - const char* a[] = { "one", "two", "three" }; + std::array<const char*, 3> a = {{"one", "two", "three"}}; - vector<std::string> test_vector(a, a + GTEST_ARRAY_SIZE_(a)); - EXPECT_THAT(test_vector, ElementsAreArray(a, GTEST_ARRAY_SIZE_(a))); + vector<std::string> test_vector(std::begin(a), std::end(a)); + EXPECT_THAT(test_vector, ElementsAreArray(a.data(), a.size())); - const char** p = a; + const char** p = a.data(); test_vector[0] = "1"; - EXPECT_THAT(test_vector, Not(ElementsAreArray(p, GTEST_ARRAY_SIZE_(a)))); + EXPECT_THAT(test_vector, Not(ElementsAreArray(p, a.size()))); } TEST(ElementsAreArrayTest, CanBeCreatedWithoutArraySize) { const char* a[] = { "one", "two", "three" }; - vector<std::string> test_vector(a, a + GTEST_ARRAY_SIZE_(a)); + vector<std::string> test_vector(std::begin(a), std::end(a)); EXPECT_THAT(test_vector, ElementsAreArray(a)); test_vector[0] = "1"; @@ -484,8 +474,8 @@ TEST(ElementsAreArrayTest, CanBeCreatedWithMatcherArray) { TEST(ElementsAreArrayTest, CanBeCreatedWithVector) { const int a[] = { 1, 2, 3 }; - vector<int> test_vector(a, a + GTEST_ARRAY_SIZE_(a)); - const vector<int> expected(a, a + GTEST_ARRAY_SIZE_(a)); + vector<int> test_vector(std::begin(a), std::end(a)); + const vector<int> expected(std::begin(a), std::end(a)); EXPECT_THAT(test_vector, ElementsAreArray(expected)); test_vector.push_back(4); EXPECT_THAT(test_vector, Not(ElementsAreArray(expected))); @@ -530,9 +520,9 @@ TEST(ElementsAreArrayTest, TEST(ElementsAreArrayTest, CanBeCreatedWithMatcherVector) { const int a[] = { 1, 2, 3 }; const Matcher<int> kMatchers[] = { Eq(1), Eq(2), Eq(3) }; - vector<int> test_vector(a, a + GTEST_ARRAY_SIZE_(a)); - const vector<Matcher<int> > expected( - kMatchers, kMatchers + GTEST_ARRAY_SIZE_(kMatchers)); + vector<int> test_vector(std::begin(a), std::end(a)); + const vector<Matcher<int>> expected(std::begin(kMatchers), + std::end(kMatchers)); EXPECT_THAT(test_vector, ElementsAreArray(expected)); test_vector.push_back(4); EXPECT_THAT(test_vector, Not(ElementsAreArray(expected))); @@ -540,11 +530,11 @@ TEST(ElementsAreArrayTest, CanBeCreatedWithMatcherVector) { TEST(ElementsAreArrayTest, CanBeCreatedWithIteratorRange) { const int a[] = { 1, 2, 3 }; - const vector<int> test_vector(a, a + GTEST_ARRAY_SIZE_(a)); - const vector<int> expected(a, a + GTEST_ARRAY_SIZE_(a)); + const vector<int> test_vector(std::begin(a), std::end(a)); + const vector<int> expected(std::begin(a), std::end(a)); EXPECT_THAT(test_vector, ElementsAreArray(expected.begin(), expected.end())); // Pointers are iterators, too. - EXPECT_THAT(test_vector, ElementsAreArray(a, a + GTEST_ARRAY_SIZE_(a))); + EXPECT_THAT(test_vector, ElementsAreArray(std::begin(a), std::end(a))); // The empty range of NULL pointers should also be okay. int* const null_int = nullptr; EXPECT_THAT(test_vector, Not(ElementsAreArray(null_int, null_int))); @@ -564,8 +554,8 @@ TEST(ElementsAreArrayTest, WorksWithNativeArray) { TEST(ElementsAreArrayTest, SourceLifeSpan) { const int a[] = { 1, 2, 3 }; - vector<int> test_vector(a, a + GTEST_ARRAY_SIZE_(a)); - vector<int> expect(a, a + GTEST_ARRAY_SIZE_(a)); + vector<int> test_vector(std::begin(a), std::end(a)); + vector<int> expect(std::begin(a), std::end(a)); ElementsAreArrayMatcher<int> matcher_maker = ElementsAreArray(expect.begin(), expect.end()); EXPECT_THAT(test_vector, matcher_maker); @@ -774,9 +764,16 @@ MATCHER_P2(ReferencesAnyOf, variable1, variable2, "") { TEST(MatcherPnMacroTest, WorksWhenExplicitlyInstantiatedWithReferences) { UncopyableFoo foo1('1'), foo2('2'), foo3('3'); - const Matcher<const UncopyableFoo&> m = + const Matcher<const UncopyableFoo&> const_m = ReferencesAnyOf<const UncopyableFoo&, const UncopyableFoo&>(foo1, foo2); + EXPECT_TRUE(const_m.Matches(foo1)); + EXPECT_TRUE(const_m.Matches(foo2)); + EXPECT_FALSE(const_m.Matches(foo3)); + + const Matcher<UncopyableFoo&> m = + ReferencesAnyOf<UncopyableFoo&, UncopyableFoo&>(foo1, foo2); + EXPECT_TRUE(m.Matches(foo1)); EXPECT_TRUE(m.Matches(foo2)); EXPECT_FALSE(m.Matches(foo3)); diff --git a/googlemock/test/gmock-internal-utils_test.cc b/googlemock/test/gmock-internal-utils_test.cc index d000e692..8019f4a3 100644 --- a/googlemock/test/gmock-internal-utils_test.cc +++ b/googlemock/test/gmock-internal-utils_test.cc @@ -36,11 +36,11 @@ #include <stdlib.h> +#include <cstdint> #include <map> #include <memory> #include <sstream> #include <string> -#include <type_traits> #include <vector> #include "gmock/gmock.h" @@ -173,9 +173,9 @@ TEST(KindOfTest, Integer) { EXPECT_EQ(kInteger, GMOCK_KIND_OF_(unsigned int)); // NOLINT EXPECT_EQ(kInteger, GMOCK_KIND_OF_(long)); // NOLINT EXPECT_EQ(kInteger, GMOCK_KIND_OF_(unsigned long)); // NOLINT + EXPECT_EQ(kInteger, GMOCK_KIND_OF_(long long)); // NOLINT + EXPECT_EQ(kInteger, GMOCK_KIND_OF_(unsigned long long)); // NOLINT EXPECT_EQ(kInteger, GMOCK_KIND_OF_(wchar_t)); // NOLINT - EXPECT_EQ(kInteger, GMOCK_KIND_OF_(Int64)); // NOLINT - EXPECT_EQ(kInteger, GMOCK_KIND_OF_(UInt64)); // NOLINT EXPECT_EQ(kInteger, GMOCK_KIND_OF_(size_t)); // NOLINT #if GTEST_OS_LINUX || GTEST_OS_MAC || GTEST_OS_CYGWIN // ssize_t is not defined on Windows and possibly some other OSes. @@ -223,11 +223,12 @@ TEST(LosslessArithmeticConvertibleTest, IntegerToInteger) { EXPECT_TRUE((LosslessArithmeticConvertible<unsigned char, int>::value)); // Unsigned => larger unsigned is fine. - EXPECT_TRUE( - (LosslessArithmeticConvertible<unsigned short, UInt64>::value)); // NOLINT + EXPECT_TRUE((LosslessArithmeticConvertible< + unsigned short, uint64_t>::value)); // NOLINT // Signed => unsigned is not fine. - EXPECT_FALSE((LosslessArithmeticConvertible<short, UInt64>::value)); // NOLINT + EXPECT_FALSE((LosslessArithmeticConvertible< + short, uint64_t>::value)); // NOLINT EXPECT_FALSE((LosslessArithmeticConvertible< signed char, unsigned int>::value)); // NOLINT @@ -243,12 +244,12 @@ TEST(LosslessArithmeticConvertibleTest, IntegerToInteger) { EXPECT_FALSE((LosslessArithmeticConvertible< unsigned char, signed char>::value)); EXPECT_FALSE((LosslessArithmeticConvertible<int, unsigned int>::value)); - EXPECT_FALSE((LosslessArithmeticConvertible<UInt64, Int64>::value)); + EXPECT_FALSE((LosslessArithmeticConvertible<uint64_t, int64_t>::value)); // Larger size => smaller size is not fine. EXPECT_FALSE((LosslessArithmeticConvertible<long, char>::value)); // NOLINT EXPECT_FALSE((LosslessArithmeticConvertible<int, signed char>::value)); - EXPECT_FALSE((LosslessArithmeticConvertible<Int64, unsigned int>::value)); + EXPECT_FALSE((LosslessArithmeticConvertible<int64_t, unsigned int>::value)); } TEST(LosslessArithmeticConvertibleTest, IntegerToFloatingPoint) { @@ -267,7 +268,7 @@ TEST(LosslessArithmeticConvertibleTest, FloatingPointToBool) { TEST(LosslessArithmeticConvertibleTest, FloatingPointToInteger) { EXPECT_FALSE((LosslessArithmeticConvertible<float, long>::value)); // NOLINT - EXPECT_FALSE((LosslessArithmeticConvertible<double, Int64>::value)); + EXPECT_FALSE((LosslessArithmeticConvertible<double, int64_t>::value)); EXPECT_FALSE((LosslessArithmeticConvertible<long double, int>::value)); } diff --git a/googlemock/test/gmock-matchers_test.cc b/googlemock/test/gmock-matchers_test.cc index 03735267..3619959f 100644 --- a/googlemock/test/gmock-matchers_test.cc +++ b/googlemock/test/gmock-matchers_test.cc @@ -41,10 +41,12 @@ #endif #include "gmock/gmock-matchers.h" -#include "gmock/gmock-more-matchers.h" #include <string.h> #include <time.h> + +#include <array> +#include <cstdint> #include <deque> #include <forward_list> #include <functional> @@ -60,9 +62,11 @@ #include <type_traits> #include <utility> #include <vector> + +#include "gmock/gmock-more-matchers.h" #include "gmock/gmock.h" -#include "gtest/gtest.h" #include "gtest/gtest-spi.h" +#include "gtest/gtest.h" namespace testing { namespace gmock_matchers_test { @@ -136,7 +140,7 @@ Matcher<int> GreaterThan(int n) { std::string OfType(const std::string& type_name) { #if GTEST_HAS_RTTI - return " (of type " + type_name + ")"; + return IsReadableTypeName(type_name) ? " (of type " + type_name + ")" : ""; #else return ""; #endif @@ -347,43 +351,43 @@ TEST(StringMatcherTest, CanBeImplicitlyConstructedFromString) { EXPECT_FALSE(m2.Matches("hello")); } -#if GTEST_HAS_ABSL +#if GTEST_INTERNAL_HAS_STRING_VIEW // Tests that a C-string literal can be implicitly converted to a -// Matcher<absl::string_view> or Matcher<const absl::string_view&>. +// Matcher<StringView> or Matcher<const StringView&>. TEST(StringViewMatcherTest, CanBeImplicitlyConstructedFromCStringLiteral) { - Matcher<absl::string_view> m1 = "cats"; + Matcher<internal::StringView> m1 = "cats"; EXPECT_TRUE(m1.Matches("cats")); EXPECT_FALSE(m1.Matches("dogs")); - Matcher<const absl::string_view&> m2 = "cats"; + Matcher<const internal::StringView&> m2 = "cats"; EXPECT_TRUE(m2.Matches("cats")); EXPECT_FALSE(m2.Matches("dogs")); } // Tests that a std::string object can be implicitly converted to a -// Matcher<absl::string_view> or Matcher<const absl::string_view&>. +// Matcher<StringView> or Matcher<const StringView&>. TEST(StringViewMatcherTest, CanBeImplicitlyConstructedFromString) { - Matcher<absl::string_view> m1 = std::string("cats"); + Matcher<internal::StringView> m1 = std::string("cats"); EXPECT_TRUE(m1.Matches("cats")); EXPECT_FALSE(m1.Matches("dogs")); - Matcher<const absl::string_view&> m2 = std::string("cats"); + Matcher<const internal::StringView&> m2 = std::string("cats"); EXPECT_TRUE(m2.Matches("cats")); EXPECT_FALSE(m2.Matches("dogs")); } -// Tests that a absl::string_view object can be implicitly converted to a -// Matcher<absl::string_view> or Matcher<const absl::string_view&>. +// Tests that a StringView object can be implicitly converted to a +// Matcher<StringView> or Matcher<const StringView&>. TEST(StringViewMatcherTest, CanBeImplicitlyConstructedFromStringView) { - Matcher<absl::string_view> m1 = absl::string_view("cats"); + Matcher<internal::StringView> m1 = internal::StringView("cats"); EXPECT_TRUE(m1.Matches("cats")); EXPECT_FALSE(m1.Matches("dogs")); - Matcher<const absl::string_view&> m2 = absl::string_view("cats"); + Matcher<const internal::StringView&> m2 = internal::StringView("cats"); EXPECT_TRUE(m2.Matches("cats")); EXPECT_FALSE(m2.Matches("dogs")); } -#endif // GTEST_HAS_ABSL +#endif // GTEST_INTERNAL_HAS_STRING_VIEW // Tests that a std::reference_wrapper<std::string> object can be implicitly // converted to a Matcher<std::string> or Matcher<const std::string&> via Eq(). @@ -761,10 +765,11 @@ TEST(SafeMatcherCastTest, FromConstReferenceToReference) { // Tests that MatcherCast<const T&>(m) works when m is a Matcher<T>. TEST(SafeMatcherCastTest, FromNonReferenceToConstReference) { - Matcher<int> m1 = Eq(0); - Matcher<const int&> m2 = SafeMatcherCast<const int&>(m1); - EXPECT_TRUE(m2.Matches(0)); - EXPECT_FALSE(m2.Matches(1)); + Matcher<std::unique_ptr<int>> m1 = IsNull(); + Matcher<const std::unique_ptr<int>&> m2 = + SafeMatcherCast<const std::unique_ptr<int>&>(m1); + EXPECT_TRUE(m2.Matches(std::unique_ptr<int>())); + EXPECT_FALSE(m2.Matches(std::unique_ptr<int>(new int))); } // Tests that SafeMatcherCast<T&>(m) works when m is a Matcher<T>. @@ -1231,17 +1236,17 @@ TEST(StrEqTest, MatchesEqualString) { EXPECT_TRUE(m2.Matches("Hello")); EXPECT_FALSE(m2.Matches("Hi")); -#if GTEST_HAS_ABSL - Matcher<const absl::string_view&> m3 = StrEq("Hello"); - EXPECT_TRUE(m3.Matches(absl::string_view("Hello"))); - EXPECT_FALSE(m3.Matches(absl::string_view("hello"))); - EXPECT_FALSE(m3.Matches(absl::string_view())); +#if GTEST_INTERNAL_HAS_STRING_VIEW + Matcher<const internal::StringView&> m3 = StrEq("Hello"); + EXPECT_TRUE(m3.Matches(internal::StringView("Hello"))); + EXPECT_FALSE(m3.Matches(internal::StringView("hello"))); + EXPECT_FALSE(m3.Matches(internal::StringView())); - Matcher<const absl::string_view&> m_empty = StrEq(""); - EXPECT_TRUE(m_empty.Matches(absl::string_view(""))); - EXPECT_TRUE(m_empty.Matches(absl::string_view())); - EXPECT_FALSE(m_empty.Matches(absl::string_view("hello"))); -#endif // GTEST_HAS_ABSL + Matcher<const internal::StringView&> m_empty = StrEq(""); + EXPECT_TRUE(m_empty.Matches(internal::StringView(""))); + EXPECT_TRUE(m_empty.Matches(internal::StringView())); + EXPECT_FALSE(m_empty.Matches(internal::StringView("hello"))); +#endif // GTEST_INTERNAL_HAS_STRING_VIEW } TEST(StrEqTest, CanDescribeSelf) { @@ -1268,12 +1273,12 @@ TEST(StrNeTest, MatchesUnequalString) { EXPECT_TRUE(m2.Matches("hello")); EXPECT_FALSE(m2.Matches("Hello")); -#if GTEST_HAS_ABSL - Matcher<const absl::string_view> m3 = StrNe("Hello"); - EXPECT_TRUE(m3.Matches(absl::string_view(""))); - EXPECT_TRUE(m3.Matches(absl::string_view())); - EXPECT_FALSE(m3.Matches(absl::string_view("Hello"))); -#endif // GTEST_HAS_ABSL +#if GTEST_INTERNAL_HAS_STRING_VIEW + Matcher<const internal::StringView> m3 = StrNe("Hello"); + EXPECT_TRUE(m3.Matches(internal::StringView(""))); + EXPECT_TRUE(m3.Matches(internal::StringView())); + EXPECT_FALSE(m3.Matches(internal::StringView("Hello"))); +#endif // GTEST_INTERNAL_HAS_STRING_VIEW } TEST(StrNeTest, CanDescribeSelf) { @@ -1292,13 +1297,13 @@ TEST(StrCaseEqTest, MatchesEqualStringIgnoringCase) { EXPECT_TRUE(m2.Matches("hello")); EXPECT_FALSE(m2.Matches("Hi")); -#if GTEST_HAS_ABSL - Matcher<const absl::string_view&> m3 = StrCaseEq(std::string("Hello")); - EXPECT_TRUE(m3.Matches(absl::string_view("Hello"))); - EXPECT_TRUE(m3.Matches(absl::string_view("hello"))); - EXPECT_FALSE(m3.Matches(absl::string_view("Hi"))); - EXPECT_FALSE(m3.Matches(absl::string_view())); -#endif // GTEST_HAS_ABSL +#if GTEST_INTERNAL_HAS_STRING_VIEW + Matcher<const internal::StringView&> m3 = StrCaseEq(std::string("Hello")); + EXPECT_TRUE(m3.Matches(internal::StringView("Hello"))); + EXPECT_TRUE(m3.Matches(internal::StringView("hello"))); + EXPECT_FALSE(m3.Matches(internal::StringView("Hi"))); + EXPECT_FALSE(m3.Matches(internal::StringView())); +#endif // GTEST_INTERNAL_HAS_STRING_VIEW } TEST(StrCaseEqTest, MatchesEqualStringWith0IgnoringCase) { @@ -1342,13 +1347,13 @@ TEST(StrCaseNeTest, MatchesUnequalStringIgnoringCase) { EXPECT_TRUE(m2.Matches("")); EXPECT_FALSE(m2.Matches("Hello")); -#if GTEST_HAS_ABSL - Matcher<const absl::string_view> m3 = StrCaseNe("Hello"); - EXPECT_TRUE(m3.Matches(absl::string_view("Hi"))); - EXPECT_TRUE(m3.Matches(absl::string_view())); - EXPECT_FALSE(m3.Matches(absl::string_view("Hello"))); - EXPECT_FALSE(m3.Matches(absl::string_view("hello"))); -#endif // GTEST_HAS_ABSL +#if GTEST_INTERNAL_HAS_STRING_VIEW + Matcher<const internal::StringView> m3 = StrCaseNe("Hello"); + EXPECT_TRUE(m3.Matches(internal::StringView("Hi"))); + EXPECT_TRUE(m3.Matches(internal::StringView())); + EXPECT_FALSE(m3.Matches(internal::StringView("Hello"))); + EXPECT_FALSE(m3.Matches(internal::StringView("hello"))); +#endif // GTEST_INTERNAL_HAS_STRING_VIEW } TEST(StrCaseNeTest, CanDescribeSelf) { @@ -1389,25 +1394,25 @@ TEST(HasSubstrTest, WorksForCStrings) { EXPECT_FALSE(m_empty.Matches(nullptr)); } -#if GTEST_HAS_ABSL -// Tests that HasSubstr() works for matching absl::string_view-typed values. +#if GTEST_INTERNAL_HAS_STRING_VIEW +// Tests that HasSubstr() works for matching StringView-typed values. TEST(HasSubstrTest, WorksForStringViewClasses) { - const Matcher<absl::string_view> m1 = HasSubstr("foo"); - EXPECT_TRUE(m1.Matches(absl::string_view("I love food."))); - EXPECT_FALSE(m1.Matches(absl::string_view("tofo"))); - EXPECT_FALSE(m1.Matches(absl::string_view())); + const Matcher<internal::StringView> m1 = HasSubstr("foo"); + EXPECT_TRUE(m1.Matches(internal::StringView("I love food."))); + EXPECT_FALSE(m1.Matches(internal::StringView("tofo"))); + EXPECT_FALSE(m1.Matches(internal::StringView())); - const Matcher<const absl::string_view&> m2 = HasSubstr("foo"); - EXPECT_TRUE(m2.Matches(absl::string_view("I love food."))); - EXPECT_FALSE(m2.Matches(absl::string_view("tofo"))); - EXPECT_FALSE(m2.Matches(absl::string_view())); + const Matcher<const internal::StringView&> m2 = HasSubstr("foo"); + EXPECT_TRUE(m2.Matches(internal::StringView("I love food."))); + EXPECT_FALSE(m2.Matches(internal::StringView("tofo"))); + EXPECT_FALSE(m2.Matches(internal::StringView())); - const Matcher<const absl::string_view&> m3 = HasSubstr(""); - EXPECT_TRUE(m3.Matches(absl::string_view("foo"))); - EXPECT_TRUE(m3.Matches(absl::string_view(""))); - EXPECT_TRUE(m3.Matches(absl::string_view())); + const Matcher<const internal::StringView&> m3 = HasSubstr(""); + EXPECT_TRUE(m3.Matches(internal::StringView("foo"))); + EXPECT_TRUE(m3.Matches(internal::StringView(""))); + EXPECT_TRUE(m3.Matches(internal::StringView())); } -#endif // GTEST_HAS_ABSL +#endif // GTEST_INTERNAL_HAS_STRING_VIEW // Tests that HasSubstr(s) describes itself properly. TEST(HasSubstrTest, CanDescribeSelf) { @@ -1644,12 +1649,12 @@ TEST(StartsWithTest, MatchesStringWithGivenPrefix) { EXPECT_FALSE(m2.Matches("H")); EXPECT_FALSE(m2.Matches(" Hi")); -#if GTEST_HAS_ABSL - const Matcher<absl::string_view> m_empty = StartsWith(""); - EXPECT_TRUE(m_empty.Matches(absl::string_view())); - EXPECT_TRUE(m_empty.Matches(absl::string_view(""))); - EXPECT_TRUE(m_empty.Matches(absl::string_view("not empty"))); -#endif // GTEST_HAS_ABSL +#if GTEST_INTERNAL_HAS_STRING_VIEW + const Matcher<internal::StringView> m_empty = StartsWith(""); + EXPECT_TRUE(m_empty.Matches(internal::StringView())); + EXPECT_TRUE(m_empty.Matches(internal::StringView(""))); + EXPECT_TRUE(m_empty.Matches(internal::StringView("not empty"))); +#endif // GTEST_INTERNAL_HAS_STRING_VIEW } TEST(StartsWithTest, CanDescribeSelf) { @@ -1672,13 +1677,13 @@ TEST(EndsWithTest, MatchesStringWithGivenSuffix) { EXPECT_FALSE(m2.Matches("i")); EXPECT_FALSE(m2.Matches("Hi ")); -#if GTEST_HAS_ABSL - const Matcher<const absl::string_view&> m4 = EndsWith(""); +#if GTEST_INTERNAL_HAS_STRING_VIEW + const Matcher<const internal::StringView&> m4 = EndsWith(""); EXPECT_TRUE(m4.Matches("Hi")); EXPECT_TRUE(m4.Matches("")); - EXPECT_TRUE(m4.Matches(absl::string_view())); - EXPECT_TRUE(m4.Matches(absl::string_view(""))); -#endif // GTEST_HAS_ABSL + EXPECT_TRUE(m4.Matches(internal::StringView())); + EXPECT_TRUE(m4.Matches(internal::StringView(""))); +#endif // GTEST_INTERNAL_HAS_STRING_VIEW } TEST(EndsWithTest, CanDescribeSelf) { @@ -1699,16 +1704,16 @@ TEST(MatchesRegexTest, MatchesStringMatchingGivenRegex) { EXPECT_FALSE(m2.Matches("az1")); EXPECT_FALSE(m2.Matches("1az")); -#if GTEST_HAS_ABSL - const Matcher<const absl::string_view&> m3 = MatchesRegex("a.*z"); - EXPECT_TRUE(m3.Matches(absl::string_view("az"))); - EXPECT_TRUE(m3.Matches(absl::string_view("abcz"))); - EXPECT_FALSE(m3.Matches(absl::string_view("1az"))); - EXPECT_FALSE(m3.Matches(absl::string_view())); - const Matcher<const absl::string_view&> m4 = MatchesRegex(""); - EXPECT_TRUE(m4.Matches(absl::string_view(""))); - EXPECT_TRUE(m4.Matches(absl::string_view())); -#endif // GTEST_HAS_ABSL +#if GTEST_INTERNAL_HAS_STRING_VIEW + const Matcher<const internal::StringView&> m3 = MatchesRegex("a.*z"); + EXPECT_TRUE(m3.Matches(internal::StringView("az"))); + EXPECT_TRUE(m3.Matches(internal::StringView("abcz"))); + EXPECT_FALSE(m3.Matches(internal::StringView("1az"))); + EXPECT_FALSE(m3.Matches(internal::StringView())); + const Matcher<const internal::StringView&> m4 = MatchesRegex(""); + EXPECT_TRUE(m4.Matches(internal::StringView(""))); + EXPECT_TRUE(m4.Matches(internal::StringView())); +#endif // GTEST_INTERNAL_HAS_STRING_VIEW } TEST(MatchesRegexTest, CanDescribeSelf) { @@ -1718,10 +1723,10 @@ TEST(MatchesRegexTest, CanDescribeSelf) { Matcher<const char*> m2 = MatchesRegex(new RE("a.*")); EXPECT_EQ("matches regular expression \"a.*\"", Describe(m2)); -#if GTEST_HAS_ABSL - Matcher<const absl::string_view> m3 = MatchesRegex(new RE("0.*")); +#if GTEST_INTERNAL_HAS_STRING_VIEW + Matcher<const internal::StringView> m3 = MatchesRegex(new RE("0.*")); EXPECT_EQ("matches regular expression \"0.*\"", Describe(m3)); -#endif // GTEST_HAS_ABSL +#endif // GTEST_INTERNAL_HAS_STRING_VIEW } // Tests ContainsRegex(). @@ -1737,16 +1742,17 @@ TEST(ContainsRegexTest, MatchesStringContainingGivenRegex) { EXPECT_TRUE(m2.Matches("az1")); EXPECT_FALSE(m2.Matches("1a")); -#if GTEST_HAS_ABSL - const Matcher<const absl::string_view&> m3 = ContainsRegex(new RE("a.*z")); - EXPECT_TRUE(m3.Matches(absl::string_view("azbz"))); - EXPECT_TRUE(m3.Matches(absl::string_view("az1"))); - EXPECT_FALSE(m3.Matches(absl::string_view("1a"))); - EXPECT_FALSE(m3.Matches(absl::string_view())); - const Matcher<const absl::string_view&> m4 = ContainsRegex(""); - EXPECT_TRUE(m4.Matches(absl::string_view(""))); - EXPECT_TRUE(m4.Matches(absl::string_view())); -#endif // GTEST_HAS_ABSL +#if GTEST_INTERNAL_HAS_STRING_VIEW + const Matcher<const internal::StringView&> m3 = + ContainsRegex(new RE("a.*z")); + EXPECT_TRUE(m3.Matches(internal::StringView("azbz"))); + EXPECT_TRUE(m3.Matches(internal::StringView("az1"))); + EXPECT_FALSE(m3.Matches(internal::StringView("1a"))); + EXPECT_FALSE(m3.Matches(internal::StringView())); + const Matcher<const internal::StringView&> m4 = ContainsRegex(""); + EXPECT_TRUE(m4.Matches(internal::StringView(""))); + EXPECT_TRUE(m4.Matches(internal::StringView())); +#endif // GTEST_INTERNAL_HAS_STRING_VIEW } TEST(ContainsRegexTest, CanDescribeSelf) { @@ -1756,10 +1762,10 @@ TEST(ContainsRegexTest, CanDescribeSelf) { Matcher<const char*> m2 = ContainsRegex(new RE("a.*")); EXPECT_EQ("contains regular expression \"a.*\"", Describe(m2)); -#if GTEST_HAS_ABSL - Matcher<const absl::string_view> m3 = ContainsRegex(new RE("0.*")); +#if GTEST_INTERNAL_HAS_STRING_VIEW + Matcher<const internal::StringView> m3 = ContainsRegex(new RE("0.*")); EXPECT_EQ("contains regular expression \"0.*\"", Describe(m3)); -#endif // GTEST_HAS_ABSL +#endif // GTEST_INTERNAL_HAS_STRING_VIEW } // Tests for wide strings. @@ -2054,6 +2060,114 @@ TEST(PairMatchBaseTest, WorksWithMoveOnly) { EXPECT_TRUE(matcher.Matches(pointers)); } +// Tests that IsNan() matches a NaN, with float. +TEST(IsNan, FloatMatchesNan) { + float quiet_nan = std::numeric_limits<float>::quiet_NaN(); + float other_nan = std::nanf("1"); + float real_value = 1.0f; + + Matcher<float> m = IsNan(); + EXPECT_TRUE(m.Matches(quiet_nan)); + EXPECT_TRUE(m.Matches(other_nan)); + EXPECT_FALSE(m.Matches(real_value)); + + Matcher<float&> m_ref = IsNan(); + EXPECT_TRUE(m_ref.Matches(quiet_nan)); + EXPECT_TRUE(m_ref.Matches(other_nan)); + EXPECT_FALSE(m_ref.Matches(real_value)); + + Matcher<const float&> m_cref = IsNan(); + EXPECT_TRUE(m_cref.Matches(quiet_nan)); + EXPECT_TRUE(m_cref.Matches(other_nan)); + EXPECT_FALSE(m_cref.Matches(real_value)); +} + +// Tests that IsNan() matches a NaN, with double. +TEST(IsNan, DoubleMatchesNan) { + double quiet_nan = std::numeric_limits<double>::quiet_NaN(); + double other_nan = std::nan("1"); + double real_value = 1.0; + + Matcher<double> m = IsNan(); + EXPECT_TRUE(m.Matches(quiet_nan)); + EXPECT_TRUE(m.Matches(other_nan)); + EXPECT_FALSE(m.Matches(real_value)); + + Matcher<double&> m_ref = IsNan(); + EXPECT_TRUE(m_ref.Matches(quiet_nan)); + EXPECT_TRUE(m_ref.Matches(other_nan)); + EXPECT_FALSE(m_ref.Matches(real_value)); + + Matcher<const double&> m_cref = IsNan(); + EXPECT_TRUE(m_cref.Matches(quiet_nan)); + EXPECT_TRUE(m_cref.Matches(other_nan)); + EXPECT_FALSE(m_cref.Matches(real_value)); +} + +// Tests that IsNan() matches a NaN, with long double. +TEST(IsNan, LongDoubleMatchesNan) { + long double quiet_nan = std::numeric_limits<long double>::quiet_NaN(); + long double other_nan = std::nan("1"); + long double real_value = 1.0; + + Matcher<long double> m = IsNan(); + EXPECT_TRUE(m.Matches(quiet_nan)); + EXPECT_TRUE(m.Matches(other_nan)); + EXPECT_FALSE(m.Matches(real_value)); + + Matcher<long double&> m_ref = IsNan(); + EXPECT_TRUE(m_ref.Matches(quiet_nan)); + EXPECT_TRUE(m_ref.Matches(other_nan)); + EXPECT_FALSE(m_ref.Matches(real_value)); + + Matcher<const long double&> m_cref = IsNan(); + EXPECT_TRUE(m_cref.Matches(quiet_nan)); + EXPECT_TRUE(m_cref.Matches(other_nan)); + EXPECT_FALSE(m_cref.Matches(real_value)); +} + +// Tests that IsNan() works with Not. +TEST(IsNan, NotMatchesNan) { + Matcher<float> mf = Not(IsNan()); + EXPECT_FALSE(mf.Matches(std::numeric_limits<float>::quiet_NaN())); + EXPECT_FALSE(mf.Matches(std::nanf("1"))); + EXPECT_TRUE(mf.Matches(1.0)); + + Matcher<double> md = Not(IsNan()); + EXPECT_FALSE(md.Matches(std::numeric_limits<double>::quiet_NaN())); + EXPECT_FALSE(md.Matches(std::nan("1"))); + EXPECT_TRUE(md.Matches(1.0)); + + Matcher<long double> mld = Not(IsNan()); + EXPECT_FALSE(mld.Matches(std::numeric_limits<long double>::quiet_NaN())); + EXPECT_FALSE(mld.Matches(std::nanl("1"))); + EXPECT_TRUE(mld.Matches(1.0)); +} + +// Tests that IsNan() can describe itself. +TEST(IsNan, CanDescribeSelf) { + Matcher<float> mf = IsNan(); + EXPECT_EQ("is NaN", Describe(mf)); + + Matcher<double> md = IsNan(); + EXPECT_EQ("is NaN", Describe(md)); + + Matcher<long double> mld = IsNan(); + EXPECT_EQ("is NaN", Describe(mld)); +} + +// Tests that IsNan() can describe itself with Not. +TEST(IsNan, CanDescribeSelfWithNot) { + Matcher<float> mf = Not(IsNan()); + EXPECT_EQ("isn't NaN", Describe(mf)); + + Matcher<double> md = Not(IsNan()); + EXPECT_EQ("isn't NaN", Describe(md)); + + Matcher<long double> mld = Not(IsNan()); + EXPECT_EQ("isn't NaN", Describe(mld)); +} + // Tests that FloatEq() matches a 2-tuple where // FloatEq(first field) matches the second field. TEST(FloatEq2Test, MatchesEqualArguments) { @@ -2763,6 +2877,33 @@ TEST(ExplainMatchResultTest, WorksWithMonomorphicMatcher) { EXPECT_EQ("", listener2.str()); } +MATCHER(ConstructNoArg, "") { return true; } +MATCHER_P(Construct1Arg, arg1, "") { return true; } +MATCHER_P2(Construct2Args, arg1, arg2, "") { return true; } + +TEST(MatcherConstruct, ExplicitVsImplicit) { + { + // No arg constructor can be constructed with empty brace. + ConstructNoArgMatcher m = {}; + (void)m; + // And with no args + ConstructNoArgMatcher m2; + (void)m2; + } + { + // The one arg constructor has an explicit constructor. + // This is to prevent the implicit conversion. + using M = Construct1ArgMatcherP<int>; + EXPECT_TRUE((std::is_constructible<M, int>::value)); + EXPECT_FALSE((std::is_convertible<int, M>::value)); + } + { + // Multiple arg matchers can be constructed with an implicit construction. + Construct2ArgsMatcherP2<int, double> m = {1, 2.2}; + (void)m; + } +} + MATCHER_P(Really, inner_matcher, "") { return ExplainMatchResult(inner_matcher, arg, result_listener); } @@ -2876,18 +3017,13 @@ TEST(MatcherAssertionTest, WorksWhenMatcherIsNotSatisfied) { static unsigned short n; // NOLINT n = 5; - // VC++ prior to version 8.0 SP1 has a bug where it will not see any - // functions declared in the namespace scope from within nested classes. - // EXPECT/ASSERT_(NON)FATAL_FAILURE macros use nested classes so that all - // namespace-level functions invoked inside them need to be explicitly - // resolved. - EXPECT_FATAL_FAILURE(ASSERT_THAT(n, ::testing::Gt(10)), + EXPECT_FATAL_FAILURE(ASSERT_THAT(n, Gt(10)), "Value of: n\n" "Expected: is > 10\n" " Actual: 5" + OfType("unsigned short")); n = 0; EXPECT_NONFATAL_FAILURE( - EXPECT_THAT(n, ::testing::AllOf(::testing::Le(7), ::testing::Ge(5))), + EXPECT_THAT(n, AllOf(Le(7), Ge(5))), "Value of: n\n" "Expected: (is <= 7) and (is >= 5)\n" " Actual: 0" + OfType("unsigned short")); @@ -2901,11 +3037,11 @@ TEST(MatcherAssertionTest, WorksForByRefArguments) { static int n; n = 0; EXPECT_THAT(n, AllOf(Le(7), Ref(n))); - EXPECT_FATAL_FAILURE(ASSERT_THAT(n, ::testing::Not(::testing::Ref(n))), + EXPECT_FATAL_FAILURE(ASSERT_THAT(n, Not(Ref(n))), "Value of: n\n" "Expected: does not reference the variable @"); // Tests the "Actual" part. - EXPECT_FATAL_FAILURE(ASSERT_THAT(n, ::testing::Not(::testing::Ref(n))), + EXPECT_FATAL_FAILURE(ASSERT_THAT(n, Not(Ref(n))), "Actual: 0" + OfType("int") + ", which is located @"); } @@ -5093,14 +5229,14 @@ TEST(WhenSortedTest, WorksForStreamlike) { // Streamlike 'container' provides only minimal iterator support. // Its iterators are tagged with input_iterator_tag. const int a[5] = {2, 1, 4, 5, 3}; - Streamlike<int> s(a, a + GTEST_ARRAY_SIZE_(a)); + Streamlike<int> s(std::begin(a), std::end(a)); EXPECT_THAT(s, WhenSorted(ElementsAre(1, 2, 3, 4, 5))); EXPECT_THAT(s, Not(WhenSorted(ElementsAre(2, 1, 4, 5, 3)))); } TEST(WhenSortedTest, WorksForVectorConstRefMatcherOnStreamlike) { const int a[] = {2, 1, 4, 5, 3}; - Streamlike<int> s(a, a + GTEST_ARRAY_SIZE_(a)); + Streamlike<int> s(std::begin(a), std::end(a)); Matcher<const std::vector<int>&> vector_match = ElementsAre(1, 2, 3, 4, 5); EXPECT_THAT(s, WhenSorted(vector_match)); EXPECT_THAT(s, Not(WhenSorted(ElementsAre(2, 1, 4, 5, 3)))); @@ -5145,7 +5281,7 @@ TEST(IsSupersetOfTest, WorksForEmpty) { TEST(IsSupersetOfTest, WorksForStreamlike) { const int a[5] = {1, 2, 3, 4, 5}; - Streamlike<int> s(a, a + GTEST_ARRAY_SIZE_(a)); + Streamlike<int> s(std::begin(a), std::end(a)); vector<int> expected; expected.push_back(1); @@ -5273,7 +5409,7 @@ TEST(IsSubsetOfTest, WorksForEmpty) { TEST(IsSubsetOfTest, WorksForStreamlike) { const int a[5] = {1, 2}; - Streamlike<int> s(a, a + GTEST_ARRAY_SIZE_(a)); + Streamlike<int> s(std::begin(a), std::end(a)); vector<int> expected; expected.push_back(1); @@ -5367,14 +5503,14 @@ TEST(IsSubsetOfTest, WorksWithMoveOnly) { TEST(ElemensAreStreamTest, WorksForStreamlike) { const int a[5] = {1, 2, 3, 4, 5}; - Streamlike<int> s(a, a + GTEST_ARRAY_SIZE_(a)); + Streamlike<int> s(std::begin(a), std::end(a)); EXPECT_THAT(s, ElementsAre(1, 2, 3, 4, 5)); EXPECT_THAT(s, Not(ElementsAre(2, 1, 4, 5, 3))); } TEST(ElemensAreArrayStreamTest, WorksForStreamlike) { const int a[5] = {1, 2, 3, 4, 5}; - Streamlike<int> s(a, a + GTEST_ARRAY_SIZE_(a)); + Streamlike<int> s(std::begin(a), std::end(a)); vector<int> expected; expected.push_back(1); @@ -5421,7 +5557,7 @@ TEST(ElementsAreTest, TakesStlContainer) { TEST(UnorderedElementsAreArrayTest, SucceedsWhenExpected) { const int a[] = {0, 1, 2, 3, 4}; - std::vector<int> s(a, a + GTEST_ARRAY_SIZE_(a)); + std::vector<int> s(std::begin(a), std::end(a)); do { StringMatchResultListener listener; EXPECT_TRUE(ExplainMatchResult(UnorderedElementsAreArray(a), @@ -5432,8 +5568,8 @@ TEST(UnorderedElementsAreArrayTest, SucceedsWhenExpected) { TEST(UnorderedElementsAreArrayTest, VectorBool) { const bool a[] = {0, 1, 0, 1, 1}; const bool b[] = {1, 0, 1, 1, 0}; - std::vector<bool> expected(a, a + GTEST_ARRAY_SIZE_(a)); - std::vector<bool> actual(b, b + GTEST_ARRAY_SIZE_(b)); + std::vector<bool> expected(std::begin(a), std::end(a)); + std::vector<bool> actual(std::begin(b), std::end(b)); StringMatchResultListener listener; EXPECT_TRUE(ExplainMatchResult(UnorderedElementsAreArray(expected), actual, &listener)) << listener.str(); @@ -5444,7 +5580,7 @@ TEST(UnorderedElementsAreArrayTest, WorksForStreamlike) { // Its iterators are tagged with input_iterator_tag, and it has no // size() or empty() methods. const int a[5] = {2, 1, 4, 5, 3}; - Streamlike<int> s(a, a + GTEST_ARRAY_SIZE_(a)); + Streamlike<int> s(std::begin(a), std::end(a)); ::std::vector<int> expected; expected.push_back(1); @@ -5527,7 +5663,7 @@ TEST_F(UnorderedElementsAreTest, WorksWithUncopyable) { TEST_F(UnorderedElementsAreTest, SucceedsWhenExpected) { const int a[] = {1, 2, 3}; - std::vector<int> s(a, a + GTEST_ARRAY_SIZE_(a)); + std::vector<int> s(std::begin(a), std::end(a)); do { StringMatchResultListener listener; EXPECT_TRUE(ExplainMatchResult(UnorderedElementsAre(1, 2, 3), @@ -5537,7 +5673,7 @@ TEST_F(UnorderedElementsAreTest, SucceedsWhenExpected) { TEST_F(UnorderedElementsAreTest, FailsWhenAnElementMatchesNoMatcher) { const int a[] = {1, 2, 3}; - std::vector<int> s(a, a + GTEST_ARRAY_SIZE_(a)); + std::vector<int> s(std::begin(a), std::end(a)); std::vector<Matcher<int> > mv; mv.push_back(1); mv.push_back(2); @@ -5553,7 +5689,7 @@ TEST_F(UnorderedElementsAreTest, WorksForStreamlike) { // Its iterators are tagged with input_iterator_tag, and it has no // size() or empty() methods. const int a[5] = {2, 1, 4, 5, 3}; - Streamlike<int> s(a, a + GTEST_ARRAY_SIZE_(a)); + Streamlike<int> s(std::begin(a), std::end(a)); EXPECT_THAT(s, UnorderedElementsAre(1, 2, 3, 4, 5)); EXPECT_THAT(s, Not(UnorderedElementsAre(2, 2, 3, 4, 5))); @@ -5869,8 +6005,9 @@ TEST_F(BipartiteNonSquareTest, SimpleBacktracking) { // :.......: // 0 1 2 MatchMatrix g(4, 3); - static const size_t kEdges[][2] = {{0, 2}, {1, 1}, {2, 1}, {3, 0}}; - for (size_t i = 0; i < GTEST_ARRAY_SIZE_(kEdges); ++i) { + constexpr std::array<std::array<size_t, 2>, 4> kEdges = { + {{{0, 2}}, {{1, 1}}, {{2, 1}}, {{3, 0}}}}; + for (size_t i = 0; i < kEdges.size(); ++i) { g.SetEdge(kEdges[i][0], kEdges[i][1], true); } EXPECT_THAT(FindBacktrackingMaxBPM(g), @@ -5916,9 +6053,9 @@ TEST_P(BipartiteRandomTest, LargerNets) { int iters = GetParam().second; MatchMatrix graph(static_cast<size_t>(nodes), static_cast<size_t>(nodes)); - auto seed = static_cast<testing::internal::UInt32>(GTEST_FLAG(random_seed)); + auto seed = static_cast<uint32_t>(GTEST_FLAG(random_seed)); if (seed == 0) { - seed = static_cast<testing::internal::UInt32>(time(nullptr)); + seed = static_cast<uint32_t>(time(nullptr)); } for (; iters > 0; --iters, ++seed) { @@ -6777,7 +6914,8 @@ TEST_F(PredicateFormatterFromMatcherTest, NoShortCircuitOnFailure) { EXPECT_FALSE(result); // Implicit cast to bool. std::string expect = "Value of: dummy-name\nExpected: [DescribeTo]\n" - " Actual: 1, [MatchAndExplain]"; + " Actual: 1" + + OfType(internal::GetTypeName<Behavior>()) + ", [MatchAndExplain]"; EXPECT_EQ(expect, result.message()); } @@ -6788,7 +6926,8 @@ TEST_F(PredicateFormatterFromMatcherTest, DetectsFlakyShortCircuit) { "Value of: dummy-name\nExpected: [DescribeTo]\n" " The matcher failed on the initial attempt; but passed when rerun to " "generate the explanation.\n" - " Actual: 2, [MatchAndExplain]"; + " Actual: 2" + + OfType(internal::GetTypeName<Behavior>()) + ", [MatchAndExplain]"; EXPECT_EQ(expect, result.message()); } diff --git a/googlemock/test/gmock-pp_test.cc b/googlemock/test/gmock-pp_test.cc index 7387d398..5d1566e3 100644 --- a/googlemock/test/gmock-pp_test.cc +++ b/googlemock/test/gmock-pp_test.cc @@ -1,5 +1,10 @@ #include "gmock/internal/gmock-pp.h" +// Used to test MSVC treating __VA_ARGS__ with a comma in it as one value +#define GMOCK_TEST_REPLACE_comma_WITH_COMMA_I_comma , +#define GMOCK_TEST_REPLACE_comma_WITH_COMMA(x) \ + GMOCK_PP_CAT(GMOCK_TEST_REPLACE_comma_WITH_COMMA_I_, x) + // Static assertions. namespace testing { namespace internal { @@ -17,6 +22,11 @@ static_assert(GMOCK_PP_NARG(x, y, z, w) == 4, ""); static_assert(!GMOCK_PP_HAS_COMMA(), ""); static_assert(GMOCK_PP_HAS_COMMA(b, ), ""); static_assert(!GMOCK_PP_HAS_COMMA((, )), ""); +static_assert(GMOCK_PP_HAS_COMMA(GMOCK_TEST_REPLACE_comma_WITH_COMMA(comma)), + ""); +static_assert( + GMOCK_PP_HAS_COMMA(GMOCK_TEST_REPLACE_comma_WITH_COMMA(comma(unrelated))), + ""); static_assert(!GMOCK_PP_IS_EMPTY(, ), ""); static_assert(!GMOCK_PP_IS_EMPTY(a), ""); static_assert(!GMOCK_PP_IS_EMPTY(()), ""); diff --git a/googlemock/test/gmock-spec-builders_test.cc b/googlemock/test/gmock-spec-builders_test.cc index 7bf5a8ad..791a2476 100644 --- a/googlemock/test/gmock-spec-builders_test.cc +++ b/googlemock/test/gmock-spec-builders_test.cc @@ -69,8 +69,8 @@ using testing::AtMost; using testing::Between; using testing::Cardinality; using testing::CardinalityInterface; -using testing::ContainsRegex; using testing::Const; +using testing::ContainsRegex; using testing::DoAll; using testing::DoDefault; using testing::Eq; diff --git a/googlemock/test/gmock_all_test.cc b/googlemock/test/gmock_all_test.cc index b2b2027d..c53d0965 100644 --- a/googlemock/test/gmock_all_test.cc +++ b/googlemock/test/gmock_all_test.cc @@ -38,7 +38,6 @@ #include "test/gmock-actions_test.cc" #include "test/gmock-cardinalities_test.cc" #include "test/gmock-generated-actions_test.cc" -#include "test/gmock-generated-function-mockers_test.cc" #include "test/gmock-generated-matchers_test.cc" #include "test/gmock-internal-utils_test.cc" #include "test/gmock-matchers_test.cc" diff --git a/googlemock/test/pump_test.py b/googlemock/test/pump_test.py new file mode 100755 index 00000000..eb5a1313 --- /dev/null +++ b/googlemock/test/pump_test.py @@ -0,0 +1,182 @@ +#!/usr/bin/env python +# +# Copyright 2010, Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +"""Tests for the Pump meta-programming tool.""" + +from google3.testing.pybase import googletest +import google3.third_party.googletest.googlemock.scripts.pump + +pump = google3.third_party.googletest.googlemock.scripts.pump +Convert = pump.ConvertFromPumpSource +StripMetaComments = pump.StripMetaComments + + +class PumpTest(googletest.TestCase): + + def testConvertsEmptyToEmpty(self): + self.assertEquals('', Convert('').strip()) + + def testConvertsPlainCodeToSame(self): + self.assertEquals('#include <stdio.h>\n', + Convert('#include <stdio.h>\n')) + + def testConvertsLongIWYUPragmaToSame(self): + long_line = '// IWYU pragma: private, include "' + (80*'a') + '.h"\n' + self.assertEquals(long_line, Convert(long_line)) + + def testConvertsIWYUPragmaWithLeadingSpaceToSame(self): + long_line = ' // IWYU pragma: private, include "' + (80*'a') + '.h"\n' + self.assertEquals(long_line, Convert(long_line)) + + def testConvertsIWYUPragmaWithSlashStarLeaderToSame(self): + long_line = '/* IWYU pragma: private, include "' + (80*'a') + '.h"\n' + self.assertEquals(long_line, Convert(long_line)) + + def testConvertsIWYUPragmaWithSlashStarAndSpacesToSame(self): + long_line = ' /* IWYU pragma: private, include "' + (80*'a') + '.h"\n' + self.assertEquals(long_line, Convert(long_line)) + + def testIgnoresMetaComment(self): + self.assertEquals('', + Convert('$$ This is a Pump meta comment.\n').strip()) + + def testSimpleVarDeclarationWorks(self): + self.assertEquals('3\n', + Convert('$var m = 3\n' + '$m\n')) + + def testVarDeclarationCanReferenceEarlierVar(self): + self.assertEquals('43 != 3;\n', + Convert('$var a = 42\n' + '$var b = a + 1\n' + '$var c = (b - a)*3\n' + '$b != $c;\n')) + + def testSimpleLoopWorks(self): + self.assertEquals('1, 2, 3, 4, 5\n', + Convert('$var n = 5\n' + '$range i 1..n\n' + '$for i, [[$i]]\n')) + + def testSimpleLoopWithCommentWorks(self): + self.assertEquals('1, 2, 3, 4, 5\n', + Convert('$var n = 5 $$ This is comment 1.\n' + '$range i 1..n $$ This is comment 2.\n' + '$for i, [[$i]]\n')) + + def testNonTrivialRangeExpressionsWork(self): + self.assertEquals('1, 2, 3, 4\n', + Convert('$var n = 5\n' + '$range i (n/n)..(n - 1)\n' + '$for i, [[$i]]\n')) + + def testLoopWithoutSeparatorWorks(self): + self.assertEquals('a + 1 + 2 + 3;\n', + Convert('$range i 1..3\n' + 'a$for i [[ + $i]];\n')) + + def testCanGenerateDollarSign(self): + self.assertEquals('$\n', Convert('$($)\n')) + + def testCanIterpolateExpressions(self): + self.assertEquals('a[2] = 3;\n', + Convert('$var i = 1\n' + 'a[$(i + 1)] = $(i*4 - 1);\n')) + + def testConditionalWithoutElseBranchWorks(self): + self.assertEquals('true\n', + Convert('$var n = 5\n' + '$if n > 0 [[true]]\n')) + + def testConditionalWithElseBranchWorks(self): + self.assertEquals('true -- really false\n', + Convert('$var n = 5\n' + '$if n > 0 [[true]]\n' + '$else [[false]] -- \n' + '$if n > 10 [[really true]]\n' + '$else [[really false]]\n')) + + def testConditionalWithCascadingElseBranchWorks(self): + self.assertEquals('a\n', + Convert('$var n = 5\n' + '$if n > 0 [[a]]\n' + '$elif n > 10 [[b]]\n' + '$else [[c]]\n')) + self.assertEquals('b\n', + Convert('$var n = 5\n' + '$if n > 10 [[a]]\n' + '$elif n > 0 [[b]]\n' + '$else [[c]]\n')) + self.assertEquals('c\n', + Convert('$var n = 5\n' + '$if n > 10 [[a]]\n' + '$elif n > 8 [[b]]\n' + '$else [[c]]\n')) + + def testNestedLexicalBlocksWork(self): + self.assertEquals('a = 5;\n', + Convert('$var n = 5\n' + 'a = [[$if n > 0 [[$n]]]];\n')) + + +class StripMetaCommentsTest(googletest.TestCase): + + def testReturnsSameStringIfItContainsNoComment(self): + self.assertEquals('', StripMetaComments('')) + self.assertEquals(' blah ', StripMetaComments(' blah ')) + self.assertEquals('A single $ is fine.', + StripMetaComments('A single $ is fine.')) + self.assertEquals('multiple\nlines', + StripMetaComments('multiple\nlines')) + + def testStripsSimpleComment(self): + self.assertEquals('yes\n', StripMetaComments('yes $$ or no?\n')) + + def testStripsSimpleCommentWithMissingNewline(self): + self.assertEquals('yes', StripMetaComments('yes $$ or no?')) + + def testStripsPureCommentLinesEntirely(self): + self.assertEquals('yes\n', + StripMetaComments('$$ a pure comment line.\n' + 'yes $$ or no?\n' + ' $$ another comment line.\n')) + + def testStripsCommentsFromMultiLineText(self): + self.assertEquals('multi-\n' + 'line\n' + 'text is fine.', + StripMetaComments('multi- $$ comment 1\n' + 'line\n' + 'text is fine. $$ comment 2')) + + +if __name__ == '__main__': + googletest.main() |