From 493d6a799be82a2df652b666d541a5e004ebcc76 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Mon, 7 Jul 2008 12:04:33 +0200 Subject: changed RainerScript testbench to a full-blow test suite it now works based on test case files, which enable to quickly generate test cases. --- tests/rscript.c | 258 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 258 insertions(+) create mode 100644 tests/rscript.c (limited to 'tests/rscript.c') diff --git a/tests/rscript.c b/tests/rscript.c new file mode 100644 index 00000000..f82107ed --- /dev/null +++ b/tests/rscript.c @@ -0,0 +1,258 @@ +/* This test checks runtime initialization and exit. Other than that, it + * also serves as the most simplistic sample of how a test can be coded. + * + * Part of the testbench for rsyslog. + * Copyright 2008 Rainer Gerhards and Adiscon GmbH. + * + * This file is part of rsyslog. + * + * Rsyslog is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Rsyslog is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Rsyslog. If not, see . + * + * A copy of the GPL can be found in the file "COPYING" in this distribution. + */ +#include "config.h" +#include +#include +#include + +#include "rsyslog.h" +#include "testbench.h" +#include "ctok.h" +#include "expr.h" + +MODULE_TYPE_TESTBENCH +/* define addtional objects we need for our tests */ +DEFobjCurrIf(expr) +DEFobjCurrIf(ctok) +DEFobjCurrIf(ctok_token) +DEFobjCurrIf(vmprg) + +BEGINInit +CODESTARTInit + pErrObj = "expr"; CHKiRet(objUse(expr, CORE_COMPONENT)); + pErrObj = "ctok"; CHKiRet(objUse(ctok, CORE_COMPONENT)); + pErrObj = "ctok_token"; CHKiRet(objUse(ctok_token, CORE_COMPONENT)); + pErrObj = "vmprg"; CHKiRet(objUse(vmprg, CORE_COMPONENT)); +ENDInit + +BEGINExit +CODESTARTExit +ENDExit + + +/* perform a single test. This involves compiling the test script, + * checking the result of the compilation (iRet) and a check of the + * generated program (via a simple strcmp). The resulting program + * check is only done if the test should not detect a syntax error + * (for obvious reasons, there is no point in checking the result of + * a failed compilation). + * rgerhards, 2008-07--07 + */ +static rsRetVal +PerformTest(cstr_t *pstrIn, rsRetVal iRetExpected, cstr_t *pstrOut) +{ + cstr_t *pstrPrg = NULL; + ctok_t *tok = NULL; + ctok_token_t *pToken = NULL; + expr_t *pExpr; + rsRetVal localRet; + DEFiRet; + + /* we first need a tokenizer... */ + CHKiRet(ctok.Construct(&tok)); + CHKiRet(ctok.Setpp(tok, rsCStrGetSzStr(pstrIn))); + CHKiRet(ctok.ConstructFinalize(tok)); + + /* now construct our expression */ + CHKiRet(expr.Construct(&pExpr)); + CHKiRet(expr.ConstructFinalize(pExpr)); + + /* ready to go... */ + localRet = expr.Parse(pExpr, tok); + + /* check if we expected an error */ + if(localRet != iRetExpected) { + printf("Error in compile return code. Expected %d, received %d\n", + iRetExpected, localRet); + CHKiRet(rsCStrConstruct(&pstrPrg)); + CHKiRet(vmprg.Obj2Str(pExpr->pVmprg, pstrPrg)); + printf("generated vmprg:\n%s\n", rsCStrGetSzStr(pstrPrg)); + ABORT_FINALIZE(iRetExpected == RS_RET_OK ? localRet : RS_RET_ERR); + } + + if(iRetExpected != RS_RET_OK) + FINALIZE; /* if we tested an error case, we are done */ + + /* OK, we got a compiled program, so now let's compare that */ + + CHKiRet(rsCStrConstruct(&pstrPrg)); + CHKiRet(vmprg.Obj2Str(pExpr->pVmprg, pstrPrg)); + + if(strcmp((char*)rsCStrGetSzStr(pstrPrg), (char*)rsCStrGetSzStr(pstrOut))) { + printf("error: compiled program different from expected result!\n"); + printf("generated vmprg:\n%s\n", rsCStrGetSzStr(pstrPrg)); + printf("expected:\n%s\n", rsCStrGetSzStr(pstrOut)); + ABORT_FINALIZE(RS_RET_ERR); + } + +finalize_it: + /* we are done, so we now need to restore things */ + if(pToken != NULL) + ctok_token.Destruct(&pToken); /* no longer needed */ + if(pstrPrg != NULL) + rsCStrDestruct(&pstrPrg); + if(tok != NULL) + ctok.Destruct(&tok); + RETiRet; +} + + +/* a helper macro to generate some often-used code... */ +#define CHKEOF \ + if(feof(fp)) { \ + printf("error: unexpected end of control file %s\n", pszFileName); \ + ABORT_FINALIZE(RS_RET_ERR); \ + } +/* process a single test file + * Note that we do not do a real parser here. The effort is not + * justified by what we need to do. So it is a quick shot. + * rgerhards, 2008-07-07 + */ +static rsRetVal +ProcessTestFile(uchar *pszFileName) +{ + FILE *fp; + char *lnptr = NULL; + size_t lenLn; + cstr_t *pstrIn = NULL; + cstr_t *pstrOut = NULL; + rsRetVal iRetExpected; + DEFiRet; + + if((fp = fopen((char*)pszFileName, "r")) == NULL) { + perror((char*)pszFileName); + ABORT_FINALIZE(RS_RET_FILE_NOT_FOUND); + } + + /* skip comments at start of file */ + + getline(&lnptr, &lenLn, fp); + while(!feof(fp)) { + if(*lnptr == '#') + getline(&lnptr, &lenLn, fp); + else + break; /* first non-comment */ + } + CHKEOF; + + /* once we had a comment, the next line MUST be "result: ". Anything + * after nbr is simply ignored. + */ + if(sscanf(lnptr, "result: %d", &iRetExpected) != 1) { + printf("error in result line, scanf failed, line: '%s'\n", lnptr); + ABORT_FINALIZE(RS_RET_ERR); + } + getline(&lnptr, &lenLn, fp); CHKEOF; + + /* and now we look for "in:" (and again ignore the rest...) */ + if(strncmp(lnptr, "in:", 3)) { + printf("error: expected 'in:'-line, but got: '%s'\n", lnptr); + ABORT_FINALIZE(RS_RET_ERR); + } + /* if we reach this point, we need to read in the input script. It is + * terminated by a line with three sole $ ($$$\n) + */ + CHKiRet(rsCStrConstruct(&pstrIn)); + getline(&lnptr, &lenLn, fp); CHKEOF; + while(strncmp(lnptr, "$$$\n", 4)) { + CHKiRet(rsCStrAppendStr(pstrIn, (uchar*)lnptr)); + getline(&lnptr, &lenLn, fp); CHKEOF; + } + getline(&lnptr, &lenLn, fp); CHKEOF; /* skip $$$-line */ + + /* and now we look for "out:" (and again ignore the rest...) */ + if(strncmp(lnptr, "out:", 4)) { + printf("error: expected 'out:'-line, but got: '%s'\n", lnptr); + ABORT_FINALIZE(RS_RET_ERR); + } + /* if we reach this point, we need to read in the expected program code. It is + * terminated by a line with three sole $ ($$$\n) + */ + CHKiRet(rsCStrConstruct(&pstrOut)); + getline(&lnptr, &lenLn, fp); CHKEOF; + while(strncmp(lnptr, "$$$\n", 4)) { + CHKiRet(rsCStrAppendStr(pstrOut, (uchar*)lnptr)); + getline(&lnptr, &lenLn, fp); CHKEOF; + } + + /* un-comment for testing: + * printf("iRet: %d, script: %s\n, out: %s\n", iRetExpected, rsCStrGetSzStr(pstrIn),rsCStrGetSzStr(pstrOut)); + */ + if(rsCStrGetSzStr(pstrIn) == NULL) { + printf("error: input script is empty!\n"); + ABORT_FINALIZE(RS_RET_ERR); + } + if(rsCStrGetSzStr(pstrOut) == NULL && iRetExpected == RS_RET_OK) { + printf("error: output script is empty!\n"); + ABORT_FINALIZE(RS_RET_ERR); + } + + CHKiRet(PerformTest(pstrIn, iRetExpected, pstrOut)); + +finalize_it: + if(pstrIn != NULL) + rsCStrDestruct(&pstrIn); + if(pstrOut != NULL) + rsCStrDestruct(&pstrOut); + RETiRet; +} + + +/* This test is parameterized. It search for test control files and + * loads all that it finds. To add tests, simply create new .rstest + * files. + * rgerhards, 2008-07-07 + */ +BEGINTest + uchar *testFile; + glob_t testFiles; + size_t i = 0; + struct stat fileInfo; +CODESTARTTest + glob("*.rstest", GLOB_MARK, NULL, &testFiles); + + for(i = 0; i < testFiles.gl_pathc; i++) { + testFile = (uchar*) testFiles.gl_pathv[i]; + + if(stat((char*) testFile, &fileInfo) != 0) + continue; /* continue with the next file if we can't stat() the file */ + + /* all regular files are run through the test logic. Symlinks don't work. */ + if(S_ISREG(fileInfo.st_mode)) { /* config file */ + printf("processing RainerScript test file '%s'...\n", testFile); + iRet = ProcessTestFile((uchar*) testFile); + if(iRet != RS_RET_OK) { + /* in this case, re-run with debugging on */ + printf("processing test case failed with %d, re-running with debug messages:\n", + iRet); + Debug = 1; /* these two are dirty, but we need them today... */ + debugging_on = 1; + CHKiRet(ProcessTestFile((uchar*) testFile)); + } + } + } + globfree(&testFiles); + +finalize_it: +ENDTest -- cgit v1.2.3 From c3c385c63b627d559bdd7a7a710c543e9c16a20a Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Tue, 29 Jul 2008 14:55:44 +0200 Subject: added testbed for config errors and fixed a bug - bugfix: no error was reported if the target of a $IncludeConfig could not be accessed. - added testbed for common config errors --- tests/rscript.c | 1 + 1 file changed, 1 insertion(+) (limited to 'tests/rscript.c') diff --git a/tests/rscript.c b/tests/rscript.c index f82107ed..d4e8caeb 100644 --- a/tests/rscript.c +++ b/tests/rscript.c @@ -2,6 +2,7 @@ * also serves as the most simplistic sample of how a test can be coded. * * Part of the testbench for rsyslog. + * * Copyright 2008 Rainer Gerhards and Adiscon GmbH. * * This file is part of rsyslog. -- cgit v1.2.3 From 935018ed625bc4cf1d6b28fa16e0986078029aaf Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Thu, 19 Mar 2009 13:58:39 +0100 Subject: adapted test framework to new script engine --- tests/rscript.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'tests/rscript.c') diff --git a/tests/rscript.c b/tests/rscript.c index d4e8caeb..3eec9c3c 100644 --- a/tests/rscript.c +++ b/tests/rscript.c @@ -101,9 +101,10 @@ PerformTest(cstr_t *pstrIn, rsRetVal iRetExpected, cstr_t *pstrOut) CHKiRet(vmprg.Obj2Str(pExpr->pVmprg, pstrPrg)); if(strcmp((char*)rsCStrGetSzStr(pstrPrg), (char*)rsCStrGetSzStr(pstrOut))) { + int iLen; printf("error: compiled program different from expected result!\n"); - printf("generated vmprg:\n%s\n", rsCStrGetSzStr(pstrPrg)); - printf("expected:\n%s\n", rsCStrGetSzStr(pstrOut)); + printf("generated vmprg (%d bytes):\n%s\n", strlen(rsCStrGetSzStr(pstrPrg)), rsCStrGetSzStr(pstrPrg)); + printf("expected (%d bytes):\n%s\n", strlen(rsCStrGetSzStr(pstrOut)), rsCStrGetSzStr(pstrOut)); ABORT_FINALIZE(RS_RET_ERR); } -- cgit v1.2.3 From 3e3a9bc9982331e44cf397fef131e75553f2ab2c Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Tue, 31 Mar 2009 12:00:40 +0200 Subject: ported non-tcl based test suite to Solaris --- tests/rscript.c | 41 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 37 insertions(+), 4 deletions(-) (limited to 'tests/rscript.c') diff --git a/tests/rscript.c b/tests/rscript.c index 3eec9c3c..4906f91a 100644 --- a/tests/rscript.c +++ b/tests/rscript.c @@ -39,6 +39,38 @@ DEFobjCurrIf(ctok) DEFobjCurrIf(ctok_token) DEFobjCurrIf(vmprg) + +/* we emulate getline (the dirty way) if we do not have it + * We do not try very hard, as this is just a test driver. + * rgerhards, 2009-03-31 + */ +#ifndef HAVE_GETLINE +ssize_t getline(char **lineptr, size_t *n, FILE *fp) +{ + int c; + int len = 0; + + if(*lineptr == NULL) + *lineptr = malloc(1024); /* quick and dirty! */ + + c = fgetc(fp); + while(c != EOF && c != '\n') { + (*lineptr)[len++] = c; + c = fgetc(fp); + } + if(c != EOF) /* need to add NL? */ + (*lineptr)[len++] = c; + + (*lineptr)[len] = '\0'; + + *n = len; + //printf("getline returns: '%s'\n", *lineptr); + + return (len > 0) ? len : -1; +} +#endif /* #ifndef HAVE_GETLINE */ + + BEGINInit CODESTARTInit pErrObj = "expr"; CHKiRet(objUse(expr, CORE_COMPONENT)); @@ -101,10 +133,9 @@ PerformTest(cstr_t *pstrIn, rsRetVal iRetExpected, cstr_t *pstrOut) CHKiRet(vmprg.Obj2Str(pExpr->pVmprg, pstrPrg)); if(strcmp((char*)rsCStrGetSzStr(pstrPrg), (char*)rsCStrGetSzStr(pstrOut))) { - int iLen; printf("error: compiled program different from expected result!\n"); - printf("generated vmprg (%d bytes):\n%s\n", strlen(rsCStrGetSzStr(pstrPrg)), rsCStrGetSzStr(pstrPrg)); - printf("expected (%d bytes):\n%s\n", strlen(rsCStrGetSzStr(pstrOut)), rsCStrGetSzStr(pstrOut)); + printf("generated vmprg (%d bytes):\n%s\n", strlen((char*)rsCStrGetSzStr(pstrPrg)), rsCStrGetSzStr(pstrPrg)); + printf("expected (%d bytes):\n%s\n", strlen((char*)rsCStrGetSzStr(pstrOut)), rsCStrGetSzStr(pstrOut)); ABORT_FINALIZE(RS_RET_ERR); } @@ -139,6 +170,7 @@ ProcessTestFile(uchar *pszFileName) size_t lenLn; cstr_t *pstrIn = NULL; cstr_t *pstrOut = NULL; + int iParse; rsRetVal iRetExpected; DEFiRet; @@ -161,10 +193,11 @@ ProcessTestFile(uchar *pszFileName) /* once we had a comment, the next line MUST be "result: ". Anything * after nbr is simply ignored. */ - if(sscanf(lnptr, "result: %d", &iRetExpected) != 1) { + if(sscanf(lnptr, "result: %d", &iParse) != 1) { printf("error in result line, scanf failed, line: '%s'\n", lnptr); ABORT_FINALIZE(RS_RET_ERR); } + iRetExpected = iParse; getline(&lnptr, &lenLn, fp); CHKEOF; /* and now we look for "in:" (and again ignore the rest...) */ -- cgit v1.2.3 From d27edc7587dba7b850759d151d90cdad1cb34a35 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Tue, 31 Mar 2009 20:35:15 +0200 Subject: porting parser tests to solaris --- tests/rscript.c | 31 ------------------------------- 1 file changed, 31 deletions(-) (limited to 'tests/rscript.c') diff --git a/tests/rscript.c b/tests/rscript.c index 4906f91a..6b232f5f 100644 --- a/tests/rscript.c +++ b/tests/rscript.c @@ -40,37 +40,6 @@ DEFobjCurrIf(ctok_token) DEFobjCurrIf(vmprg) -/* we emulate getline (the dirty way) if we do not have it - * We do not try very hard, as this is just a test driver. - * rgerhards, 2009-03-31 - */ -#ifndef HAVE_GETLINE -ssize_t getline(char **lineptr, size_t *n, FILE *fp) -{ - int c; - int len = 0; - - if(*lineptr == NULL) - *lineptr = malloc(1024); /* quick and dirty! */ - - c = fgetc(fp); - while(c != EOF && c != '\n') { - (*lineptr)[len++] = c; - c = fgetc(fp); - } - if(c != EOF) /* need to add NL? */ - (*lineptr)[len++] = c; - - (*lineptr)[len] = '\0'; - - *n = len; - //printf("getline returns: '%s'\n", *lineptr); - - return (len > 0) ? len : -1; -} -#endif /* #ifndef HAVE_GETLINE */ - - BEGINInit CODESTARTInit pErrObj = "expr"; CHKiRet(objUse(expr, CORE_COMPONENT)); -- cgit v1.2.3 From 5ab3e8005f62c2016bdb2d3b099d1d8c1a4cf2bc Mon Sep 17 00:00:00 2001 From: Michael Biebl Date: Mon, 18 May 2009 21:07:07 +0200 Subject: Fix compiler warnings include for memcpy and strlen. Signed-off-by: Rainer Gerhards --- tests/rscript.c | 1 + 1 file changed, 1 insertion(+) (limited to 'tests/rscript.c') diff --git a/tests/rscript.c b/tests/rscript.c index 6b232f5f..ce81491c 100644 --- a/tests/rscript.c +++ b/tests/rscript.c @@ -24,6 +24,7 @@ */ #include "config.h" #include +#include #include #include -- cgit v1.2.3 From 58e707b441aea88cd318762e6968e1db1211f949 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Thu, 4 Jun 2009 09:57:45 +0200 Subject: backported some of the v5 testbench this permits us to keep a persistent test environment between v4 and v5, most importantly using the same tools. As far as the actual tests are concerned, some had issues. I had no time to check if that was an issue with the test or an actual issue with the v3/4 engine. Will do that at some later stage. --- tests/rscript.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'tests/rscript.c') diff --git a/tests/rscript.c b/tests/rscript.c index ce81491c..6361aec4 100644 --- a/tests/rscript.c +++ b/tests/rscript.c @@ -104,8 +104,8 @@ PerformTest(cstr_t *pstrIn, rsRetVal iRetExpected, cstr_t *pstrOut) if(strcmp((char*)rsCStrGetSzStr(pstrPrg), (char*)rsCStrGetSzStr(pstrOut))) { printf("error: compiled program different from expected result!\n"); - printf("generated vmprg (%d bytes):\n%s\n", strlen((char*)rsCStrGetSzStr(pstrPrg)), rsCStrGetSzStr(pstrPrg)); - printf("expected (%d bytes):\n%s\n", strlen((char*)rsCStrGetSzStr(pstrOut)), rsCStrGetSzStr(pstrOut)); + printf("generated vmprg (%d bytes):\n%s\n", (int)strlen((char*)rsCStrGetSzStr(pstrPrg)), rsCStrGetSzStr(pstrPrg)); + printf("expected (%d bytes):\n%s\n", (int)strlen((char*)rsCStrGetSzStr(pstrOut)), rsCStrGetSzStr(pstrOut)); ABORT_FINALIZE(RS_RET_ERR); } -- cgit v1.2.3 From d348558a51402d08310d95cfd6e8a2d6b9fce1b2 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Tue, 19 Apr 2011 11:26:37 +0200 Subject: milestone: conf obj interface now utilzes rsconf_t --- tests/rscript.c | 1 + 1 file changed, 1 insertion(+) (limited to 'tests/rscript.c') diff --git a/tests/rscript.c b/tests/rscript.c index 6361aec4..5baf74cc 100644 --- a/tests/rscript.c +++ b/tests/rscript.c @@ -33,6 +33,7 @@ #include "ctok.h" #include "expr.h" +rsconf_t *ourConf; MODULE_TYPE_TESTBENCH /* define addtional objects we need for our tests */ DEFobjCurrIf(expr) -- cgit v1.2.3