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。

在这种情况下,您可能会复制一个错误 – 如果没有对xy边界测试,那么malloc调用中的乘法本身就是错误的(考虑在32位size_tsizeof(pixel) == 4的系统上会发生什么情况sizeof(pixel) == 4x == 40000y == 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运行它也有助于其他事情,例如检测内存泄漏。