summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--ChangeLog8
-rw-r--r--configure.ac16
-rw-r--r--doc/manual.html2
-rw-r--r--doc/status.html14
-rw-r--r--runtime/var.c40
-rw-r--r--runtime/var.h1
-rw-r--r--runtime/vmop.c37
-rw-r--r--runtime/vmop.h2
-rw-r--r--runtime/vmprg.c39
-rw-r--r--runtime/vmprg.h3
-rw-r--r--tests/.gitignore2
-rw-r--r--tests/1.rstest26
-rw-r--r--tests/2.rstest10
-rw-r--r--tests/Makefile.am11
-rw-r--r--tests/err1.rstest7
-rw-r--r--tests/rscript-parse.c100
-rw-r--r--tests/rscript.c258
-rw-r--r--tests/testbench.h3
-rw-r--r--tools/Makefile.am6
-rw-r--r--tools/gethostn.c46
21 files changed, 509 insertions, 123 deletions
diff --git a/.gitignore b/.gitignore
index bb5e1609..ea044fbe 100644
--- a/.gitignore
+++ b/.gitignore
@@ -34,3 +34,4 @@ tmp*
log
logfile
debug
+core.*
diff --git a/ChangeLog b/ChangeLog
index da102b14..03aac459 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,12 @@
---------------------------------------------------------------------------
+Version 3.21.0 [DEVEL] (rgerhards), 2008-07-18
+- starts a new devel branch
+- added a generic test driver for RainerScript plus some test cases
+ to the testbench
+- added a small diagnostic tool to obtain result of gethostname() API
+- imported all changes from 3.18.1 until today (some quite important,
+ see below)
+---------------------------------------------------------------------------
Version 3.19.11 [BETA] (rgerhards), 2008-??-??
---------------------------------------------------------------------------
Version 3.19.10 [BETA] (rgerhards), 2008-07-15
diff --git a/configure.ac b/configure.ac
index 13ef63d0..8352de64 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2,7 +2,7 @@
# Process this file with autoconf to produce a configure script.
AC_PREREQ(2.61)
-AC_INIT([rsyslog],[3.19.11],[rsyslog@lists.adiscon.com])
+AC_INIT([rsyslog],[3.21.0],[rsyslog@lists.adiscon.com])
AM_INIT_AUTOMAKE
AC_CONFIG_SRCDIR([ChangeLog])
AC_CONFIG_HEADERS([config.h])
@@ -331,6 +331,19 @@ if test "$enable_valgrind" = "yes"; then
fi
+# compile diagnostic tools (small helpers usually not needed)
+AC_ARG_ENABLE(diagtools,
+ [AS_HELP_STRING([--enable-diagtools],[Enable diagnostic tools @<:@default=no@:>@])],
+ [case "${enableval}" in
+ yes) enable_diagtools="yes" ;;
+ no) enable_diagtools="no" ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-diagtools) ;;
+ esac],
+ [enable_mail=no]
+)
+AM_CONDITIONAL(ENABLE_DIAGTOOLS, test x$enable_diagtools = xyes)
+
+
# MySQL support
AC_ARG_ENABLE(mysql,
@@ -671,6 +684,7 @@ echo "GnuTLS network stream driver enabled: $enable_gnutls"
echo "Enable GSSAPI Kerberos 5 support: $want_gssapi_krb5"
echo "Debug mode enabled: $enable_debug"
echo "Runtime Instrumentation enabled: $enable_rtinst"
+echo "Diagnostic tools enabled: $enable_diagtools"
echo "valgrind support settings enabled: $enable_valgrind"
echo "rsyslog runtime will be built: $enable_rsyslogrt"
echo "rsyslogd will be built: $enable_rsyslogd"
diff --git a/doc/manual.html b/doc/manual.html
index 91c58a43..fe97ef84 100644
--- a/doc/manual.html
+++ b/doc/manual.html
@@ -16,7 +16,7 @@ relay chains while at the same time being very easy to setup for the
novice user. And as we know what enterprise users really need, there is
also <a href="professional_support.html">professional
rsyslog support</a> available directly from the source!</p>
-<p><b>This documentation is for version 3.19.11 (beta branch) of rsyslog.</b>
+<p><b>This documentation is for version 3.21.0 (devel branch) of rsyslog.</b>
Visit the <i> <a href="http://www.rsyslog.com/doc-status.html">rsyslog status page</a></i></b> to obtain current
version information and project status.
</p><p><b>If you like rsyslog, you might
diff --git a/doc/status.html b/doc/status.html
index 90932fca..be012524 100644
--- a/doc/status.html
+++ b/doc/status.html
@@ -2,21 +2,19 @@
<html><head><title>rsyslog status page</title></head>
<body>
<h2>rsyslog status page</h2>
-<p>This page reflects the status as of 2008-07-15.</p>
+<p>This page reflects the status as of 2008-07-18.</p>
<h2>Current Releases</h2>
-<!-- no devel at this time!
-<p><b>development:</b> 3.19.9 [2008-07-07] -
-<a href="http://www.rsyslog.com/Article250.phtml">change log</a> -
-<a href="http://www.rsyslog.com/Downloads-req-viewdownloaddetails-lid-117.phtml">download</a>
--->
+<p><b>development:</b> 3.21.0 [2008-07-18] -
+<a href="http://www.rsyslog.com/Article258.phtml">change log</a> -
+<a href="http://www.rsyslog.com/Downloads-req-viewdownloaddetails-lid-121.phtml">download</a>
<br><b>beta:</b> 3.19.10 [2008-07-15] -
<a href="http://www.rsyslog.com/Article256.phtml">change log</a> -
-<a href="http://www.rsyslog.com/Downloads-req-viewdownloaddetails-lid-109.phtml">download</a></p>
+<a href="http://www.rsyslog.com/Downloads-req-viewdownloaddetails-lid-120.phtml">download</a></p>
<p><b>v3 stable:</b> 3.18.0 [2008-07-11] - <a href="http://www.rsyslog.com/Article254.phtml">change log</a> -
-<a href="http://www.rsyslog.com/Downloads-req-viewdownloaddetails-lid-120.phtml">download</a>
+<a href="http://www.rsyslog.com/Downloads-req-viewdownloaddetails-lid-119.phtml">download</a>
<br><b>v2 stable:</b> 2.0.5 [2008-05-15] - <a href="http://www.rsyslog.com/Article226.phtml">change log</a> -
<a href="http://www.rsyslog.com/Downloads-req-viewdownloaddetails-lid-104.phtml">download</a>
diff --git a/runtime/var.c b/runtime/var.c
index 7e51fc6d..559bc56c 100644
--- a/runtime/var.c
+++ b/runtime/var.c
@@ -29,6 +29,7 @@
*/
#include "config.h"
+#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
@@ -89,6 +90,44 @@ CODESTARTobjDebugPrint(var)
ENDobjDebugPrint(var)
+/* This function is similar to DebugPrint, but does not send its output to
+ * the debug log but instead to a caller-provided string. The idea here is that
+ * we can use this string to get a textual representation of a variable.
+ * Among others, this is useful for creating testbenches, our first use case for
+ * it. Here, it enables simple comparison of the resulting program to a
+ * reference program by simple string compare.
+ * Note that the caller must initialize the string object. We always add
+ * data to it. So, it can be easily combined into a chain of methods
+ * to generate the final string.
+ * rgerhards, 2008-07-07
+ */
+static rsRetVal
+Obj2Str(var_t *pThis, cstr_t *pstrPrg)
+{
+ DEFiRet;
+ size_t lenBuf;
+ uchar szBuf[2048];
+
+ ISOBJ_TYPE_assert(pThis, var);
+ assert(pstrPrg != NULL);
+ switch(pThis->varType) {
+ case VARTYPE_STR:
+ lenBuf = snprintf((char*) szBuf, sizeof(szBuf), "%s[cstr]", rsCStrGetSzStr(pThis->val.pStr));
+ break;
+ case VARTYPE_NUMBER:
+ lenBuf = snprintf((char*) szBuf, sizeof(szBuf), "%lld[nbr]", pThis->val.num);
+ break;
+ default:
+ lenBuf = snprintf((char*) szBuf, sizeof(szBuf), "**UNKNOWN**[%d]", pThis->varType);
+ break;
+ }
+ CHKiRet(rsCStrAppendStrWithLen(pstrPrg, szBuf, lenBuf));
+
+finalize_it:
+ RETiRet;
+}
+
+
/* duplicates a var instance
* rgerhards, 2008-02-25
*/
@@ -387,6 +426,7 @@ CODESTARTobjQueryInterface(var)
pIf->ConstructFinalize = varConstructFinalize;
pIf->Destruct = varDestruct;
pIf->DebugPrint = varDebugPrint;
+ pIf->Obj2Str = Obj2Str;
pIf->SetNumber = varSetNumber;
pIf->SetString = varSetString;
pIf->ConvForOperation = ConvForOperation;
diff --git a/runtime/var.h b/runtime/var.h
index bbe7ba33..6d890ec9 100644
--- a/runtime/var.h
+++ b/runtime/var.h
@@ -59,6 +59,7 @@ BEGINinterface(var) /* name must also be changed in ENDinterface macro! */
rsRetVal (*ConvToNumber)(var_t *pThis);
rsRetVal (*ConvToBool)(var_t *pThis);
rsRetVal (*ConvToString)(var_t *pThis);
+ rsRetVal (*Obj2Str)(var_t *pThis, cstr_t*);
rsRetVal (*Duplicate)(var_t *pThis, var_t **ppNew);
ENDinterface(var)
#define varCURR_IF_VERSION 1 /* increment whenever you change the interface above! */
diff --git a/runtime/vmop.c b/runtime/vmop.c
index 219315c4..fcacb15b 100644
--- a/runtime/vmop.c
+++ b/runtime/vmop.c
@@ -25,6 +25,7 @@
*/
#include "config.h"
+#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
@@ -81,6 +82,39 @@ CODESTARTobjDebugPrint(vmop)
ENDobjDebugPrint(vmop)
+/* This function is similar to DebugPrint, but does not send its output to
+ * the debug log but instead to a caller-provided string. The idea here is that
+ * we can use this string to get a textual representation of an operation.
+ * Among others, this is useful for creating testbenches, our first use case for
+ * it. Here, it enables simple comparison of the resulting program to a
+ * reference program by simple string compare.
+ * Note that the caller must initialize the string object. We always add
+ * data to it. So, it can be easily combined into a chain of methods
+ * to generate the final string.
+ * rgerhards, 2008-07-04
+ */
+static rsRetVal
+Obj2Str(vmop_t *pThis, cstr_t *pstrPrg)
+{
+ uchar *pOpcodeName;
+ uchar szBuf[2048];
+ size_t lenBuf;
+ DEFiRet;
+
+ ISOBJ_TYPE_assert(pThis, vmop);
+ assert(pstrPrg != NULL);
+ vmopOpcode2Str(pThis, &pOpcodeName);
+ lenBuf = snprintf((char*) szBuf, sizeof(szBuf), "%s\t", pOpcodeName);
+ CHKiRet(rsCStrAppendStrWithLen(pstrPrg, szBuf, lenBuf));
+ if(pThis->operand.pVar != NULL)
+ CHKiRet(var.Obj2Str(pThis->operand.pVar, pstrPrg));
+ CHKiRet(rsCStrAppendChar(pstrPrg, '\n'));
+
+finalize_it:
+ RETiRet;
+}
+
+
/* set operand (variant case)
* rgerhards, 2008-02-20
*/
@@ -206,8 +240,6 @@ CODESTARTobjQueryInterface(vmop)
* work here (if we can support an older interface version - that,
* of course, also affects the "if" above).
*/
- //xxxpIf->oID = OBJvmop;
-
pIf->Construct = vmopConstruct;
pIf->ConstructFinalize = vmopConstructFinalize;
pIf->Destruct = vmopDestruct;
@@ -215,6 +247,7 @@ CODESTARTobjQueryInterface(vmop)
pIf->SetOpcode = vmopSetOpcode;
pIf->SetVar = vmopSetVar;
pIf->Opcode2Str = vmopOpcode2Str;
+ pIf->Obj2Str = Obj2Str;
finalize_it:
ENDobjQueryInterface(vmop)
diff --git a/runtime/vmop.h b/runtime/vmop.h
index 97f924d7..c3d5d5f4 100644
--- a/runtime/vmop.h
+++ b/runtime/vmop.h
@@ -26,6 +26,7 @@
#define INCLUDED_VMOP_H
#include "ctok_token.h"
+#include "stringbuf.h"
/* machine instructions types */
typedef enum { /* do NOT start at 0 to detect uninitialized types after calloc() */
@@ -83,6 +84,7 @@ BEGINinterface(vmop) /* name must also be changed in ENDinterface macro! */
rsRetVal (*SetOpcode)(vmop_t *pThis, opcode_t opcode);
rsRetVal (*SetVar)(vmop_t *pThis, var_t *pVar);
rsRetVal (*Opcode2Str)(vmop_t *pThis, uchar **ppName);
+ rsRetVal (*Obj2Str)(vmop_t *pThis, cstr_t *pstr);
ENDinterface(vmop)
#define vmopCURR_IF_VERSION 1 /* increment whenever you change the interface structure! */
diff --git a/runtime/vmprg.c b/runtime/vmprg.c
index a2b744d7..705e6948 100644
--- a/runtime/vmprg.c
+++ b/runtime/vmprg.c
@@ -24,12 +24,14 @@
*/
#include "config.h"
+#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include "rsyslog.h"
#include "obj.h"
#include "vmprg.h"
+#include "stringbuf.h"
/* static data */
DEFobjStaticHelpers
@@ -79,6 +81,40 @@ CODESTARTobjDebugPrint(vmprg)
ENDobjDebugPrint(vmprg)
+/* This function is similar to DebugPrint, but does not send its output to
+ * the debug log but instead to a caller-provided string. The idea here is that
+ * we can use this string to get a textual representation of a bytecode program.
+ * Among others, this is useful for creating testbenches, our first use case for
+ * it. Here, it enables simple comparison of the resulting program to a
+ * reference program by simple string compare.
+ * Note that the caller must initialize the string object. We always add
+ * data to it. So, it can be easily combined into a chain of methods
+ * to generate the final string.
+ * rgerhards, 2008-07-04
+ */
+static rsRetVal
+Obj2Str(vmprg_t *pThis, cstr_t *pstrPrg)
+{
+ uchar szAddr[12];
+ vmop_t *pOp;
+ int i;
+ int lenAddr;
+ DEFiRet;
+
+ ISOBJ_TYPE_assert(pThis, vmprg);
+ assert(pstrPrg != NULL);
+ i = 0; /* "program counter" */
+ for(pOp = pThis->vmopRoot ; pOp != NULL ; pOp = pOp->pNext) {
+ lenAddr = snprintf((char*)szAddr, sizeof(szAddr), "%8.8d: ", i++);
+ CHKiRet(rsCStrAppendStrWithLen(pstrPrg, szAddr, lenAddr));
+ vmop.Obj2Str(pOp, pstrPrg);
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+
/* add an operation (instruction) to the end of the current program. This
* function is expected to be called while creating the program, but never
* again after this is done and it is being executed. Results are undefined if
@@ -146,12 +182,11 @@ CODESTARTobjQueryInterface(vmprg)
* work here (if we can support an older interface version - that,
* of course, also affects the "if" above).
*/
- //xxxpIf->oID = OBJvmprg;
-
pIf->Construct = vmprgConstruct;
pIf->ConstructFinalize = vmprgConstructFinalize;
pIf->Destruct = vmprgDestruct;
pIf->DebugPrint = vmprgDebugPrint;
+ pIf->Obj2Str = Obj2Str;
pIf->AddOperation = vmprgAddOperation;
pIf->AddVarOperation = vmprgAddVarOperation;
finalize_it:
diff --git a/runtime/vmprg.h b/runtime/vmprg.h
index db1f62f0..c1042f7d 100644
--- a/runtime/vmprg.h
+++ b/runtime/vmprg.h
@@ -38,7 +38,7 @@
#define INCLUDED_VMPRG_H
#include "vmop.h"
-
+#include "stringbuf.h"
/* the vmprg object */
typedef struct vmprg_s {
@@ -56,6 +56,7 @@ BEGINinterface(vmprg) /* name must also be changed in ENDinterface macro! */
rsRetVal (*Destruct)(vmprg_t **ppThis);
rsRetVal (*AddOperation)(vmprg_t *pThis, vmop_t *pOp);
rsRetVal (*AddVarOperation)(vmprg_t *pThis, opcode_t opcode, var_t *pVar);
+ rsRetVal (*Obj2Str)(vmprg_t *pThis, cstr_t *pstr);
ENDinterface(vmprg)
#define vmprgCURR_IF_VERSION 1 /* increment whenever you change the interface structure! */
diff --git a/tests/.gitignore b/tests/.gitignore
index e961c766..a8177ad4 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -1,3 +1,3 @@
-rscript_parse
+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/Makefile.am b/tests/Makefile.am
index d85a56f8..6057a7a8 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -1,14 +1,15 @@
-check_PROGRAMS = rt_init rscript_parse
+check_PROGRAMS = rt_init rscript
TESTS = $(check_PROGRAMS)
test_files = testbench.h runtime-dummy.c
+EXTRA_DIST=1.rstest 2.rstest err1.rstest
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_parse_SOURCES = rscript-parse.c $(test_files)
-rscript_parse_CPPFLAGS = -I$(top_srcdir) $(pthreads_cflags) $(rsrt_cflags)
-rscript_parse_LDADD = $(rsrt_libs) $(zlib_libs) $(pthreads_libs)
-rscript_parse_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/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-parse.c b/tests/rscript-parse.c
deleted file mode 100644
index 176f3f7e..00000000
--- a/tests/rscript-parse.c
+++ /dev/null
@@ -1,100 +0,0 @@
-/* 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"
-#include "ctok.h"
-#include "expr.h"
-
-MODULE_TYPE_TESTBENCH
-/* define addtional objects we need for our tests */
-DEFobjCurrIf(expr)
-DEFobjCurrIf(ctok)
-DEFobjCurrIf(ctok_token)
-
-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));
-ENDInit
-
-BEGINExit
-CODESTARTExit
-ENDExit
-
-BEGINTest
- ctok_t *tok;
- ctok_token_t *pToken;
- expr_t *pExpr;
- /* the string below is an expression as defined up to 3.19.x - note that the
- * then and the space after it MUST be present!
- */
- uchar szExpr[] = " $msg contains 'test' then ";
- /*uchar szSynErr[] = "$msg == 1 and syntaxerror ";*/
-CODESTARTTest
- /* we first need a tokenizer... */
- CHKiRet(ctok.Construct(&tok));
- CHKiRet(ctok.Setpp(tok, szExpr));
- CHKiRet(ctok.ConstructFinalize(tok));
-
- /* now construct our expression */
- CHKiRet(expr.Construct(&pExpr));
- CHKiRet(expr.ConstructFinalize(pExpr));
-
- /* ready to go... */
- CHKiRet(expr.Parse(pExpr, tok));
-
- /* we now need to parse off the "then" - and note an error if it is
- * missing...
- *
- * rgerhards, 2008-07-01: we disable the check below, because I can not
- * find the cause of the misalignment. The problem is that pToken structure has
- * a different member alignment inside the runtime library then inside of
- * this program. I checked compiler options, but could not find the cause.
- * Should anyone have any insight, I'd really appreciate if you drop me
- * a line.
- */
-#if 0
- CHKiRet(ctok.GetToken(tok, &pToken));
- if(pToken->tok != ctok_THEN) {
-//printf("invalid token, probably due to invalid alignment between runtime lib and this program\n");
- ctok_token.Destruct(&pToken);
- ABORT_FINALIZE(RS_RET_SYNTAX_ERROR);
- }
-
- ctok_token.Destruct(&pToken); /* no longer needed */
-#endif
-
- /* we are done, so we now need to restore things */
- CHKiRet(ctok.Destruct(&tok));
-finalize_it:
- /* here we may do custom error reporting */
- if(iRet != RS_RET_OK) {
- uchar *pp;
- ctok.Getpp(tok, &pp);
- printf("error on or before '%s'\n", pp);
- }
-ENDTest
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 <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/testbench.h b/tests/testbench.h
index 6f26724a..12687743 100644
--- a/tests/testbench.h
+++ b/tests/testbench.h
@@ -40,7 +40,8 @@ int main(int __attribute__((unused)) argc, char __attribute__((unused)) *argv[])
CHKiRet(doTest()); \
CHKiRet(doExit()); \
finalize_it: \
- printf("test returns iRet %d\n", iRet); \
+ if(iRet != RS_RET_OK) \
+ printf("test returns iRet %d\n", iRet); \
RETiRet; \
}
diff --git a/tools/Makefile.am b/tools/Makefile.am
index b2b7a8ca..a265af9c 100644
--- a/tools/Makefile.am
+++ b/tools/Makefile.am
@@ -21,9 +21,13 @@ rsyslogd_SOURCES = \
pidfile.h \
\
../dirty.h
-
rsyslogd_CPPFLAGS = $(pthreads_cflags) $(rsrt_cflags)
rsyslogd_LDADD = $(zlib_libs) $(pthreads_libs) $(rsrt_libs)
rsyslogd_LDFLAGS = -export-dynamic
+if ENABLE_DIAGTOOLS
+sbin_PROGRAMS += rsyslog_diag_hostname
+rsyslog_diag_hostname_SOURCES = gethostn.c
+endif
+
EXTRA_DIST = $(man_MANS)
diff --git a/tools/gethostn.c b/tools/gethostn.c
new file mode 100644
index 00000000..746b9381
--- /dev/null
+++ b/tools/gethostn.c
@@ -0,0 +1,46 @@
+/* gethostn - a small diagnostic utility to show what the
+ * gethostname() API returns. Of course, this tool duplicates
+ * functionality already found in other tools. But the point is
+ * that the API shall be called by a program that is compiled like
+ * rsyslogd and does exactly what rsyslog does.
+ *
+ * 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 <unistd.h>
+
+int main(int __attribute__((unused)) argc, char __attribute__((unused)) *argv[])
+{
+ char hostname[4096]; /* this should always be sufficient ;) */
+ int err;
+
+ err = gethostname(hostname, sizeof(hostname));
+
+ if(err) {
+ perror("gethostname failed");
+ exit(1);
+ }
+
+ printf("hostname of this system is '%s'.\n", hostname);
+
+ return 0;
+}