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