aboutsummaryrefslogtreecommitdiffstats
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/gmock-spec-builders_test.cc48
-rwxr-xr-xtest/gmock_leak_test.py84
-rw-r--r--test/gmock_leak_test_.cc95
-rwxr-xr-xtest/gmock_output_test.py2
-rw-r--r--test/gmock_output_test_.cc29
-rw-r--r--test/gmock_output_test_golden.txt7
-rw-r--r--test/gmock_test.cc7
7 files changed, 270 insertions, 2 deletions
diff --git a/test/gmock-spec-builders_test.cc b/test/gmock-spec-builders_test.cc
index 287a63e2..e8c39028 100644
--- a/test/gmock-spec-builders_test.cc
+++ b/test/gmock-spec-builders_test.cc
@@ -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();
+}
diff --git a/test/gmock_leak_test.py b/test/gmock_leak_test.py
new file mode 100755
index 00000000..51358f06
--- /dev/null
+++ b/test/gmock_leak_test.py
@@ -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()
diff --git a/test/gmock_leak_test_.cc b/test/gmock_leak_test_.cc
new file mode 100644
index 00000000..157bd7ec
--- /dev/null
+++ b/test/gmock_leak_test_.cc
@@ -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
diff --git a/test/gmock_output_test.py b/test/gmock_output_test.py
index f7f37abb..2e992190 100755
--- a/test/gmock_output_test.py
+++ b/test/gmock_output_test.py
@@ -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)
diff --git a/test/gmock_output_test_.cc b/test/gmock_output_test_.cc
index bb56b7cd..c97bc78c 100644
--- a/test/gmock_output_test_.cc
+++ b/test/gmock_output_test_.cc
@@ -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();
+}
diff --git a/test/gmock_output_test_golden.txt b/test/gmock_output_test_golden.txt
index 374e6659..50ef7b75 100644
--- a/test/gmock_output_test_golden.txt
+++ b/test/gmock_output_test_golden.txt
@@ -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.
diff --git a/test/gmock_test.cc b/test/gmock_test.cc
index 63c3fe8d..0c832607 100644
--- a/test/gmock_test.cc
+++ b/test/gmock_test.cc
@@ -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.
+}