TTCN中PTC的运行流程

来源:互联网 发布:怎样查看自己的淘宝号 编辑:程序博客网 时间:2024/05/16 06:52

一些概念

Component(测试组件或者测试成分),TTCN接触下来最频繁的就是MTC(Main Test Component,主测试组件),在执行测试用例前,需要首先创建一个MTC,在testcase运行过程中,只能有唯一的MTC。如果没有指明testcase需要runs on在某个Component,系统默认的component就是MTC。在testcase代码中,不能控制MTC的建立与停止。

非主测试组件的测试组件叫PTC(ParallelTest Component, 并行测试组件), PTC是由testcase控制的,最后由系统销毁。testcase可以执行create,start,stop等操作 。

简单说,一个PTC就可以理解为TTCN模拟出来的一台远程主机的进程。通过它,模拟出其他主机实现并行测试。而测试组件之间,通过通信端口实现通信。


一个简单的例子

这个testcase中,简单执行:

telnet_IPworks();//check if every port configuration is rightstartClient(tsp_ptcClientName0);  //在这里启动名为tsp_ptcClientName0的PTCstartClient(tsp_ptcClientName1);startClient(tsp_ptcClientName2);startClient(tsp_ptcClientName3);startClient(tsp_ptcClientName4);startClient(tsp_ptcClientName11);…sendCommand_byPTC("date ",tsp_ptcClientName11,2.2);


PCT和startClient的实现(common/CLI/CLI_Function.ttcn.linux):

//定义了接下来需要使用的PTC,类似C中的结构体概念type component PTC_CT    {        port TELNETasp_PT telnet_client_port; //与ipwork测试系统接口通信的端口        port ProcePort managePort; //与mtc通讯的端口        var BatchCommand tcv_batchCommand;        //if tcv_bcheckBatchResp== true ,check BatchCommad's Response from SUT ,or not        var boolean tcv_bcheckBatchResp := true;    }function startClient(charstring p_ClientName) runs on MTC_CT    {        //initial PTC//如果没有初始化PTC的列表,则根据ipwork.cfg中定义的tsp_ptcClientName*名,初始化若干PTC备用        if(tcv_isPTCInitial == false)                        {// PTC_CT.create(tsp_ptcClientName0)建立一个名为tsp_ptcClientName0的PTC,但不启动            ptcClientName[0]:= PTC_CT.create(tsp_ptcClientName0);            ptcClientName[1]:= PTC_CT.create(tsp_ptcClientName1);            ptcClientName[2]:= PTC_CT.create(tsp_ptcClientName2);            ptcClientName[3]:= PTC_CT.create(tsp_ptcClientName3);           ptcClientName[4]:= PTC_CT.create(tsp_ptcClientName4);            ptcClientName[5]:= PTC_CT.create(tsp_ptcClientName5);            ptcClientName[6]:= PTC_CT.create(tsp_ptcClientName6);            ptcClientName[7]:= PTC_CT.create(tsp_ptcClientName7);           ptcClientName[8]:= PTC_CT.create(tsp_ptcClientName8);            ptcClientName[9]:= PTC_CT.create(tsp_ptcClientName9);            ptcClientName[10]:= PTC_CT.create(tsp_ptcClientName10);           ptcClientName[11]:= PTC_CT.create(tsp_ptcClientName11);            tcv_isPTCInitial := true; //have been intialed        }//获取名为p_ClientName的PTC引用p_ptcClient        var PTC_CT p_ptcClient := getCurrentPTC(p_ClientName);log(getCurrentPTC(p_ClientName));//如果p_ptcClient已经停止运行        if(false == p_ptcClient.running)        {//利用map,将测试组件p_ptcClient映射到ipwork测试系统接口上,system是测试系统的组件引用         map(p_ptcClient:telnet_client_port,system:telnet_client_port);   //connect直接把p_ptcClient的端口managePort连接到mtc的managePort端口,//这样建立一条双工的通信关系          connect(p_ptcClient:managePort,mtc:managePort);//启动PTC引用p_ptcClient,启动后执行CliSimulator()          p_ptcClient.start(CliSimulator());          pause(1.0);        }                 //sendCommand_byPTC("ipwcli",p_ClientName,0.2);         //sendCommand_byPTC(tsp_user_admin,p_ClientName,0.2);         //sendCommand_byPTC(tsp_adminpassword,p_ClientName,1.2);}

startClient首先检查PCT的存储容器ptcClientName是否被初始化,如果没有,则根据配置文件ipwork.cfg中设定的名字,create(两个概念,这里只是create,而不start)若干PCT引用填入ptcClientName备用。然后,根据参数p_ClientName获取相应的PCT引用。

