[amop-group] How to use amop for non pure virtual classes

33 views
Skip to first unread message

gbollani

unread,
Apr 20, 2010, 6:08:33 PM4/20/10
to amop group
Hi all,
I have some suggestion on using amop for non pure virtual classes:

Usually the class MockObject<T> is used as virtual table of an
interface class.
Now Consider a class with some attributes, virtual methods and
methods not virtual

It's possible to mock a class T by replacing the owned virtual table
with the pseudo virtual table of the class of MockObject < T >

Consider the class:

class TrueClass {
private:
int val;
public:
TrueClass() { val=5; }
virtual int F1() { return 1; }
virtual int F2(){ return 2; }
int Sum_F1_F2() { return (F1() + F2()); }
int Sum_F1_F2_val() { return (F1() + F2() + val); }
};

Replacing the virtual table of TrueClass with the pseudo VT of
MockObject < TrueClass >
We can Test Sum_F1_F2() and Sum_F1_F2_val() using the Mocked F1() and
F2() Methods

For example:

TEST(Associated)
{
MockObject<TrueClass> myMock;
TrueClass myTrueClass;

// Substitution of TrueClass VT with the PVT of MockObject<TrueClass>
void* vptr = &myClass;
int* obj_start = reinterpret_cast<int*>(&myTrueClass);
*(obj_start) = *(reinterpret_cast<int*>(vptr));
//

// Mocking F1 and F1
myMock.everyCall(&TrueClass::F1).returning(10);
myMock.everyCall(&TrueClass::F2).returning(11);

CHECK_EQUAL(1, myTrueClass.F1()); // Call True Method
TrueClass* ptrClass = &myTrueClass;
CHECK_EQUAL(10, ptrClass->F1()); // Call Mock Method

CHECK_EQUAL(2, myTrueClass.F2()); // Call True Method
CHECK_EQUAL(11, ptrClass->F2()); // Call Mock Method

CHECK_EQUAL(21, myTrueClass.Sum_F1_F2());
// Use Mocked F1() and F2() instead of True F1 and F2

CHECK_EQUAL(26, myTrueClass.Sum_F1_F2_val());
// Use Mocked F1() and F2() instead of True F1 and F2
}

You is able besides, to use a class to encapsulate the substitution of
the
virtual table of the class T with the virtual Table associated to
MockObject < T >

template <class T> class LinkObjToMock {
public:
LinkObjToMock(T& _obj, MockObject<T>& _mock)
{
void* vptr = &(*_mock);
int* obj_start = reinterpret_cast<int*>(&_obj);
vtObj = (*(obj_start));

*(obj_start) = *(reinterpret_cast<int*>(vptr));
obj = &_obj;
}
~LinkObjToMock()
{
int* obj_start = reinterpret_cast<int*>(obj);
*(obj_start) = vtObj;
}
private:
int vtObj;
T* obj;
};


The code of test becomes...

TEST(Associated)
{
MockObject<TrueClass> myMock;
TrueClass myTrueClass;

LinkObjToMock<TrueClass> link(myTrueClass, myMock);


myMock.everyCall(&TrueClass::F1).returning(10);
...

}


Besides it is possible to use some macros to define
in phase of test as virtual all the methods of a class

#ifdef __INSIDE_UNIT_TEST__
#define VT_METHOD virtual
#else
#define VT_METHOD
#endif

class TrueClass {
...
virtual int F1();
virtual int F2();
VT_METHOD int F3();
VT_METHOD int F4();
...
};

Using these suggestions i have easily developed some projects with the
TDD method using Amop for all the classes

Please give me some feedback's to these suggestions

thanks

--
You received this message because you are subscribed to the Google Groups "amop group" group.
To post to this group, send email to amop-...@googlegroups.com.
To unsubscribe from this group, send email to amop-group+...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/amop-group?hl=en.

Kirk Korver

unread,
Apr 20, 2010, 6:30:18 PM4/20/10
to amop-...@googlegroups.com
This does work, but there is extreme weirdness that will happen.
Very short answer: Do not do it

Long Winded Answer:
Think for a moment about the variables of your class, such as 'val' in your
class below?
The compiler has been tricked into believing that an instance of your
TrueClass has been properly instantiated? But has it? The answer is no.

A valid instance was not created. A 'vtable' has been properly created, and
that is all. Very, very likely the memory that exists by the 'val' variable
is owned by the process, so the operating system will not complain about
memory access. When you start accessing the variable val, now you are
writing into memory owned by your processs, but not actually belonging to
the class. In other words, you are stomping on random memory that exists
inside of your program. What is this memory actually doing? Your guess is as
good as mine.

Now if you ONLY access the virtual functions, and you NEVER touch any of
your variables, you can get away with this trick, but it is too easy to
forget and then access a variable. Once you do this, you have 'randomly
occurring memory bug'. Certainly a difficult problem to debug.

Hope this helps.
--Kirk
> group+un...@googlegroups.com.

g.bo...@libero.it

unread,
Apr 21, 2010, 1:57:19 AM4/21/10
to amop-group
Thanks for your answer
I try to better explain what i really want to say:
In the reported example instead of using only the mocked virtual table
without instantiate the real class, i instatiated the real class calling the implementeted constructor
see the line:
TrueClass myTrueClass;
and then i replaced the real virtual table of it with the virtual table of MockObject<TrueClass>
sse the lines:
// Substitution of TrueClass VT with the PVT of
MockObject<TrueClass>
void* vptr = &myClass;
int* obj_start = reinterpret_cast<int*>(&myTrueClass);
*(obj_start) = *(reinterpret_cast<int*>(vptr));
//
Obviously this is a tricky but it works fine for
effective instantiated class
thanks

---------- Initial Header -----------

From : amop-...@googlegroups.com
To : amop-...@googlegroups.com
Cc :
Date : Tue, 20 Apr 2010 15:30:18 -0700
Subject : RE: [amop-group] How to use amop for non pure virtual classes
Reply all
Reply to author
Forward
0 new messages