3

我试图弄清楚,在 CUnit 中断言数组相等的最佳方法是什么。

我知道的文档根本不包含与数组相关的任何内容。

到目前为止我考虑的可能性:

  • 循环遍历数组元素并使用CU_ASSERT_EQUAL.

  • 只需CU_ASSERT_EQUAL在两个数组上使用。根据提到的文档,这不应该工作,因为CU_ASSERT_EQUAL只是转换为==. 实际上,以下测试会导致失败:

   const uchar arr1[] = {1,2};
   const uchar arr2[] = {1,2};
   CU_ASSERT_EQUAL(arr1, arr2);
  • CU_ASSERT_NSTRING_EQUAL似乎有效,但名称暗示它适用于字符串:
   const uchar arr1[] = {1,2};
   const uchar arr2[] = {1,2};
   CU_ASSERT_NSTRING_EQUAL(arr1, arr2, 2);  /* succeeds: OK */

   const uchar arr1[] = {1,3};
   const uchar arr2[] = {1,2};
   CU_ASSERT_NSTRING_EQUAL(arr1, arr2, 2);  /* fails: OK */

我最倾向于使用CU_ASSERT_NSTRING_EQUAL.

所以问题的问题如下:

  • 除了(稍微)误导的名称之外,该解决方案是否CU_ASSERT_NSTRING_EQUAL有任何缺点?(我知道字符串只是数组,以 . 结尾\0。)
  • 这个问题有更好的解决方案吗?

注意:在我能找到的相关问题/答案中,还建议对元素进行迭代(尽管我不认为这与我的问题重复,因为它没有直接询问检查平等的最佳方法是什么一般的数组)。

4

2 回答 2

3

我得到这个答案有点晚了,但是......

我在与数组相关的文档中也找不到任何内容。这似乎是一个缺失的功能。但是,您可以使用:

CU_ASSERT_EQUAL(0, memcmp(actual, expected, count));

在您的示例中,它将是:

CU_ASSERT_EQUAL(0, memcmp(arr1, arr2, 2));

于 2018-03-21T05:35:06.683 回答
0

为什么要使用字符串比较断言?

忽略名称中有 a 的事实STRING并使用CU_ASSERT_NSTRING_EQUAL(actual, expected, count)。特别是在您的情况下,断言可能是

//Assert that the arrays are the same size.
//If not, they can't have deep equality.
CU_ASSERT_EQUAL(sizeof(arr1), sizeof(arr2));

//Now assert byte-by-byte equality
//for the size of both arrays
CU_ASSERT_NSTRING_EQUAL(arr1, arr2, sizeof(arr1));

查看文档,您可以看到 CU_ASSERT_NSTRING_EQUAL 的语义含义是“断言实际和预期的第一个计数字符相同”。回想一下,achar只是内存中的一个字节。&arr1尽管您将through的字节解释&arr + (1 * sizeof(uchar))为无符号字符,但字符串比较是通过逐个递增字符并检查它们的字节值来完成的。因为CU_ASSERT_STRING_EQUAL(actual, expected)这种情况会一直发生,直到遇到空字节,因为这就是字符串的终止方式。对于CU_ASSERT_NSTRING_EQUAL(actual, expected, count),传递了一个大小,因为您要检查count-bytes,无论是否遇到空字节。数组中的类型可能大于char,但没关系。在下面,它们仍然只是连续位于内存中的固定数量的字节。

请注意,这仅在您可以告诉单元测试框架要检查的对象的大小时才有效。这需要使用 来检查对象sizeof(),或者知道对象的大小并拥有指向该对象的指针(回想一下sizeof(),无论指向的对象的大小如何,指针总是相同的)。对于动态大小的对象,这可能是不可能的。

但是遍历数组仍然有效吗?

也许。但是您需要对每个索引都有一个断言。同样,这仅在您知道编译时数组的大小时才有效(即,其空间由堆获取malloc并位于堆上的数组在编译时将具有未知大小,因此CU_ASSERT_EQUAL断言的 for 循环不会工作)。在您的情况下,这可能是这样的事情

//Assert that the arrays are the same size
//If not, they can't have deep equality.
CU_ASSERT_EQUAL(sizeof(arr1), sizeof(arr2));

//Now assert index-by-index equality
for (size_t i=0; i < sizeof(arr1) / sizeof(uchar); i++)
    CU_ASSERT_EQUAL(arr1[i], arr2[i]);

问题是您的套件很快就会充满大型数组的断言。您不想知道数组中不匹配的每个元素......您想知道数组中的任何元素都不匹配。一旦CU_ASSERT_NSTRING_EQUAL发现不匹配,测试就会失败。这不是CU_ASSERT_EQUAL断言循环的情况。由于 CUnit 断言是作为宏实现的,因此没有要检查的返回值,这样您就可以跳出循环。即使您进行了单独的非断言比较,您仍然会留下在第一个非匹配索引之前完成的断言的踪迹。

于 2017-09-25T17:37:41.353 回答