michael@0: // Copyright 2009 Google Inc. All Rights Reserved. michael@0: // michael@0: // Redistribution and use in source and binary forms, with or without michael@0: // modification, are permitted provided that the following conditions are michael@0: // met: michael@0: // michael@0: // * Redistributions of source code must retain the above copyright michael@0: // notice, this list of conditions and the following disclaimer. michael@0: // * Redistributions in binary form must reproduce the above michael@0: // copyright notice, this list of conditions and the following disclaimer michael@0: // in the documentation and/or other materials provided with the michael@0: // distribution. michael@0: // * Neither the name of Google Inc. nor the names of its michael@0: // contributors may be used to endorse or promote products derived from michael@0: // this software without specific prior written permission. michael@0: // michael@0: // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS michael@0: // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT michael@0: // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR michael@0: // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT michael@0: // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, michael@0: // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT michael@0: // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, michael@0: // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY michael@0: // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT michael@0: // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE michael@0: // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. michael@0: // michael@0: // Author: vladl@google.com (Vlad Losev) michael@0: michael@0: // This sample shows how to use Google Test listener API to implement michael@0: // a primitive leak checker. michael@0: michael@0: #include michael@0: #include michael@0: michael@0: #include "gtest/gtest.h" michael@0: michael@0: using ::testing::EmptyTestEventListener; michael@0: using ::testing::InitGoogleTest; michael@0: using ::testing::Test; michael@0: using ::testing::TestCase; michael@0: using ::testing::TestEventListeners; michael@0: using ::testing::TestInfo; michael@0: using ::testing::TestPartResult; michael@0: using ::testing::UnitTest; michael@0: michael@0: namespace { michael@0: michael@0: // We will track memory used by this class. michael@0: class Water { michael@0: public: michael@0: // Normal Water declarations go here. michael@0: michael@0: // operator new and operator delete help us control water allocation. michael@0: void* operator new(size_t allocation_size) { michael@0: allocated_++; michael@0: return malloc(allocation_size); michael@0: } michael@0: michael@0: void operator delete(void* block, size_t /* allocation_size */) { michael@0: allocated_--; michael@0: free(block); michael@0: } michael@0: michael@0: static int allocated() { return allocated_; } michael@0: michael@0: private: michael@0: static int allocated_; michael@0: }; michael@0: michael@0: int Water::allocated_ = 0; michael@0: michael@0: // This event listener monitors how many Water objects are created and michael@0: // destroyed by each test, and reports a failure if a test leaks some Water michael@0: // objects. It does this by comparing the number of live Water objects at michael@0: // the beginning of a test and at the end of a test. michael@0: class LeakChecker : public EmptyTestEventListener { michael@0: private: michael@0: // Called before a test starts. michael@0: virtual void OnTestStart(const TestInfo& /* test_info */) { michael@0: initially_allocated_ = Water::allocated(); michael@0: } michael@0: michael@0: // Called after a test ends. michael@0: virtual void OnTestEnd(const TestInfo& /* test_info */) { michael@0: int difference = Water::allocated() - initially_allocated_; michael@0: michael@0: // You can generate a failure in any event handler except michael@0: // OnTestPartResult. Just use an appropriate Google Test assertion to do michael@0: // it. michael@0: EXPECT_LE(difference, 0) << "Leaked " << difference << " unit(s) of Water!"; michael@0: } michael@0: michael@0: int initially_allocated_; michael@0: }; michael@0: michael@0: TEST(ListenersTest, DoesNotLeak) { michael@0: Water* water = new Water; michael@0: delete water; michael@0: } michael@0: michael@0: // This should fail when the --check_for_leaks command line flag is michael@0: // specified. michael@0: TEST(ListenersTest, LeaksWater) { michael@0: Water* water = new Water; michael@0: EXPECT_TRUE(water != NULL); michael@0: } michael@0: michael@0: } // namespace michael@0: michael@0: int main(int argc, char **argv) { michael@0: InitGoogleTest(&argc, argv); michael@0: michael@0: bool check_for_leaks = false; michael@0: if (argc > 1 && strcmp(argv[1], "--check_for_leaks") == 0 ) michael@0: check_for_leaks = true; michael@0: else michael@0: printf("%s\n", "Run this program with --check_for_leaks to enable " michael@0: "custom leak checking in the tests."); michael@0: michael@0: // If we are given the --check_for_leaks command line flag, installs the michael@0: // leak checker. michael@0: if (check_for_leaks) { michael@0: TestEventListeners& listeners = UnitTest::GetInstance()->listeners(); michael@0: michael@0: // Adds the leak checker to the end of the test event listener list, michael@0: // after the default text output printer and the default XML report michael@0: // generator. michael@0: // michael@0: // The order is important - it ensures that failures generated in the michael@0: // leak checker's OnTestEnd() method are processed by the text and XML michael@0: // printers *before* their OnTestEnd() methods are called, such that michael@0: // they are attributed to the right test. Remember that a listener michael@0: // receives an OnXyzStart event *after* listeners preceding it in the michael@0: // list received that event, and receives an OnXyzEnd event *before* michael@0: // listeners preceding it. michael@0: // michael@0: // We don't need to worry about deleting the new listener later, as michael@0: // Google Test will do it. michael@0: listeners.Append(new LeakChecker); michael@0: } michael@0: return RUN_ALL_TESTS(); michael@0: }