Implements --gmock_catch_leaked_mocks and Mock::AllowLeak.
This commit is contained in:
		@@ -1612,6 +1612,43 @@ TEST_F(GMockVerboseFlagTest, InvalidFlagIsTreatedAsWarning) {
 | 
			
		||||
 | 
			
		||||
#endif  // 0
 | 
			
		||||
 | 
			
		||||
TEST(AllowLeakTest, AllowsLeakingUnusedMockObject) {
 | 
			
		||||
  MockA* a = new MockA;
 | 
			
		||||
  Mock::AllowLeak(a);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST(AllowLeakTest, CanBeCalledBeforeOnCall) {
 | 
			
		||||
  MockA* a = new MockA;
 | 
			
		||||
  Mock::AllowLeak(a);
 | 
			
		||||
  ON_CALL(*a, DoA(_)).WillByDefault(Return());
 | 
			
		||||
  a->DoA(0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST(AllowLeakTest, CanBeCalledAfterOnCall) {
 | 
			
		||||
  MockA* a = new MockA;
 | 
			
		||||
  ON_CALL(*a, DoA(_)).WillByDefault(Return());
 | 
			
		||||
  Mock::AllowLeak(a);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST(AllowLeakTest, CanBeCalledBeforeExpectCall) {
 | 
			
		||||
  MockA* a = new MockA;
 | 
			
		||||
  Mock::AllowLeak(a);
 | 
			
		||||
  EXPECT_CALL(*a, DoA(_));
 | 
			
		||||
  a->DoA(0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST(AllowLeakTest, CanBeCalledAfterExpectCall) {
 | 
			
		||||
  MockA* a = new MockA;
 | 
			
		||||
  EXPECT_CALL(*a, DoA(_)).Times(AnyNumber());
 | 
			
		||||
  Mock::AllowLeak(a);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST(AllowLeakTest, WorksWhenBothOnCallAndExpectCallArePresent) {
 | 
			
		||||
  MockA* a = new MockA;
 | 
			
		||||
  ON_CALL(*a, DoA(_)).WillByDefault(Return());
 | 
			
		||||
  EXPECT_CALL(*a, DoA(_)).Times(AnyNumber());
 | 
			
		||||
  Mock::AllowLeak(a);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Tests that we can verify and clear a mock object's expectations
 | 
			
		||||
// when none of its methods has expectations.
 | 
			
		||||
@@ -1916,3 +1953,14 @@ void Helper(MockC* c) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}  // namespace
 | 
			
		||||
 | 
			
		||||
int main(int argc, char **argv) {
 | 
			
		||||
  testing::InitGoogleMock(&argc, argv);
 | 
			
		||||
 | 
			
		||||
  // Ensures that the tests pass no matter what value of
 | 
			
		||||
  // --gmock_catch_leaked_mocks and --gmock_verbose the user specifies.
 | 
			
		||||
  testing::GMOCK_FLAG(catch_leaked_mocks) = true;
 | 
			
		||||
  testing::GMOCK_FLAG(verbose) = testing::internal::kWarningVerbosity;
 | 
			
		||||
 | 
			
		||||
  return RUN_ALL_TESTS();
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										84
									
								
								test/gmock_leak_test.py
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										84
									
								
								test/gmock_leak_test.py
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,84 @@
 | 
			
		||||
#!/usr/bin/env python
 | 
			
		||||
#
 | 
			
		||||
# Copyright 2009, Google Inc.
 | 
			
		||||
# All rights reserved.
 | 
			
		||||
#
 | 
			
		||||
# Redistribution and use in source and binary forms, with or without
 | 
			
		||||
# modification, are permitted provided that the following conditions are
 | 
			
		||||
# met:
 | 
			
		||||
#
 | 
			
		||||
#     * Redistributions of source code must retain the above copyright
 | 
			
		||||
# notice, this list of conditions and the following disclaimer.
 | 
			
		||||
#     * Redistributions in binary form must reproduce the above
 | 
			
		||||
# copyright notice, this list of conditions and the following disclaimer
 | 
			
		||||
# in the documentation and/or other materials provided with the
 | 
			
		||||
# distribution.
 | 
			
		||||
#     * Neither the name of Google Inc. nor the names of its
 | 
			
		||||
# contributors may be used to endorse or promote products derived from
 | 
			
		||||
# this software without specific prior written permission.
 | 
			
		||||
#
 | 
			
		||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | 
			
		||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | 
			
		||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 | 
			
		||||
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | 
			
		||||
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | 
			
		||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | 
			
		||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | 
			
		||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | 
			
		||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | 
			
		||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | 
			
		||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
 | 
			
		||||
"""Tests that leaked mock objects can be caught be Google Mock."""
 | 
			
		||||
 | 
			
		||||
__author__ = 'wan@google.com (Zhanyong Wan)'
 | 
			
		||||
 | 
			
		||||
import gmock_test_utils
 | 
			
		||||
import os
 | 
			
		||||
import unittest
 | 
			
		||||
 | 
			
		||||
IS_WINDOWS = os.name == 'nt'
 | 
			
		||||
 | 
			
		||||
if IS_WINDOWS:
 | 
			
		||||
  # TODO(wan@google.com): test the opt build too.  We should do it
 | 
			
		||||
  # when Vlad Losev's work on Google Test's Python test driver is
 | 
			
		||||
  # done, such that we can reuse the work.
 | 
			
		||||
  PROGRAM = r'..\build.dbg\gmock_leak_test_.exe'
 | 
			
		||||
else:
 | 
			
		||||
  PROGRAM = 'gmock_leak_test_'
 | 
			
		||||
 | 
			
		||||
PROGRAM_PATH = os.path.join(gmock_test_utils.GetBuildDir(), PROGRAM)
 | 
			
		||||
TEST_WITH_EXPECT_CALL = PROGRAM_PATH + ' --gtest_filter=*ExpectCall*'
 | 
			
		||||
TEST_WITH_ON_CALL = PROGRAM_PATH + ' --gtest_filter=*OnCall*'
 | 
			
		||||
TEST_MULTIPLE_LEAKS = PROGRAM_PATH + ' --gtest_filter=*MultipleLeaked*'
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class GMockLeakTest(unittest.TestCase):
 | 
			
		||||
 | 
			
		||||
  def testDoesNotCatchLeakedMockByDefault(self):
 | 
			
		||||
    self.assertEquals(0, os.system(TEST_WITH_EXPECT_CALL))
 | 
			
		||||
    self.assertEquals(0, os.system(TEST_WITH_ON_CALL))
 | 
			
		||||
 | 
			
		||||
  def testDoesNotCatchLeakedMockWhenDisabled(self):
 | 
			
		||||
    self.assertEquals(
 | 
			
		||||
        0, os.system(TEST_WITH_EXPECT_CALL + ' --gmock_catch_leaked_mocks=0'))
 | 
			
		||||
    self.assertEquals(
 | 
			
		||||
        0, os.system(TEST_WITH_ON_CALL + ' --gmock_catch_leaked_mocks=0'))
 | 
			
		||||
 | 
			
		||||
  def testCatchesLeakedMockWhenEnabled(self):
 | 
			
		||||
    self.assertNotEqual(
 | 
			
		||||
        os.system(TEST_WITH_EXPECT_CALL + ' --gmock_catch_leaked_mocks'), 0)
 | 
			
		||||
    self.assertNotEqual(
 | 
			
		||||
        os.system(TEST_WITH_ON_CALL + ' --gmock_catch_leaked_mocks'), 0)
 | 
			
		||||
 | 
			
		||||
  def testCatchesLeakedMockWhenEnabledWithExplictFlagValue(self):
 | 
			
		||||
    self.assertNotEqual(
 | 
			
		||||
        os.system(TEST_WITH_EXPECT_CALL + ' --gmock_catch_leaked_mocks=1'), 0)
 | 
			
		||||
 | 
			
		||||
  def testCatchesMultipleLeakedMocks(self):
 | 
			
		||||
    self.assertNotEqual(
 | 
			
		||||
        os.system(TEST_MULTIPLE_LEAKS + ' --gmock_catch_leaked_mocks'), 0)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
if __name__ == '__main__':
 | 
			
		||||
  gmock_test_utils.Main()
 | 
			
		||||
							
								
								
									
										95
									
								
								test/gmock_leak_test_.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										95
									
								
								test/gmock_leak_test_.cc
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,95 @@
 | 
			
		||||
// Copyright 2009, Google Inc.
 | 
			
		||||
// All rights reserved.
 | 
			
		||||
//
 | 
			
		||||
// Redistribution and use in source and binary forms, with or without
 | 
			
		||||
// modification, are permitted provided that the following conditions are
 | 
			
		||||
// met:
 | 
			
		||||
//
 | 
			
		||||
//     * Redistributions of source code must retain the above copyright
 | 
			
		||||
// notice, this list of conditions and the following disclaimer.
 | 
			
		||||
//     * Redistributions in binary form must reproduce the above
 | 
			
		||||
// copyright notice, this list of conditions and the following disclaimer
 | 
			
		||||
// in the documentation and/or other materials provided with the
 | 
			
		||||
// distribution.
 | 
			
		||||
//     * Neither the name of Google Inc. nor the names of its
 | 
			
		||||
// contributors may be used to endorse or promote products derived from
 | 
			
		||||
// this software without specific prior written permission.
 | 
			
		||||
//
 | 
			
		||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | 
			
		||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | 
			
		||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 | 
			
		||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | 
			
		||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | 
			
		||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | 
			
		||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | 
			
		||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | 
			
		||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | 
			
		||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | 
			
		||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
//
 | 
			
		||||
// Author: wan@google.com (Zhanyong Wan)
 | 
			
		||||
 | 
			
		||||
// Google Mock - a framework for writing C++ mock classes.
 | 
			
		||||
//
 | 
			
		||||
// This program is for verifying that a leaked mock object can be
 | 
			
		||||
// caught by Google Mock's leak detector.
 | 
			
		||||
 | 
			
		||||
#include <gmock/gmock.h>
 | 
			
		||||
 | 
			
		||||
namespace {
 | 
			
		||||
 | 
			
		||||
using ::testing::Return;
 | 
			
		||||
 | 
			
		||||
class FooInterface {
 | 
			
		||||
 public:
 | 
			
		||||
  virtual ~FooInterface() {}
 | 
			
		||||
  virtual void DoThis() = 0;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class MockFoo : public FooInterface {
 | 
			
		||||
 public:
 | 
			
		||||
  MOCK_METHOD0(DoThis, void());
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
TEST(LeakTest, LeakedMockWithExpectCallCausesFailureWhenLeakCheckingIsEnabled) {
 | 
			
		||||
  MockFoo* foo = new MockFoo;
 | 
			
		||||
 | 
			
		||||
  EXPECT_CALL(*foo, DoThis());
 | 
			
		||||
  foo->DoThis();
 | 
			
		||||
 | 
			
		||||
  // In order to test the leak detector, we deliberately leak foo.
 | 
			
		||||
 | 
			
		||||
  // Makes sure Google Mock's leak detector can change the exit code
 | 
			
		||||
  // to 1 even when the code is already exiting with 0.
 | 
			
		||||
  exit(0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST(LeakTest, LeakedMockWithOnCallCausesFailureWhenLeakCheckingIsEnabled) {
 | 
			
		||||
  MockFoo* foo = new MockFoo;
 | 
			
		||||
 | 
			
		||||
  ON_CALL(*foo, DoThis()).WillByDefault(Return());
 | 
			
		||||
 | 
			
		||||
  // In order to test the leak detector, we deliberately leak foo.
 | 
			
		||||
 | 
			
		||||
  // Makes sure Google Mock's leak detector can change the exit code
 | 
			
		||||
  // to 1 even when the code is already exiting with 0.
 | 
			
		||||
  exit(0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST(LeakTest, CatchesMultipleLeakedMockObjects) {
 | 
			
		||||
  MockFoo* foo1 = new MockFoo;
 | 
			
		||||
  MockFoo* foo2 = new MockFoo;
 | 
			
		||||
 | 
			
		||||
  ON_CALL(*foo1, DoThis()).WillByDefault(Return());
 | 
			
		||||
  EXPECT_CALL(*foo2, DoThis());
 | 
			
		||||
  foo2->DoThis();
 | 
			
		||||
 | 
			
		||||
  // In order to test the leak detector, we deliberately leak foo1 and
 | 
			
		||||
  // foo2.
 | 
			
		||||
 | 
			
		||||
  // Makes sure Google Mock's leak detector can change the exit code
 | 
			
		||||
  // to 1 even when the code is already exiting with 0.
 | 
			
		||||
  exit(0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}  // namespace
 | 
			
		||||
@@ -59,7 +59,7 @@ else:
 | 
			
		||||
  PROGRAM = 'gmock_output_test_'
 | 
			
		||||
 | 
			
		||||
PROGRAM_PATH = os.path.join(gmock_test_utils.GetBuildDir(), PROGRAM)
 | 
			
		||||
COMMAND = PROGRAM_PATH + ' --gtest_stack_trace_depth=0'
 | 
			
		||||
COMMAND = PROGRAM_PATH + ' --gtest_stack_trace_depth=0 --gtest_print_time=0'
 | 
			
		||||
GOLDEN_NAME = 'gmock_output_test_golden.txt'
 | 
			
		||||
GOLDEN_PATH = os.path.join(gmock_test_utils.GetSourceDir(),
 | 
			
		||||
                           GOLDEN_NAME)
 | 
			
		||||
 
 | 
			
		||||
@@ -40,6 +40,7 @@
 | 
			
		||||
#include <gtest/gtest.h>
 | 
			
		||||
 | 
			
		||||
using testing::_;
 | 
			
		||||
using testing::AnyNumber;
 | 
			
		||||
using testing::Ge;
 | 
			
		||||
using testing::InSequence;
 | 
			
		||||
using testing::Ref;
 | 
			
		||||
@@ -239,3 +240,31 @@ TEST_F(GMockOutputTest, ExplicitActionsRunOutWithDefaultAction) {
 | 
			
		||||
  foo_.Bar2(2, 2);
 | 
			
		||||
  foo_.Bar2(1, 1);  // Explicit actions in EXPECT_CALL run out.
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_F(GMockOutputTest, CatchesLeakedMocks) {
 | 
			
		||||
  MockFoo* foo1 = new MockFoo;
 | 
			
		||||
  MockFoo* foo2 = new MockFoo;
 | 
			
		||||
 | 
			
		||||
  // Invokes ON_CALL on foo1.
 | 
			
		||||
  ON_CALL(*foo1, Bar(_, _, _)).WillByDefault(Return('a'));
 | 
			
		||||
 | 
			
		||||
  // Invokes EXPECT_CALL on foo2.
 | 
			
		||||
  EXPECT_CALL(*foo2, Bar2(_, _));
 | 
			
		||||
  EXPECT_CALL(*foo2, Bar2(1, _));
 | 
			
		||||
  EXPECT_CALL(*foo2, Bar3(_, _)).Times(AnyNumber());
 | 
			
		||||
  foo2->Bar2(2, 1);
 | 
			
		||||
  foo2->Bar2(1, 1);
 | 
			
		||||
 | 
			
		||||
  // Both foo1 and foo2 are deliberately leaked.
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int main(int argc, char **argv) {
 | 
			
		||||
  testing::InitGoogleMock(&argc, argv);
 | 
			
		||||
 | 
			
		||||
  // Ensures that the tests pass no matter what value of
 | 
			
		||||
  // --gmock_catch_leaked_mocks and --gmock_verbose the user specifies.
 | 
			
		||||
  testing::GMOCK_FLAG(catch_leaked_mocks) = true;
 | 
			
		||||
  testing::GMOCK_FLAG(verbose) = "warning";
 | 
			
		||||
 | 
			
		||||
  return RUN_ALL_TESTS();
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,3 @@
 | 
			
		||||
Running main() from gmock_main.cc
 | 
			
		||||
[ RUN      ] GMockOutputTest.ExpectedCall
 | 
			
		||||
 | 
			
		||||
FILE:#: EXPECT_CALL(foo_, Bar2(0, _)) invoked
 | 
			
		||||
@@ -280,6 +279,8 @@ Called 2 times, but only 1 WillOnce() is specified - taking default action speci
 | 
			
		||||
FILE:#:
 | 
			
		||||
Stack trace:
 | 
			
		||||
[       OK ] GMockOutputTest.ExplicitActionsRunOutWithDefaultAction
 | 
			
		||||
[ RUN      ] GMockOutputTest.CatchesLeakedMocks
 | 
			
		||||
[       OK ] GMockOutputTest.CatchesLeakedMocks
 | 
			
		||||
[  FAILED  ] GMockOutputTest.UnexpectedCall
 | 
			
		||||
[  FAILED  ] GMockOutputTest.UnexpectedCallToVoidFunction
 | 
			
		||||
[  FAILED  ] GMockOutputTest.ExcessiveCall
 | 
			
		||||
@@ -294,3 +295,7 @@ Stack trace:
 | 
			
		||||
[  FAILED  ] GMockOutputTest.UnexpectedCallWithDefaultAction
 | 
			
		||||
[  FAILED  ] GMockOutputTest.ExcessiveCallWithDefaultAction
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
FILE:#: ERROR: this mock object should be deleted but never is. Its address is @0x#.
 | 
			
		||||
FILE:#: ERROR: this mock object should be deleted but never is. Its address is @0x#.
 | 
			
		||||
ERROR: 2 leaked mock objects found at program exit.
 | 
			
		||||
 
 | 
			
		||||
@@ -246,3 +246,10 @@ TEST(WideInitGoogleMockTest, CallsInitGoogleTest) {
 | 
			
		||||
  TestInitGoogleMock(argv, new_argv, "error");
 | 
			
		||||
  EXPECT_EQ(old_init_gtest_count + 1, g_init_gtest_count);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Makes sure Google Mock flags can be accessed in code.
 | 
			
		||||
TEST(FlagTest, IsAccessibleInCode) {
 | 
			
		||||
  bool dummy = testing::GMOCK_FLAG(catch_leaked_mocks) &&
 | 
			
		||||
      testing::GMOCK_FLAG(verbose) == "";
 | 
			
		||||
  dummy = dummy;  // Avoids the "unused local variable" warning.
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user