如何在这个malloc包装上跟踪TDD测试失败?

时间:2012-09-20 09:56:18

标签: c testing tdd malloc

我正在尝试使用TDD和C.我想按照TDD方法编写一个简单的malloc包装器。我正试图遵循Bob Martin的TDD三法则

  1. 除非要通过失败的单元测试,否则不要编写生产代码。
  2. 不要写更多的单元测试而不是足以失败,并且构建失败就是失败。
  3. 不要写出足以通过一次失败的单元测试的生产代码。
  4. 到目前为止,这是我的代码:

        J_STATUS MemAlloc(long Size, void **OutPtr) {
            J_STATUS ReturnStatus;
            void *Ptr;
    
            Ptr = NULL;
    
            if (Size >= 0) {
                Ptr = malloc(Size);
                *OutPtr = Ptr;
                ReturnStatus = SUCCESS;
                //TODO controllare malloc error
            } else {
                ReturnStatus = ERROR;
            }
            return ReturnStatus;
        }
    

    这些是我的测试(我正在使用Unity测试框架):

        #include "../unity/unity.h"
        #include "../src/jMem.h"
        #include "stdlib.h"
    
        static int *ptr;
        static J_STATUS Result;
        static long Size;
        static long Count;
    
        void setUp() {
            ptr = NULL;
            Size = 10;
            Count = 5;
        }
    
        void tearDown() {
            if (ptr != NULL) {
                free(ptr);
            }
        }
    
        void test_MemAllocShouldAllocateMemoryAndReturnSuccess(void) {
            Result = MemAlloc(Size, (void **) &ptr);
            TEST_ASSERT_EQUAL(SUCCESS, Result);
            TEST_ASSERT_NOT_NULL(ptr);
    
        }
    
        void test_MemAllocShouldReturnErrorIfSizeIsNegative(void) {
            Size = -4;
    
            Result = MemAlloc(Size, (void **) &ptr);
    
            TEST_ASSERT_EQUAL(ERROR, Result);
        }
    

    现在我如何为失败的malloc编写测试?我知道我可以链接一个不同版本的malloc,或者我可以编写一个宏来使malloc失败,但这应该只适用于这个测试,而在另一个我想使用真正的malloc。

    有什么想法吗? 谢谢

3 个答案:

答案 0 :(得分:1)

也许这是一个你不需要测试的边缘情况。只需编写代码即可。 : - )

另一方面,由于我们都喜欢练习良好的TDD,另一种选择是将malloc调用提升为函数参数。作为函数指针,您可以在一次测试中传递常规malloc的地址,在错误测试用例中传递malloc_that_errors的地址。

请注意,它会污染您的包装器的界面,我个人不喜欢它。它打破了你想要的抽象,我讨厌在任何地方传递malloc。鉴于此,我会回去不测试它。 :-D

希望有所帮助!

布兰登

答案 1 :(得分:0)

当malloc包装器使用long而不是size_t作为size参数时,它不是很有说服力。

您应该能够通过分配大量内存使其失败,使用size_t并找到最大值。大多数真正的malloc()都不会成功分配,因此它们会失败。

当然,这仍然是让它失败的一种相当假的方式,我想唯一合适的方法是提供钩子,这样你就可以替换不同的malloc()

答案 2 :(得分:0)

老问题,但我觉得,根据你的编译器,有一个答案缺失。 GNU LD有一个--wrap symbol选项,允许您在链接时覆盖某些函数。

void *
__wrap_malloc (int c)
{
  printf ("malloc called with %ld\n", c);
  return __real_malloc (c);
}

与此代码一样,对malloc的每次调用都会被调用__wrap_malloc替换,如果您想调用真正的malloc,则可通过__real_malloc获取。

此功能可能适用于其他连接器,我也不知道,但对于GCC来说,这是一个不错的选择。