当前位置:首页 » 编程软件 » 编译打桩

编译打桩

发布时间: 2023-06-14 11:58:33

① 你在编程中写过最多的代码是什么

java的时候,我想我写的最多的一句话是System.out.println();在后台打印出变量的值,判断传进去的参数或处理的数据是否正确。其实写java的时候,最不喜欢的就是调试,后来接触到ruby可以实时查看结果不用重启服务器,再回来写java时,那个麻烦啊,重新编译重新部署,总要耗费你一段时间,这个时间之前倒没觉得有多痛苦。

php打桩是什么意思

PHP打桩算法

打桩是一种用定制的函数替换链接库函数且不需重新编译的技术。甚至可用此技术替换系统调用(更确切地说,库函数包装系统调用)。可能的应用是沙盒、调试或性能优化库。为演示过程,此处给出一个简单库,以记录GNU/Linux中
malloc 调用次数。

/*_GNU_SOURCEisneededforRTLD_NEXT,GCCwillnotdefineitbydefault*/
#define_GNU_SOURCE
#include<stdio.h>
#include<stdlib.h>
#include<dlfcn.h>
#include<stdint.h>
#include<inttypes.h>

staticuint32_tmalloc_count=0;
staticuint64_ttotal=0;

voidsummary(){
fprintf(stderr,"malloccalled:%utimes ",count);
fprintf(stderr,"totalallocatedmemory:%"PRIu64"bytes ",total);
}

void*malloc(size_tsize){
staticvoid*(*real_malloc)(size_t)=NULL;
void*ptr=0;

if(real_malloc==NULL){
real_malloc=dlsym(RTLD_NEXT,"malloc");
atexit(summary);
}

count++;
total+=size;

returnreal_malloc(size);
}

打桩祥皮要在链接libc.so之前加载此库,这样我们的 malloc 实现就会在二进制文件执行时被链接。可通过设置 LD_PRELOAD
环境变量为我们想让链接器优先链接的全路径。这也能确保其他动态链接库的调用最终使用我们的 malloc
实现。因为我们的目标只是记录调用次数,不是真正地实现内存分配,所以我们仍需要调用“真正”的 malloc 。通过传递 RTLD_NEXT 伪处理程序到
dlsym,我们获得了指向下一个已加载的链接库中 malloc 事件的指针。第一次 malloc 调用 libc 的 malloc,当程序终止时,会调用由
atexit 注册的获取和 summary 函数。看GNU/Linxu中打桩行为(真的184次调用!):

$gcc-shared-ldl-fPICmalloc_counter.c-o/tmp/libmcnt.so
$exportLD_PRELOAD="/tmp/libstr.so"
$ps
PIDTTYTIMECMD
2758pts/200:00:00bash
4371pts/200:00:00ps
malloccalled:184times
totalallocatedmemory:302599bytes

下面来看下PHP打桩算法在使用时出现的问题。

当构造测试用例的数据,是在函数内部被另一个外部函数所使用时,我们需要忽略外部函数所带来的影响。

需要进行“打桩”,举一个具体的例子

classDataGetter{
public:
...
boolRun();
...
private:
...
Client*m_ptr_client;
...
};
.....
.....
boolDataGetter::Run(){
...
std::stringdata;
boolret=m_ptr_client->GetData(data);
...
}
....
....

比如要对run这个函数进行单元测试,它内部调用了ptr_client->GetData(data)的方法,它是通过tcp协议从服务端取数据到data里,测试run这个函数,必然要构造data。

如果不“打桩”,要测试的话,我们就需要再从服务端去构造数据,而且还可能收到其他因素的影响。

这时候“桩”就是很好的一种技术。

那如何去构造“桩”呢。

那么如何构造呢?

原理:利用c++ virtual的特性,改变m_ptr_client指针所指向的对象,重写一个“打桩”测试类。

当然,前提是GetData的定谨桥差义本身是virtual的消宏。

假设Client的定义如下

classClient{
......
public:
virtualboolGetData(std::string&data);
......
};

我们只需要重写Getdata的方法,并且当参数data被传进来时,我们可以返回特定的值。

这一套方法,google已经提供了很好的一套框架:gmock

下面介绍一下它的用法

#include"client.h"//被mock的类的头文件
#include//gmock的头文件
classMockClient:publicClient{
public:
MockClient():Client(){}
MOCK_METHOD1(GetData,bool(std::string&));
}

这里使用了一个宏MOCK_METHOD1

原形是MOCK_METHOD#1(#2, #3(#4) )

#1表示被mock的函数参数个数,#2表示被mock的函数名称,#3表示被mock的函数返回值,#4表示被mock的函数参数列表

这样,一个“桩”就“打”好了。

如何正确简便地使用

首先,要先改变m_ptr_client指向的对象,对于private的变量,在前一章有描述方法,

然后测试的时候,直接将 m_ptr_client = new
MockClient()即可,不过要记得释放它之前new的资源(如果有的话),不然就内存泄露了,哈哈

使用gmock的几个宏,用一个例子简单介绍下:

EXPECT_CALL(//mock被调用时,要发生的动作
*m_ptr_client,//被mock的对象,看清楚,是对象,不是指针了
GetData(test::_)//被mock的方法,参数为占位符
).Times(2)//表示被调用2次
.WillOnce(第一次调用
testing::SetArgReferee<0>(“test”),//设置第0个参数的值为“test”
testing::Return(true),//设置返回值为true
)
.WillOnce(第二次调用
testing::SetArgReferee<0>(“test”),//设置第0个参数的值为“test”
testing::Return(false),//设置返回值为false
);

测试的原则,尽量不修改被测函数,覆盖函数的每一个分支,保证外部条件都是正确的。

热点内容
视易锋云系统如何架设辅助服务器 发布:2025-02-09 06:47:08 浏览:768
mysql备份脚本shell 发布:2025-02-09 06:46:33 浏览:14
腾讯云服务器怎样调整分辨率 发布:2025-02-09 06:46:30 浏览:368
php上一个页面 发布:2025-02-09 06:41:25 浏览:488
改装配置后不想重启怎么办 发布:2025-02-09 06:36:40 浏览:445
算法复杂度定义 发布:2025-02-09 06:30:46 浏览:585
昵图源码接口 发布:2025-02-09 06:30:37 浏览:724
微信怎么没有支付密码 发布:2025-02-09 06:29:52 浏览:33
mplayer编译版 发布:2025-02-09 06:29:13 浏览:762
免费网盘源码 发布:2025-02-09 06:29:07 浏览:5