diff options
Diffstat (limited to 'tests/nettester.c')
-rw-r--r-- | tests/nettester.c | 191 |
1 files changed, 144 insertions, 47 deletions
diff --git a/tests/nettester.c b/tests/nettester.c index 566f553b..07a1c052 100644 --- a/tests/nettester.c +++ b/tests/nettester.c @@ -38,6 +38,7 @@ #include <sys/socket.h> #include <sys/wait.h> #include <sys/stat.h> +#include <sys/time.h> #include <arpa/inet.h> #include <assert.h> #include <unistd.h> @@ -46,6 +47,7 @@ #include <signal.h> #include <netinet/in.h> #include <getopt.h> +#include <ctype.h> #define EXIT_FAILURE 1 #define INVALID_SOCKET -1 @@ -60,7 +62,11 @@ static char *testSuite = NULL; /* name of current test suite */ static int iPort = 12514; /* port which shall be used for sending data */ static char* pszCustomConf = NULL; /* custom config file, use -c conf to specify */ static int verbose = 0; /* verbose output? -v option */ +static int useDebugEnv = 0; /* activate debugging environment (for rsyslog debug log)? */ +/* these two are quick hacks... */ +int iFailed = 0; +int iTests = 0; /* provide user-friednly name of input mode */ @@ -79,14 +85,27 @@ static char *inputMode2Str(inputMode_t mode) void readLine(int fd, char *ln) { + char *orig = ln; char c; int lenRead; + + if(verbose) + fprintf(stderr, "begin readLine\n"); lenRead = read(fd, &c, 1); while(lenRead == 1 && c != '\n') { + if(c == '\0') { + *ln = c; + fprintf(stderr, "Warning: there was a '\\0'-Byte in the read response " + "right after this string: '%s'\n", orig); + c = '?'; + } *ln++ = c; - lenRead = read(fd, &c, 1); + lenRead = read(fd, &c, 1); } *ln = '\0'; + + if(verbose) + fprintf(stderr, "end readLine, val read '%s'\n", orig); } @@ -104,6 +123,7 @@ tcpSend(char *buf, int lenBuf) { static int sock = INVALID_SOCKET; struct sockaddr_in addr; + int retries; if(sock == INVALID_SOCKET) { /* first time, need to connect to target */ @@ -119,10 +139,20 @@ tcpSend(char *buf, int lenBuf) fprintf(stderr, "inet_aton() failed\n"); return(1); } - if(connect(sock, (struct sockaddr*)&addr, sizeof(addr)) != 0) { - fprintf(stderr, "connect() failed\n"); - return(1); - } + retries = 0; + while(1) { /* loop broken inside */ + if(connect(sock, (struct sockaddr*)&addr, sizeof(addr)) == 0) { + break; + } else { + if(retries++ == 50) { + ++iFailed; + fprintf(stderr, "connect() failed\n"); + return(1); + } else { + usleep(100000); /* 0.1 sec, these are us! */ + } + } + } } /* send test data */ @@ -189,11 +219,8 @@ int openPipe(char *configFile, pid_t *pid, int *pfd) "-M../runtime/.libs:../.libs", NULL }; char confFile[1024]; char *newenviron[] = { NULL }; - /* debug aide... - char *newenviron[] = { "RSYSLOG_DEBUG=debug nostdout", - "RSYSLOG_DEBUGLOG=tmp", NULL }; - */ - + char *newenvironDeb[] = { "RSYSLOG_DEBUG=debug nostdout", + "RSYSLOG_DEBUGLOG=log", NULL }; sprintf(confFile, "-f%s/testsuites/%s.conf", srcdir, (pszCustomConf == NULL) ? configFile : pszCustomConf); @@ -216,7 +243,7 @@ int openPipe(char *configFile, pid_t *pid, int *pfd) close(pipefd[1]); close(pipefd[0]); fclose(stdin); - execve("../tools/rsyslogd", newargv, newenviron); + execve("../tools/rsyslogd", newargv, (useDebugEnv) ? newenvironDeb : newenviron); } else { close(pipefd[1]); *pid = cpid; @@ -227,6 +254,62 @@ int openPipe(char *configFile, pid_t *pid, int *pfd) } +/* This function unescapes a string of testdata. That it, escape sequences + * are converted into their one-character equivalent. While doing so, it applies + * C-like semantics. This was made necessary for easy integration of control + * characters inside test cases. -- rgerhards, 2009-03-11 + * Currently supported: + * \\ single backslash + * \n, \t, \r as in C + * \nnn where nnn is a 1 to 3 character octal sequence + * Note that when a problem occurs, the end result is undefined. After all, this + * is for a testsuite generatort, it must not be 100% bullet proof (so do not + * copy this code into something that must be!). Also note that we do in-memory + * unescaping and assume that the string gets shorter but NEVER longer! + */ +void unescapeTestdata(char *testdata) +{ + char *pDst; + char *pSrc; + int i; + int c; + + pDst = pSrc = testdata; + while(*pSrc) { + if(*pSrc == '\\') { + switch(*++pSrc) { + case '\\': *pDst++ = *pSrc++; + break; + case 'n': *pDst++ = '\n'; + ++pSrc; + break; + case 'r': *pDst++ = '\r'; + ++pSrc; + break; + case 't': *pDst++ = '\t'; + ++pSrc; + break; + case '0': + case '1': + case '2': + case '3': c = *pSrc++ - '0'; + i = 1; /* we already processed one digit! */ + while(i < 3 && isdigit(*pSrc)) { + c = c * 8 + *pSrc++ - '0'; + ++i; + } + *pDst++ = c; + break; + default: break; + } + } else { + *pDst++ = *pSrc++; + } + } + *pDst = '\0'; +} + + /* Process a specific test case. File name is provided. * Needs to return 0 if all is OK, something else otherwise. */ @@ -247,41 +330,54 @@ processTestFile(int fd, char *pszFileName) /* skip comments at start of file */ - getline(&testdata, &lenLn, fp); while(!feof(fp)) { - if(*testdata == '#') - getline(&testdata, &lenLn, fp); - else - break; /* first non-comment */ - } - + getline(&testdata, &lenLn, fp); + while(!feof(fp)) { + if(*testdata == '#') + getline(&testdata, &lenLn, fp); + else + break; /* first non-comment */ + } - testdata[strlen(testdata)-1] = '\0'; /* remove \n */ - /* now we have the test data to send (we could use function pointers here...) */ - if(inputMode == inputUDP) { - if(udpSend(testdata, strlen(testdata)) != 0) - return(2); - } else { - if(tcpSend(testdata, strlen(testdata)) != 0) - return(2); - } + /* this is not perfect, but works ;) */ + if(feof(fp)) + break; - /* next line is expected output - * we do not care about EOF here, this will lead to a failure and thus - * draw enough attention. -- rgerhards, 2009-03-31 - */ - getline(&expected, &lenLn, fp); - expected[strlen(expected)-1] = '\0'; /* remove \n */ + ++iTests; /* increment test count, we now do one! */ + + testdata[strlen(testdata)-1] = '\0'; /* remove \n */ + /* now we have the test data to send (we could use function pointers here...) */ + unescapeTestdata(testdata); + if(inputMode == inputUDP) { + if(udpSend(testdata, strlen(testdata)) != 0) + return(2); + } else { + if(tcpSend(testdata, strlen(testdata)) != 0) + return(2); + } - /* pull response from server and then check if it meets our expectation */ - readLine(fd, buf); - if(strcmp(expected, buf)) { - printf("\nExpected Response:\n'%s'\nActual Response:\n'%s'\n", - expected, buf); - ret = 1; + /* next line is expected output + * we do not care about EOF here, this will lead to a failure and thus + * draw enough attention. -- rgerhards, 2009-03-31 + */ + getline(&expected, &lenLn, fp); + expected[strlen(expected)-1] = '\0'; /* remove \n */ + + /* pull response from server and then check if it meets our expectation */ + readLine(fd, buf); + if(strcmp(expected, buf)) { + ++iFailed; + printf("\nFile %s:\nExpected Response:\n'%s'\nActual Response:\n'%s'\n", + pszFileName, expected, buf); + ret = 1; + } + /* we need to free buffers, as we have potentially modified them! */ + free(testdata); + testdata = NULL; + free(expected); + expected = NULL; } - free(testdata); free(expected); fclose(fp); return(ret); @@ -297,8 +393,6 @@ processTestFile(int fd, char *pszFileName) int doTests(int fd, char *files) { - int iFailed = 0; - int iTests = 0; int ret; char *testFile; glob_t testFiles; @@ -313,7 +407,6 @@ doTests(int fd, char *files) if(stat((char*) testFile, &fileInfo) != 0) continue; /* continue with the next file if we can't stat() the file */ - ++iTests; /* all regular files are run through the test logic. Symlinks don't work. */ if(S_ISREG(fileInfo.st_mode)) { /* config file */ if(verbose) printf("processing test case '%s' ... ", testFile); @@ -321,8 +414,9 @@ doTests(int fd, char *files) if(ret == 0) { if(verbose) printf("successfully completed\n"); } else { - if(verbose) printf("failed!\n"); - ++iFailed; + if(!verbose) + printf("test '%s' ", testFile); + printf("failed!\n"); } } } @@ -365,11 +459,14 @@ int main(int argc, char *argv[]) char buf[4096]; char testcases[4096]; - while((opt = getopt(argc, argv, "c:i:p:t:v")) != EOF) { + while((opt = getopt(argc, argv, "dc:i:p:t:v")) != EOF) { switch((char)opt) { case 'c': pszCustomConf = optarg; break; + case 'd': + useDebugEnv = 1; + break; case 'i': if(!strcmp(optarg, "udp")) inputMode = inputUDP; @@ -390,7 +487,7 @@ int main(int argc, char *argv[]) verbose = 1; break; default:printf("Invalid call of nettester, invalid option '%c'.\n", opt); - printf("Usage: nettester -ttestsuite-name -iudp|tcp [-pport] [-ccustomConfFile] \n"); + printf("Usage: nettester -d -ttestsuite-name -iudp|tcp [-pport] [-ccustomConfFile] \n"); exit(1); } } |