unit testingC库,内存管理
我正在开发一个相当大的C库,现在没有任何测试。 由于API开始是最终的,我想开始编写unit testing。
几乎所有的函数都作用于第一个参数(一个结构)。
unit testing的朴素方法是使预函数调用结构处于已知状态,调用函数,然后将预调用结构与预期结果进行比较。
现在这适用于由标量类型组成的结构,但至于分配的内存,我想知道你正在使用什么样的方法。
例如,想象一下图像结构,当你这样做时:
CreateImage(&img, x, y);
你希望img-> x是x,img-> y是y而img->像素是一个指向大到足以容纳x * y * sizeof(pixel)
东西的指针。
检查前两个是微不足道的,但img->像素怎么样? 我不是要检查malloc调用是否成功,因为我可以重载 malloc,但我想知道malloc是否被正确调用。
在以下情况下,这一点尤为重要:
CreateImage(*img, x, y) { img->x = x; img->y = y; /* do something, dhoo, that something is broken and modify x or y */ img->pixels = malloc(x * y * sizeof(pixel)); /* wrong allocation size */ if(!img->pixels) error("no memory"); }
我希望我的问题很清楚。
谢谢。
在unit testing中,让重载的malloc
函数记录调用它的值(例如alloc_size
)。
然后测试所有这些都是真的:
-
alloc_size % sizeof(pixel) == 0
-
alloc_size % x == 0
-
alloc_size % y == 0
-
((alloc_size / sizeof(pixel)) / x ) / y == 1
不要只是复制你正在测试的函数的代码 – 即。 乘法 – 因为你最终可能会复制一个bug。
在这种情况下,您可能会复制一个错误 – 如果没有对x
和y
边界测试,那么malloc
调用中的乘法本身就是错误的(考虑在32位size_t
, sizeof(pixel) == 4
的系统上会发生什么情况sizeof(pixel) == 4
, x == 40000
和y == 40000
)。
您可以重载malloc以便为其设置许多期望。 既然你在打电话之前知道它需要分配多少内存,你就可以做出类似的事情。
SetMallocExpectation(x * y * sizeof(pixel)); CreateImage(&img, x, y); if ( InvalidMalloc() ) { // The malloc call was with a different size } ResetMalloc();
至于实现,我认为它看起来像这样
size_t mallocExpectations[SOME_SIZE]; int mallocCur = 0; int mallocError = 0; int numExpectations = 0; void* MyMalloc(size_t size) { if ( size != mallocExpectations[mallocCur++] ) { mallocError = 1; } return (*malloc)(size); } void SetMallocExpectation(size_t size) { mallocExpectations[numExpectations++] = size; } int InvalidMalloc() { return mallocError; } void ResetMalloc() { mallocCur = 0; mallocError = 0; curExpecations = 0; }
另一个想法是尝试将malloc
创建的缓冲区填充到最大大小,然后使用Valgrind运行测试套件。 这应该是表面分配问题。 使用Valgrind运行它也有助于其他事情,例如检测内存泄漏。