├── .gitignore ├── COPYRIGHT ├── README.md ├── include └── mockpp │ ├── Invocation.h │ ├── Matchers.h │ ├── Mock.h │ ├── MockProbe.h │ ├── MockValidator.h │ ├── detail │ └── ArgumentMatcher.h │ ├── helpers.h │ ├── mockpp.h │ └── variadic_macro_helpers.h └── test ├── HelpersTest.cpp ├── InvocationTest.cpp ├── Makefile ├── MockProbeTest.cpp ├── MockTest.cpp └── MockValidatorTest.cpp /.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | *.swo 3 | *.o 4 | *.gcda 5 | *.gcno 6 | test/coverage 7 | test/mockcpp_test 8 | test/mockcpp_test.dSYM 9 | cscope.* 10 | tags 11 | -------------------------------------------------------------------------------- /COPYRIGHT: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013 Justin Handville 2 | All Rights Reserved 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in 12 | all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Mock++: A Portable Mocking Framework for C++ 2 | ============================================ 3 | 4 | The Mock++ framework provides portable mocking support for unit testing C++ 5 | applications. This framework makes use of concepts available in C++11, such as 6 | variadic templates and tuples, and combines these with simple macros to make the 7 | creation and use of mock objects as easy as possible in a language that lacks 8 | runtime reflection. 9 | 10 | Other frameworks may take advantage of non-portable vtable implementation 11 | details, but this framework should work with any compiler that is compliant with 12 | the C++11 standard. Using this framework does not require a migration to C++11, 13 | however, as code can be written in C++98 or whichever subsets one chooses to 14 | use. Only the unit tests themselves must make use of these features. 15 | 16 | Usage Example 17 | ============= 18 | 19 | The following example illustrates the use of this library. We can mock any 20 | virtual method that can be overridden by a derived type, but for sake of 21 | example, we will create a pure abstract interface. 22 | 23 | ```c++ 24 | class Widget 25 | { 26 | public: 27 | virtual bool isReady() = 0; 28 | virtual void performAction(int) = 0; 29 | virtual ~Widget() = 0; 30 | }; 31 | ``` 32 | 33 | Let's assume that this interface is being passed to an object we intend to unit 34 | test. We'll call this object A. 35 | 36 | ```c++ 37 | class A 38 | { 39 | public: 40 | ///Construct an A using a Widget. A owns this widget. 41 | A(Widget*); 42 | 43 | ///frobulate the widget 44 | void frobulate(); 45 | 46 | private: 47 | std::shared_ptr widget_; 48 | }; 49 | ``` 50 | 51 | Now, we can pass a mock Widget to A, but first we need to create a mock of 52 | Widget. Unlike reflective languages, there is a bit of scaffolding, but helper 53 | macros make this simple. 54 | 55 | ```c++ 56 | class MockWidget : public Widget, public mockpp::Mock 57 | { 58 | public: 59 | 60 | ~MockWidget() { } 61 | 62 | MOCK_FUNCTION(bool, isReady); 63 | MOCK_FUNCTION_VOID_ARGS(performAction, int); 64 | }; 65 | ``` 66 | 67 | Within our unit test, we can construct the MockWidget, and control how it works. 68 | 69 | ```c++ 70 | using mockpp; 71 | 72 | auto widget = new MockWidget(); 73 | 74 | PROBE(widget, isReady).toReturn(true); 75 | PROBE(widget, performAction).toDo([](int i) { ASSERT_EQ(i, 1); }); 76 | auto aObj = make_shared(widget); //a takes ownership of widget 77 | 78 | aObj->frobulate(); 79 | 80 | //assuming Google Test semantics here. 81 | ASSERT_TRUE(VALIDATE(widget, isReady).called()); 82 | ASSERT_TRUE(VALIDATE(widget, performAction).called(1)); 83 | ``` 84 | 85 | Mocks have several different selectors, which allow the user to access 86 | functionality. The first selector here is PROBE. The probe selector allows us 87 | to control behavior of the mock object. In this case, we probe the isReady 88 | function to return true when called. By default, a mocked function will return 89 | whichever value is considered the default value initialization for a constructed 90 | type. In this case, bools return false. Ints return 0. Pointers return 91 | nullptr. Next, we probe the performAction function so that it performs the 92 | lambda expression we pass in, which asserts that the parameter passed into 93 | performAction equals 1. Being able to override the behavior of mocked functions 94 | is a powerful feature found in most mocking frameworks. With C++11 lambda 95 | expressions, we can do the same thing. 96 | 97 | The mock is then passed to the constructor of A. When the frobulate method of A 98 | is called, it uses the mock object. We can then validate its use of the mock by 99 | using the validate selector. This selector allows us to verify that methods in 100 | the mock object were called, and we can even test the values passed to the 101 | methods by adding them to the call. The default behavior of the validate 102 | selector is to test each invocation in order. For instance, this test would 103 | have failed if performAction were called before isReady. Also, the called() 104 | method fails if the arguments passed to the selector are invalid. So, if the 105 | above assertion were changed to validate(widget).performAction(2).called(), the 106 | result would be false, which would cause the Google Test assertion to fail. 107 | 108 | Headers 109 | ======= 110 | 111 | Headers in mockpp are differentiated between class headers and package headers. 112 | Class headers always begin with a capital letter, as do the classes they 113 | contain. Class headers are always named the same as the type they contain. 114 | Package headers are convenient utility headers that contain all classes in a 115 | given namespace. Finally, package forwarding headers contain just the forward 116 | declarations of classes in a given namespace, which is convenient for handling 117 | cyclic resolution issues, or for facilitating a faster compilation on systems 118 | that don't support precompiled headers. 119 | 120 | mockpp/mockpp.h effectively includes world. This is a quick and easy way to 121 | get started. 122 | 123 | Strict and Relaxed Evaluation 124 | ============================= 125 | 126 | By default, Mock++ uses strict evaluation of invocations. This means that it 127 | cares about the order in which invocations are validated. The reason why strict 128 | evaluation is useful is because it is often important to perform operations on 129 | an interface in a certain order. For instance, we may wish to assert that the 130 | code under unit test empties a container before it adds elements to it. If the 131 | calls happen in a different order, then we may not be able to easily test 132 | certain invariance rules. 133 | 134 | The downside of strict evaluation is that it can make unit tests brittle when 135 | the order of evaluation does not matter. Mock++ provides a different mocking 136 | interface for relaxing this evaluation mechanism called RelaxedMock. The 137 | RelaxedMock template is a plug-in replacement for Mock. Instead of popping 138 | invocations off a queue and evaluating them against assertions in the test, it 139 | uses the called() matcher as a query, and finds the first result in the queue 140 | that matches this query. This item is then popped off the queue. If no matches 141 | are found, then the test assertion fails. 142 | 143 | ```c++ 144 | class RelaxedMockWidget : public Widget, public mockpp::RelaxedMock 145 | { 146 | public: 147 | 148 | ~RelaxedMockWidget() { } 149 | 150 | MOCK_FUNCTION(bool, isReady); 151 | MOCK_FUNCTION_VOID_ARGS(performAction, int); 152 | } 153 | ``` 154 | 155 | Here, RelaxedMockWidget can be used in our original test above, and the order of 156 | the two assertions at the bottom can be swapped with no ill effect. 157 | 158 | Matchers and "Don't Care" 159 | ========================= 160 | 161 | So far, the called() matcher has been demonstrated. This matcher takes 162 | arguments that match the arguments of the call to the invoked method. However, 163 | sometimes the test does not care about which arguments were passed to the 164 | invocation. Other times, there is no way for the unit test to predict the 165 | parameters, such as when an ephemeral object is passed to the invoked method. 166 | In these cases, more sophisticated matchers are needed. 167 | 168 | Under the covers, the called() matcher is builds up a chain of matchers for 169 | individual elements. It then uses this chain to match against invocations. The 170 | called method is a template, and it will accept alternative arguments. A user 171 | can either pass in the argument type called is expecting, which creates an 172 | std::equal matcher, or the user can pass in a matcher argument, which can vary 173 | from std::greater / std::less to a user-defined lambda. 174 | 175 | Consider the following modification to the above example, which ignores the 176 | argument passed to performAction. Here, the assertion passes, as expected. 177 | 178 | ```c++ 179 | ASSERT_TRUE(VALIDATE(widget, performAction).called(Ignore())); 180 | ``` 181 | 182 | It is also beneficial to have the ability to pass in lambda expressions to 183 | evaluate the parameter. For instance, this assertion returns true only if the 184 | argument for the invocation of performAction is greater than 5. 185 | 186 | ```c++ 187 | ASSERT_TRUE(VALIDATE(widget, performAction).called([](int x) { return x > 5; })); 188 | ``` 189 | 190 | Future features 191 | =============== 192 | 193 | Mock++ works now, and I am currently using it to unit test a compiler I am 194 | writing. However, there are aspects of this framework which are not easy. For 195 | one thing, there is no easy way to understand why assertions fail when using the 196 | called matcher. It would be relatively easy to extend the MockValidator and 197 | MockProbe to accept a stringified name of the function and type, so that more 198 | intelligent error messages could be displayed. Since this requires tighter 199 | integration with the unit testing framework, I kept this as a TODO. 200 | 201 | I would like to make this framework easier to use and understand. Suggestions 202 | about how to do this are welcome. My first priority was to get the framework 203 | running, and my second idea was to make it available to others who might need 204 | something like this. 205 | -------------------------------------------------------------------------------- /include/mockpp/Invocation.h: -------------------------------------------------------------------------------- 1 | #ifndef MOCKPP_INVOCATION_HEADER_GUARD 2 | # define MOCKPP_INVOCATION_HEADER_GUARD 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | namespace mockpp { 11 | 12 | /** 13 | * BaseInvocation is a base type that allows simple RTTI tracking of mocked 14 | * function call invocations. 15 | */ 16 | class BaseInvocation 17 | { 18 | public: 19 | /** 20 | * BaseInvocation constructor. Cache the hash code of the invocation. 21 | */ 22 | BaseInvocation(std::size_t _hashCode) 23 | : hashCode_(_hashCode) 24 | { 25 | } 26 | 27 | /** 28 | * Virtual destructor for proper cleanup. 29 | */ 30 | virtual ~BaseInvocation() 31 | { 32 | } 33 | 34 | /** 35 | * Get the unique hash code for this invocation type. 36 | */ 37 | std::size_t hashCode() const 38 | { 39 | return hashCode_; 40 | } 41 | 42 | private: 43 | std::size_t hashCode_; 44 | }; 45 | 46 | /** 47 | * Invocation is a base type that allows simple RTTI tracking of mocked 48 | * function call invocations. 49 | */ 50 | template< 51 | typename BaseType, 52 | typename... ArgumentTypes> 53 | class Invocation : public BaseInvocation 54 | { 55 | public: 56 | using ArgsType = std::tuple; 57 | 58 | /** 59 | * Create an invocation from a list of arguments. 60 | */ 61 | Invocation(ArgumentTypes... _args) 62 | : BaseInvocation(typeid(Invocation).hash_code()) 63 | , args_(_args...) 64 | { 65 | } 66 | 67 | /** 68 | * Return the list of arguments as a tuple. 69 | */ 70 | const ArgsType args() const 71 | { 72 | return args_; 73 | } 74 | 75 | private: 76 | ArgsType args_; 77 | }; 78 | 79 | /** 80 | * A reference counted pointer to a particular invocation. 81 | */ 82 | typedef 83 | std::shared_ptr 84 | BaseInvocationPtr; 85 | 86 | /** 87 | * A list of invocations, which can be scanned for matching assertions in 88 | * unit tests. 89 | */ 90 | typedef 91 | std::list 92 | InvocationList; 93 | 94 | } /* namespace mockpp */ 95 | 96 | #endif //MOCKPP_INVOCATION_HEADER_GUARD 97 | -------------------------------------------------------------------------------- /include/mockpp/Matchers.h: -------------------------------------------------------------------------------- 1 | #ifndef MOCKPP_MATCHERS_HEADER_GUARD 2 | # define MOCKPP_MATCHERS_HEADER_GUARD 3 | 4 | #include 5 | 6 | namespace mockpp { 7 | 8 | /** 9 | * Ignore is an empty tag structure used to specify that an argument is to 10 | * be ignored. 11 | */ 12 | struct Ignore 13 | { 14 | }; 15 | } 16 | 17 | #endif //MOCKPP_MATCHERS_HEADER_GUARD 18 | -------------------------------------------------------------------------------- /include/mockpp/Mock.h: -------------------------------------------------------------------------------- 1 | #ifndef MOCKPP_MOCK_HEADER_GUARD 2 | # define MOCKPP_MOCK_HEADER_GUARD 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | namespace mockpp { 9 | 10 | /** 11 | * The base mock class contains an invocation list and some helper 12 | * functions. 13 | */ 14 | class BaseMock 15 | { 16 | public: 17 | /** 18 | * Clear all invocation history from the mock object. 19 | */ 20 | void clear() 21 | { 22 | invocations_.clear(); 23 | } 24 | 25 | /** 26 | * accessor for the list of invocations 27 | */ 28 | InvocationList& invocations() 29 | { 30 | return invocations_; 31 | } 32 | 33 | /** 34 | * accessor to return an invocation at the given offset 35 | */ 36 | InvocationList::value_type& invocations(size_t offset) 37 | { 38 | auto iter = invocations_.begin(); 39 | std::advance(iter, offset); 40 | 41 | return *iter; 42 | } 43 | 44 | /** 45 | * Called validator. See if a particular invocation matcher matches an 46 | * invocation. 47 | */ 48 | virtual bool called( 49 | std::function matcher) = 0; 50 | 51 | private: 52 | InvocationList invocations_; 53 | }; 54 | 55 | /** 56 | * Mock is a wrapper template that provides mocking facilities for a given 57 | * type. Mock uses strict checking for invocations, meaning that assertions 58 | * based on invocations must be given in the order that they were made. 59 | * Users who wish for assertions without the strict order of evaluation 60 | * should used RelaxedMock. 61 | */ 62 | template < 63 | typename MockedType> 64 | class Mock : public BaseMock 65 | { 66 | protected: 67 | 68 | /** 69 | * Perform strict order evaluation of method invocations using the 70 | * provided matcher. 71 | */ 72 | virtual bool called( 73 | std::function matcher) 74 | { 75 | if (invocations().empty()) 76 | return false; 77 | 78 | auto v = invocations().front(); 79 | invocations().pop_front(); 80 | 81 | return 82 | matcher(v.get()); 83 | } 84 | }; 85 | 86 | /** 87 | * RelaxedMock is a wrapper template that provides mocking facilities for a 88 | * given type. Mock uses relaxed checking for invocations, meaning that 89 | * assertions can be made in any order, but as with Mock, cannot be 90 | * duplicated. This allows the code under unit test to be refactored in a 91 | * way that changes the order of invocation of mock methods without breaking 92 | * the unit test. 93 | */ 94 | template < 95 | typename MockedType> 96 | class RelaxedMock : public BaseMock 97 | { 98 | protected: 99 | 100 | /** 101 | * Perform non-strict order evaluation of method invocations using the 102 | * provided matcher. 103 | */ 104 | virtual bool called( 105 | std::function matcher) 106 | { 107 | auto& inv = invocations(); 108 | 109 | //no need to go further if the invocations are empty 110 | if (inv.empty()) 111 | return false; 112 | 113 | //find an invocation that matches our matcher. 114 | auto v = std::find_if( 115 | begin(inv), 116 | end(inv), 117 | [&](const BaseInvocationPtr& ptr) -> bool { 118 | return matcher(ptr.get()); } ); 119 | 120 | //stop if no matching entries were found 121 | if (v == inv.end()) 122 | return false; 123 | 124 | //result found. Remove it. 125 | inv.erase(v); 126 | 127 | //success 128 | return true; 129 | } 130 | }; 131 | 132 | } /* mockpp */ 133 | 134 | #endif //MOCKPP_MOCK_HEADER_GUARD 135 | -------------------------------------------------------------------------------- /include/mockpp/MockProbe.h: -------------------------------------------------------------------------------- 1 | #ifndef MOCKPP_MOCK_PROBE_HEADER_GUARD 2 | # define MOCKPP_MOCK_PROBE_HEADER_GUARD 3 | 4 | #include 5 | 6 | namespace mockpp { 7 | 8 | /** 9 | * The mock probe helper class allows the user to compose custom behaviors 10 | * for mocked functions. 11 | */ 12 | template< 13 | typename ReturnType, 14 | typename... ArgumentTypes> 15 | class MockProbe 16 | { 17 | public: 18 | /** 19 | * Default constructor. 20 | */ 21 | MockProbe() 22 | : override_(nullptr) 23 | , returnVal_() 24 | { 25 | } 26 | 27 | /** 28 | * Perform the probed operation, or return the defined return type if not 29 | * probed. 30 | */ 31 | ReturnType operator()(ArgumentTypes... args) 32 | { 33 | if (override_ != nullptr) 34 | { 35 | return override_(args...); 36 | } 37 | else 38 | { 39 | return returnVal_; 40 | } 41 | } 42 | 43 | /** 44 | * Allow the user to override the default return type. 45 | */ 46 | void toReturn(const ReturnType& val) 47 | { 48 | returnVal_ = val; 49 | } 50 | 51 | /** 52 | * Allow the user to override the default action. 53 | */ 54 | void toDo(std::function func) 55 | { 56 | override_ = func; 57 | } 58 | 59 | private: 60 | std::function override_; 61 | bool overrideSet_; 62 | 63 | ReturnType returnVal_; 64 | }; 65 | 66 | /** 67 | * The mock probe helper class allows the user to compose custom behaviors 68 | * for mocked functions. 69 | */ 70 | template< 71 | typename... ArgumentTypes> 72 | class MockProbe 73 | { 74 | public: 75 | MockProbe() 76 | : override_(nullptr) 77 | { 78 | } 79 | 80 | ///Perform the probed operation, or do nothing if not probed. 81 | void operator()(ArgumentTypes... args) 82 | { 83 | if (override_ != nullptr) 84 | { 85 | override_(args...); 86 | } 87 | } 88 | 89 | ///Override the default action. 90 | void toDo(std::function func) 91 | { 92 | override_ = func; 93 | } 94 | 95 | private: 96 | std::function override_; 97 | }; 98 | 99 | } /* namespace mockpp */ 100 | 101 | #endif //MOCKPP_MOCK_PROBE_HEADER_GUARD 102 | -------------------------------------------------------------------------------- /include/mockpp/MockValidator.h: -------------------------------------------------------------------------------- 1 | #ifndef MOCKPP_MOCK_VALIDATOR_HEADER_GUARD 2 | # define MOCKPP_MOCK_VALIDATOR_HEADER_GUARD 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | namespace mockpp { 12 | 13 | /** 14 | * Forward declaration for ValidationBuilder. 15 | */ 16 | template< 17 | typename ReturnType, 18 | typename... ArgumentTypes> 19 | class ValidationBuilder; 20 | 21 | /** 22 | * The mock validator helper class tracks invocations and provides a 23 | * builder framework for querying these invocations. 24 | */ 25 | template< 26 | typename ReturnType, 27 | typename... ArgumentTypes> 28 | class MockValidator 29 | { 30 | public: 31 | /** 32 | * Add an invocation with the given arguments. 33 | */ 34 | void addInvocation(BaseMock& mock, ArgumentTypes... args) 35 | { 36 | mock.invocations().push_back( 37 | std::make_shared< Invocation >( 38 | args...)); 39 | } 40 | 41 | /** 42 | * Add an invocation with the given arguments. 43 | */ 44 | void addInvocation(const BaseMock& mock, ArgumentTypes... args) 45 | { 46 | const_cast(mock).invocations().push_back( 47 | std::make_shared< Invocation >( 48 | args...)); 49 | } 50 | 51 | /** 52 | * Create a ValidationBuilder for this mock. 53 | */ 54 | ValidationBuilder 55 | validationBuilder(BaseMock& mock) 56 | { 57 | return 58 | ValidationBuilder(mock); 59 | } 60 | }; 61 | 62 | /** 63 | * The ValidationBuilder class provides a simple wrapper around a base mock 64 | * object so that validation queries can be performed against it. In most 65 | * test code, this is created as a temporary to allow simplified matching 66 | * semantics. 67 | */ 68 | template< 69 | typename ReturnType, 70 | typename... ArgumentTypes> 71 | class ValidationBuilder 72 | { 73 | public: 74 | ValidationBuilder(BaseMock& mock) : mockRef(mock) { } 75 | 76 | template< 77 | typename... ArgTypes> 78 | bool called(ArgTypes... args) 79 | { 80 | return 81 | mockRef.called(buildCallMatcher(args...)); 82 | } 83 | 84 | protected: 85 | 86 | /** 87 | * Build a lambda expression for matching our arguments. 88 | */ 89 | template< 90 | typename... ArgTypes> 91 | std::function 92 | buildCallMatcher(ArgTypes... args) 93 | { 94 | auto argsMatcher = 95 | detail::ArgumentMatcher<0, std::tuple >(args...); 96 | 97 | return [=](const BaseInvocation* inv) -> bool { 98 | //cast this invocation to our invocation type 99 | auto ptr = 100 | dynamic_cast< 101 | const Invocation< 102 | MockValidator, 103 | ArgumentTypes...>* >(inv); 104 | 105 | //this was an invocation for a different function. 106 | if (ptr == nullptr) 107 | return false; 108 | 109 | //it must match our expected args 110 | return 111 | argsMatcher(ptr->args()); 112 | }; 113 | } 114 | 115 | /** 116 | * Build a lambda expression for matching our arguments. 117 | * This version handles no arguments. 118 | */ 119 | std::function 120 | buildCallMatcher() 121 | { 122 | return [=](const BaseInvocation* inv) -> bool { 123 | //cast this invocation to our invocation type 124 | auto ptr = 125 | dynamic_cast< 126 | const Invocation< 127 | MockValidator, 128 | ArgumentTypes...>* >(inv); 129 | 130 | //if the pointer is not null, then it is an invocation for this 131 | //function. 132 | return 133 | ptr != nullptr; 134 | }; 135 | } 136 | 137 | private: 138 | BaseMock& mockRef; 139 | }; 140 | 141 | } /* namespace mockpp */ 142 | 143 | #endif //MOCKPP_MOCK_VALIDATOR_HEADER_GUARD 144 | -------------------------------------------------------------------------------- /include/mockpp/detail/ArgumentMatcher.h: -------------------------------------------------------------------------------- 1 | #ifndef MOCKPP_DETAIL_ARGUMENT_MATCHER_HEADER_GUARD 2 | # define MOCKPP_DETAIL_ARGUMENT_MATCHER_HEADER_GUARD 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | namespace mockpp { namespace detail { 9 | 10 | /** 11 | * ArgumentMatcher is a recursively defined functor which accepts a list of 12 | * arguments, and matches against either these arguments, a defined Matcher, 13 | * or a lambda expression that returns true or false. The argument for the 14 | * ArgumentMatcher functor is an argument of the given type, and the result 15 | * is true or false. 16 | */ 17 | template< 18 | int offset, 19 | typename TupleType> 20 | struct ArgumentMatcher 21 | { 22 | //Helper for the argument type 23 | typedef 24 | typename std::tuple_element::type 25 | ArgumentType; 26 | 27 | /** 28 | * The single element constructor. 29 | */ 30 | ArgumentMatcher( 31 | ArgumentType argument) 32 | { 33 | matcher_ = 34 | [=](const TupleType& toCompare) -> bool { 35 | return std::get(toCompare) == argument; 36 | }; 37 | } 38 | 39 | /** 40 | * The default constructor creates an ArgumentMatcher which matches 41 | * against the given value. 42 | */ 43 | template< 44 | typename... Args> 45 | ArgumentMatcher( 46 | ArgumentType argument, 47 | Args... args) 48 | { 49 | auto tailMatcher = ArgumentMatcher(args...); 50 | 51 | matcher_ = 52 | [=](const TupleType& toCompare) -> bool { 53 | return std::get(toCompare) == argument 54 | && tailMatcher(toCompare); 55 | }; 56 | } 57 | 58 | /** 59 | * This constructor ignores the last argument. 60 | */ 61 | ArgumentMatcher(Ignore) 62 | { 63 | matcher_ = 64 | [](const TupleType& toCompare) -> bool { 65 | return true; 66 | }; 67 | } 68 | 69 | /** 70 | * This constructor ignores the argument. 71 | */ 72 | template< 73 | typename... Args> 74 | ArgumentMatcher(Ignore, Args... args) 75 | { 76 | auto tailMatcher = ArgumentMatcher(args...); 77 | 78 | matcher_ = 79 | [=](const TupleType& toCompare) -> bool { 80 | return true 81 | && tailMatcher(toCompare); 82 | }; 83 | } 84 | 85 | /** 86 | * This constructor allows the last argument to be a user specified 87 | * functor. 88 | */ 89 | ArgumentMatcher( 90 | std::function userFunctor) 91 | { 92 | matcher_ = 93 | [=](const TupleType& toCompare) -> bool { 94 | return userFunctor(std::get(toCompare)); 95 | }; 96 | } 97 | 98 | /** 99 | * This constructor allows the matching functor to be specified by the 100 | * user. 101 | */ 102 | template< 103 | typename... Args> 104 | ArgumentMatcher( 105 | std::function userFunctor, 106 | Args... args) 107 | { 108 | auto tailMatcher = ArgumentMatcher(args...); 109 | 110 | matcher_ = 111 | [=](const TupleType& toCompare) -> bool { 112 | return userFunctor(std::get(toCompare)) 113 | && tailMatcher(toCompare); 114 | }; 115 | } 116 | 117 | /** 118 | * This functor operator wraps our internal lambda expression. 119 | */ 120 | bool operator()(const TupleType& tuple) const 121 | { 122 | return matcher_(tuple); 123 | } 124 | 125 | private: 126 | std::function matcher_; 127 | }; 128 | 129 | } /* namespace detail */ } /* namespace mockpp */ 130 | 131 | #endif //MOCKPP_DETAIL_ARGUMENT_MATCHER_HEADER_GUARD 132 | -------------------------------------------------------------------------------- /include/mockpp/helpers.h: -------------------------------------------------------------------------------- 1 | #ifndef MOCKPP_HELPERS_HEADER_GUARD 2 | # define MOCKPP_HELPERS_HEADER_GUARD 3 | 4 | #include 5 | #include 6 | 7 | #define MOCK_POLY_FUNCTION(returnType, functionName, helperName) \ 8 | returnType functionName() \ 9 | { \ 10 | helperName##_VALIDATE.addInvocation(*this); \ 11 | \ 12 | return helperName##_PROBE(); \ 13 | }\ 14 | \ 15 | ::mockpp::MockProbe helperName##_PROBE; \ 16 | ::mockpp::MockValidator helperName##_VALIDATE; 17 | 18 | #define MOCK_POLY_FUNCTION_VOID(functionName, helperName) \ 19 | void functionName() \ 20 | { \ 21 | helperName##_VALIDATE.addInvocation(*this); \ 22 | \ 23 | return helperName##_PROBE(); \ 24 | }\ 25 | \ 26 | ::mockpp::MockProbe helperName##_PROBE; \ 27 | ::mockpp::MockValidator helperName##_VALIDATE; 28 | 29 | #define MOCK_POLY_FUNCTION_VOID_ARGS(functionName,helperName,...) \ 30 | void functionName(MAKE_PARAMS(__VA_ARGS__)) \ 31 | { \ 32 | helperName##_VALIDATE.addInvocation(*this, MAKE_ARGS(__VA_ARGS__)); \ 33 | \ 34 | return helperName##_PROBE(MAKE_ARGS(__VA_ARGS__)); \ 35 | }\ 36 | \ 37 | ::mockpp::MockProbe helperName##_PROBE; \ 38 | ::mockpp::MockValidator helperName##_VALIDATE; 39 | 40 | #define MOCK_POLY_FUNCTION_ARGS(returnType,functionName,helperName,...) \ 41 | returnType functionName(MAKE_PARAMS(__VA_ARGS__)) \ 42 | { \ 43 | helperName##_VALIDATE.addInvocation(*this, MAKE_ARGS(__VA_ARGS__)); \ 44 | \ 45 | return helperName##_PROBE(MAKE_ARGS(__VA_ARGS__)); \ 46 | }\ 47 | \ 48 | ::mockpp::MockProbe helperName##_PROBE; \ 49 | ::mockpp::MockValidator helperName##_VALIDATE; 50 | 51 | 52 | #define MOCK_POLY_CONST_FUNCTION(returnType, functionName, helperName) \ 53 | returnType functionName() const \ 54 | { \ 55 | helperName##_VALIDATE.addInvocation(*this); \ 56 | \ 57 | return helperName##_PROBE(); \ 58 | }\ 59 | \ 60 | mutable ::mockpp::MockProbe helperName##_PROBE; \ 61 | mutable ::mockpp::MockValidator helperName##_VALIDATE; 62 | 63 | #define MOCK_POLY_CONST_FUNCTION_VOID(functionName, helperName) \ 64 | void functionName() const \ 65 | { \ 66 | helperName##_VALIDATE.addInvocation(*this); \ 67 | \ 68 | return helperName##_PROBE(); \ 69 | }\ 70 | \ 71 | mutable ::mockpp::MockProbe helperName##_PROBE; \ 72 | mutable ::mockpp::MockValidator helperName##_VALIDATE; 73 | 74 | #define MOCK_POLY_CONST_FUNCTION_VOID_ARGS(functionName,helperName,...) \ 75 | void functionName(MAKE_PARAMS(__VA_ARGS__)) const \ 76 | { \ 77 | helperName##_VALIDATE.addInvocation(*this, MAKE_ARGS(__VA_ARGS__)); \ 78 | \ 79 | return helperName##_PROBE(MAKE_ARGS(__VA_ARGS__)); \ 80 | }\ 81 | \ 82 | mutable ::mockpp::MockProbe helperName##_PROBE; \ 83 | mutable ::mockpp::MockValidator helperName##_VALIDATE; 84 | 85 | #define MOCK_POLY_CONST_FUNCTION_ARGS(returnType,functionName,helperName,...) \ 86 | returnType functionName(MAKE_PARAMS(__VA_ARGS__)) const \ 87 | { \ 88 | helperName##_VALIDATE.addInvocation(*this, MAKE_ARGS(__VA_ARGS__)); \ 89 | \ 90 | return helperName##_PROBE(MAKE_ARGS(__VA_ARGS__)); \ 91 | }\ 92 | \ 93 | mutable ::mockpp::MockProbe helperName##_PROBE; \ 94 | mutable ::mockpp::MockValidator helperName##_VALIDATE; 95 | 96 | #define MOCK_FUNCTION(returnType, functionName) \ 97 | MOCK_POLY_FUNCTION(returnType, functionName, functionName) 98 | 99 | #define MOCK_FUNCTION_VOID(functionName) \ 100 | MOCK_POLY_FUNCTION_VOID(functionName, functionName) 101 | 102 | #define MOCK_FUNCTION_VOID_ARGS(functionName,...) \ 103 | MOCK_POLY_FUNCTION_VOID_ARGS(functionName,functionName,__VA_ARGS__) 104 | 105 | #define MOCK_FUNCTION_ARGS(returnType,functionName,...) \ 106 | MOCK_POLY_FUNCTION_ARGS(returnType,functionName,functionName,__VA_ARGS__) 107 | 108 | #define MOCK_CONST_FUNCTION(returnType, functionName) \ 109 | MOCK_POLY_CONST_FUNCTION(returnType,functionName,functionName) 110 | 111 | #define MOCK_CONST_FUNCTION_VOID(functionName) \ 112 | MOCK_POLY_CONST_FUNCTION_VOID(functionName,functionName) 113 | 114 | #define MOCK_CONST_FUNCTION_VOID_ARGS(functionName,...) \ 115 | MOCK_POLY_CONST_FUNCTION_VOID_ARGS(functionName,functionName,__VA_ARGS__) 116 | 117 | #define MOCK_CONST_FUNCTION_ARGS(returnType,functionName,...) \ 118 | MOCK_POLY_CONST_FUNCTION_ARGS(returnType,functionName,functionName,__VA_ARGS__) 119 | 120 | #define PROBE(obj, method) (obj).method##_PROBE 121 | #define VALIDATE(obj, method) (obj).method##_VALIDATE.validationBuilder(obj) 122 | 123 | #endif //MOCKPP_HELPERS_HEADER_GUARD 124 | -------------------------------------------------------------------------------- /include/mockpp/mockpp.h: -------------------------------------------------------------------------------- 1 | #ifndef MOCKPP_MOCKPP_HEADER_GUARD 2 | # define MOCKPP_MOCKPP_HEADER_GUARD 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #endif //MOCKPP_MOCKPP_HEADER_GUARD 10 | -------------------------------------------------------------------------------- /include/mockpp/variadic_macro_helpers.h: -------------------------------------------------------------------------------- 1 | #ifndef MOCKPP_VARIADIC_MACRO_HELPERS_HEADER_GUARD 2 | # define MOCKPP_VARIADIC_MACRO_HELPERS_HEADER_GUARD 3 | 4 | //Determine the number of arguments passed to a variadic template 5 | #define _NUM_ARGS2(_0,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,N,...) N 6 | #define NUM_ARGS(...) _NUM_ARGS2(0, ##__VA_ARGS__, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0) 7 | 8 | //turn types into a parameter list with arg1, arg2, ... 9 | 10 | #define MAKE_PARAMS_0() 11 | #define MAKE_PARAMS_1(type1) \ 12 | type1 arg1 13 | #define MAKE_PARAMS_2(type1, type2) \ 14 | MAKE_PARAMS_1(type1), \ 15 | type2 arg2 16 | #define MAKE_PARAMS_3(type1, type2, type3) \ 17 | MAKE_PARAMS_2(type1, type2), \ 18 | type3 arg3 19 | #define MAKE_PARAMS_4(type1, type2, type3, type4) \ 20 | MAKE_PARAMS_3(type1, type2, type3), \ 21 | type4 arg4 22 | #define MAKE_PARAMS_5(type1, type2, type3, type4, type5) \ 23 | MAKE_PARAMS_4(type1, type2, type3, type4), \ 24 | type5 arg5 25 | #define MAKE_PARAMS_6(type1, type2, type3, type4, type5, type6) \ 26 | MAKE_PARAMS_5(type1, type2, type3, type4, type5), \ 27 | type6 arg6 28 | #define MAKE_PARAMS_7(type1, type2, type3, type4, type5, type6, type7) \ 29 | MAKE_PARAMS_6(type1, type2, type3, type4, type5, type6), \ 30 | type7 arg7 31 | #define MAKE_PARAMS_8(type1, type2, type3, type4, type5, type6, type7, type8) \ 32 | MAKE_PARAMS_7(type1, type2, type3, type4, type5, type6, type7), \ 33 | type8 arg8 34 | #define MAKE_PARAMS_9(type1, type2, type3, type4, type5, type6, type7, type8, \ 35 | type9) \ 36 | MAKE_PARAMS_8(type1, type2, type3, type4, type5, type6, type7, type8), \ 37 | type9 arg9 38 | #define MAKE_PARAMS_10(type1, type2, type3, type4, type5, type6, type7, type8,\ 39 | type9, type10) \ 40 | MAKE_PARAMS_9(type1, type2, type3, type4, type5, type6, type7, type8, \ 41 | type9), \ 42 | type10 arg10 43 | #define MAKE_PARAMS_11(type1, type2, type3, type4, type5, type6, type7, type8,\ 44 | type9, type10, type11) \ 45 | MAKE_PARAMS_10(type1, type2, type3, type4, type5, type6, type7, type8,\ 46 | type9, type10), \ 47 | type11 arg11 48 | #define MAKE_PARAMS_12(type1, type2, type3, type4, type5, type6, type7, type8,\ 49 | type9, type10, type11, type12) \ 50 | MAKE_PARAMS_11(type1, type2, type3, type4, type5, type6, type7, type8,\ 51 | type9, type10, type11), \ 52 | type12 arg12 53 | #define MAKE_PARAMS_13(type1, type2, type3, type4, type5, type6, type7, type8,\ 54 | type9, type10, type11, type12, type13) \ 55 | MAKE_PARAMS_12(type1, type2, type3, type4, type5, type6, type7, type8,\ 56 | type9, type10, type11, type12), \ 57 | type13 arg13 58 | #define MAKE_PARAMS_14(type1, type2, type3, type4, type5, type6, type7, type8,\ 59 | type9, type10, type11, type12, type13, type14) \ 60 | MAKE_PARAMS_13(type1, type2, type3, type4, type5, type6, type7, type8,\ 61 | type9, type10, type11, type12, type13), \ 62 | type14 arg14 63 | #define MAKE_PARAMS_15(type1, type2, type3, type4, type5, type6, type7, type8,\ 64 | type9, type10, type11, type12, type13, type14, type15) \ 65 | MAKE_PARAMS_14(type1, type2, type3, type4, type5, type6, type7, type8,\ 66 | type9, type10, type11, type12, type13, type14), \ 67 | type15 arg15 68 | #define MAKE_PARAMS_16(type1, type2, type3, type4, type5, type6, type7, type8,\ 69 | type9, type10, type11, type12, type13, type14, type15, \ 70 | type16) \ 71 | MAKE_PARAMS_15(type1, type2, type3, type4, type5, type6, type7, type8,\ 72 | type9, type10, type11, type12, type13, type14, type15), \ 73 | type16 arg16 74 | #define MAKE_PARAMS_N(N, ...) MAKE_PARAMS_##N(__VA_ARGS__) 75 | #define MAKE_PARAMS_FORCE_N(N, ...) MAKE_PARAMS_N(N, __VA_ARGS__) 76 | #define MAKE_PARAMS(...) MAKE_PARAMS_FORCE_N(NUM_ARGS(__VA_ARGS__), __VA_ARGS__) 77 | 78 | //get the arguments for a particular type list 79 | #define MAKE_ARGS_0() 80 | #define MAKE_ARGS_1(type) \ 81 | arg1 82 | #define MAKE_ARGS_2(t1, t2) \ 83 | MAKE_ARGS_1(t1), \ 84 | arg2 85 | #define MAKE_ARGS_3(t1, t2, t3) \ 86 | MAKE_ARGS_2(t1, t2), \ 87 | arg3 88 | #define MAKE_ARGS_4(t1, t2, t3, t4) \ 89 | MAKE_ARGS_3(t1, t2, t3), \ 90 | arg4 91 | #define MAKE_ARGS_5(t1, t2, t3, t4, t5) \ 92 | MAKE_ARGS_4(t1, t2, t3, t4), \ 93 | arg5 94 | #define MAKE_ARGS_6(t1, t2, t3, t4, t5, t6) \ 95 | MAKE_ARGS_5(t1, t2, t3, t4, t5), \ 96 | arg6 97 | #define MAKE_ARGS_7(t1, t2, t3, t4, t5, t6, t7) \ 98 | MAKE_ARGS_6(t1, t2, t3, t4, t5, t6), \ 99 | arg7 100 | #define MAKE_ARGS_8(t1, t2, t3, t4, t5, t6, t7, t8) \ 101 | MAKE_ARGS_7(t1, t2, t3, t4, t5, t6, t7), \ 102 | arg8 103 | #define MAKE_ARGS_9(t1, t2, t3, t4, t5, t6, t7, t8, t9) \ 104 | MAKE_ARGS_8(t1, t2, t3, t4, t5, t6, t7, t8), \ 105 | arg9 106 | #define MAKE_ARGS_10(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10) \ 107 | MAKE_ARGS_9(t1, t2, t3, t4, t5, t6, t7, t8, t9), \ 108 | arg10 109 | #define MAKE_ARGS_11(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11) \ 110 | MAKE_ARGS_10(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10), \ 111 | arg11 112 | #define MAKE_ARGS_12(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12) \ 113 | MAKE_ARGS_11(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11), \ 114 | arg12 115 | #define MAKE_ARGS_13(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13) \ 116 | MAKE_ARGS_12(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12), \ 117 | arg13 118 | #define MAKE_ARGS_14(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, \ 119 | t14) \ 120 | MAKE_ARGS_13(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13), \ 121 | arg14 122 | #define MAKE_ARGS_15(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, \ 123 | t14, t15) \ 124 | MAKE_ARGS_14(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14), \ 125 | arg15 126 | #define MAKE_ARGS_16(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, \ 127 | t14, t15, t16) \ 128 | MAKE_ARGS_15(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14, \ 129 | t15), \ 130 | arg16 131 | 132 | #define MAKE_ARGS_N(N, ...) MAKE_ARGS_##N(__VA_ARGS__) 133 | #define MAKE_ARGS_FORCE_N(N, ...) MAKE_ARGS_N(N, __VA_ARGS__) 134 | #define MAKE_ARGS(...) MAKE_ARGS_FORCE_N(NUM_ARGS(__VA_ARGS__), __VA_ARGS__) 135 | 136 | //Remove references of the given types 137 | #define REMOVE_REFS_0() 138 | #define REMOVE_REFS_1(t1) \ 139 | std::remove_reference::type 140 | #define REMOVE_REFS_2(t1, t2) \ 141 | REMOVE_REFS_1(t1), \ 142 | std::remove_reference::type 143 | #define REMOVE_REFS_3(t1, t2, t3) \ 144 | REMOVE_REFS_2(t1, t2), \ 145 | std::remove_reference::type 146 | #define REMOVE_REFS_4(t1, t2, t3, t4) \ 147 | REMOVE_REFS_3(t1, t2, t3), \ 148 | std::remove_reference::type 149 | #define REMOVE_REFS_5(t1, t2, t3, t4, t5) \ 150 | REMOVE_REFS_4(t1, t2, t3, t4), \ 151 | std::remove_reference::type 152 | #define REMOVE_REFS_6(t1, t2, t3, t4, t5, t6) \ 153 | REMOVE_REFS_5(t1, t2, t3, t4, t5), \ 154 | std::remove_reference::type 155 | #define REMOVE_REFS_7(t1, t2, t3, t4, t5, t6, t7) \ 156 | REMOVE_REFS_6(t1, t2, t3, t4, t5, t6), \ 157 | std::remove_reference::type 158 | #define REMOVE_REFS_8(t1, t2, t3, t4, t5, t6, t7, t8) \ 159 | REMOVE_REFS_7(t1, t2, t3, t4, t5, t6, t7), \ 160 | std::remove_reference::type 161 | #define REMOVE_REFS_9(t1, t2, t3, t4, t5, t6, t7, t8, t9) \ 162 | REMOVE_REFS_8(t1, t2, t3, t4, t5, t6, t7, t8), \ 163 | std::remove_reference::type 164 | #define REMOVE_REFS_10(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10) \ 165 | REMOVE_REFS_9(t1, t2, t3, t4, t5, t6, t7, t8, t9), \ 166 | std::remove_reference::type 167 | #define REMOVE_REFS_11(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11) \ 168 | REMOVE_REFS_10(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10), \ 169 | std::remove_reference::type 170 | #define REMOVE_REFS_12(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12) \ 171 | REMOVE_REFS_11(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11), \ 172 | std::remove_reference::type 173 | #define REMOVE_REFS_13(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13) \ 174 | REMOVE_REFS_12(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12), \ 175 | std::remove_reference::type 176 | #define REMOVE_REFS_14(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, \ 177 | t14) \ 178 | REMOVE_REFS_13(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13), \ 179 | std::remove_reference::type 180 | #define REMOVE_REFS_15(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, \ 181 | t14, t15) \ 182 | REMOVE_REFS_14(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14), \ 183 | std::remove_reference::type 184 | #define REMOVE_REFS_16(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, \ 185 | t14, t15, t16) \ 186 | REMOVE_REFS_15(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14, \ 187 | t15), \ 188 | std::remove_reference::type 189 | 190 | #define REMOVE_REFS_N(N, ...) REMOVE_REFS_##N(__VA_ARGS__) 191 | #define REMOVE_REFS_FORCE_N(N, ...) REMOVE_REFS_N(N, __VA_ARGS__) 192 | #define REMOVE_REFS(...) REMOVE_REFS_FORCE_N(NUM_ARGS(__VA_ARGS__), __VA_ARGS__) 193 | 194 | #endif //MOCKPP_VARIADIC_MACRO_HELPERS_HEADER_GUARD 195 | -------------------------------------------------------------------------------- /test/HelpersTest.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace mockpp; 7 | using namespace std; 8 | 9 | /** 10 | * Widget interface. 11 | */ 12 | class Widget 13 | { 14 | public: 15 | virtual bool isReady() = 0; 16 | virtual void performAction(int) = 0; 17 | virtual ~Widget() { } 18 | }; 19 | 20 | /** 21 | * Our test interface. 22 | */ 23 | class A 24 | { 25 | public: 26 | A(Widget* widget) : widget_(widget) { } 27 | 28 | virtual void frobulate() = 0; 29 | 30 | private: 31 | std::shared_ptr widget_; 32 | }; 33 | 34 | /** 35 | * Const test interface. 36 | */ 37 | class B 38 | { 39 | public: 40 | 41 | virtual void frobulate() const = 0; 42 | virtual bool testIt(int x) const = 0; 43 | }; 44 | 45 | /** 46 | * reference test interface. 47 | */ 48 | class C 49 | { 50 | public: 51 | 52 | virtual void testRef(const string&) const = 0; 53 | }; 54 | 55 | /** 56 | * polymorphic test interface 57 | */ 58 | class Poly 59 | { 60 | public: 61 | 62 | virtual void testPoly(const int&) const = 0; 63 | virtual void testPoly(const string&) const = 0; 64 | }; 65 | 66 | /** 67 | * Mock the Widget interface. 68 | */ 69 | class MockWidget : public Widget, public mockpp::Mock 70 | { 71 | public: 72 | ~MockWidget() { } 73 | 74 | MOCK_FUNCTION(bool, isReady); 75 | MOCK_FUNCTION_VOID_ARGS(performAction, int); 76 | }; 77 | 78 | /** 79 | * Mock the Widget interface (relaxed). 80 | */ 81 | class RelaxedMockWidget : public Widget, public mockpp::RelaxedMock 82 | { 83 | public: 84 | ~RelaxedMockWidget() { } 85 | 86 | MOCK_FUNCTION(bool, isReady); 87 | MOCK_FUNCTION_VOID_ARGS(performAction, int); 88 | }; 89 | 90 | /** 91 | * Mock the test interface. 92 | */ 93 | class MockA : public A, public mockpp::Mock 94 | { 95 | public: 96 | MockA(Widget* widget) : A(widget) { } 97 | 98 | MOCK_FUNCTION_VOID(frobulate); 99 | }; 100 | 101 | /** 102 | * Mock const test interface. 103 | */ 104 | class MockB : public B, public mockpp::Mock 105 | { 106 | public: 107 | 108 | MOCK_CONST_FUNCTION_VOID(frobulate); 109 | MOCK_CONST_FUNCTION_ARGS(bool, testIt, int); 110 | }; 111 | 112 | /** 113 | * Mock reference test interface. 114 | */ 115 | class MockC : public mockpp::Mock 116 | { 117 | public: 118 | 119 | MOCK_CONST_FUNCTION_VOID_ARGS(testRef, const string&); 120 | }; 121 | 122 | /** 123 | * Mock poly test interface. 124 | */ 125 | class MockPoly : public mockpp::Mock 126 | { 127 | public: 128 | 129 | MOCK_POLY_CONST_FUNCTION_VOID_ARGS(testPoly,testPolyInt,const int&); 130 | MOCK_POLY_CONST_FUNCTION_VOID_ARGS(testPoly,testPolyString,const string&); 131 | }; 132 | 133 | /** 134 | * Test construction of mocks. 135 | */ 136 | TEST(HelperTest, construction) 137 | { 138 | auto widget = new MockWidget(); //A takes ownership 139 | auto a = make_shared(widget); 140 | } 141 | 142 | /** 143 | * Test Probing and Validation (documented example, more or less) 144 | */ 145 | TEST(HelperTest, basics) 146 | { 147 | auto widget = new MockWidget(); //A takes ownership 148 | 149 | PROBE(*widget, isReady).toReturn(true); 150 | PROBE(*widget, performAction).toDo([](int i) { ASSERT_EQ(i, 1); }); 151 | 152 | auto a = make_shared(widget); 153 | PROBE(*a, frobulate).toDo([&]() { 154 | if (widget->isReady()) 155 | widget->performAction(1); 156 | }); 157 | 158 | a->frobulate(); 159 | 160 | ASSERT_TRUE(VALIDATE(*widget, isReady).called()); 161 | ASSERT_TRUE(VALIDATE(*widget, performAction).called(1)); 162 | } 163 | 164 | /** 165 | * Test Probing and Validation (relaxed mock example 1) 166 | */ 167 | TEST(HelperTest, basics_relaxed_in_order) 168 | { 169 | auto widget = new RelaxedMockWidget(); //A takes ownership 170 | 171 | PROBE(*widget, isReady).toReturn(true); 172 | PROBE(*widget, performAction).toDo([](int i) { ASSERT_EQ(i, 1); }); 173 | 174 | auto a = make_shared(widget); 175 | PROBE(*a, frobulate).toDo([&]() { 176 | if (widget->isReady()) 177 | widget->performAction(1); 178 | }); 179 | 180 | a->frobulate(); 181 | 182 | //test the invocations in order 183 | ASSERT_TRUE(VALIDATE(*widget, isReady).called()); 184 | ASSERT_TRUE(VALIDATE(*widget, performAction).called(1)); 185 | 186 | //our test consumed all invocations 187 | ASSERT_EQ(0, widget->invocations().size()); 188 | } 189 | 190 | /** 191 | * Test Probing and Validation out of order (relaxed mock example 1) 192 | */ 193 | TEST(HelperTest, basics_relaxed_out_of_order) 194 | { 195 | auto widget = new RelaxedMockWidget(); //A takes ownership 196 | 197 | PROBE(*widget, isReady).toReturn(true); 198 | PROBE(*widget, performAction).toDo([](int i) { ASSERT_EQ(i, 1); }); 199 | 200 | auto a = make_shared(widget); 201 | PROBE(*a, frobulate).toDo([&]() { 202 | if (widget->isReady()) 203 | widget->performAction(1); 204 | }); 205 | 206 | a->frobulate(); 207 | 208 | //test the invocations in order 209 | ASSERT_TRUE(VALIDATE(*widget, performAction).called(1)); 210 | ASSERT_TRUE(VALIDATE(*widget, isReady).called()); 211 | 212 | //our test consumed all invocations 213 | ASSERT_EQ(0, widget->invocations().size()); 214 | } 215 | 216 | /** 217 | * Test Probing and Validation with Ignore (example 3) 218 | */ 219 | TEST(HelperTest, basics_with_ignore) 220 | { 221 | auto widget = new MockWidget(); //A takes ownership 222 | 223 | PROBE(*widget, isReady).toReturn(true); 224 | PROBE(*widget, performAction).toDo([](int i) { ASSERT_EQ(i, 1); }); 225 | 226 | auto a = make_shared(widget); 227 | PROBE(*a, frobulate).toDo([&]() { 228 | if (widget->isReady()) 229 | widget->performAction(1); 230 | }); 231 | 232 | a->frobulate(); 233 | 234 | ASSERT_TRUE(VALIDATE(*widget, isReady).called()); 235 | ASSERT_TRUE(VALIDATE(*widget, performAction).called(Ignore())); 236 | } 237 | 238 | /** 239 | * Test Probing and Validation with lambda expressions (example 4) 240 | */ 241 | TEST(HelperTest, basics_with_lambda) 242 | { 243 | auto widget = new MockWidget(); //A takes ownership 244 | 245 | PROBE(*widget, isReady).toReturn(true); 246 | 247 | auto a = make_shared(widget); 248 | PROBE(*a, frobulate).toDo([&]() { 249 | if (widget->isReady()) 250 | widget->performAction(6); //note that this is > 5 251 | }); 252 | 253 | a->frobulate(); 254 | 255 | ASSERT_TRUE(VALIDATE(*widget, isReady).called()); 256 | ASSERT_TRUE(VALIDATE(*widget, performAction).called([](int x) { return x > 5; })); 257 | } 258 | 259 | /** 260 | * Test validation on an empty invocation list. 261 | */ 262 | TEST(HelperTest, validation_empty) 263 | { 264 | auto widget = new RelaxedMockWidget(); //A takes ownership 265 | auto a = make_shared(widget); 266 | 267 | ASSERT_FALSE(VALIDATE(*widget, isReady).called()); 268 | } 269 | 270 | /** 271 | * Test validation on a non-empty invocation list without the given invocation. 272 | */ 273 | TEST(HelperTest, validation_none) 274 | { 275 | auto widget = new RelaxedMockWidget(); //A takes ownership 276 | auto a = make_shared(widget); 277 | 278 | PROBE(*a, frobulate).toDo([&]() { 279 | widget->performAction(1); 280 | }); 281 | 282 | //perform the frobulation operation. 283 | a->frobulate(); 284 | 285 | //there should now be one invocation 286 | ASSERT_EQ(1, widget->invocations().size()); 287 | 288 | //it isn't our invocation 289 | ASSERT_FALSE(VALIDATE(*widget, isReady).called()); 290 | 291 | //there should still be one invocation 292 | ASSERT_EQ(1, widget->invocations().size()); 293 | } 294 | 295 | /** 296 | * Should be able to instantiate and use MockB interface with constant 297 | * functions 298 | */ 299 | TEST(HelperTest, const_member_functions) 300 | { 301 | auto b = make_shared(); 302 | 303 | ASSERT_FALSE(VALIDATE(*b, frobulate).called()); 304 | ASSERT_FALSE(VALIDATE(*b, testIt).called(0)); 305 | 306 | b->frobulate(); 307 | b->testIt(0); 308 | 309 | EXPECT_TRUE(VALIDATE(*b, frobulate).called()); 310 | EXPECT_TRUE(VALIDATE(*b, testIt).called(0)); 311 | } 312 | 313 | /** 314 | * Should be able to store values to references. 315 | */ 316 | TEST(HelperTest, reference_removal) 317 | { 318 | const string EXPECTED_STRING("This is a test."); 319 | auto c = make_shared(); 320 | 321 | ASSERT_FALSE(VALIDATE(*c, testRef).called(EXPECTED_STRING)); 322 | 323 | //create a temporary 324 | string x = EXPECTED_STRING; 325 | 326 | c->testRef(x); 327 | 328 | //mutate this temporary 329 | x = "Some other value."; 330 | 331 | EXPECT_TRUE(VALIDATE(*c, testRef).called(EXPECTED_STRING)); 332 | } 333 | 334 | /** 335 | * Should be able to mock polymorphic functions. 336 | */ 337 | TEST(HelperTest, polymorphic_mock) 338 | { 339 | const int EXPECTED_INT = 31; 340 | const string EXPECTED_STRING("This is a test."); 341 | auto c = make_shared(); 342 | 343 | ASSERT_FALSE(VALIDATE(*c, testPolyString).called(EXPECTED_STRING)); 344 | ASSERT_FALSE(VALIDATE(*c, testPolyInt).called(EXPECTED_INT)); 345 | 346 | //create a temporary 347 | string x = EXPECTED_STRING; 348 | int y = EXPECTED_INT; 349 | 350 | c->testPoly(x); 351 | c->testPoly(y); 352 | 353 | //mutate this temporary 354 | x = "Some other value."; 355 | y = 21; 356 | 357 | EXPECT_TRUE(VALIDATE(*c, testPolyString).called(EXPECTED_STRING)); 358 | EXPECT_TRUE(VALIDATE(*c, testPolyInt).called(EXPECTED_INT)); 359 | } 360 | -------------------------------------------------------------------------------- /test/InvocationTest.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace mockpp; 5 | 6 | typedef int DummyBaseType; 7 | 8 | /** 9 | * The BaseInvocation constructor should initialize the hashCode value. 10 | */ 11 | TEST(BaseInvocation, constructor) 12 | { 13 | const size_t HASH_CODE_VALUE = 124; 14 | 15 | BaseInvocation b(HASH_CODE_VALUE); 16 | ASSERT_EQ(HASH_CODE_VALUE, b.hashCode()); 17 | 18 | //hashCode should be const safe 19 | const BaseInvocation cb = b; 20 | ASSERT_EQ(HASH_CODE_VALUE, b.hashCode()); 21 | } 22 | 23 | /** 24 | * Two Invocation types should not have the same hashCode. 25 | */ 26 | TEST(Invocation, hashCodeInequality) 27 | { 28 | Invocation x(1); 29 | Invocation y(false); 30 | 31 | ASSERT_NE(x.hashCode(), y.hashCode()); 32 | } 33 | 34 | /** 35 | * Two instances of the same invocation type should have the same hashCode. 36 | */ 37 | TEST(Invocation, hashCodeInstanceEquality) 38 | { 39 | Invocation x(7); 40 | Invocation y(0); 41 | 42 | ASSERT_EQ(x.hashCode(), y.hashCode()); 43 | } 44 | 45 | /** 46 | * Two instances of different invocation types with the same arguments should 47 | * have different hashCodes. 48 | */ 49 | TEST(Invocation, hashCodeDifferentInstanceInequality) 50 | { 51 | Invocation x(7); 52 | Invocation y(0); 53 | 54 | ASSERT_NE(x.hashCode(), y.hashCode()); 55 | } 56 | 57 | /** 58 | * Two instances of different invocation types with similar but different named 59 | * structures should have different hashCodes. 60 | */ 61 | TEST(Invocation, hashCodeSameStructureDifferentName) 62 | { 63 | struct Struct1Tag {}; 64 | struct Struct2Tag {}; 65 | 66 | Invocation x(7); 67 | Invocation y(7); 68 | 69 | ASSERT_NE(x.hashCode(), y.hashCode()); 70 | } 71 | -------------------------------------------------------------------------------- /test/Makefile: -------------------------------------------------------------------------------- 1 | ifeq ($(strip $(GOOGLETEST_DIR)),) 2 | $(error GOOGLETEST_DIR not defined. This must be set to the base directory which contains the Google Test framework.) 3 | endif 4 | 5 | GOOGLETEST_INCLUDE=-I$(GOOGLETEST_DIR)/include -I$(GOOGLETEST_DIR) 6 | export GOOGLETEST_INCLUDE 7 | 8 | MOCKCPP_INCLUDE=-I../include 9 | export MOCKCPP_INCLUDE 10 | 11 | CXXFLAGS+=-O0 -fprofile-arcs --coverage -g -stdlib=libc++ -std=c++11 $(GOOGLETEST_INCLUDE) $(MOCKCPP_INCLUDE) 12 | 13 | GOOGLETEST_SOURCES=$(GOOGLETEST_DIR)/src/gtest_main.cc $(GOOGLETEST_DIR)/src/gtest-all.cc 14 | 15 | SOURCES=$(wildcard *.cpp) 16 | OBJECTS=$(SOURCES:.cpp=.o) 17 | 18 | .PHONY: ALL clean 19 | 20 | ALL: mockcpp_test 21 | mkdir -p coverage 22 | lcov -b .. --directory . --zerocounters 23 | ./mockcpp_test 24 | lcov -b .. --directory . --capture --output-file coverage/mockcpp_test.info 25 | lcov --remove coverage/mockcpp_test.info "/usr/*" -o coverage/mockcpp_test.info 26 | lcov --remove coverage/mockcpp_test.info "src/gtest*" -o coverage/mockcpp_test.info 27 | lcov --remove coverage/mockcpp_test.info "gtest/*" -o coverage/mockcpp_test.info 28 | lcov --remove coverage/mockcpp_test.info "test/*" -o coverage/mockcpp_test.info 29 | genhtml -o coverage coverage/mockcpp_test.info 30 | 31 | mockcpp_test: $(OBJECTS) $(GOOGLETEST_SOURCES) 32 | $(CXX) $(CXXFLAGS) $(LDFLAGS) -o mockcpp_test $(OBJECTS) $(GOOGLETEST_SOURCES) -lstdc++ 33 | 34 | clean: 35 | rm -f mockcpp_test 36 | rm -f mockcpp_test.info 37 | rm -rf mockcpp_test.dSYM 38 | rm -f $(OBJECTS) 39 | rm -f *.gcda 40 | rm -f *.gcno 41 | rm -rf coverage 42 | -------------------------------------------------------------------------------- /test/MockProbeTest.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace mockpp; 5 | 6 | /** 7 | * MockProbe can be instantiated 8 | */ 9 | TEST(MockProbe, instantiation) 10 | { 11 | MockProbe dummy; 12 | } 13 | 14 | /** 15 | * MockProbe returns the default value of a type by default. 16 | */ 17 | TEST(MockProbe, returnDefaults) 18 | { 19 | ASSERT_EQ(false, MockProbe()()); 20 | ASSERT_EQ(0, MockProbe()()); 21 | ASSERT_EQ(0, MockProbe()()); 22 | } 23 | 24 | /** 25 | * MockProbe has a toReturn accessor, which sets the return type of the probed 26 | * function. 27 | */ 28 | TEST(MockProbe, toReturnBool) 29 | { 30 | MockProbe probe; 31 | 32 | probe.toReturn(true); 33 | 34 | ASSERT_EQ(true, probe()); 35 | } 36 | 37 | /** 38 | * MockProbe has a toDo accessor, which sets the action to be performed when the 39 | * functor is called. 40 | */ 41 | TEST(MockProbe, toDoVoid) 42 | { 43 | MockProbe probe; 44 | bool called = false; 45 | 46 | probe.toDo([&](int x) { called = true; } ); 47 | 48 | //call the provided action 49 | probe(17); 50 | 51 | //called should be set to true. 52 | ASSERT_EQ(true, called); 53 | } 54 | 55 | /** 56 | * MockProbe has a toDo accessor, which sets the action to be performed when the 57 | * functor is called. This version returns a value. 58 | */ 59 | TEST(MockProbe, toDoReturn) 60 | { 61 | const int RETURN_VAL = 17; 62 | MockProbe probe; 63 | bool called = false; 64 | 65 | probe.toDo([&called](bool x) -> int { called = true; return RETURN_VAL; } ); 66 | 67 | //call the provided action 68 | ASSERT_EQ(RETURN_VAL, probe(false)); 69 | 70 | //called should be set to true. 71 | ASSERT_EQ(true, called); 72 | } 73 | -------------------------------------------------------------------------------- /test/MockTest.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace mockpp; 5 | using namespace std; 6 | 7 | struct EmptyType { }; 8 | 9 | /** 10 | * Mock can be instantiated. 11 | */ 12 | TEST(Mock, instantiation) 13 | { 14 | Mock mock; 15 | } 16 | 17 | /** 18 | * Mock has an invocations method which returns the invocationList. 19 | */ 20 | TEST(Mock, invocationsAccessor) 21 | { 22 | Mock mock; 23 | 24 | ASSERT_EQ(0, mock.invocations().size()); 25 | } 26 | 27 | /** 28 | * Mock has an invocations method which returns the invocation at a given offset 29 | * in the list. 30 | */ 31 | TEST(Mock, invocationsWithOffsetAccessor) 32 | { 33 | Mock mock; 34 | 35 | ASSERT_EQ(0, mock.invocations().size()); 36 | 37 | mock.invocations().push_back(make_shared>()); 38 | 39 | ASSERT_EQ(1, mock.invocations().size()); 40 | 41 | //Make sure this invocation matches our type, and test the accessor. 42 | ASSERT_EQ(typeid(Invocation).hash_code(), mock.invocations(0)->hashCode()); 43 | } 44 | -------------------------------------------------------------------------------- /test/MockValidatorTest.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace mockpp; 5 | 6 | /** 7 | * MockValidator can be instantiated 8 | */ 9 | TEST(MockValidator, instantiation) 10 | { 11 | MockValidator dummy1; 12 | 13 | MockValidator dummy2; 14 | } 15 | 16 | /** 17 | * MockValidator adds invocations to a mock. 18 | */ 19 | TEST(MockValidator, addInvocations) 20 | { 21 | struct DummyType { }; 22 | Mock dummyMock; 23 | 24 | MockValidator dummyFunc; 25 | 26 | ASSERT_EQ(0, dummyMock.invocations().size()); 27 | 28 | dummyFunc.addInvocation(dummyMock); 29 | 30 | //there is now an invocation in the mock 31 | ASSERT_EQ(1, dummyMock.invocations().size()); 32 | 33 | //that invocation matches our method. 34 | ASSERT_EQ( 35 | typeid(Invocation>).hash_code(), 36 | dummyMock.invocations(0)->hashCode()); 37 | } 38 | 39 | /** 40 | * MockValidator adds invocations with arguments to a mock. 41 | */ 42 | TEST(MockValidator, addInvocationsWithArgs) 43 | { 44 | const int INT_VALUE = 17; 45 | const bool BOOL_VALUE = true; 46 | struct DummyType { }; 47 | Mock dummyMock; 48 | 49 | MockValidator dummyFunc; 50 | 51 | ASSERT_EQ(0, dummyMock.invocations().size()); 52 | 53 | dummyFunc.addInvocation(dummyMock, INT_VALUE, BOOL_VALUE); 54 | 55 | //there is now an invocation in the mock 56 | ASSERT_EQ(1, dummyMock.invocations().size()); 57 | 58 | //that invocation matches our method. 59 | ASSERT_EQ( 60 | typeid(Invocation, int, bool>).hash_code(), 61 | dummyMock.invocations(0)->hashCode()); 62 | } 63 | 64 | /** 65 | * MockValidator has a validationBuilder function which returns an appropriate 66 | * ValidationBuilder for the type. 67 | */ 68 | TEST(MockValidator, validationBuilderBasics) 69 | { 70 | const int INT_VALUE = 17; 71 | const bool BOOL_VALUE = true; 72 | struct DummyType { }; 73 | Mock dummyMock; 74 | 75 | MockValidator dummyFunc; 76 | 77 | dummyFunc.validationBuilder(dummyMock); 78 | } 79 | 80 | /** 81 | * ValidationBuilder provides a called method which queries the base mock about 82 | * whether a certain invocation has been made. 83 | */ 84 | TEST(MockValidator, validationBuilder_called) 85 | { 86 | struct DummyType { }; 87 | Mock dummyMock; 88 | 89 | MockValidator dummyFunc; 90 | 91 | //no invocations have occurred 92 | ASSERT_EQ(0, dummyMock.invocations().size()); 93 | 94 | //the validator DOES NOT match this invocation 95 | ASSERT_FALSE(dummyFunc.validationBuilder(dummyMock).called()); 96 | 97 | dummyFunc.addInvocation(dummyMock); 98 | 99 | //there is now an invocation in the mock 100 | ASSERT_EQ(1, dummyMock.invocations().size()); 101 | 102 | //the validator matches this invocation 103 | ASSERT_TRUE(dummyFunc.validationBuilder(dummyMock).called()); 104 | } 105 | 106 | /** 107 | * ValidationBuilder provides a called method which queries the base mock about 108 | * whether a certain invocation has been made, including arguments. 109 | */ 110 | TEST(MockValidator, validationBuilder_called_args) 111 | { 112 | const int INT_VALUE = 17; 113 | const bool BOOL_VALUE = true; 114 | struct DummyType { }; 115 | Mock dummyMock; 116 | 117 | MockValidator dummyFunc; 118 | 119 | //no invocations have occurred 120 | ASSERT_EQ(0, dummyMock.invocations().size()); 121 | 122 | //the validator DOES NOT match this invocation 123 | ASSERT_FALSE( 124 | dummyFunc.validationBuilder(dummyMock).called(INT_VALUE, BOOL_VALUE)); 125 | 126 | //add an invocation 127 | dummyFunc.addInvocation(dummyMock, INT_VALUE, BOOL_VALUE); 128 | 129 | //there is now an invocation in the mock 130 | ASSERT_EQ(1, dummyMock.invocations().size()); 131 | 132 | //the validator matches this invocation 133 | ASSERT_TRUE( 134 | dummyFunc.validationBuilder(dummyMock).called(INT_VALUE, BOOL_VALUE)); 135 | 136 | //reset the mock 137 | dummyMock.clear(); 138 | 139 | //add an invocation 140 | dummyFunc.addInvocation(dummyMock, INT_VALUE, BOOL_VALUE); 141 | 142 | //the validator DOES NOT match this invocation, because the arguments don't 143 | //match 144 | ASSERT_FALSE( 145 | dummyFunc.validationBuilder(dummyMock).called(0, false)); 146 | } 147 | 148 | /** 149 | * ValidationBuilder.called returns false when a different invocation was made. 150 | */ 151 | TEST(MockValidator, validationBuilder_called_different_function) 152 | { 153 | const int INT_VALUE = 17; 154 | const bool BOOL_VALUE = true; 155 | struct DummyType { }; 156 | Mock dummyMock; 157 | 158 | MockValidator dummyFunc; 159 | MockValidator otherFunc; 160 | 161 | //no invocations have occurred 162 | ASSERT_EQ(0, dummyMock.invocations().size()); 163 | 164 | //the validator DOES NOT match this invocation 165 | ASSERT_FALSE( 166 | otherFunc.validationBuilder(dummyMock).called()); 167 | 168 | //add an invocation 169 | dummyFunc.addInvocation(dummyMock, INT_VALUE, BOOL_VALUE); 170 | 171 | //there is now an invocation in the mock 172 | ASSERT_EQ(1, dummyMock.invocations().size()); 173 | 174 | //the validator DOES NOT match this invocation; it was a dummyFunc 175 | //invocation. 176 | ASSERT_FALSE( 177 | otherFunc.validationBuilder(dummyMock).called()); 178 | } 179 | 180 | /** 181 | * The called method accepts Ignore as arguments, and ignores these arguments 182 | * when evaluating whether a method was called. 183 | */ 184 | TEST(MockValidator, validationBuilder_called_ignore) 185 | { 186 | const int INT_VALUE = 17; 187 | const bool BOOL_VALUE = true; 188 | struct DummyType { }; 189 | Mock dummyMock; 190 | 191 | MockValidator dummyFunc; 192 | 193 | //no invocations have occurred 194 | ASSERT_EQ(0, dummyMock.invocations().size()); 195 | 196 | //the validator DOES NOT match this invocation 197 | ASSERT_FALSE( 198 | dummyFunc.validationBuilder(dummyMock).called(INT_VALUE, BOOL_VALUE)); 199 | 200 | //add an invocation 201 | dummyFunc.addInvocation(dummyMock, INT_VALUE, BOOL_VALUE); 202 | 203 | //there is now an invocation in the mock 204 | ASSERT_EQ(1, dummyMock.invocations().size()); 205 | 206 | //the validator matches these arguments because they are ignored. 207 | ASSERT_TRUE( 208 | dummyFunc.validationBuilder(dummyMock).called(Ignore(), Ignore())); 209 | } 210 | 211 | /** 212 | * The called method accepts Ignore as a single argument. 213 | */ 214 | TEST(MockValidator, validationBuilder_called_single_ignore) 215 | { 216 | const int INT_VALUE = 17; 217 | struct DummyType { }; 218 | Mock dummyMock; 219 | 220 | MockValidator dummyFunc; 221 | 222 | //no invocations have occurred 223 | ASSERT_EQ(0, dummyMock.invocations().size()); 224 | 225 | //the validator DOES NOT match this invocation 226 | ASSERT_FALSE( 227 | dummyFunc.validationBuilder(dummyMock).called(Ignore())); 228 | 229 | //add an invocation 230 | dummyFunc.addInvocation(dummyMock, INT_VALUE); 231 | 232 | //there is now an invocation in the mock 233 | ASSERT_EQ(1, dummyMock.invocations().size()); 234 | 235 | //the validator matches these arguments because they are ignored. 236 | ASSERT_TRUE( 237 | dummyFunc.validationBuilder(dummyMock).called(Ignore())); 238 | } 239 | 240 | /** 241 | * The called method accepts Ignore as arguments, and ignores these arguments 242 | * when evaluating whether a method was called. It returns false when the 243 | * function was not called. 244 | */ 245 | TEST(MockValidator, validationBuilder_called_ignore_no_invocation) 246 | { 247 | const int INT_VALUE = 17; 248 | const bool BOOL_VALUE = true; 249 | struct DummyType { }; 250 | Mock dummyMock; 251 | 252 | MockValidator dummyFunc; 253 | 254 | //no invocations have occurred 255 | ASSERT_EQ(0, dummyMock.invocations().size()); 256 | 257 | //the validator DOES NOT match this invocation 258 | ASSERT_FALSE( 259 | dummyFunc.validationBuilder(dummyMock).called(INT_VALUE, BOOL_VALUE)); 260 | 261 | //No invocations for this mock exist 262 | ASSERT_EQ(0, dummyMock.invocations().size()); 263 | 264 | //the validator matches these arguments because they are ignored. 265 | //It returns false because no invocation of this function was made. 266 | ASSERT_FALSE( 267 | dummyFunc.validationBuilder(dummyMock).called(Ignore(), Ignore())); 268 | } 269 | 270 | /** 271 | * The called method returns false when a different method was called, even when 272 | * arguments are ignored. 273 | */ 274 | TEST(MockValidator, validationBuilder_called_ignore_different_function) 275 | { 276 | const int INT_VALUE = 17; 277 | const bool BOOL_VALUE = true; 278 | struct DummyType { }; 279 | Mock dummyMock; 280 | 281 | MockValidator dummyFunc; 282 | MockValidator differentFunc; 283 | 284 | //no invocations have occurred 285 | ASSERT_EQ(0, dummyMock.invocations().size()); 286 | 287 | //the validator DOES NOT match this invocation 288 | ASSERT_FALSE( 289 | dummyFunc.validationBuilder(dummyMock).called(INT_VALUE, BOOL_VALUE)); 290 | 291 | //add an invocation of the other function 292 | differentFunc.addInvocation(dummyMock, INT_VALUE); 293 | 294 | //there is now an invocation in the mock 295 | ASSERT_EQ(1, dummyMock.invocations().size()); 296 | 297 | //the validator returns false because a different function was invoked 298 | ASSERT_FALSE( 299 | dummyFunc.validationBuilder(dummyMock).called(Ignore(), Ignore())); 300 | } 301 | 302 | /** 303 | * The called method accepts lambda arguments, and invokes these arguments to 304 | * decide whether the call matches. 305 | */ 306 | TEST(MockValidator, validationBuilder_called_ignore_lambda) 307 | { 308 | const int INT_VALUE = 17; 309 | const bool BOOL_VALUE = true; 310 | struct DummyType { }; 311 | Mock dummyMock; 312 | 313 | MockValidator dummyFunc; 314 | 315 | //no invocations have occurred 316 | ASSERT_EQ(0, dummyMock.invocations().size()); 317 | 318 | //the validator DOES NOT match this invocation 319 | ASSERT_FALSE( 320 | dummyFunc.validationBuilder(dummyMock).called(INT_VALUE, BOOL_VALUE)); 321 | 322 | //add an invocation 323 | dummyFunc.addInvocation(dummyMock, INT_VALUE, BOOL_VALUE); 324 | 325 | //there is now an invocation in the mock 326 | ASSERT_EQ(1, dummyMock.invocations().size()); 327 | 328 | //the validator matches these arguments 329 | ASSERT_TRUE( 330 | dummyFunc.validationBuilder(dummyMock).called([](int x) -> bool { return x > 5; }, Ignore())); 331 | } 332 | 333 | /** 334 | * The called method accepts a single lambda argument for a function that takes 335 | * one argument. 336 | */ 337 | TEST(MockValidator, validationBuilder_called_single_lambda) 338 | { 339 | const int INT_VALUE = 17; 340 | struct DummyType { }; 341 | Mock dummyMock; 342 | 343 | MockValidator dummyFunc; 344 | 345 | //no invocations have occurred 346 | ASSERT_EQ(0, dummyMock.invocations().size()); 347 | 348 | //the validator DOES NOT match this invocation 349 | ASSERT_FALSE( 350 | dummyFunc.validationBuilder(dummyMock).called(INT_VALUE)); 351 | 352 | //add an invocation 353 | dummyFunc.addInvocation(dummyMock, INT_VALUE); 354 | 355 | //there is now an invocation in the mock 356 | ASSERT_EQ(1, dummyMock.invocations().size()); 357 | 358 | //the validator matches these arguments 359 | ASSERT_TRUE( 360 | dummyFunc.validationBuilder(dummyMock).called([](int x) -> bool { return x > 5; })); 361 | 362 | //clear the mock 363 | dummyMock.clear(); 364 | 365 | //this validator does not match these arguments 366 | ASSERT_FALSE( 367 | dummyFunc.validationBuilder(dummyMock).called([](int x) -> bool { return x > 5; })); 368 | 369 | //add an invocation 370 | dummyFunc.addInvocation(dummyMock, INT_VALUE); 371 | 372 | //this validator does not match these arguments 373 | ASSERT_FALSE( 374 | dummyFunc.validationBuilder(dummyMock).called([](int x) -> bool { return x < 5; })); 375 | } 376 | --------------------------------------------------------------------------------