桩函数 API 为简单类型值提供开箱即用的支持。高级用户可以扩展桩函数 API 以建立对选定复杂类型的专用支持。此过程在使用复杂类型的高级方法中进行了描述。然而,在许多情况下,使用复杂类型的基本方法,与桩函数主体的 helper 命名参数一起使用,就足够了。下面给出了这种方法的一个示例。

处理复杂类型的基本方法

考虑以下结构定义:

struct Point { 
          int _x;
          int _y;

};

桩函数是为以下函数声明创建的:

Point movePoint(Point line, int xoff, int yoff);

如果需要修改函数返回值,则必须对存根主体进行以下修改:

  1. 应该为每个要修改的成员引入 Helper 变量
  2. 变量应该公开以供外部修改(通过测试用例代码)
  3. 修改后的值应重新分配回原始返回值

 

Point CppTest_Stub_movePoint (Point point)
{
   Point __return = Point();
   int __callOrig = 0;
   int __point_x = __return._x; /* [1] helper variable for complex type member */    
   int __point_y = __return._y; /* [1] helper variable for complex type member */
   CPPTEST_ACTUAL_CALL("movePoint").WithArg("point", &point).
     WithArg("__return", &__return)).WithArg("__callOrig", ByRef(__callOrig)). 
     /* [2] expose variable for external modification */
     WithArg("__point_x", ByRef(__point_x)).
     /* [b] expose variable for external modification */
     WithArg("__point_y", ByRef(__point_y)).
     End();
   __return._x = __point_x; /* [3] update return value with modified value */
   __return._y = __point_y; /* [3] update return value with modified value */ 
   if (__callOrig) {
      Point __return = movePoint(point); 
      CPPTEST_ACTUAL_AFTER_CALL("movePoint").
         WithArg("point", &point).WithArg("__return", &__return)).
         WithArg("__callOrig", ByRef(__callOrig)).End();
      return __return;
   }
   return __return;
}

 

然后,在测试用例内部可以修改返回值,如下所示:

CPPTEST_ON_CALL("movePoint").Arg("__point_x").Assign(1).
Arg("__point_y").Assign(2);

处理复杂类型的高级方法

将复杂类型与桩函数 API 一起使用需要编写额外的特定于类型的 helper 程序代码,以便于访问复杂类型的数据成员。提供此附加类型特定实用程序代码后,您可以使用基本桩函数 API 中的函数访问复杂类型字段。

为了说明这个概念,假设以下结构定义:

struct Point {
          int _x;
          int _y;
};
struct Line {
         Point _p1;
         Point _p2;
};

桩函数是为以下函数声明创建的:

Line moveLine(Line line, int xoff, int yoff);

在此示例中,目标是按照以下构造为复杂类型参数和参数启用桩函数行为配置:

CPPTEST_ON_CALL("moveLine").Arg("__return").Field("_p1").Field("_x").Assign(0);
CPPTEST_ON_CALL("moveLine").Arg("__line").Field("_p2").Field("_y").Assign(12);

为了实现上述目标,必须将以下代码添加到定义 moveLine() 函数桩函数的源文件中。
 

/**
  * Field access function for Point structure
  * /
 tgr_value CppTest_Tgr_GetField_Point(tgr_value_ptr obj, tgr_value_ptr field_name) 
{
   Point *point = (Point *)obj->value.ptr;
   const char* name = tgr_value_get_string(field_name);
   if (tgr_strcmp(name, "_x") == 0) {
      return tgr_int_ref(&point->_x);
   } else if (tgr_strcmp(name, "_y") == 0) {
      return tgr_int_ref(&point->_y);    
   } else {
      return tgr_error(c_tgr_error_wrong_get_field_argument);
   }
}
/**
 * Helper function returning pointer to structure with Point type
 * specific utilities
 */
 tgr_type_ptr CppTest_Tgr_Type_Data(void)
{
   static struct tgr_class_definition class_definition = {tgr_false};
   if (!class_definition.initialized) {
      tgr_initialize_class_definition(&class_definition);
      class_definition.vtbl.get_field = CppTest_Tgr_GetField_Data;
  }
  return &class_definition.type;
}
/**
 * Field access function for Line structure
 */
tgr_value TRIGGER_CDECL CppTest_Tgr_GetField_Line(tgr_value_ptr obj, 
tgr_value_ptr field_name)
{
   Line *line = (Line *)obj->value.ptr;
   const char* name = tgr_value_get_string(field_name);

   if (tgr_strcmp(name, "_p1") == 0) {
      return tgr_object(&line->p1, CppTest_Tgr_Type_Point());
   } else if (tgr_strcmp(name, "_p2") == 0) {
      return tgr_object(&line->_p2, CppTest_Tgr_Type_Point());
   } else {
     return tgr_error(c_tgr_error_wrong_get_field_argument);
   }
}
/**
* Helper function returning pointer to structure with Line type
* specific utilities
*/
tgr_type_ptr CppTest_Tgr_Type_Line(void)
{
   static struct tgr_class_definition class_definition = {tgr_false};
   if (!class_definition.initialized) {
      tgr_initialize_class_definition(&class_definition);
      class_definition.vtbl.get_field = CppTest_Tgr_GetField_Line;
   }
   return &class_definition.type;
}

 

最后,需要在桩函数主体中安装特定于类型的操作代码。这需要修改自动生成的桩函数主体并将以下方法调用替换为新调用:

WithArg(const char* name, RValue value)

替换调用:

WithArg(const char* name, const volatile void* obj, tgr_type_ptr type)

方法调用允许您指定专用类型实用程序。修改后的桩函数主体应类似于以下示例:

 

Line CppTest_Stub_moveLine (Line line, int xoff, int yoff)
{
   Line __return = Line();
   int __callOrig = 0;
   CPPTEST_ACTUAL_CALL("moveLine ").
      WithArg("line", &line, CppTest_Tgr_Type_Line()).
      WithArg("xoff", ByRef(xoff)).
      WithArg("xoff", ByRef(yoff)).
      WithArg("__return", &__return, CppTest_Tgr_Type_Line()).
      WithArg("__callOrig", ByRef(__callOrig)).End();
   if (__callOrig) {
      Line __return = moveLine(line, xoff, yoff);
      CPPTEST_ACTUAL_AFTER_CALL("moveLine ").
         WithArg("line", &line, CppTest_Tgr_Type_Line()).
         WithArg("xoff", ByRef(xoff)).
         WithArg("xoff", ByRef(yoff)).
         WithArg("__return", &__return, CppTest_Tgr_Type_Line()).
         WithArg("__callOrig", ByRef(__callOrig)).End();
      return __return;
   }    
   return __return;
}
  • No labels