
- Added a multicountsersec to teplace hmcontrol and multicounter - Fixed a case sensitivity bug in haddcheck - Made oscillate work with second generation motors for POLDI - Added a time stamper to trace. Now there will be time stamps in trace files which allow to correlate things from the master log with the trace. - Updated polterwrite. - Updated testprot to work with the behave test SKIPPED: psi/make_gen psi/polterwrite.c psi/psi.c psi/sputterprot.c
190 lines
5.2 KiB
C
190 lines
5.2 KiB
C
/*
|
|
* This is a testing and simulation protocol for use with
|
|
* scriptcontext. This protocol does not build a network
|
|
* connection. Rather it has two modes of operation:
|
|
* - In the simplest mode of operation it just returns an echo of the
|
|
* command given.
|
|
* - When initialized with a filename it reads that file as a dictionary
|
|
* of commands and responses. Thus responses can be programmed. Through
|
|
* a special escape, stored as tclescape in the dictionary it executes
|
|
* the response as a Tcl function with the command string as a parameter.
|
|
* Thus replies can be programmed for software testing.
|
|
*
|
|
* testprot.c
|
|
*
|
|
* Created on: Feb 2, 2010
|
|
* Author: Mark Koennecke
|
|
*/
|
|
#include <stdio.h>
|
|
#include <tcl.h>
|
|
#include <sics.h>
|
|
#include <ascon.h>
|
|
#include <ascon.i>
|
|
#include <stringdict.h>
|
|
/*--------------------------------------------------------------------------*/
|
|
static void killDict(void *data)
|
|
{
|
|
pStringDict dict = NULL;
|
|
if(data != NULL){
|
|
dict = (pStringDict)data;
|
|
DeleteStringDict(dict);
|
|
}
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
static void readDictionary(Ascon *a, SConnection *con, char *filename)
|
|
{
|
|
pStringDict dict = NULL;
|
|
FILE *fd = NULL;
|
|
char pLine[256], *c;
|
|
|
|
fd = fopen(filename,"r");
|
|
if(fd == NULL){
|
|
SCPrintf(con,eError,"ERROR: dictionary file %s not found!", filename);
|
|
return;
|
|
}
|
|
dict = CreateStringDict();
|
|
if(dict == NULL){
|
|
SCWrite(con,"ERROR: failed to allocate dictionary", eError);
|
|
return;
|
|
}
|
|
while(fgets(pLine,256,fd) != NULL){
|
|
/*
|
|
* get rid of the trailing \n
|
|
*/
|
|
c = strrchr(pLine,'\n');
|
|
if(c != NULL){
|
|
*c = '\0';
|
|
}
|
|
/* split at = */
|
|
c = strchr(pLine,'=');
|
|
if(c == NULL){
|
|
SCPrintf(con,eWarning, "WARNING: Invalid line %s in %s",
|
|
pLine, filename);
|
|
continue;
|
|
}
|
|
*c = '\0';
|
|
StringDictAddPair(dict,pLine,c+1);
|
|
}
|
|
fclose(fd);
|
|
a->private = dict;
|
|
a->killPrivate = killDict;
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
static int TestProtInit(Ascon *a, SConnection *con, int argc, char *argv[])
|
|
{
|
|
a->hostport = strdup("None");
|
|
a->sendTerminator = strdup("\n");
|
|
a->timeout = 0;
|
|
a->reconnectInterval = -1; /* immediate */
|
|
a->replyTerminator = strdup("\n");
|
|
if(argc > 0){
|
|
readDictionary(a,con,argv[1]);
|
|
}
|
|
return 1;
|
|
}
|
|
/*---------------------------------------------------------------------------*/
|
|
static void findResponse(Ascon *a)
|
|
{
|
|
pStringDict dict = NULL;
|
|
char tclEscape[80], response[256], *test = NULL, command[512];
|
|
int status;
|
|
|
|
DynStringClear(a->rdBuffer);
|
|
DynStringClear(a->errmsg);
|
|
/* simple echo operation */
|
|
if(a->private == NULL){
|
|
DynStringConcat(a->rdBuffer,GetCharArray(a->wrBuffer));
|
|
return;
|
|
}
|
|
/* dictionary operation */
|
|
memset(response,0,sizeof(response));
|
|
memset(tclEscape,0,sizeof(tclEscape));
|
|
|
|
dict = (pStringDict)a->private;
|
|
status = StringDictGet(dict,GetCharArray(a->wrBuffer),response, sizeof(response));
|
|
if(status != 1){
|
|
if(StringDictGet(dict,"echofail",response,sizeof(response)) == 1) {
|
|
DynStringConcat(a->rdBuffer,GetCharArray(a->wrBuffer));
|
|
return;
|
|
} else {
|
|
a->state = AsconFailed;
|
|
DynStringConcat(a->errmsg,"ERROR: no response found in dictionary for ");
|
|
DynStringConcat(a->errmsg,GetCharArray(a->wrBuffer));
|
|
return;
|
|
}
|
|
}
|
|
/**
|
|
Tclescape is an escape string/character which identifies a response as a tcl invocation.
|
|
Thus the algorithm runs:
|
|
* Find out if there is a Tcl escape
|
|
* If so:
|
|
* Is the tslcescape in the response
|
|
* If so:
|
|
* Invoke the Tcl function for the response
|
|
In all other cases the response is passed on unmodified.
|
|
**/
|
|
status = StringDictGet(dict,"tclescape",tclEscape,sizeof(tclEscape));
|
|
if(status == 1){
|
|
test = strstr(response, tclEscape);
|
|
if(test != NULL){
|
|
/* Tcl operation! */
|
|
test += strlen(tclEscape);
|
|
snprintf(command,sizeof(command),"%s %s", test, GetCharArray(a->wrBuffer));
|
|
status = Tcl_Eval(InterpGetTcl(pServ->pSics), command);
|
|
if(status != TCL_OK){
|
|
DynStringConcat(a->errmsg, "ERROR:");
|
|
DynStringConcat(a->errmsg, (char *)Tcl_GetStringResult(InterpGetTcl(pServ->pSics)));
|
|
a->state = AsconFailed;
|
|
} else {
|
|
DynStringConcat(a->rdBuffer,(char *)Tcl_GetStringResult(InterpGetTcl(pServ->pSics)));
|
|
}
|
|
} else {
|
|
DynStringConcat(a->rdBuffer,response);
|
|
}
|
|
} else {
|
|
DynStringConcat(a->rdBuffer,response);
|
|
}
|
|
}
|
|
/*---------------------------------------------------------------------------*/
|
|
static int TestProtHandler(Ascon * a)
|
|
{
|
|
int i;
|
|
|
|
switch (a->state) {
|
|
case AsconConnectStart:
|
|
case AsconConnecting:
|
|
a->state = AsconConnectDone;
|
|
break;
|
|
case AsconWriteStart:
|
|
a->state = AsconWriting;
|
|
break;
|
|
case AsconWriting:
|
|
a->state = AsconWriteDone;
|
|
findResponse(a);
|
|
break;
|
|
case AsconReadStart:
|
|
for(i = 0; i < 100; i++){
|
|
TaskYield(pServ->pTasker);
|
|
}
|
|
a->state = AsconReading;
|
|
break;
|
|
case AsconReading:
|
|
a->state = AsconReadDone;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
return 1;
|
|
}
|
|
/*-------------------------------------------------------------------------*/
|
|
void AddTestProt()
|
|
{
|
|
AsconProtocol *prot = NULL;
|
|
|
|
prot = calloc(sizeof(AsconProtocol), 1);
|
|
prot->name = strdup("testprot");
|
|
prot->init = TestProtInit;
|
|
prot->handler = TestProtHandler;
|
|
AsconInsertProtocol(prot);
|
|
}
|