Files
sics/testprot.c
koennecke ad241bd99e - Added a protocol driver for the munich sputter machine
- 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
2013-11-04 12:55:15 +00:00

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);
}