shiqian | e35fdd9 | 2008-12-10 05:08:54 +0000 | [diff] [blame^] | 1 | // Copyright 2007, Google Inc. |
| 2 | // All rights reserved. |
| 3 | // |
| 4 | // Redistribution and use in source and binary forms, with or without |
| 5 | // modification, are permitted provided that the following conditions are |
| 6 | // met: |
| 7 | // |
| 8 | // * Redistributions of source code must retain the above copyright |
| 9 | // notice, this list of conditions and the following disclaimer. |
| 10 | // * Redistributions in binary form must reproduce the above |
| 11 | // copyright notice, this list of conditions and the following disclaimer |
| 12 | // in the documentation and/or other materials provided with the |
| 13 | // distribution. |
| 14 | // * Neither the name of Google Inc. nor the names of its |
| 15 | // contributors may be used to endorse or promote products derived from |
| 16 | // this software without specific prior written permission. |
| 17 | // |
| 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 29 | // |
| 30 | // Author: wan@google.com (Zhanyong Wan) |
| 31 | |
| 32 | // Google Mock - a framework for writing C++ mock classes. |
| 33 | // |
| 34 | // This file implements the spec builder syntax (ON_CALL and |
| 35 | // EXPECT_CALL). |
| 36 | |
| 37 | #include <gmock/gmock-spec-builders.h> |
| 38 | |
| 39 | #include <set> |
| 40 | #include <gtest/gtest.h> |
| 41 | |
| 42 | namespace testing { |
| 43 | namespace internal { |
| 44 | |
| 45 | // Protects the mock object registry (in class Mock), all function |
| 46 | // mockers, and all expectations. |
| 47 | Mutex g_gmock_mutex(Mutex::NO_CONSTRUCTOR_NEEDED_FOR_STATIC_MUTEX); |
| 48 | |
| 49 | // Constructs an ExpectationBase object. |
| 50 | ExpectationBase::ExpectationBase(const char* file, int line) |
| 51 | : file_(file), |
| 52 | line_(line), |
| 53 | cardinality_specified_(false), |
| 54 | cardinality_(Exactly(1)), |
| 55 | call_count_(0), |
| 56 | retired_(false) { |
| 57 | } |
| 58 | |
| 59 | // Destructs an ExpectationBase object. |
| 60 | ExpectationBase::~ExpectationBase() {} |
| 61 | |
| 62 | // Explicitly specifies the cardinality of this expectation. Used by |
| 63 | // the subclasses to implement the .Times() clause. |
| 64 | void ExpectationBase::SpecifyCardinality(const Cardinality& cardinality) { |
| 65 | cardinality_specified_ = true; |
| 66 | cardinality_ = cardinality; |
| 67 | } |
| 68 | |
| 69 | // Retires all pre-requisites of this expectation. |
| 70 | void ExpectationBase::RetireAllPreRequisites() { |
| 71 | if (is_retired()) { |
| 72 | // We can take this short-cut as we never retire an expectation |
| 73 | // until we have retired all its pre-requisites. |
| 74 | return; |
| 75 | } |
| 76 | |
| 77 | for (ExpectationBaseSet::const_iterator it = |
| 78 | immediate_prerequisites_.begin(); |
| 79 | it != immediate_prerequisites_.end(); |
| 80 | ++it) { |
| 81 | ExpectationBase* const prerequisite = (*it).get(); |
| 82 | if (!prerequisite->is_retired()) { |
| 83 | prerequisite->RetireAllPreRequisites(); |
| 84 | prerequisite->Retire(); |
| 85 | } |
| 86 | } |
| 87 | } |
| 88 | |
| 89 | // Returns true iff all pre-requisites of this expectation have been |
| 90 | // satisfied. |
| 91 | // L >= g_gmock_mutex |
| 92 | bool ExpectationBase::AllPrerequisitesAreSatisfied() const { |
| 93 | g_gmock_mutex.AssertHeld(); |
| 94 | for (ExpectationBaseSet::const_iterator it = immediate_prerequisites_.begin(); |
| 95 | it != immediate_prerequisites_.end(); ++it) { |
| 96 | if (!(*it)->IsSatisfied() || |
| 97 | !(*it)->AllPrerequisitesAreSatisfied()) |
| 98 | return false; |
| 99 | } |
| 100 | return true; |
| 101 | } |
| 102 | |
| 103 | // Adds unsatisfied pre-requisites of this expectation to 'result'. |
| 104 | // L >= g_gmock_mutex |
| 105 | void ExpectationBase::FindUnsatisfiedPrerequisites( |
| 106 | ExpectationBaseSet* result) const { |
| 107 | g_gmock_mutex.AssertHeld(); |
| 108 | for (ExpectationBaseSet::const_iterator it = immediate_prerequisites_.begin(); |
| 109 | it != immediate_prerequisites_.end(); ++it) { |
| 110 | if ((*it)->IsSatisfied()) { |
| 111 | // If *it is satisfied and has a call count of 0, some of its |
| 112 | // pre-requisites may not be satisfied yet. |
| 113 | if ((*it)->call_count_ == 0) { |
| 114 | (*it)->FindUnsatisfiedPrerequisites(result); |
| 115 | } |
| 116 | } else { |
| 117 | // Now that we know *it is unsatisfied, we are not so interested |
| 118 | // in whether its pre-requisites are satisfied. Therefore we |
| 119 | // don't recursively call FindUnsatisfiedPrerequisites() here. |
| 120 | result->insert(*it); |
| 121 | } |
| 122 | } |
| 123 | } |
| 124 | |
| 125 | // Points to the implicit sequence introduced by a living InSequence |
| 126 | // object (if any) in the current thread or NULL. |
| 127 | ThreadLocal<Sequence*> g_gmock_implicit_sequence; |
| 128 | |
| 129 | // Reports an uninteresting call (whose description is in msg) in the |
| 130 | // manner specified by 'reaction'. |
| 131 | void ReportUninterestingCall(CallReaction reaction, const string& msg) { |
| 132 | switch (reaction) { |
| 133 | case ALLOW: |
| 134 | Log(INFO, msg, 4); |
| 135 | break; |
| 136 | case WARN: |
| 137 | Log(WARNING, msg, 4); |
| 138 | break; |
| 139 | default: // FAIL |
| 140 | Expect(false, NULL, -1, msg); |
| 141 | } |
| 142 | } |
| 143 | |
| 144 | } // namespace internal |
| 145 | |
| 146 | // Class Mock. |
| 147 | |
| 148 | namespace { |
| 149 | |
| 150 | typedef std::set<internal::UntypedFunctionMockerBase*> FunctionMockers; |
| 151 | typedef std::map<const void*, FunctionMockers> MockObjectRegistry; |
| 152 | |
| 153 | // Maps a mock object to the set of mock methods it owns. Protected |
| 154 | // by g_gmock_mutex. |
| 155 | MockObjectRegistry g_mock_object_registry; |
| 156 | |
| 157 | // Maps a mock object to the reaction Google Mock should have when an |
| 158 | // uninteresting method is called. Protected by g_gmock_mutex. |
| 159 | std::map<const void*, internal::CallReaction> g_uninteresting_call_reaction; |
| 160 | |
| 161 | // Sets the reaction Google Mock should have when an uninteresting |
| 162 | // method of the given mock object is called. |
| 163 | // L < g_gmock_mutex |
| 164 | void SetReactionOnUninterestingCalls(const void* mock_obj, |
| 165 | internal::CallReaction reaction) { |
| 166 | internal::MutexLock l(&internal::g_gmock_mutex); |
| 167 | g_uninteresting_call_reaction[mock_obj] = reaction; |
| 168 | } |
| 169 | |
| 170 | } // namespace |
| 171 | |
| 172 | // Tells Google Mock to allow uninteresting calls on the given mock |
| 173 | // object. |
| 174 | // L < g_gmock_mutex |
| 175 | void Mock::AllowUninterestingCalls(const void* mock_obj) { |
| 176 | SetReactionOnUninterestingCalls(mock_obj, internal::ALLOW); |
| 177 | } |
| 178 | |
| 179 | // Tells Google Mock to warn the user about uninteresting calls on the |
| 180 | // given mock object. |
| 181 | // L < g_gmock_mutex |
| 182 | void Mock::WarnUninterestingCalls(const void* mock_obj) { |
| 183 | SetReactionOnUninterestingCalls(mock_obj, internal::WARN); |
| 184 | } |
| 185 | |
| 186 | // Tells Google Mock to fail uninteresting calls on the given mock |
| 187 | // object. |
| 188 | // L < g_gmock_mutex |
| 189 | void Mock::FailUninterestingCalls(const void* mock_obj) { |
| 190 | SetReactionOnUninterestingCalls(mock_obj, internal::FAIL); |
| 191 | } |
| 192 | |
| 193 | // Tells Google Mock the given mock object is being destroyed and its |
| 194 | // entry in the call-reaction table should be removed. |
| 195 | // L < g_gmock_mutex |
| 196 | void Mock::UnregisterCallReaction(const void* mock_obj) { |
| 197 | internal::MutexLock l(&internal::g_gmock_mutex); |
| 198 | g_uninteresting_call_reaction.erase(mock_obj); |
| 199 | } |
| 200 | |
| 201 | // Returns the reaction Google Mock will have on uninteresting calls |
| 202 | // made on the given mock object. |
| 203 | // L < g_gmock_mutex |
| 204 | internal::CallReaction Mock::GetReactionOnUninterestingCalls( |
| 205 | const void* mock_obj) { |
| 206 | internal::MutexLock l(&internal::g_gmock_mutex); |
| 207 | return (g_uninteresting_call_reaction.count(mock_obj) == 0) ? |
| 208 | internal::WARN : g_uninteresting_call_reaction[mock_obj]; |
| 209 | } |
| 210 | |
| 211 | // Verifies and clears all expectations on the given mock object. If |
| 212 | // the expectations aren't satisfied, generates one or more Google |
| 213 | // Test non-fatal failures and returns false. |
| 214 | // L < g_gmock_mutex |
| 215 | bool Mock::VerifyAndClearExpectations(void* mock_obj) { |
| 216 | internal::MutexLock l(&internal::g_gmock_mutex); |
| 217 | return VerifyAndClearExpectationsLocked(mock_obj); |
| 218 | } |
| 219 | |
| 220 | // Verifies all expectations on the given mock object and clears its |
| 221 | // default actions and expectations. Returns true iff the |
| 222 | // verification was successful. |
| 223 | // L < g_gmock_mutex |
| 224 | bool Mock::VerifyAndClear(void* mock_obj) { |
| 225 | internal::MutexLock l(&internal::g_gmock_mutex); |
| 226 | ClearDefaultActionsLocked(mock_obj); |
| 227 | return VerifyAndClearExpectationsLocked(mock_obj); |
| 228 | } |
| 229 | |
| 230 | // Verifies and clears all expectations on the given mock object. If |
| 231 | // the expectations aren't satisfied, generates one or more Google |
| 232 | // Test non-fatal failures and returns false. |
| 233 | // L >= g_gmock_mutex |
| 234 | bool Mock::VerifyAndClearExpectationsLocked(void* mock_obj) { |
| 235 | internal::g_gmock_mutex.AssertHeld(); |
| 236 | if (g_mock_object_registry.count(mock_obj) == 0) { |
| 237 | // No EXPECT_CALL() was set on the given mock object. |
| 238 | return true; |
| 239 | } |
| 240 | |
| 241 | // Verifies and clears the expectations on each mock method in the |
| 242 | // given mock object. |
| 243 | bool expectations_met = true; |
| 244 | FunctionMockers& mockers = g_mock_object_registry[mock_obj]; |
| 245 | for (FunctionMockers::const_iterator it = mockers.begin(); |
| 246 | it != mockers.end(); ++it) { |
| 247 | if (!(*it)->VerifyAndClearExpectationsLocked()) { |
| 248 | expectations_met = false; |
| 249 | } |
| 250 | } |
| 251 | |
| 252 | // We don't clear the content of mockers, as they may still be |
| 253 | // needed by ClearDefaultActionsLocked(). |
| 254 | return expectations_met; |
| 255 | } |
| 256 | |
| 257 | // Registers a mock object and a mock method it owns. |
| 258 | // L < g_gmock_mutex |
| 259 | void Mock::Register(const void* mock_obj, |
| 260 | internal::UntypedFunctionMockerBase* mocker) { |
| 261 | internal::MutexLock l(&internal::g_gmock_mutex); |
| 262 | g_mock_object_registry[mock_obj].insert(mocker); |
| 263 | } |
| 264 | |
| 265 | // Unregisters a mock method; removes the owning mock object from the |
| 266 | // registry when the last mock method associated with it has been |
| 267 | // unregistered. This is called only in the destructor of |
| 268 | // FunctionMockerBase. |
| 269 | // L >= g_gmock_mutex |
| 270 | void Mock::UnregisterLocked(internal::UntypedFunctionMockerBase* mocker) { |
| 271 | internal::g_gmock_mutex.AssertHeld(); |
| 272 | for (MockObjectRegistry::iterator it = g_mock_object_registry.begin(); |
| 273 | it != g_mock_object_registry.end(); ++it) { |
| 274 | FunctionMockers& mockers = it->second; |
| 275 | if (mockers.erase(mocker) > 0) { |
| 276 | // mocker was in mockers and has been just removed. |
| 277 | if (mockers.empty()) { |
| 278 | g_mock_object_registry.erase(it); |
| 279 | } |
| 280 | return; |
| 281 | } |
| 282 | } |
| 283 | } |
| 284 | |
| 285 | // Clears all ON_CALL()s set on the given mock object. |
| 286 | // L >= g_gmock_mutex |
| 287 | void Mock::ClearDefaultActionsLocked(void* mock_obj) { |
| 288 | internal::g_gmock_mutex.AssertHeld(); |
| 289 | |
| 290 | if (g_mock_object_registry.count(mock_obj) == 0) { |
| 291 | // No ON_CALL() was set on the given mock object. |
| 292 | return; |
| 293 | } |
| 294 | |
| 295 | // Clears the default actions for each mock method in the given mock |
| 296 | // object. |
| 297 | FunctionMockers& mockers = g_mock_object_registry[mock_obj]; |
| 298 | for (FunctionMockers::const_iterator it = mockers.begin(); |
| 299 | it != mockers.end(); ++it) { |
| 300 | (*it)->ClearDefaultActionsLocked(); |
| 301 | } |
| 302 | |
| 303 | // We don't clear the content of mockers, as they may still be |
| 304 | // needed by VerifyAndClearExpectationsLocked(). |
| 305 | } |
| 306 | |
| 307 | // Adds an expectation to a sequence. |
| 308 | void Sequence::AddExpectation( |
| 309 | const internal::linked_ptr<internal::ExpectationBase>& expectation) const { |
| 310 | if (*last_expectation_ != expectation) { |
| 311 | if (*last_expectation_ != NULL) { |
| 312 | expectation->immediate_prerequisites_.insert(*last_expectation_); |
| 313 | } |
| 314 | *last_expectation_ = expectation; |
| 315 | } |
| 316 | } |
| 317 | |
| 318 | // Creates the implicit sequence if there isn't one. |
| 319 | InSequence::InSequence() { |
| 320 | if (internal::g_gmock_implicit_sequence.get() == NULL) { |
| 321 | internal::g_gmock_implicit_sequence.set(new Sequence); |
| 322 | sequence_created_ = true; |
| 323 | } else { |
| 324 | sequence_created_ = false; |
| 325 | } |
| 326 | } |
| 327 | |
| 328 | // Deletes the implicit sequence if it was created by the constructor |
| 329 | // of this object. |
| 330 | InSequence::~InSequence() { |
| 331 | if (sequence_created_) { |
| 332 | delete internal::g_gmock_implicit_sequence.get(); |
| 333 | internal::g_gmock_implicit_sequence.set(NULL); |
| 334 | } |
| 335 | } |
| 336 | |
| 337 | } // namespace testing |