summaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/.gitignore3
-rw-r--r--tests/1.rstest26
-rw-r--r--tests/2.rstest10
-rw-r--r--tests/DevNull.cfgtest2
-rw-r--r--tests/Makefile.am33
-rw-r--r--tests/NoExistFile.cfgtest2
-rw-r--r--tests/README9
-rwxr-xr-xtests/cfg.sh139
-rw-r--r--tests/cfg1.cfgtest3
-rw-r--r--tests/cfg1.testin2
-rw-r--r--tests/cfg2.cfgtest3
-rw-r--r--tests/cfg2.testin1
-rw-r--r--tests/cfg3.cfgtest5
-rw-r--r--tests/cfg3.testin1
-rw-r--r--tests/cfg4.cfgtest1
-rw-r--r--tests/cfg4.testin67
-rw-r--r--tests/err1.rstest7
-rw-r--r--tests/rscript.c259
-rw-r--r--tests/rt-init.c44
-rw-r--r--tests/runtime-dummy.c41
-rw-r--r--tests/testbench.h103
-rw-r--r--tests/testsuites/invalid.conf3
-rw-r--r--tests/testsuites/valid.conf3
-rwxr-xr-xtests/validation-run.sh38
24 files changed, 805 insertions, 0 deletions
diff --git a/tests/.gitignore b/tests/.gitignore
new file mode 100644
index 00000000..a8177ad4
--- /dev/null
+++ b/tests/.gitignore
@@ -0,0 +1,3 @@
+rscript
+rt_init
+tmp
diff --git a/tests/1.rstest b/tests/1.rstest
new file mode 100644
index 00000000..5c152589
--- /dev/null
+++ b/tests/1.rstest
@@ -0,0 +1,26 @@
+# a simple RainerScript test
+result: 0
+in:
+'test 1' <> $var or /* some comment */($SEVERITY == -4 +5 -(3 * - 2) and $fromhost == '127.0.0.1') then
+$$$
+out:
+00000000: PUSHCONSTANT test 1[cstr]
+00000001: PUSHMSGVAR var[cstr]
+00000002: !=
+00000003: PUSHMSGVAR severity[cstr]
+00000004: PUSHCONSTANT 4[nbr]
+00000005: UNARY_MINUS
+00000006: PUSHCONSTANT 5[nbr]
+00000007: +
+00000008: PUSHCONSTANT 3[nbr]
+00000009: PUSHCONSTANT 2[nbr]
+00000010: UNARY_MINUS
+00000011: *
+00000012: -
+00000013: ==
+00000014: PUSHMSGVAR fromhost[cstr]
+00000015: PUSHCONSTANT 127.0.0.1[cstr]
+00000016: ==
+00000017: and
+00000018: or
+$$$
diff --git a/tests/2.rstest b/tests/2.rstest
new file mode 100644
index 00000000..7fb5b799
--- /dev/null
+++ b/tests/2.rstest
@@ -0,0 +1,10 @@
+# a simple RainerScript test
+result: 0
+in:
+$msg contains 'test' then
+$$$
+out:
+00000000: PUSHMSGVAR msg[cstr]
+00000001: PUSHCONSTANT test[cstr]
+00000002: contains
+$$$
diff --git a/tests/DevNull.cfgtest b/tests/DevNull.cfgtest
new file mode 100644
index 00000000..7822b6df
--- /dev/null
+++ b/tests/DevNull.cfgtest
@@ -0,0 +1,2 @@
+rsyslogd: CONFIG ERROR: there are no active actions configured. Inputs will run, but no output whatsoever is created. [try http://www.rsyslog.com/e/2103 ]
+rsyslogd: EMERGENCY CONFIGURATION ACTIVATED - fix rsyslog config file!
diff --git a/tests/Makefile.am b/tests/Makefile.am
new file mode 100644
index 00000000..802a3ccb
--- /dev/null
+++ b/tests/Makefile.am
@@ -0,0 +1,33 @@
+check_PROGRAMS = rt_init rscript
+TESTS = $(check_PROGRAMS) cfg.sh \
+ validation-run.sh
+TESTS_ENVIRONMENT = RSYSLOG_MODDIR='$(abs_top_builddir)'/runtime/.libs/
+#TESTS = $(check_PROGRAMS)
+
+test_files = testbench.h runtime-dummy.c
+EXTRA_DIST=1.rstest 2.rstest err1.rstest \
+ validation-run.sh \
+ testsuites/invalid.conf \
+ testsuites/valid.conf \
+ cfg.sh \
+ cfg1.cfgtest \
+ cfg1.testin \
+ cfg2.cfgtest \
+ cfg2.testin \
+ cfg3.cfgtest \
+ cfg3.testin \
+ cfg4.cfgtest \
+ cfg4.testin \
+ DevNull.cfgtest \
+ err1.rstest \
+ NoExistFile.cfgtest
+
+rt_init_SOURCES = rt-init.c $(test_files)
+rt_init_CPPFLAGS = -I$(top_srcdir) $(PTHREADS_CFLAGS) $(RSRT_CFLAGS)
+rt_init_LDADD = $(RSRT_LIBS) $(ZLIB_LIBS) $(PTHREADS_LIBS)
+rt_init_LDFLAGS = -export-dynamic
+
+rscript_SOURCES = rscript.c $(test_files)
+rscript_CPPFLAGS = -I$(top_srcdir) $(PTHREADS_CFLAGS) $(RSRT_CFLAGS)
+rscript_LDADD = $(RSRT_LIBS) $(ZLIB_LIBS) $(PTHREADS_LIBS)
+rscript_LDFLAGS = -export-dynamic
diff --git a/tests/NoExistFile.cfgtest b/tests/NoExistFile.cfgtest
new file mode 100644
index 00000000..88d3123f
--- /dev/null
+++ b/tests/NoExistFile.cfgtest
@@ -0,0 +1,2 @@
+rsyslogd: CONFIG ERROR: could not interpret master config file '/This/does/not/exist'. [try http://www.rsyslog.com/e/2013 ]
+rsyslogd: EMERGENCY CONFIGURATION ACTIVATED - fix rsyslog config file!
diff --git a/tests/README b/tests/README
new file mode 100644
index 00000000..0ce79f63
--- /dev/null
+++ b/tests/README
@@ -0,0 +1,9 @@
+This directory contains the rsyslog testbench. It is slowly
+evolving. New tests are always welcome. So far, most tests check
+out the functionality of a single module. More complex tests are
+welcome.
+
+For a simple sample, see rtinit.c, which does a simple
+init/deinit check of the runtime system.
+
+rgerhards, 2008-06-13
diff --git a/tests/cfg.sh b/tests/cfg.sh
new file mode 100755
index 00000000..99729823
--- /dev/null
+++ b/tests/cfg.sh
@@ -0,0 +1,139 @@
+# /bin/bash
+# This is a simple shell script that carries out some checks against
+# configurations we expect from some provided config files. We use
+# rsyslogd's verifcation function. Note that modifications to the
+# config elements, or even simple text changes, cause these checks to
+# fail. However, it should be fairly easy to adapt them to the changed
+# environment. And while nothing changed, they permit is to make sure
+# that everything works well and is not broken by interim changes.
+# Note that we always compare starting with the second output line.
+# This is because the first line contains the rsyslog version ;)
+# rgerhards, 2008-07-29
+#
+# 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 <http://www.gnu.org/licenses/>.
+#
+# A copy of the GPL can be found in the file "COPYING" in this distribution.
+#set -x
+rm -f tmp
+echo "local directory"
+#
+# check empty config file
+#
+../tools/rsyslogd -c3 -N1 -f/dev/null 2>&1 |tail --lines=+2 > tmp
+cmp tmp $srcdir/DevNull.cfgtest
+if [ ! $? -eq 0 ]; then
+echo "DevNull.cfgtest failed"
+echo "Expected:"
+cat $srcdir/DevNull.cfgtest
+echo "Received:"
+cat tmp
+exit 1
+else
+echo "DevNull.cfgtest succeeded"
+fi;
+#
+# check missing config file
+#
+../tools/rsyslogd -c3 -N1 -f/This/does/not/exist 2>&1 |tail --lines=+2 > tmp
+cmp tmp $srcdir/NoExistFile.cfgtest
+if [ ! $? -eq 0 ]; then
+echo "NoExistFile.cfgtest failed"
+echo "Expected:"
+cat $srcdir/NoExistFile.cfgtest
+echo "Received:"
+cat tmp
+exit 1
+else
+echo "NoExistFile.cfgtest succeeded"
+fi;
+
+
+# TODO: re-enable the following checks. They need to have support in
+# rsyslogd so that the log file name is NOT contained in the error
+# messages - this prevents proper comparison in make distcheck
+rm -f tmp
+exit 0
+
+#
+# check config with invalid directive
+#
+../tools/rsyslogd -c3 -u2 -N1 -f$srcdir/cfg1.testin 2>&1 |tail --lines=+2 > tmp
+cmp tmp $srcdir/cfg1.cfgtest
+if [ ! $? -eq 0 ]; then
+echo "cfg1.cfgtest failed"
+echo "Expected:"
+cat $srcdir/cfg1.cfgtest
+echo "Received:"
+cat tmp
+exit 1
+else
+echo "cfg1.cfgtest succeeded"
+fi;
+#
+# now check for included config file. We use a sample similar to
+# the one with the invalid config directive, so that we may see
+# an effect of the included config ;)
+#
+../tools/rsyslogd -c3 -u2 -N1 -f$srcdir/cfg2.testin 2>&1 |tail --lines=+2 > tmp
+cmp tmp $srcdir/cfg2.cfgtest
+if [ ! $? -eq 0 ]; then
+echo "cfg2.cfgtest failed"
+echo "Expected:"
+cat $srcdir/cfg2.cfgtest
+echo "Received:"
+cat tmp
+exit 1
+else
+echo "cfg2.cfgtest succeeded"
+fi;
+#
+# check included config file, where included file does not exist
+#
+../tools/rsyslogd -c3 -u2 -N1 -f$srcdir/cfg3.testin 2>&1 |tail --lines=+2 > tmp
+cmp tmp $srcdir/cfg3.cfgtest
+if [ ! $? -eq 0 ]; then
+echo "cfg3.cfgtest failed"
+echo "Expected:"
+cat $srcdir/cfg3.cfgtest
+echo "Received:"
+cat tmp
+exit 1
+else
+echo "cfg3.cfgtest succeeded"
+fi;
+#
+# check a reasonable complex, but correct, log file
+#
+../tools/rsyslogd -c3 -u2 -N1 -f$srcdir/cfg4.testin 2>&1 |tail --lines=+2 > tmp
+cmp tmp $srcdir/cfg4.cfgtest
+if [ ! $? -eq 0 ]; then
+echo "cfg4.cfgtest failed"
+echo "Expected:"
+cat $srcdir/cfg4.cfgtest
+echo "Received:"
+cat tmp
+exit 1
+else
+echo "cfg4.cfgtest succeeded"
+fi;
+#
+# done, some cleanup
+#
+rm -f tmp
diff --git a/tests/cfg1.cfgtest b/tests/cfg1.cfgtest
new file mode 100644
index 00000000..099ba929
--- /dev/null
+++ b/tests/cfg1.cfgtest
@@ -0,0 +1,3 @@
+rsyslogd: invalid or yet-unknown config file command - have you forgotten to load a module? [try http://www.rsyslog.com/e/3003 ]
+rsyslogd: the last error occured in ./cfg1.testin, line 2
+rsyslogd: End of config validation run. Bye.
diff --git a/tests/cfg1.testin b/tests/cfg1.testin
new file mode 100644
index 00000000..7d7b594c
--- /dev/null
+++ b/tests/cfg1.testin
@@ -0,0 +1,2 @@
+*.* *
+$invaliddirective test
diff --git a/tests/cfg2.cfgtest b/tests/cfg2.cfgtest
new file mode 100644
index 00000000..b44a487e
--- /dev/null
+++ b/tests/cfg2.cfgtest
@@ -0,0 +1,3 @@
+rsyslogd: invalid or yet-unknown config file command - have you forgotten to load a module? [try http://www.rsyslog.com/e/3003 ]
+rsyslogd: the last error occured in cfg1.testin, line 2
+rsyslogd: End of config validation run. Bye.
diff --git a/tests/cfg2.testin b/tests/cfg2.testin
new file mode 100644
index 00000000..b6d98c8f
--- /dev/null
+++ b/tests/cfg2.testin
@@ -0,0 +1 @@
+$includeconfig cfg1.testin
diff --git a/tests/cfg3.cfgtest b/tests/cfg3.cfgtest
new file mode 100644
index 00000000..68bc17d4
--- /dev/null
+++ b/tests/cfg3.cfgtest
@@ -0,0 +1,5 @@
+rsyslogd: error accessing config file or directory 'file-does-not-exist': No such file or directory [try http://www.rsyslog.com/e/2040 ]
+rsyslogd: the last error occured in ./cfg3.testin, line 1
+rsyslogd: CONFIG ERROR: there are no active actions configured. Inputs will run, but no output whatsoever is created. [try http://www.rsyslog.com/e/2103 ]
+rsyslogd: EMERGENCY CONFIGURATION ACTIVATED - fix rsyslog config file!
+rsyslogd: End of config validation run. Bye.
diff --git a/tests/cfg3.testin b/tests/cfg3.testin
new file mode 100644
index 00000000..9789d939
--- /dev/null
+++ b/tests/cfg3.testin
@@ -0,0 +1 @@
+$includeconfig file-does-not-exist
diff --git a/tests/cfg4.cfgtest b/tests/cfg4.cfgtest
new file mode 100644
index 00000000..04acf84f
--- /dev/null
+++ b/tests/cfg4.cfgtest
@@ -0,0 +1 @@
+rsyslogd: End of config validation run. Bye.
diff --git a/tests/cfg4.testin b/tests/cfg4.testin
new file mode 100644
index 00000000..a49c0fb6
--- /dev/null
+++ b/tests/cfg4.testin
@@ -0,0 +1,67 @@
+# This is more or less the sample config, but without imklog being
+# active. imklog must not always be present and as such may spoil
+# our testing result. The core point at this test is that a valid
+# config file should not lead to any error messages.
+# It may be a good idea to update this file from time to time, so that
+# it contains a reasonable complex config sample.
+
+# if you experience problems, check
+# http://www.rsyslog.com/troubleshoot for assistance
+
+# rsyslog v3: load input modules
+# If you do not load inputs, nothing happens!
+# You may need to set the module load path if modules are not found.
+
+#$ModLoad immark # provides --MARK-- message capability
+#$ModLoad imuxsock # provides support for local system logging (e.g. via logger command)
+#$ModLoad imklog # kernel logging (formerly provided by rklogd)
+
+# Log all kernel messages to the console.
+# Logging much else clutters up the screen.
+#kern.* /dev/console
+
+# Log anything (except mail) of level info or higher.
+# Don't log private authentication messages!
+*.info;mail.none;authpriv.none;cron.none -/var/log/messages
+
+# The authpriv file has restricted access.
+authpriv.* /var/log/secure
+
+# Log all the mail messages in one place.
+mail.* -/var/log/maillog
+
+
+# Log cron stuff
+cron.* -/var/log/cron
+
+# Everybody gets emergency messages
+*.emerg *
+
+# Save news errors of level crit and higher in a special file.
+uucp,news.crit -/var/log/spooler
+
+# Save boot messages also to boot.log
+local7.* /var/log/boot.log
+
+# Remote Logging (we use TCP for reliable delivery)
+# An on-disk queue is created for this action. If the remote host is
+# down, messages are spooled to disk and sent when it is up again.
+#$WorkDirectory /rsyslog/spool # where to place spool files
+#$ActionQueueFileName uniqName # unique name prefix for spool files
+#$ActionQueueMaxDiskSpace 1g # 1gb space limit (use as much as possible)
+#$ActionQueueSaveOnShutdown on # save messages to disk on shutdown
+#$ActionQueueType LinkedList # run asynchronously
+#$ActionResumeRetryCount -1 # infinite retries if host is down
+# remote host is: name/ip:port, e.g. 192.168.0.1:514, port optional
+#*.* @@remote-host:514
+
+
+# ######### Receiving Messages from Remote Hosts ##########
+# TCP Syslog Server:
+# provides TCP syslog reception and GSS-API (if compiled to support it)
+#$ModLoad imtcp.so # load module
+#$InputTCPServerRun 514 # start up TCP listener at port 514
+
+# UDP Syslog Server:
+#$ModLoad imudp.so # provides UDP syslog reception
+#$UDPServerRun 514 # start a UDP syslog server at standard port 514
diff --git a/tests/err1.rstest b/tests/err1.rstest
new file mode 100644
index 00000000..8c56887e
--- /dev/null
+++ b/tests/err1.rstest
@@ -0,0 +1,7 @@
+# This test case check for an error condition
+result: -2051
+in:
+'test 1' <> == $hostname
+$$$
+out:
+$$$
diff --git a/tests/rscript.c b/tests/rscript.c
new file mode 100644
index 00000000..d4e8caeb
--- /dev/null
+++ b/tests/rscript.c
@@ -0,0 +1,259 @@
+/* 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 <http://www.gnu.org/licenses/>.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ */
+#include "config.h"
+#include <stdio.h>
+#include <glob.h>
+#include <sys/stat.h>
+
+#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: <nbr>". 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
diff --git a/tests/rt-init.c b/tests/rt-init.c
new file mode 100644
index 00000000..aaac7ed1
--- /dev/null
+++ b/tests/rt-init.c
@@ -0,0 +1,44 @@
+/* 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 <http://www.gnu.org/licenses/>.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ */
+#include <stdio.h>
+
+#include "rsyslog.h"
+#include "testbench.h"
+
+MODULE_TYPE_TESTBENCH
+
+
+BEGINInit
+CODESTARTInit
+ENDInit
+
+BEGINExit
+CODESTARTExit
+ENDExit
+
+BEGINTest
+CODESTARTTest
+finalize_it:
+ /* room for custom error reporter, leave blank if not needed */
+ENDTest
diff --git a/tests/runtime-dummy.c b/tests/runtime-dummy.c
new file mode 100644
index 00000000..9cddd913
--- /dev/null
+++ b/tests/runtime-dummy.c
@@ -0,0 +1,41 @@
+/* Testbench for rsyslog
+ *
+ * This are dummy calls for "runtime" routines which are not yet properly
+ * abstracted and part of the actual runtime libraries. This module tries
+ * to make the linker happy. Please note that it does NOT provide anything
+ * more but the symbols. If a test requires these functions (or functions
+ * that depend on them), this dummy can not be used.
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ */
+#include <stdlib.h>
+
+int bReduceRepeatMsgs = 0;
+int repeatinterval = 30;
+int bActExecWhenPrevSusp = 0;
+int iActExecOnceInterval = 1;
+int MarkInterval = 30;
+
+void cflineClassic(void) {};
+void selectorAddList(void) {};
+void selectorConstruct(void) {};
+void selectorDestruct(void) {};
+
+/* these are required by some dynamically loaded modules */
diff --git a/tests/testbench.h b/tests/testbench.h
new file mode 100644
index 00000000..12687743
--- /dev/null
+++ b/tests/testbench.h
@@ -0,0 +1,103 @@
+/* Defines for a rsyslog standard testbench application.
+ *
+ * Work begun 2008-06-13 by Rainer Gerhards (written from scratch)
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ *
+ * A copy of the GPL can be found in the file "COPYING" in this distribution.
+ */
+#include <stdlib.h>
+
+/* everything we need to begin a testbench */
+#define MODULE_TYPE_TESTBENCH \
+/* definitions for objects we access */ \
+DEFobjCurrIf(obj) \
+\
+static rsRetVal doInit(void); \
+static rsRetVal doTest(void); \
+static rsRetVal doExit(void); \
+\
+/* Below is the driver, which is always the same */ \
+int main(int __attribute__((unused)) argc, char __attribute__((unused)) *argv[]) \
+{ \
+ DEFiRet; \
+ CHKiRet(doInit()); \
+ CHKiRet(doTest()); \
+ CHKiRet(doExit()); \
+finalize_it: \
+ if(iRet != RS_RET_OK) \
+ printf("test returns iRet %d\n", iRet); \
+ RETiRet; \
+}
+
+
+/* Initialize everything (most importantly the runtime objects) for the test. The framework
+ * initializes the global runtime, user must add those objects that it needs additionally.
+ */
+#define BEGINInit \
+static rsRetVal doInit(void) \
+{ \
+ DEFiRet; \
+ char *pErrObj; /* tells us which object failed if that happens */ \
+ putenv("RSYSLOG_MODDIR=../runtime/.libs/"); /* this is a bit hackish... */ \
+ \
+ dbgClassInit(); \
+ /* Intialize the runtime system */ \
+ pErrObj = "rsyslog runtime"; /* set in case the runtime errors before setting an object */ \
+ CHKiRet(rsrtInit(&pErrObj, &obj)); \
+
+#define CODESTARTInit
+
+#define ENDInit \
+finalize_it: \
+ if(iRet != RS_RET_OK) { \
+ printf("failure occured during init of object '%s'\n", pErrObj); \
+ } \
+ \
+ RETiRet; \
+}
+
+
+
+/* Carry out the actual test...
+ */
+#define BEGINTest \
+rsRetVal doTest(void) \
+{ \
+ DEFiRet;
+
+#define CODESTARTTest
+
+#define ENDTest \
+ RETiRet; \
+}
+
+
+/* De-init everything (most importantly the runtime objects) for the test. */
+#define BEGINExit \
+rsRetVal doExit(void) \
+{ \
+ DEFiRet; \
+ CHKiRet(rsrtExit());
+
+#define CODESTARTExit
+
+#define ENDExit \
+finalize_it: \
+ RETiRet; \
+}
diff --git a/tests/testsuites/invalid.conf b/tests/testsuites/invalid.conf
new file mode 100644
index 00000000..8a865ba5
--- /dev/null
+++ b/tests/testsuites/invalid.conf
@@ -0,0 +1,3 @@
+# This is an invalid config file that shall trigger an exit code
+# with the config verification run
+$invalid
diff --git a/tests/testsuites/valid.conf b/tests/testsuites/valid.conf
new file mode 100644
index 00000000..250f0546
--- /dev/null
+++ b/tests/testsuites/valid.conf
@@ -0,0 +1,3 @@
+# This is an invalid config file that shall trigger an exit code
+# with the config verification run
+*.* /tmp/data.log
diff --git a/tests/validation-run.sh b/tests/validation-run.sh
new file mode 100755
index 00000000..10981290
--- /dev/null
+++ b/tests/validation-run.sh
@@ -0,0 +1,38 @@
+# check if the configuration test run detects invalid config files.
+#
+# Part of the testbench for rsyslog.
+#
+# Copyright 2009 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 <http://www.gnu.org/licenses/>.
+#
+# A copy of the GPL can be found in the file "COPYING" in this distribution.
+#set -x
+echo "testing a failed configuration verification run"
+../tools/rsyslogd -u2 -c3 -N1 -f$srcdir/testsuites/invalid.conf
+if [ $? -ne 1 ]; then
+ exit 1
+fi
+echo testing a valid config verification run
+../tools/rsyslogd -u2 -c3 -N1 -f$srcdir/testsuites/valid.conf
+if [ $? -ne 0 ]; then
+ exit 1
+fi
+echo testing empty config file
+../tools/rsyslogd -u2 -c3 -N1 -f/dev/null
+if [ $? -ne 1 ]; then
+ exit 1
+fi