随后,调用p_ptcClient.running检测,p_ptcClient是否在运行(running运行在一个测试部件上检查另一个测试部件是否运行,这里实在mtc上检查p_ptcClient)。如果没有运行,则依次执行map和connect,map为p_ptcClient与ipwork之间建立映射 ,connect为mtc和p_ptcClient建立一个双工的通信关系,即mtc的输出口指向p_ptcClient的输入口,p_ptcClient的输出口指向mtc的输入口。然后,执行p_ptcClient.start启动PTC,PTC启动后执行的就是start的参数CliSimulator(),如同pthread_create或者exec执行线程或进程函数一样。

我们已经启动了新的PTC,那么看看p_ptcClient的CliSimulator()里面究竟执行了那些东西:

function CliSimulator() runs on PTC_CT{      var charstring command := "";      var charstring result := "";      var charstring keyWords := "";      timer t := 5.0;      alt      {//根据模板signature sig_Command(inout charstring p_Command),等待另一个测试组//件的调用请求,远程调用时传入的参数p_Command将被赋予command。这里的managePort就是//之前mtc与p_ptcClient建立关联的端口,那么这里就是等待mtc的调用[]managePort.getcall(sig_Command:{?}) -> param(command)            {//根据mtc的command,telnet_client_port 即之前map建立的p_ptcClient与//ipwork建立的关联, telnet_client_port.send(command)将把mtc传来的command转发//给ipwork                telnet_client_port.send(command);                  repeat;            }            //Batch command operation        []managePort.getcall(sig_BatchCommand:{?,?,?}) -param(tcv_batchCommand,keyWords,tcv_bcheckBatchResp)            {                var integer number := sizeof(tcv_batchCommand);                for(var integer i:=0;i<number;i:=i+1)                {                    telnet_client_port.send(tcv_batchCommand[i]);                   if(tcv_bcheckBatchResp == true)                    {                        t.start;    //启动计时器                        alt                        {//接收到回复                            []telnet_client_port.receive(charstring:?) -> value result;                              {                                //返回值与keyword比较result := regexp(result,"*("&keyWords&")*",0);                                t.stop;  //关闭计时器//错误结果                                if(result == "")                                {                                    log(tcv_batchCommand[i]," fail");                                   setverdict(fail);   //设置测试失败                                    stop;      //停止当前component                                                     }                                else if(result == keyWords)                                {                                    log("Execute command:",tcv_batchCommand[i]," success");                                }                            }                            []t.timeout       //超时                                {                                    log("Time out ,don't receive Response from SUT.fail");                                    setverdict(fail);                                    stop;                            }                        }                                                telnet_client_port.clear;                                            }                }//调用sig_sendBatchcommandFinished,不等待,直接执行下一步                managePort.call(sig_sendBatchcommandFinished:{},nowait);                repeat;                            }            []telnet_client_port.receive(charstring:?) -> value result            {                managePort.call(sig_Command:{result},nowait);                repeat;                }            []telnet_client_port.receive            {                repeat;            }                    } }

这里的alt是可选步,如同一个switch的消息循环,每个case选项或是等待远程过程调用请求,或是等待接受数据,如果有请求或者数据传输,程序就会跳进对应的case,,这里主要关心[]managePort.getcall(sig_Command:{?}) ->param(command)

getcall等待远程的call,managePort就是之前mtc与p_ptcClient建立关联的端口,那么这里就是等待mtc的call调用,根据module CLI_Signature中定义的函数原型signature sig_Command(inout charstring p_Command)mtc远程call时传入的参数p_Command将被赋予command,telnet_client_port 即之前map建立的p_ptcClient与ipwork建立的关联, telnet_client_port.send(command)将把mtc传来的command转发给ipwork。这样就完成了,从mtc传送命令交由模拟的PTC转发给ipwork测试系统接口的过程。下面的[]managePort.getcall(sig_BatchCommand也大体类似,只是将一串命令打包执行。

最后看下mtc中如何调用p_ptcClient的方法 ,使用sendCommand_byPTC("date ",tsp_ptcClientName11,2.2),它的作用就是通过名为tsp_ptcClientName11的PTC发送date给ipwork:

function sendCommand_byPTC(charstring p_Command,charstring p_ClientName,float p_pause) runs on MTC_CT{        var PTC_CT p_ptcClient;        p_ptcClient := getCurrentPTC(p_ClientName);   //获取名为p_ClientName的PTC引用//调用managePort通信的远程方法,方法模板sig_Command,传入参数p_Command        managePort.call(sig_Command:{p_Command},nowait) to p_ptcClient;        pause(p_pause);}

这里首先获取了获取名为p_ClientName的PTC引用,然后利用managePort调用远程方法(也就是mtc与p_ptcClient关联的端口),这里的远程方法会到p_ptcClient中去找模板为sig_Command的方法,也就是之前提到的CliSimulator()中相关内容。



2 0
原创粉丝点击