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 | |
zhanyong.wan | df35a76 | 2009-04-22 22:25:31 +0000 | [diff] [blame] | 39 | #include <stdlib.h> |
| 40 | #include <iostream> // NOLINT |
| 41 | #include <map> |
shiqian | e35fdd9 | 2008-12-10 05:08:54 +0000 | [diff] [blame] | 42 | #include <set> |
zhanyong.wan | df35a76 | 2009-04-22 22:25:31 +0000 | [diff] [blame] | 43 | #include <gmock/gmock.h> |
shiqian | e35fdd9 | 2008-12-10 05:08:54 +0000 | [diff] [blame] | 44 | #include <gtest/gtest.h> |
| 45 | |
zhanyong.wan | df35a76 | 2009-04-22 22:25:31 +0000 | [diff] [blame] | 46 | #if GTEST_OS_CYGWIN || GTEST_OS_LINUX || GTEST_OS_MAC |
| 47 | #include <unistd.h> // NOLINT |
| 48 | #endif |
| 49 | |
shiqian | e35fdd9 | 2008-12-10 05:08:54 +0000 | [diff] [blame] | 50 | namespace testing { |
| 51 | namespace internal { |
| 52 | |
| 53 | // Protects the mock object registry (in class Mock), all function |
| 54 | // mockers, and all expectations. |
| 55 | Mutex g_gmock_mutex(Mutex::NO_CONSTRUCTOR_NEEDED_FOR_STATIC_MUTEX); |
| 56 | |
| 57 | // Constructs an ExpectationBase object. |
| 58 | ExpectationBase::ExpectationBase(const char* file, int line) |
| 59 | : file_(file), |
| 60 | line_(line), |
| 61 | cardinality_specified_(false), |
| 62 | cardinality_(Exactly(1)), |
| 63 | call_count_(0), |
| 64 | retired_(false) { |
| 65 | } |
| 66 | |
| 67 | // Destructs an ExpectationBase object. |
| 68 | ExpectationBase::~ExpectationBase() {} |
| 69 | |
| 70 | // Explicitly specifies the cardinality of this expectation. Used by |
| 71 | // the subclasses to implement the .Times() clause. |
| 72 | void ExpectationBase::SpecifyCardinality(const Cardinality& cardinality) { |
| 73 | cardinality_specified_ = true; |
| 74 | cardinality_ = cardinality; |
| 75 | } |
| 76 | |
| 77 | // Retires all pre-requisites of this expectation. |
| 78 | void ExpectationBase::RetireAllPreRequisites() { |
| 79 | if (is_retired()) { |
| 80 | // We can take this short-cut as we never retire an expectation |
| 81 | // until we have retired all its pre-requisites. |
| 82 | return; |
| 83 | } |
| 84 | |
| 85 | for (ExpectationBaseSet::const_iterator it = |
| 86 | immediate_prerequisites_.begin(); |
| 87 | it != immediate_prerequisites_.end(); |
| 88 | ++it) { |
| 89 | ExpectationBase* const prerequisite = (*it).get(); |
| 90 | if (!prerequisite->is_retired()) { |
| 91 | prerequisite->RetireAllPreRequisites(); |
| 92 | prerequisite->Retire(); |
| 93 | } |
| 94 | } |
| 95 | } |
| 96 | |
| 97 | // Returns true iff all pre-requisites of this expectation have been |
| 98 | // satisfied. |
| 99 | // L >= g_gmock_mutex |
| 100 | bool ExpectationBase::AllPrerequisitesAreSatisfied() const { |
| 101 | g_gmock_mutex.AssertHeld(); |
| 102 | for (ExpectationBaseSet::const_iterator it = immediate_prerequisites_.begin(); |
| 103 | it != immediate_prerequisites_.end(); ++it) { |
| 104 | if (!(*it)->IsSatisfied() || |
| 105 | !(*it)->AllPrerequisitesAreSatisfied()) |
| 106 | return false; |
| 107 | } |
| 108 | return true; |
| 109 | } |
| 110 | |
| 111 | // Adds unsatisfied pre-requisites of this expectation to 'result'. |
| 112 | // L >= g_gmock_mutex |
| 113 | void ExpectationBase::FindUnsatisfiedPrerequisites( |
| 114 | ExpectationBaseSet* result) const { |
| 115 | g_gmock_mutex.AssertHeld(); |
| 116 | for (ExpectationBaseSet::const_iterator it = immediate_prerequisites_.begin(); |
| 117 | it != immediate_prerequisites_.end(); ++it) { |
| 118 | if ((*it)->IsSatisfied()) { |
| 119 | // If *it is satisfied and has a call count of 0, some of its |
| 120 | // pre-requisites may not be satisfied yet. |
| 121 | if ((*it)->call_count_ == 0) { |
| 122 | (*it)->FindUnsatisfiedPrerequisites(result); |
| 123 | } |
| 124 | } else { |
| 125 | // Now that we know *it is unsatisfied, we are not so interested |
| 126 | // in whether its pre-requisites are satisfied. Therefore we |
| 127 | // don't recursively call FindUnsatisfiedPrerequisites() here. |
| 128 | result->insert(*it); |
| 129 | } |
| 130 | } |
| 131 | } |
| 132 | |
| 133 | // Points to the implicit sequence introduced by a living InSequence |
| 134 | // object (if any) in the current thread or NULL. |
| 135 | ThreadLocal<Sequence*> g_gmock_implicit_sequence; |
| 136 | |
| 137 | // Reports an uninteresting call (whose description is in msg) in the |
| 138 | // manner specified by 'reaction'. |
| 139 | void ReportUninterestingCall(CallReaction reaction, const string& msg) { |
| 140 | switch (reaction) { |
| 141 | case ALLOW: |
| 142 | Log(INFO, msg, 4); |
| 143 | break; |
| 144 | case WARN: |
| 145 | Log(WARNING, msg, 4); |
| 146 | break; |
| 147 | default: // FAIL |
| 148 | Expect(false, NULL, -1, msg); |
| 149 | } |
| 150 | } |
| 151 | |
| 152 | } // namespace internal |
| 153 | |
| 154 | // Class Mock. |
| 155 | |
| 156 | namespace { |
| 157 | |
| 158 | typedef std::set<internal::UntypedFunctionMockerBase*> FunctionMockers; |
shiqian | e35fdd9 | 2008-12-10 05:08:54 +0000 | [diff] [blame] | 159 | |
zhanyong.wan | df35a76 | 2009-04-22 22:25:31 +0000 | [diff] [blame] | 160 | // The current state of a mock object. Such information is needed for |
| 161 | // detecting leaked mock objects and explicitly verifying a mock's |
| 162 | // expectations. |
| 163 | struct MockObjectState { |
| 164 | MockObjectState() |
| 165 | : first_used_file(NULL), first_used_line(-1), leakable(false) {} |
| 166 | |
| 167 | // Where in the source file an ON_CALL or EXPECT_CALL is first |
| 168 | // invoked on this mock object. |
| 169 | const char* first_used_file; |
| 170 | int first_used_line; |
zhanyong.wan | e7bb5ed | 2009-05-05 23:14:47 +0000 | [diff] [blame^] | 171 | ::std::string first_used_test_case; |
| 172 | ::std::string first_used_test; |
zhanyong.wan | df35a76 | 2009-04-22 22:25:31 +0000 | [diff] [blame] | 173 | bool leakable; // true iff it's OK to leak the object. |
| 174 | FunctionMockers function_mockers; // All registered methods of the object. |
| 175 | }; |
| 176 | |
| 177 | // A global registry holding the state of all mock objects that are |
| 178 | // alive. A mock object is added to this registry the first time |
| 179 | // Mock::AllowLeak(), ON_CALL(), or EXPECT_CALL() is called on it. It |
| 180 | // is removed from the registry in the mock object's destructor. |
| 181 | class MockObjectRegistry { |
| 182 | public: |
| 183 | // Maps a mock object (identified by its address) to its state. |
| 184 | typedef std::map<const void*, MockObjectState> StateMap; |
| 185 | |
| 186 | // This destructor will be called when a program exits, after all |
| 187 | // tests in it have been run. By then, there should be no mock |
| 188 | // object alive. Therefore we report any living object as test |
| 189 | // failure, unless the user explicitly asked us to ignore it. |
| 190 | ~MockObjectRegistry() { |
| 191 | using ::std::cout; |
| 192 | |
| 193 | if (!GMOCK_FLAG(catch_leaked_mocks)) |
| 194 | return; |
| 195 | |
| 196 | int leaked_count = 0; |
| 197 | for (StateMap::const_iterator it = states_.begin(); it != states_.end(); |
| 198 | ++it) { |
| 199 | if (it->second.leakable) // The user said it's fine to leak this object. |
| 200 | continue; |
| 201 | |
| 202 | // TODO(wan@google.com): Print the type of the leaked object. |
| 203 | // This can help the user identify the leaked object. |
| 204 | cout << "\n"; |
| 205 | const MockObjectState& state = it->second; |
| 206 | internal::FormatFileLocation( |
| 207 | state.first_used_file, state.first_used_line, &cout); |
zhanyong.wan | e7bb5ed | 2009-05-05 23:14:47 +0000 | [diff] [blame^] | 208 | cout << " ERROR: this mock object"; |
| 209 | if (state.first_used_test != "") { |
| 210 | cout << " (used in test " << state.first_used_test_case << "." |
| 211 | << state.first_used_test << ")"; |
| 212 | } |
| 213 | cout << " should be deleted but never is. Its address is @" |
| 214 | << it->first << "."; |
zhanyong.wan | df35a76 | 2009-04-22 22:25:31 +0000 | [diff] [blame] | 215 | leaked_count++; |
| 216 | } |
| 217 | if (leaked_count > 0) { |
| 218 | cout << "\nERROR: " << leaked_count |
| 219 | << " leaked mock " << (leaked_count == 1 ? "object" : "objects") |
| 220 | << " found at program exit.\n"; |
| 221 | cout.flush(); |
| 222 | ::std::cerr.flush(); |
| 223 | // RUN_ALL_TESTS() has already returned when this destructor is |
| 224 | // called. Therefore we cannot use the normal Google Test |
| 225 | // failure reporting mechanism. |
| 226 | _exit(1); // We cannot call exit() as it is not reentrant and |
| 227 | // may already have been called. |
| 228 | } |
| 229 | } |
| 230 | |
| 231 | StateMap& states() { return states_; } |
| 232 | private: |
| 233 | StateMap states_; |
| 234 | }; |
| 235 | |
| 236 | // Protected by g_gmock_mutex. |
shiqian | e35fdd9 | 2008-12-10 05:08:54 +0000 | [diff] [blame] | 237 | MockObjectRegistry g_mock_object_registry; |
| 238 | |
| 239 | // Maps a mock object to the reaction Google Mock should have when an |
| 240 | // uninteresting method is called. Protected by g_gmock_mutex. |
| 241 | std::map<const void*, internal::CallReaction> g_uninteresting_call_reaction; |
| 242 | |
| 243 | // Sets the reaction Google Mock should have when an uninteresting |
| 244 | // method of the given mock object is called. |
| 245 | // L < g_gmock_mutex |
| 246 | void SetReactionOnUninterestingCalls(const void* mock_obj, |
| 247 | internal::CallReaction reaction) { |
| 248 | internal::MutexLock l(&internal::g_gmock_mutex); |
| 249 | g_uninteresting_call_reaction[mock_obj] = reaction; |
| 250 | } |
| 251 | |
| 252 | } // namespace |
| 253 | |
| 254 | // Tells Google Mock to allow uninteresting calls on the given mock |
| 255 | // object. |
| 256 | // L < g_gmock_mutex |
| 257 | void Mock::AllowUninterestingCalls(const void* mock_obj) { |
| 258 | SetReactionOnUninterestingCalls(mock_obj, internal::ALLOW); |
| 259 | } |
| 260 | |
| 261 | // Tells Google Mock to warn the user about uninteresting calls on the |
| 262 | // given mock object. |
| 263 | // L < g_gmock_mutex |
| 264 | void Mock::WarnUninterestingCalls(const void* mock_obj) { |
| 265 | SetReactionOnUninterestingCalls(mock_obj, internal::WARN); |
| 266 | } |
| 267 | |
| 268 | // Tells Google Mock to fail uninteresting calls on the given mock |
| 269 | // object. |
| 270 | // L < g_gmock_mutex |
| 271 | void Mock::FailUninterestingCalls(const void* mock_obj) { |
| 272 | SetReactionOnUninterestingCalls(mock_obj, internal::FAIL); |
| 273 | } |
| 274 | |
| 275 | // Tells Google Mock the given mock object is being destroyed and its |
| 276 | // entry in the call-reaction table should be removed. |
| 277 | // L < g_gmock_mutex |
| 278 | void Mock::UnregisterCallReaction(const void* mock_obj) { |
| 279 | internal::MutexLock l(&internal::g_gmock_mutex); |
| 280 | g_uninteresting_call_reaction.erase(mock_obj); |
| 281 | } |
| 282 | |
| 283 | // Returns the reaction Google Mock will have on uninteresting calls |
| 284 | // made on the given mock object. |
| 285 | // L < g_gmock_mutex |
| 286 | internal::CallReaction Mock::GetReactionOnUninterestingCalls( |
| 287 | const void* mock_obj) { |
| 288 | internal::MutexLock l(&internal::g_gmock_mutex); |
| 289 | return (g_uninteresting_call_reaction.count(mock_obj) == 0) ? |
| 290 | internal::WARN : g_uninteresting_call_reaction[mock_obj]; |
| 291 | } |
| 292 | |
zhanyong.wan | df35a76 | 2009-04-22 22:25:31 +0000 | [diff] [blame] | 293 | // Tells Google Mock to ignore mock_obj when checking for leaked mock |
| 294 | // objects. |
| 295 | // L < g_gmock_mutex |
| 296 | void Mock::AllowLeak(const void* mock_obj) { |
| 297 | internal::MutexLock l(&internal::g_gmock_mutex); |
| 298 | g_mock_object_registry.states()[mock_obj].leakable = true; |
| 299 | } |
| 300 | |
shiqian | e35fdd9 | 2008-12-10 05:08:54 +0000 | [diff] [blame] | 301 | // Verifies and clears all expectations on the given mock object. If |
| 302 | // the expectations aren't satisfied, generates one or more Google |
| 303 | // Test non-fatal failures and returns false. |
| 304 | // L < g_gmock_mutex |
| 305 | bool Mock::VerifyAndClearExpectations(void* mock_obj) { |
| 306 | internal::MutexLock l(&internal::g_gmock_mutex); |
| 307 | return VerifyAndClearExpectationsLocked(mock_obj); |
| 308 | } |
| 309 | |
| 310 | // Verifies all expectations on the given mock object and clears its |
| 311 | // default actions and expectations. Returns true iff the |
| 312 | // verification was successful. |
| 313 | // L < g_gmock_mutex |
| 314 | bool Mock::VerifyAndClear(void* mock_obj) { |
| 315 | internal::MutexLock l(&internal::g_gmock_mutex); |
| 316 | ClearDefaultActionsLocked(mock_obj); |
| 317 | return VerifyAndClearExpectationsLocked(mock_obj); |
| 318 | } |
| 319 | |
| 320 | // Verifies and clears all expectations on the given mock object. If |
| 321 | // the expectations aren't satisfied, generates one or more Google |
| 322 | // Test non-fatal failures and returns false. |
| 323 | // L >= g_gmock_mutex |
| 324 | bool Mock::VerifyAndClearExpectationsLocked(void* mock_obj) { |
| 325 | internal::g_gmock_mutex.AssertHeld(); |
zhanyong.wan | df35a76 | 2009-04-22 22:25:31 +0000 | [diff] [blame] | 326 | if (g_mock_object_registry.states().count(mock_obj) == 0) { |
shiqian | e35fdd9 | 2008-12-10 05:08:54 +0000 | [diff] [blame] | 327 | // No EXPECT_CALL() was set on the given mock object. |
| 328 | return true; |
| 329 | } |
| 330 | |
| 331 | // Verifies and clears the expectations on each mock method in the |
| 332 | // given mock object. |
| 333 | bool expectations_met = true; |
zhanyong.wan | df35a76 | 2009-04-22 22:25:31 +0000 | [diff] [blame] | 334 | FunctionMockers& mockers = |
| 335 | g_mock_object_registry.states()[mock_obj].function_mockers; |
shiqian | e35fdd9 | 2008-12-10 05:08:54 +0000 | [diff] [blame] | 336 | for (FunctionMockers::const_iterator it = mockers.begin(); |
| 337 | it != mockers.end(); ++it) { |
| 338 | if (!(*it)->VerifyAndClearExpectationsLocked()) { |
| 339 | expectations_met = false; |
| 340 | } |
| 341 | } |
| 342 | |
| 343 | // We don't clear the content of mockers, as they may still be |
| 344 | // needed by ClearDefaultActionsLocked(). |
| 345 | return expectations_met; |
| 346 | } |
| 347 | |
| 348 | // Registers a mock object and a mock method it owns. |
| 349 | // L < g_gmock_mutex |
| 350 | void Mock::Register(const void* mock_obj, |
| 351 | internal::UntypedFunctionMockerBase* mocker) { |
| 352 | internal::MutexLock l(&internal::g_gmock_mutex); |
zhanyong.wan | df35a76 | 2009-04-22 22:25:31 +0000 | [diff] [blame] | 353 | g_mock_object_registry.states()[mock_obj].function_mockers.insert(mocker); |
| 354 | } |
| 355 | |
| 356 | // Tells Google Mock where in the source code mock_obj is used in an |
| 357 | // ON_CALL or EXPECT_CALL. In case mock_obj is leaked, this |
| 358 | // information helps the user identify which object it is. |
| 359 | // L < g_gmock_mutex |
| 360 | void Mock::RegisterUseByOnCallOrExpectCall( |
| 361 | const void* mock_obj, const char* file, int line) { |
| 362 | internal::MutexLock l(&internal::g_gmock_mutex); |
| 363 | MockObjectState& state = g_mock_object_registry.states()[mock_obj]; |
| 364 | if (state.first_used_file == NULL) { |
| 365 | state.first_used_file = file; |
| 366 | state.first_used_line = line; |
zhanyong.wan | e7bb5ed | 2009-05-05 23:14:47 +0000 | [diff] [blame^] | 367 | const TestInfo* const test_info = |
| 368 | UnitTest::GetInstance()->current_test_info(); |
| 369 | if (test_info != NULL) { |
| 370 | // TODO(wan@google.com): record the test case name when the |
| 371 | // ON_CALL or EXPECT_CALL is invoked from SetUpTestCase() or |
| 372 | // TearDownTestCase(). |
| 373 | state.first_used_test_case = test_info->test_case_name(); |
| 374 | state.first_used_test = test_info->name(); |
| 375 | } |
zhanyong.wan | df35a76 | 2009-04-22 22:25:31 +0000 | [diff] [blame] | 376 | } |
shiqian | e35fdd9 | 2008-12-10 05:08:54 +0000 | [diff] [blame] | 377 | } |
| 378 | |
| 379 | // Unregisters a mock method; removes the owning mock object from the |
| 380 | // registry when the last mock method associated with it has been |
| 381 | // unregistered. This is called only in the destructor of |
| 382 | // FunctionMockerBase. |
| 383 | // L >= g_gmock_mutex |
| 384 | void Mock::UnregisterLocked(internal::UntypedFunctionMockerBase* mocker) { |
| 385 | internal::g_gmock_mutex.AssertHeld(); |
zhanyong.wan | df35a76 | 2009-04-22 22:25:31 +0000 | [diff] [blame] | 386 | for (MockObjectRegistry::StateMap::iterator it = |
| 387 | g_mock_object_registry.states().begin(); |
| 388 | it != g_mock_object_registry.states().end(); ++it) { |
| 389 | FunctionMockers& mockers = it->second.function_mockers; |
shiqian | e35fdd9 | 2008-12-10 05:08:54 +0000 | [diff] [blame] | 390 | if (mockers.erase(mocker) > 0) { |
| 391 | // mocker was in mockers and has been just removed. |
| 392 | if (mockers.empty()) { |
zhanyong.wan | df35a76 | 2009-04-22 22:25:31 +0000 | [diff] [blame] | 393 | g_mock_object_registry.states().erase(it); |
shiqian | e35fdd9 | 2008-12-10 05:08:54 +0000 | [diff] [blame] | 394 | } |
| 395 | return; |
| 396 | } |
| 397 | } |
| 398 | } |
| 399 | |
| 400 | // Clears all ON_CALL()s set on the given mock object. |
| 401 | // L >= g_gmock_mutex |
| 402 | void Mock::ClearDefaultActionsLocked(void* mock_obj) { |
| 403 | internal::g_gmock_mutex.AssertHeld(); |
| 404 | |
zhanyong.wan | df35a76 | 2009-04-22 22:25:31 +0000 | [diff] [blame] | 405 | if (g_mock_object_registry.states().count(mock_obj) == 0) { |
shiqian | e35fdd9 | 2008-12-10 05:08:54 +0000 | [diff] [blame] | 406 | // No ON_CALL() was set on the given mock object. |
| 407 | return; |
| 408 | } |
| 409 | |
| 410 | // Clears the default actions for each mock method in the given mock |
| 411 | // object. |
zhanyong.wan | df35a76 | 2009-04-22 22:25:31 +0000 | [diff] [blame] | 412 | FunctionMockers& mockers = |
| 413 | g_mock_object_registry.states()[mock_obj].function_mockers; |
shiqian | e35fdd9 | 2008-12-10 05:08:54 +0000 | [diff] [blame] | 414 | for (FunctionMockers::const_iterator it = mockers.begin(); |
| 415 | it != mockers.end(); ++it) { |
| 416 | (*it)->ClearDefaultActionsLocked(); |
| 417 | } |
| 418 | |
| 419 | // We don't clear the content of mockers, as they may still be |
| 420 | // needed by VerifyAndClearExpectationsLocked(). |
| 421 | } |
| 422 | |
| 423 | // Adds an expectation to a sequence. |
| 424 | void Sequence::AddExpectation( |
| 425 | const internal::linked_ptr<internal::ExpectationBase>& expectation) const { |
| 426 | if (*last_expectation_ != expectation) { |
| 427 | if (*last_expectation_ != NULL) { |
| 428 | expectation->immediate_prerequisites_.insert(*last_expectation_); |
| 429 | } |
| 430 | *last_expectation_ = expectation; |
| 431 | } |
| 432 | } |
| 433 | |
| 434 | // Creates the implicit sequence if there isn't one. |
| 435 | InSequence::InSequence() { |
| 436 | if (internal::g_gmock_implicit_sequence.get() == NULL) { |
| 437 | internal::g_gmock_implicit_sequence.set(new Sequence); |
| 438 | sequence_created_ = true; |
| 439 | } else { |
| 440 | sequence_created_ = false; |
| 441 | } |
| 442 | } |
| 443 | |
| 444 | // Deletes the implicit sequence if it was created by the constructor |
| 445 | // of this object. |
| 446 | InSequence::~InSequence() { |
| 447 | if (sequence_created_) { |
| 448 | delete internal::g_gmock_implicit_sequence.get(); |
| 449 | internal::g_gmock_implicit_sequence.set(NULL); |
| 450 | } |
| 451 | } |
| 452 | |
| 453 | } // namespace testing |