question on c++ / TEST_GROUP / var scope

636 views
Skip to first unread message

Davis Ford

unread,
Oct 16, 2012, 10:10:57 AM10/16/12
to cppu...@googlegroups.com
Full disclosure, my c++ is very old / rusty, so I'm sure this is a simple question, and a matter of my ignorance, but hopefully this question is quickly answered by someone with more c++-fu than I

I have my own MockNamedValueComparator declared in my test file...e.g.

class MyComparator : public MockNamedValueComparator
   private:
      int len;
   public:
     MyComparator(int len) {
         this.len = len;
     }
    // etc.
}

and then in my setup() I want to reset it each time - this is b/c the int length is passed into the constructor and I use that in my isEqual implementation.  For most of the test cases, the length variable is the same, but for some I need to set it explicitly...so I tried

So I tried this:

TEST_GROUP(MyGroup) 
{
    MyComparator comparator = NULL;

    void setup()
    {
        // usually the length is 3, so each test case can assume that
        MyComparator comparator = MyComparator(3);
    }
    void teardown()
    {
        mock().checkExpectations();
        mock().removeAllComparators();
        mock().clear();
    }
}

TEST(MyGroup, Test1)
{
    // implicitly use MyComparator with length 3
    mock().installComparator("MyComparator", comparator);
}

TEST(MyGroup, Test2)
{
   // explicitly set my own with different length
   comparator = MyComparator(10);
   mock().installComparator("MyComparator", comparator);
}

On Mac OS with clang, this works ok, but I get the warning:

warning: in-class initialization of non-static data member is a C++11 extension [-Wc++11-extensions]

..and the tests work ok.

On Linux, it won't compile.

error: ISO C++ forbids initialization of member ‘comparator’ [-fpermissive]
error: making ‘comparator’ static [-fpermissive]
error: invalid in-class initialization of static data member of non-integral type ‘MyComparator’

It looks like I can fix it by adding -fpermissive flag, but I'd prefer to fix it in the code, if possible.

I tried a few different things, like moving the declaration out of TEST_GROUP itself, e.g.

MyComparator comparator;

TEST_GROUP(MyGroup) { void setup() { comparator = MyComparator(3); }  }

But then my tests start failing, as if the comparator isn't working.

If I explicitly call the constructor in each TEST macro, it works

TEST(FooTest) 
{
   comparator = MyComparator(3);
   mock().installComparator(...)
}

I was simply trying to reduce the lines of code necessary for my tests, but I'm missing something here with respect to c++ / cpputest macros / scope, etc.  I come from java / c background, so my viewpoint is skewed in that respect.

TL;DR: I want to make a per-test global scope variable and re-initialize on each test setup() call -- what am I doing wrong?

Terry Yin

unread,
Oct 16, 2012, 10:34:01 AM10/16/12
to cppu...@googlegroups.com
Hi,

Wow. C++11 is so ... uhm, alien:-) You cannot assign value to member variables in test group.
So in the line
MyComparator comparator = NULL;
You can not do the assignment there. I have 3 options to this problem:
1. Use a pointer instead, and new in setup, delete in teardown.
2. Define it outside the test group as a global. (There seems not reason to reset it each time)
3. Define a default constructor and a copy constructor for comparator.

I will go with option1.

br, Terry
--
-terry
-------------------------
Blog: http://terryyin.blogbus.com/
twitter: http://twitter.com/terryyin


Bas Vodde

unread,
Oct 16, 2012, 8:20:24 PM10/16/12
to cppu...@googlegroups.com

Hi Davis,

This probably relates to the code you had earlier. I'd probably do it quite different.

I'd define a small helper struct, such at:

struct PointerAndLength
{
void* pointer;
int len;
};

Then you want to comparator work on the PointerAndLength type, rather than just on the pointer.

So, the call to ActualCall would change from what you mailed earlier to:

PointerAndLength ptrLen(buf, len);
mock_c()->actualCall("bcm2835_spi_transfern")->withParameterOfType("PointerAndLength", "buf", ptrLen);

Doing it this way, the pointer and length will be passed in your comparator via the ActualCall and you can extract the length from it from there. That way you don't need the len member variable at all anymore in the comparator.

If you do that, then the most common way to register the comparator is in the main and register it on the MockPlugin. That way it will be automatically available for every single TEST_GROUP.

Wiould this make sense?

Thanks!

Bas

Davis Ford

unread,
Oct 17, 2012, 11:29:14 PM10/17/12
to cppu...@googlegroups.com
Thanks Terry / Bas -- makes a lot of sense - thanks for the tips

On Tuesday, October 16, 2012 8:20:24 PM UTC-4, Bas Vodde wrote:

>

Reply all
Reply to author
Forward
0 new messages