测试构造函数初始化列表

时间:2012-10-25 07:51:35

标签: c++ unit-testing

我正在进行一项测试,检查是否在构造函数中初始化了所有类属性。 我当前的解决方案适用于非指针属性:

void CSplitVectorTest::TestConstructorInitialization()
{
    const size_t memorySize = sizeof(CSplitVector);
    char* pBuffer1 = (char*) malloc(memorySize);
    char* pBuffer2 = (char*) malloc(memorySize);
    memset(pBuffer1,'?',memorySize);
    memset(pBuffer2,'-',memorySize);
    new(pBuffer1) CSplitVector;
    new(pBuffer2) CSplitVector;
    const bool bObjectsAreEqual = memcmp(pBuffer1,pBuffer2,memorySize)==0;
    if (!TEST(bObjectsAreEqual))
    {
        COMMENT("Constructor initialization list not complete!");
    }
    free(pBuffer1);
    free(pBuffer2);
}

您是否知道如何测试指针是否已初始化?

3 个答案:

答案 0 :(得分:0)

您的测试检查构造函数是否已写入对象的每个字节。作为直接内存检查,它看起来没问题,但如果该类包含其他不必完全初始化的对象,则可能会遇到麻烦。

那就是说,我的主要问题是:它真的是一个有效的测试吗?例如,CSplitVector类中的每个属性是否都由初始化列表初始化是至关重要的?你或许有一些可能不需要在这一点初始化?另外,如何检查属性是否设置为您期望的值?

答案 1 :(得分:0)

您可能应该使用正确的填充或字大小,而不是逐字节进行比较,并测试每个字的任何字节是否已初始化。这样你就可以使用填充和构造函数绕过编译器,在填充的短于字的字段之间留下未初始化的字节。

为了测试真正的填充大小,从臀部拍摄,下面的代码应该非常可靠地完成:

struct PaddingTest {
  volatile char c; // volatile probably not needed, but will not hurt either
  volatile int i;

  static int getCharPadding() { 
    PaddingTest *t = new PaddingTest;
    int diff = (int)(&(t->i)) - (int)&((t->c));
    delete t;
    return diff;
  }
}

编辑:您仍然需要这两个对象,但是您不再将它们与其他对象进行比较,您只需将每个初始化数据与memset值进行比较,如果任一对象有任何更改,则表示该单词被触摸(同样在另一个,它只是被初始化为你设置的相同值的机会。

答案 2 :(得分:0)

我找到了上述问题的解决方案,使用初始化/未初始化的指针和不同长度类型对其进行了测试。

在测试标题中,我添加了#pragma pack(1)(我正在使用gcc)

#pragma pack(1)
#include <CSplitVector>

测试有点复杂:

void CSplitVectorTest::TestConstructorInitialization()
{
    const size_t memorySize = sizeof(CSplitVector);
    char* pBuffer = (char*) malloc(memorySize);
    memset(pBuffer,'?',memorySize);
    CSplitVector* pSplitVector = new(pBuffer) CSplitVector;

    // find pointers for all '?'
    QList<char*> aFound;
    char* pFoundChar = (char*) memchr(pBuffer,'?',memorySize);
    while (pFoundChar)
    {
        aFound.append(pFoundChar);
        char* pStartFrom = pFoundChar+1;
        pFoundChar = (char*) memchr(pStartFrom,'?',memorySize-(int)(pStartFrom-pBuffer));
    }
    // if there are any '?'....
    if (aFound.count())
    {
        // allocate the same area with '-'...
        pSplitVector->~CSplitVector();
        memset(pBuffer,'-',memorySize);
        pSplitVector = new(pBuffer) CSplitVector;
        // and check if places found before contain '-'
        while (aFound.count())
        {
            pFoundChar = aFound.takeFirst();
            if (*pFoundChar=='-')
            {
                // if yes then class has uninitialized attribute
                TEST_FAILED("Constructor initialization list not complete!");
                pSplitVector->~CSplitVector();
                free(pBuffer);
                return;
            }
        }
    }
    // if no then all attributes are initialized
    pSplitVector->~CSplitVector();
    free(pBuffer);
    TEST(true);
}

随意指出此解决方案中的任何缺陷。