Search code examples
c++exceptionmemory-leaksvalgrindgoogletest

How to free up a resource used by a function in a googletest ASSERT_THROW statement?


In googletest you can use ASSERT_THROW to test that a certain function throws an error. For instance

ASSERT_THROW(PhysicalPropertyResource p("other/identifier72652"), InappropriateResourceException);

How would you explicitely call another method for releasing some memory used by PhysicalPropertyResource? Normally used like so:

PhysicalPropertyResource p("other/identifier72652");
p.free();

Or should I just not worry about the memory leak since its only in a test and therefore benign. (Its just my OCD to want to keep valgrind completly happy).

I've tried this:

    ASSERT_THROW(
            PhysicalPropertyResource p("other/identifier72652");
            p.free();
            , InappropriateResourceException);

}

which doesn't free the memory.


Solution

  • The proper syntax for executing multiple instructions would to wrap them in a block:

    ASSERT_THROW({PhysicalPropertyResource p("other/identifier72652");
                  p.free();}, 
                InappropriateResourceException);
    

    However, this won't help it's not the last line that throws, because then p.free() will not be called. You could create your own "assertion"

    void shouldThrow() {
        std::unique_ptr<PhysicalPropertyResource> p;
        try {
            p = std::make_unique<PhysicalPropertyResource>("other/identifier72652");
        } catch (const InappropriateResourceException&) {
            if (p) //note that this is not possible if it is really constructor that throws
                p->free(); 
            return; //test succeeded
        } catch (...) {
            if (p)
                p->free();
            FAIL();
        }
    
        if (p)
            p->free;
        FAIL();
    }
    

    Note: If you are writing C++ code that uses C library, then your best solution is creation of a RAII wrapper that will take care of resources. If you create a wrapper class, it can free resources in destructor and you will never leak them. You can even write such wrapper for unit tests only, just to avoid this ugly assertion-like code.