diff options
Diffstat (limited to 'test')
-rw-r--r-- | test/gmock-spec-builders_test.cc | 48 | ||||
-rwxr-xr-x | test/gmock_leak_test.py | 84 | ||||
-rw-r--r-- | test/gmock_leak_test_.cc | 95 | ||||
-rwxr-xr-x | test/gmock_output_test.py | 2 | ||||
-rw-r--r-- | test/gmock_output_test_.cc | 29 | ||||
-rw-r--r-- | test/gmock_output_test_golden.txt | 7 | ||||
-rw-r--r-- | test/gmock_test.cc | 7 |
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. +} |