我正在尝试使用TDD和C.我想按照TDD方法编写一个简单的malloc包装器。我正试图遵循Bob Martin的TDD三法则
到目前为止,这是我的代码:
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。
有什么想法吗? 谢谢
答案 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来说,这是一个不错的选择。