Heap/leak checking googletest tests

Leak checking is part of good programming practice (as leaked objects normally point to bugs in general). Symbian has its leak checking macros, but they aren’t completely trivial to use with Googletest (googletest has been designed with a whole-program reachability-based leak checker in mind, like OS X’s ‘leaks’) – googletest itself allocates memory in some cases.

The easiest way to add Symbian-style leak checking is to use a test fixture. Just add an instance of HeapChecker as the first member of your test fixture. HeapChecker looks like:

Header:

#ifndef TESTING_PUBLIC_HEAPCHECK_H_INCLUDED_
#define TESTING_PUBLIC_HEAPCHECK_H_INCLUDED_

#include "third_party/googletest/include/gtest/gtest.h"

// HeapChecker is a scoped object that checks whether any memory has been
// leaked over its lifetime. It is used together with googletest test fixtures:
// it checks whether the test had any failures which cause allocations and
// in that case doesn't do the checking. It is meant to be held as
// the first member of a test fixture.
class HeapChecker {
 public:
  HeapChecker(testing::Test* test);
  ~HeapChecker();

 private:
  testing::Test* test_;
  int alloc_count_;
};

Code:

#include "testing/public/heapcheck.h"

#include <e32std.h>
#include <ecom/ecom.h>

#include "third_party/googletest/include/gtest/gtest.h"

namespace {
bool any_failures = false;
}

HeapChecker::HeapChecker(testing::Test* test) : test_(test) {
  if (any_failures) return;
  User::__DbgMarkStart(EFalse /* aKernel */);
  alloc_count_ = User::Heap().Count();
}

HeapChecker::~HeapChecker() {
  REComSession::FinalClose();
  if (any_failures) return;
  TInt ignore_alloc_count = 0;
  if (test_->HasFailure()) {
    ignore_alloc_count = User::Heap().Count() - alloc_count_;
  }
  User::__DbgMarkEnd(EFalse /* aKernel */, ignore_alloc_count);
  if (test_->HasFailure()) {
    any_failures = true;
  }
}

Using a base test fixture for all your tests is good practice, as it’s the best way to insert custom checks – the actual test runner in Googletest doesn’t have (enough) hooks.

This entry was posted in Symbian. Bookmark the permalink.

3 Responses to Heap/leak checking googletest tests

  1. Zhanyong Wan says:

    Hi Mika,

    Have you tried googletest’s event listener API (http://code.google.com/p/googletest/wiki/GoogleTestAdvancedGuide#Extending_Google_Test_by_Handling_Test_Events)? It’s meant to provide hooks for implementing custom leak checkers, etc. http://code.google.com/p/googletest/source/browse/trunk/samples/sample10_unittest.cc is an example.

  2. Morten V. Pedersen says:

    Hi Mika and Zhanyong,
    I tried the event listner api – seems to work (first class called TLeakChecker):
    http://mobdevtrac.es.aau.dk/symbian-util/browser/trunk/util_gtest/source/util_gtest.h

    Mika, one question I tried to use the same approach as you did – however I had some problems with the User::__DbgXX functions. So I tried to only use the User::Heap().Count() and it seems to catch all allocations – is there some reason to use the User::__Dbg that I’m not aware of?

    Br, Morten

  3. Mika says:

    Hah, serves me right for not keeping up-to-date. The first time I was thinking about this the event listener interface didn’t exist yet. Will take a look. Thanks Wan.