1 背景
“驱动+桩”是一种比较成熟的服务器端模块测试模式,易于实施自动化。
Receiver应用于桩构建的场景,提高构建服务器端测试桩的效率,在大多数应用场景下用户可以通过配置xml文件实习桩功能,支持功能和性能测试使用
Receiver只支持linux环境使用
2 名词解释
A模式: 普通xml解析模式
B模式: 逻辑xml解析模式
C模式: so加载模式
3 功能
 ※能够模拟提供二进制socket接口的服务器程序
 ※能够支持功能与性能的要求
 ※提供三种使用模式:
(1) 普通xml解析模式(模拟单个接口,指定接口格式及回报数据)
(2) 逻辑xml解析模式(模拟多个接口,除指定接口格式及回报数据外,定制部分逻辑)
(3) so加载模式(特殊场景使用,用户可以自己实现包处理函数)
※ 提供各类辅助函数, 帮助更快速的开发桩程序
4 使用说明
4.1 普通xml模式
假设一个服务器模块提供的某个socket接口请求格式为header+req1,回包格式为header+resp1,struct描述如下:
struct header{
int cmd;
char provider[200];
int len;
};
struct req1{
int id;
};
Struct item{
Int a;
Int b;
};
struct resp1{
int result;
char name[50];
int count;
struct item items[];
};
那么我们需要先构造三个xml描述
 ※header1.xml
<packet type="struct" repeat="1" value=" header" endian="0">
<cmd type="int32_t" value="" repeat="1"/>
<provider type="char" value="" repeat="200"/>
<len type=”int32_t” value=” #flowlen()” repeat="1">
</packet>
 ※req1.xml
<packet type="struct" repeat="1" value=" req1" endian="0">
<id type="int32_t" value="" repeat="1"/>
</packet>
※ resp1.xml
<packet type="struct" repeat="1" value=" resp1" endian="0">
<result type="int32_t" value="$TEMPRESULT" repeat="1"/>
<name type="char" value="hello world" repeat="50"/>
<count type="int32_t" value="5" repeat="1"/>
<items type="struct" repeat="@count" value=" ">
<a type="int32_t" value="1" repeat="1"/>
<b type="int32_t" value="2" repeat="1"/>
</items>
</packet>

注:endian用来描述字节序,0为主机序(默认)
Repeat用于指定该数据段重复数字,用于数组定义,也可以用在struct的描述上
Type为该字段类型,工具内置类型见附录
#flowlen()为内置函数,指定此处自动计算,根据后面所有结构体的长度计算,其他关键字见附录
$TEMPRESULT表示从环境变量TEMPRESULT中读取数据
@count 表示该字段值由<count type="int32_t" value="5" repeat="1"/>值反填,也就是5
回包值可以指定固定值、从环境变量中读取或者利用random内置函数随机生成
运行receiver:./receiver –p 3306 –r ./header.xml –r req1.xml –s header.xml –s resp1.xml -l 1 -u 0 -n -1 即可模拟这个服务器的接口
那么当receiver收到一个header+req1的请求,它会回一个header+resp1的应答(result为对应系统变量实际值,name为hello world),-l 1表示长连接, -u 0 表示tcp请求, -n -1 表示receiver不会退出,一直处理请求

4.2 逻辑xml模式
上个例子给出了模拟一个服务器程序单一接口的使用方法,逻辑xml主要用于模拟一个程序多个接口的场景。
假设说某模块提供的接口格式如下:
header1+header2+reqX
回包格式为:
header1+header2+respX
(X为未知数,具体请求与回应的结构体由header2中的cmd域来定义,例如如果cmd取值为5,则请求为header1+header2+req5,回应为header1+header2+resp5)
我们想启动一个桩实例来模拟这些接口,那么可以使用逻辑xml模式,逻辑xmll的使用方法如下:
首先构造逻辑xml:
[gaowei@db-testing-cs33.db01.baidu.com receiver]$ cat xml/config.xml
<config>
<req_header path="header1.xml" /><!—请求包头1-->

<req_header path="header2.xml " key="cmd" /><!—请求包头2,这个结构体中的cmd决定如何回包-->
<resp_body key="1" respkey="5" path="resp1.xml " /><!—如果cmd为1,则用resp1回包 -->
<resp_body key="2" respkey="6" path="resp2.xml" /><!—如果cmd为2,则用resp2回包 -->
</config>
运行receiver:./receiver –p 3306 –b config.xml -l 1 -u 0 -n -1 –t 5即可模拟这个服务器的多个接口
4.3 so模式
如果以上两种方式不能满足用户需求,用户可以继承receiver提供的plugin基类,实现自己的包处理函数
class IPlugin
{
public:
IPlugin( const std::string& name) ;
virtual ~IPlugin();
virtual const std::string& GetPluginName();
virtual void Process( void *);
protected:
std::string m_strPluginName;
};

Receiver使用了Epool和线程池模型,当有socket可读,会立刻回调用户的Process( void *)函数,传给用户socket句柄,用户可自行执行收包及处理函数
一个简单示例如下:
testplugin.h:
#include "plugin.h"
class TestPlugin: public IPlugin{
public:
TestPlugin():IPlugin("testplugin"){
printf("create TestPlugin\n");
}
void Process( void *);
};

testplugin.cpp:
#include "testplugin.h"
#include "mysocket.h"
#include <iostream>
using namespace std;

extern "C"
TestPlugin* create_testplugin()
{
return new TestPlugin();
}
void TestPlugin::Process(void * p){
int sock = (int)p;
cout << " handle epool event , socket= " << sock << endl;
SocketLayer::close_delepoll(sock);
}
5 工具参数
receiver三种模式: xml模式(A),逻辑xml模式(B),so模式(C),参数含义如下:
 -r 指定接收的结构体描述,A模式使用
 -s 指定发送的普通结构体描述,A模式使用
 -m 指定发送的mcpack1结构体描述,A模式使用
 -x 指定发送的mcpack2结构体描述,A模式使用
 -S 指定延迟发送时间,A、B模式使用
 -n 指定响应次数(-1 表示不退出),A、B模式使用
 -l 指定处理请求后是否断连接,A、B模式使用
 -u 指定是否为udp,A、B模式使用
 -b 指定一个逻辑xml,B模式使用
 -d 指定自定义so路径,C模式使用
 -a 指定自定义so名称,C模式使用
 -t 指定线程数,A、B、C模式使用
 -p 指定端口号,A、B、C模式使用

6 附录
6.1 关键字列表
 #randuint(a,b):返回从a到b之间的一个随机数
 #timenow():返回当前时间的秒数
 #md5(16,str):根据str生成md5
 #fromto(a,b):返回[a,b]的整数,随运行次数递增
 #randin(a,b,c,d):在abcd中随机抽一个数
 flowlen():计算后续部分的长度

6.2 内置类型
 int8_t uint8_t
 int16_t uint16_t
 int32_t uint32_t
 int64_t uint64_t
 int
 time_t
 long
 short
 char

(baiduqa,邮箱:qablog@baidu.com)

 

【本文转自 百度测试技术空间http://hi.baidu.com/baiduqa/blog/item/13920ec00322f20e0ef4773e.html
关注百度技术沙龙