检查是否正确释放了一个gobject

San*_*nti 2 unit-testing gobject glib

我正在使用glib的测试框架进行单元测试.我的库也使用了gobject,在我的测试unities中我想检查在每个对象的最后一次_unref之后是否正确释放了对象.当g_test_trap_fork可用时,我在每次_unref之后使用它,第二次调用_unref,然后检查g_test_trap_assert_failed().

但是,现在g_test_trap_fork正在被弃用,我正朝着g_test_trap_subprocess迈进.问题是现在我必须为每个要检查的_unref编写一个单独的测试用例,因为每个case都可以包含几个对象,这些对象意味着每个测试用例的重复,为每个已经存在的测试用例添加第二个_unref.

例如,我试图像这样修复:

NcmVector *v = test->v;
GVariant *var = ncm_vector_get_variant (v);

g_assert (!g_variant_is_floating (var));
g_assert (g_variant_is_container (var));
g_assert_cmpuint (ncm_vector_len (v), ==, g_variant_n_children (var));

{
  NcmVector *nv = ncm_vector_new_variant (var);
  gint i;

  g_assert_cmpuint (ncm_vector_len (v), ==, ncm_vector_len (nv));
  for (i = 0; i < ncm_vector_len (v); i++)
  {
    ncm_assert_cmpdouble (ncm_vector_get (v, i), ==, ncm_vector_get (nv, i));
  }

  ncm_vector_free (nv);
  NCM_TEST_FAIL (ncm_vector_free (nv));
}

g_variant_unref (var);
NCM_TEST_FAIL (g_variant_unref (var); fprintf (stderr, "fail (%s)", g_variant_get_type_string (var)));
Run Code Online (Sandbox Code Playgroud)

宏NCM_TEST_FAIL由下式给出:

#define NCM_TEST_FAIL(cmd) \
G_STMT_START { \
  if (g_test_subprocess ()) \
  { \
    cmd; \
    exit (0); \
  } \
  else \
  { \
    g_test_trap_subprocess (NULL, 0, 0); \
    g_test_trap_assert_failed (); \
  } \
} G_STMT_END
Run Code Online (Sandbox Code Playgroud)

该解决方案的问题在于它只能在每个测试用例中使用一次.如果第二次使用,如上例所示,它只会测试g_test_subprocess()的第一次出现.

我考虑在gobject结构内部检查引用计数,就在最后一个_unref之前检查它是否是== 1.但是这将涉及访问该结构的私有部分,如果可能的话我会避免.

有关如何在同一测试用例中多次检查错误代码的任何想法?

eba*_*ssi 7

如果您需要检查GObject是否正确处置,您可以使用g_object_add_weak_pointer(),例如:

FooObject *o = g_object_new (foo_object_get_type (), NULL);

g_assert_nonnull (o);

// the contents of the pointer are reset to NULL when the last reference to
// the GObject instance goes away; by passing a pointer to the same instance
// we can check it for NULL later
g_object_add_weak_pointer (G_OBJECT (o), (gpointer *) &o);

// ...test FooObject...

// drop the last reference
g_object_unref (o);

// at this point, the object should be NULL if nothing is holding
// an additional reference.
g_assert_null (o);
Run Code Online (Sandbox Code Playgroud)

但是,在上面的例子中,你正在使用GVariant,它不是a GObject,因此它没有弱引用.

由于二进制兼容性原因,GLib没有共同的引用计数类型; 引用计数类型的所有公共代码都在GObject.