Content

Not quite a Yegge long.

Mock Objects for C++, Part 1

Tuesday 4 November 2008 - Filed under Code

Executive summary: First part of a series (with source code) on automatically creating mock objects against interfaces in C++.

Get the library here (works with Visual C++ 2005/2008). This has been tested and used successfully in a project for one of my clients.

If you’re curious as to how this works, I’ll explain over the course of the next few posts. Part 1: Fundamentals of Virtual Function Table Hacking.

It’s no secret that I like testing. Quite a bit. Unfortunately, I don’t write nearly enough tests, because the overhead of building fake versions of all the collaborating objects is too great.

Some time ago, I ran across JMock/EasyMock/NMock, and suddenly things got a whole lot easier. Being able to cook up a fake implementation of an interface in a single line is pretty cool. It would be even cooler if we could do that in C++, right?

But then, C++ isn’t exactly designed for clever reflective magic. You can’t iterate over the methods (and their signatures) on an interface at runtime. You can’t do it at compile time either, despite having a supposedly-Turing-complete mechanism for compile-time evaluation. Having all that power at your fingertips isn’t worth a damn if you can’t have the compiler give you the data you need. So, best you can do is to define some preprocessor magic and a pile of templates that you can use to quickly build a fake version of an object, right? Not so fast. I’ve got a better plan, which I will explain the inner workings of, over the next few posts.

As you may know, there’s not really any magic to what actually happens with virtual function calls in C++. For each class, the compiler emits a table of function pointers. Each object of that class then gets a pointer to the virtual function table as its first member. Derived classes have a copy of that table with the same layout, but where a function is overridden, the function pointer gets replaced. Then when you actually invoke a virtual function, the compiler emits a call through the virtual function table.

Now, assuming we’re trying to mock a pure virtual class ("interface"), what is the compiler going to assume exists? An object whose first 4 bytes are a pointer to a table of virtual functions. Nothing more.

So let’s build an object that looks like that, but gives us complete control, on a per-object basis, over what functions exist at which indices:

class _declspec(novtable) PerObjectVtable
{
    void ** vt;    // must be first member
    void * functions[ MAX_VTABLE_SLOTS ];

public:
    PerObjectVtable() { vt = functions; }
};

template< typename I >
I * CreateMock() 
{
    return (I*) new PerObjectVtable();
}

Now if you put pointers to functions of the appropriate types in the array, you get polymorphism at object- rather than class-granularity. This is an important capability, since we’re going to have to mutate the vtable at runtime, when we "discover" method signatures.

And that brings us to the end of the first part of the problem. In Part 2, we’ll look at recovering vtable indices from function pointers, for classes that don’t really exist.

Part 3 will cover expectations, and how we can covertly extract method signatures from them.

See you next time!

2008-11-04  »  admin

Talkback x 3

  1. Chris on Software » Blog Archive » Mock Objects for C++, Part 2
    4 November 2008 @ 7:40 pm

    [...] Chris on Software Not quite a Yegge long. « Mock Objects for C++, Part 1 [...]

  2. Chris on Software » Blog Archive » Mock Objects for C++, Part 3
    4 November 2008 @ 8:28 pm

    [...] In Part 1, we made fake vtables, which we could manipulate however we pleased, and callers were none the wiser. [...]

  3. Lars
    6 November 2008 @ 2:30 am

    Smart! I can’t wait for the rest!

Share your thoughts

Re: Mock Objects for C++, Part 1







Tags you can use (optional):
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>