testbench: queue timeouts via imdiag module params; yaml-only mode fixes and docs

- imdiag: add 5 module-scope config params to control key queue timeouts
  (mainmsgqueuetimeoutshutdown, mainmsgqueuetimeoutenqueue,
  inputshutdowntimeout, defaultactionqueuetimeoutshutdown,
  defaultactionqueuetimeoutenqueue); these replace per-test legacy
  $MainMsg* directives and eliminate races on slow machines (Solaris)
- imdiag: add assert(0) for unhandled params in setModCnf/newInpInst
- imdiag: modExit sets abortTimeout=-1 after joining timeoutGuard thread
  to prevent double-cancel if resetConfigVariables runs afterwards
- diag.sh: generate_conf --yaml-only flag for YAML-only test mode
- diag.sh: yaml preamble uses new imdiag module params
- diag.sh: add RSTB_MAIN_Q_TO_ENQUEUE separate from action queue var
- diag.sh: restore .started with instance-ID suffix for content_check
- diag.sh: wait_startup() uses imdiag port file for startup detection
- tests: add yaml-basic-yamlonly.sh smoke test
- doc: 6 new reference pages for new imdiag params (with meta blocks)
- doc: imdiag.rst updated with new module-scope params table
- doc: dev_testbench.rst corrected .started vs port-file description

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
Rainer Gerhards 2026-03-29 17:26:39 +02:00
parent b2caab060e
commit 5a78def249
14 changed files with 768 additions and 108 deletions

View File

@ -453,8 +453,14 @@ EXTRA_DIST = \
source/rainerscript/variable_property_types.rst \
source/reference/parameters/im3195-input3195listenport.rst \
source/reference/parameters/imdiag-aborttimeout.rst \
source/reference/parameters/imdiag-defaultactionqueuetimeoutenqueue.rst \
source/reference/parameters/imdiag-defaultactionqueuetimeoutshutdown.rst \
source/reference/parameters/imdiag-injectdelaymode.rst \
source/reference/parameters/imdiag-inputshutdowntimeout.rst \
source/reference/parameters/imdiag-listenportfilename.rst \
source/reference/parameters/imdiag-listenportfilename-module.rst \
source/reference/parameters/imdiag-mainmsgqueuetimeoutenqueue.rst \
source/reference/parameters/imdiag-mainmsgqueuetimeoutshutdown.rst \
source/reference/parameters/imdiag-maxsessions.rst \
source/reference/parameters/imdiag-serverinputname.rst \
source/reference/parameters/imdiag-serverrun.rst \

View File

@ -37,6 +37,30 @@ Module Parameters
- .. include:: ../../reference/parameters/imdiag-aborttimeout.rst
:start-after: .. summary-start
:end-before: .. summary-end
* - :ref:`param-imdiag-listenportfilename-module`
- .. include:: ../../reference/parameters/imdiag-listenportfilename-module.rst
:start-after: .. summary-start
:end-before: .. summary-end
* - :ref:`param-imdiag-mainmsgqueuetimeoutshutdown`
- .. include:: ../../reference/parameters/imdiag-mainmsgqueuetimeoutshutdown.rst
:start-after: .. summary-start
:end-before: .. summary-end
* - :ref:`param-imdiag-mainmsgqueuetimeoutenqueue`
- .. include:: ../../reference/parameters/imdiag-mainmsgqueuetimeoutenqueue.rst
:start-after: .. summary-start
:end-before: .. summary-end
* - :ref:`param-imdiag-inputshutdowntimeout`
- .. include:: ../../reference/parameters/imdiag-inputshutdowntimeout.rst
:start-after: .. summary-start
:end-before: .. summary-end
* - :ref:`param-imdiag-defaultactionqueuetimeoutshutdown`
- .. include:: ../../reference/parameters/imdiag-defaultactionqueuetimeoutshutdown.rst
:start-after: .. summary-start
:end-before: .. summary-end
* - :ref:`param-imdiag-defaultactionqueuetimeoutenqueue`
- .. include:: ../../reference/parameters/imdiag-defaultactionqueuetimeoutenqueue.rst
:start-after: .. summary-start
:end-before: .. summary-end
* - :ref:`param-imdiag-injectdelaymode`
- .. include:: ../../reference/parameters/imdiag-injectdelaymode.rst
:start-after: .. summary-start
@ -96,10 +120,49 @@ ephemeral port, and records the chosen port for the testbench to read.
listenPortFileName="/var/run/rsyslog/imdiag.port"
serverRun="0")
YAML-only testbench configuration
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In YAML-only mode the testbench preamble uses the ``testbench_modules:``
key (an alias for ``modules:`` reserved for testbench infrastructure) so
that it does not conflict with the test's own ``modules:`` section.
.. code-block:: yaml
version: 2
global:
debug.abortOnProgramError: "on"
testbench_modules:
- load: "../plugins/imdiag/.libs/imdiag"
listenportfilename: "test.imdiag.port"
aborttimeout: "580"
mainmsgqueuetimeoutshutdown: "10000"
mainmsgqueuetimeoutenqueue: "30000"
inputshutdowntimeout: "60000"
defaultactionqueuetimeoutshutdown: "20000"
defaultactionqueuetimeoutenqueue: "30000"
modules:
- load: "../plugins/imtcp/.libs/imtcp"
inputs:
- type: imdiag
port: "0"
- type: imtcp
port: "0"
.. toctree::
:hidden:
../../reference/parameters/imdiag-aborttimeout
../../reference/parameters/imdiag-listenportfilename-module
../../reference/parameters/imdiag-mainmsgqueuetimeoutshutdown
../../reference/parameters/imdiag-mainmsgqueuetimeoutenqueue
../../reference/parameters/imdiag-inputshutdowntimeout
../../reference/parameters/imdiag-defaultactionqueuetimeoutshutdown
../../reference/parameters/imdiag-defaultactionqueuetimeoutenqueue
../../reference/parameters/imdiag-injectdelaymode
../../reference/parameters/imdiag-maxsessions
../../reference/parameters/imdiag-listenportfilename

View File

@ -1,20 +1,191 @@
writing rsyslog tests
Writing rsyslog Tests
=====================
The rsyslog testbench is executed via `make check` or `make distcheck`. For details, on
these modes, see the GNU autotools documentation. The most important thing is that
the `make distcheck` test execution environment is considerably different from its
`make check` counterpart. The rsyslog testbench is crafted to handle both cases and
does so with the (intensive) use of environment variables.
The rsyslog testbench is executed via ``make check`` or ``make distcheck``. For details
on these modes, see the GNU autotools documentation. The most important thing is that
the ``make distcheck`` test execution environment is considerably different from its
``make check`` counterpart. The rsyslog testbench is crafted to handle both cases and
does so with the intensive use of environment variables.
The rsyslog testbench aims to support parallel tests. This is not yet fully implemented,
but we are working towards that goal. This has a number of implications/requirements:
* all file names, ports, etc need to be unique
* the diag.sh framework supports auto-generation capabilities to support this:
use `${RSYSLOG_DYNNAME}` a prefix for all files you generate. For the frequently
used files, the framework already defines `${RSYSLOG_OUT_LOG}` and `${RSYSLOG_OUT_LOG2}`
* All file names, ports, etc. need to be unique.
* The ``diag.sh`` framework supports auto-generation capabilities to support this:
use ``${RSYSLOG_DYNNAME}`` as a prefix for all files you generate. For the frequently
used files, the framework already defines ``${RSYSLOG_OUT_LOG}`` and
``${RSYSLOG_OUT_LOG2}``.
When writing new tests, it is in general advisable to copy an existing test and modify
it. This also ensures you inherit the correct boilerplate and environment setup.
Test Modes
----------
The testbench supports two configuration modes for rsyslogd:
RainerScript mode (default)
The classic mode. ``generate_conf`` writes a ``.conf`` file using
``module()`` / ``input()`` / ``global()`` v2 RainerScript syntax. Legacy
``$Directive`` syntax is still accepted but deprecated.
YAML-only mode
Pure-YAML configuration. ``generate_conf --yaml-only`` writes a ``.yaml``
file using the rsyslog v2 YAML loader. No RainerScript preamble is written.
See `YAML-only mode`_ below.
Startup detection uses the imdiag port file in both modes. In RainerScript
mode, rsyslogd's own messages (startup, shutdown, errors) are also captured to
the instance's ``.started`` file via the syslogtag filter rule; tests may
use that file for content checks. In YAML-only mode no ``.started`` file is
written.
.. _yaml-only-mode:
YAML-only Mode
--------------
Use ``generate_conf --yaml-only`` when a test must validate the YAML
configuration loader or when you want to avoid any RainerScript entirely.
How It Works
~~~~~~~~~~~~
1. ``generate_conf --yaml-only [instance]`` writes
``${TESTCONF_NM}[instance].yaml`` containing:
- ``version: 2``
- ``global:`` section with ``debug.abortOnProgramError: "on"`` (and
``net.ipprotocol:`` if ``RSTB_FORCE_IPV4=1`` or ``RSTB_NET_IPPROTO`` is
set)
- ``testbench_modules:`` section that loads ``imdiag`` with all testbench
parameters set (port file, abort timeout, queue/input timeouts)
The ``testbench_modules:`` key is recognised by rsyslogd as an alias for
``modules:``. It is reserved for testbench infrastructure so it does not
conflict with the test's own ``modules:`` section.
2. Tests add their own sections with ``add_yaml_conf``.
3. Tests must call ``add_yaml_imdiag_input`` inside their ``inputs:`` section
so that startup detection works.
Helper Functions
~~~~~~~~~~~~~~~~
``generate_conf --yaml-only [instance]``
Create the YAML preamble. Sets ``RSYSLOG_YAML_ONLY=1``.
``add_yaml_conf 'fragment' [instance]``
Append a YAML fragment to ``${TESTCONF_NM}[instance].yaml``.
``add_yaml_imdiag_input [instance]``
Append the imdiag ``inputs:`` entry inside an already-opened ``inputs:``
block. **Required** in every yaml-only test for startup detection.
Startup detection
~~~~~~~~~~~~~~~~~
Both RainerScript and yaml-only modes use the imdiag port file
(``${RSYSLOG_DYNNAME}.imdiag[instance].port``) as the sole startup signal.
``wait_startup`` polls for this file and fast-fails if rsyslogd exits before
it appears. No ``.started`` marker file is used.
Queue and Input Timeouts
~~~~~~~~~~~~~~~~~~~~~~~~
Default testbench timeout values are set via the ``RSTB_*`` environment
variables before ``generate_conf`` is called. The variables and their defaults
are:
.. list-table::
:widths: 40 20 40
:header-rows: 1
* - Variable
- Default (ms)
- Controls
* - ``RSTB_GLOBAL_QUEUE_SHUTDOWN_TIMEOUT``
- 10000
- Main message queue shutdown timeout
* - ``RSTB_GLOBAL_INPUT_SHUTDOWN_TIMEOUT``
- 60000
- Input shutdown timeout
* - ``RSTB_ACTION_DEFAULT_Q_TO_SHUTDOWN``
- 20000
- Default action queue shutdown timeout
* - ``RSTB_ACTION_DEFAULT_Q_TO_ENQUEUE``
- 30000
- Default action queue enqueue timeout
* - ``RSTB_MAIN_Q_TO_ENQUEUE``
- 30000
- Main message queue enqueue timeout
These are injected as ``imdiag`` module parameters at config-load time, so
they take effect before any test-specific config is parsed. A test can
override a value by setting the variable before calling ``generate_conf``.
If a test needs a *different* value for the main queue shutdown timeout (for
example, a queue-persistence test that sets ``$MainMsgQueueTimeoutShutdown 1``
in RainerScript), it should set the value in the configuration fragment itself.
Legacy ``$MainMsgQueueTimeout*`` directives still work and override the
imdiag-supplied defaults in RainerScript mode.
Limitations in YAML-only Mode
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The following RainerScript-specific features are not available in yaml-only
mode:
* **Legacy ``$Directive`` syntax** -- not parsed by the YAML loader.
* **``setvar_RS_HOSTNAME``** -- uses a RainerScript ``$template`` internally;
it always runs against a RainerScript instance and its result is still
available via ``$RS_HOSTNAME`` for yaml-only tests.
Example Test
~~~~~~~~~~~~
.. code-block:: bash
#!/bin/bash
. ${srcdir:=.}/diag.sh init
require_plugin imtcp
export NUMMESSAGES=100
export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines
generate_conf --yaml-only
# Test-specific modules go in a standard modules: section.
# Testbench infrastructure (imdiag) is already in testbench_modules:.
add_yaml_conf 'modules:'
add_yaml_conf ' - load: "../plugins/imtcp/.libs/imtcp"'
add_yaml_conf ''
add_yaml_conf 'templates:'
add_yaml_conf ' - name: outfmt'
add_yaml_conf ' type: string'
add_yaml_conf ' string: "%msg:F,58:2%\n"'
add_yaml_conf ''
add_yaml_conf 'inputs:'
add_yaml_imdiag_input # required -- provides startup detection
add_yaml_conf " - type: imtcp"
add_yaml_conf ' port: "0"'
add_yaml_conf " listenPortFileName: \"${RSYSLOG_DYNNAME}.tcpflood_port\""
add_yaml_conf ' ruleset: main'
add_yaml_conf ''
add_yaml_conf 'rulesets:'
add_yaml_conf ' - name: main'
add_yaml_conf ' script: |'
add_yaml_conf " :msg, contains, \"msgnum:\" action(type=\"omfile\""
add_yaml_conf " template=\"outfmt\" file=\"${RSYSLOG_OUT_LOG}\")"
startup
tcpflood -m $NUMMESSAGES
shutdown_when_empty
wait_shutdown
seq_check
exit_test
Naming and Registration
~~~~~~~~~~~~~~~~~~~~~~~
Name yaml-only tests ``yaml-<area>-yamlonly.sh`` (or append ``-yamlonly`` to
an existing test name). Register them in ``tests/Makefile.am`` under
``TESTS_LIBYAML`` so they are skipped on systems without libyaml.
When writing new tests, it is in general advisable to copy an existing test and change
it. This also helps you get requirements files.

View File

@ -0,0 +1,61 @@
.. _param-imdiag-defaultactionqueuetimeoutenqueue:
.. _imdiag.parameter.module.defaultactionqueuetimeoutenqueue:
.. meta::
:description: Reference for the imdiag defaultActionQueueTimeoutEnqueue module parameter.
:keywords: rsyslog, imdiag, defaultactionqueuetimeoutenqueue, testbench, timeout, action queue
DefaultActionQueueTimeoutEnqueue
=================================
.. index::
single: imdiag; DefaultActionQueueTimeoutEnqueue
.. summary-start
Sets the default action queue enqueue timeout at config load time.
.. summary-end
This parameter applies to :doc:`../../configuration/modules/imdiag`.
:Name: DefaultActionQueueTimeoutEnqueue
:Scope: module
:Type: integer (milliseconds)
:Default: 30000
:Required?: no
:Introduced: 8.x
Description
-----------
Sets ``globals.actq_dflt_toEnq`` — the default enqueue timeout for action
queues created after this point — at config-load time. This only affects
action queues that do not specify their own timeout. When an action queue is
full, a producer waits up to this duration before dropping the message.
.. note::
This parameter affects action queues created *after* the module is
loaded. Existing queues are unaffected.
Override per-test via ``RSTB_ACTION_DEFAULT_Q_TO_ENQUEUE`` before
``generate_conf``.
Module usage
------------
.. code-block:: rsyslog
module(load="imdiag" defaultActionQueueTimeoutEnqueue="30000")
YAML usage
----------
.. code-block:: yaml
testbench_modules:
- load: "../plugins/imdiag/.libs/imdiag"
defaultactionqueuetimeoutenqueue: "30000"
See also
--------
See also :doc:`../../configuration/modules/imdiag`.

View File

@ -0,0 +1,61 @@
.. _param-imdiag-defaultactionqueuetimeoutshutdown:
.. _imdiag.parameter.module.defaultactionqueuetimeoutshutdown:
.. meta::
:description: Reference for the imdiag defaultActionQueueTimeoutShutdown module parameter.
:keywords: rsyslog, imdiag, defaultactionqueuetimeoutshutdown, testbench, timeout, action queue
DefaultActionQueueTimeoutShutdown
==================================
.. index::
single: imdiag; DefaultActionQueueTimeoutShutdown
.. summary-start
Sets the default action queue shutdown timeout at config load time.
.. summary-end
This parameter applies to :doc:`../../configuration/modules/imdiag`.
:Name: DefaultActionQueueTimeoutShutdown
:Scope: module
:Type: integer (milliseconds)
:Default: 20000
:Required?: no
:Introduced: 8.x
Description
-----------
Sets ``globals.actq_dflt_toQShutdown`` — the default shutdown timeout for
action queues created after this point — at config-load time. This only
affects action queues that do not specify their own timeout. The testbench
uses this to ensure action queues drain cleanly under test conditions.
.. note::
This parameter affects action queues created *after* the module is
loaded. Existing queues are unaffected.
Override per-test via ``RSTB_ACTION_DEFAULT_Q_TO_SHUTDOWN`` before
``generate_conf``.
Module usage
------------
.. code-block:: rsyslog
module(load="imdiag" defaultActionQueueTimeoutShutdown="20000")
YAML usage
----------
.. code-block:: yaml
testbench_modules:
- load: "../plugins/imdiag/.libs/imdiag"
defaultactionqueuetimeoutshutdown: "20000"
See also
--------
See also :doc:`../../configuration/modules/imdiag`.

View File

@ -0,0 +1,57 @@
.. _param-imdiag-inputshutdowntimeout:
.. _imdiag.parameter.module.inputshutdowntimeout:
.. meta::
:description: Reference for the imdiag inputShutdownTimeout module parameter.
:keywords: rsyslog, imdiag, inputshutdowntimeout, testbench, timeout, shutdown
InputShutdownTimeout
====================
.. index::
single: imdiag; InputShutdownTimeout
.. summary-start
Sets the input shutdown timeout at config load time.
.. summary-end
This parameter applies to :doc:`../../configuration/modules/imdiag`.
:Name: InputShutdownTimeout
:Scope: module
:Type: integer (milliseconds)
:Default: 60000
:Required?: no
:Introduced: 8.x
Description
-----------
Sets ``globals.inputTimeoutShutdown`` — the time rsyslog allows each input
plugin to stop during an orderly shutdown — at config-load time. The
testbench uses this to ensure inputs have enough time to shut down cleanly
under load, in both RainerScript and YAML-only modes.
Override per-test via ``RSTB_GLOBAL_INPUT_SHUTDOWN_TIMEOUT`` before
``generate_conf``.
Module usage
------------
.. code-block:: rsyslog
module(load="imdiag" inputShutdownTimeout="60000")
YAML usage
----------
.. code-block:: yaml
testbench_modules:
- load: "../plugins/imdiag/.libs/imdiag"
inputshutdowntimeout: "60000"
See also
--------
See also :doc:`../../configuration/modules/imdiag`.

View File

@ -0,0 +1,59 @@
.. _param-imdiag-listenportfilename-module:
.. _imdiag.parameter.module.listenportfilename:
.. meta::
:description: Reference for the imdiag listenPortFileName module-scope parameter.
:keywords: rsyslog, imdiag, listenportfilename, testbench, port file, startup
ListenPortFileName (module scope)
==================================
.. index::
single: imdiag; ListenPortFileName (module)
.. summary-start
Path of the file to which imdiag writes its chosen TCP listen port number,
set at module load time.
.. summary-end
This parameter applies to :doc:`../../configuration/modules/imdiag`.
:Name: ListenPortFileName
:Scope: module
:Type: string (file path)
:Default: none
:Required?: no (but recommended for testbench use)
:Introduced: 8.x
Description
-----------
When set at module scope, ``ListenPortFileName`` specifies the file that
imdiag will create and populate with its chosen listen port number after the
TCP listener is ready. The testbench reads this file to discover the port
without needing a fixed port number.
This is the module-scope version of the parameter. The same name can also
be set at input scope via ``input(type="imdiag" listenPortFileName=...)``.
Module usage
------------
.. code-block:: rsyslog
module(load="imdiag" listenPortFileName="/tmp/imdiag.port")
YAML usage
----------
.. code-block:: yaml
testbench_modules:
- load: "../plugins/imdiag/.libs/imdiag"
listenportfilename: "/tmp/imdiag.port"
See also
--------
See also :doc:`../../configuration/modules/imdiag` and
:ref:`param-imdiag-listenportfilename`.

View File

@ -0,0 +1,59 @@
.. _param-imdiag-mainmsgqueuetimeoutenqueue:
.. _imdiag.parameter.module.mainmsgqueuetimeoutenqueue:
.. meta::
:description: Reference for the imdiag mainMsgQueueTimeoutEnqueue module parameter.
:keywords: rsyslog, imdiag, mainmsgqueuetimeoutenqueue, testbench, timeout, queue
MainMsgQueueTimeoutEnqueue
===========================
.. index::
single: imdiag; MainMsgQueueTimeoutEnqueue
.. summary-start
Sets the main message queue enqueue timeout at config load time.
.. summary-end
This parameter applies to :doc:`../../configuration/modules/imdiag`.
:Name: MainMsgQueueTimeoutEnqueue
:Scope: module
:Type: integer (milliseconds)
:Default: 30000
:Required?: no
:Introduced: 8.x
Description
-----------
Sets ``globals.mainQ.iMainMsgQtoEnq`` — the time a producer will wait when
the main message queue is full before dropping the message — at config-load
time. The testbench uses this to establish a safe default without relying on
legacy ``$MainMsgQueueTimeoutEnqueue`` directives, which are not available in
YAML-only mode.
Override per-test via ``RSTB_MAIN_Q_TO_ENQUEUE`` before
``generate_conf``, or via a ``$MainMsgQueueTimeoutEnqueue`` directive in the
RainerScript test fragment.
Module usage
------------
.. code-block:: rsyslog
module(load="imdiag" mainMsgQueueTimeoutEnqueue="30000")
YAML usage
----------
.. code-block:: yaml
testbench_modules:
- load: "../plugins/imdiag/.libs/imdiag"
mainmsgqueuetimeoutenqueue: "30000"
See also
--------
See also :doc:`../../configuration/modules/imdiag`.

View File

@ -0,0 +1,61 @@
.. _param-imdiag-mainmsgqueuetimeoutshutdown:
.. _imdiag.parameter.module.mainmsgqueuetimeoutshutdown:
.. meta::
:description: Reference for the imdiag mainMsgQueueTimeoutShutdown module parameter.
:keywords: rsyslog, imdiag, mainmsgqueuetimeoutshutdown, testbench, timeout, queue
MainMsgQueueTimeoutShutdown
============================
.. index::
single: imdiag; MainMsgQueueTimeoutShutdown
.. summary-start
Sets the main message queue shutdown timeout at config load time.
.. summary-end
This parameter applies to :doc:`../../configuration/modules/imdiag`.
:Name: MainMsgQueueTimeoutShutdown
:Scope: module
:Type: integer (milliseconds)
:Default: 10000
:Required?: no
:Introduced: 8.x
Description
-----------
Sets ``globals.mainQ.iMainMsgQtoQShutdown`` — the time rsyslog waits for
the main message queue to drain during an orderly shutdown — at config-load
time. The testbench uses this to establish a safe default without relying on
legacy ``$MainMsgQueueTimeoutShutdown`` directives, which are not available
in YAML-only mode.
The value can be overridden per-test by setting the
``RSTB_GLOBAL_QUEUE_SHUTDOWN_TIMEOUT`` environment variable before calling
``generate_conf``, or by writing a ``$MainMsgQueueTimeoutShutdown`` directive
in the test's RainerScript configuration fragment (legacy directives apply
after module params and therefore take precedence).
Module usage
------------
.. code-block:: rsyslog
module(load="imdiag" mainMsgQueueTimeoutShutdown="10000")
YAML usage
----------
.. code-block:: yaml
testbench_modules:
- load: "../plugins/imdiag/.libs/imdiag"
mainmsgqueuetimeoutshutdown: "10000"
See also
--------
See also :doc:`../../configuration/modules/imdiag`.

View File

@ -57,6 +57,7 @@
#include "datetime.h"
#include "ratelimit.h"
#include "queue.h"
#include "rsconf.h"
#include "lookup.h"
#include "net.h" /* for permittedPeers, may be removed when this is removed */
#include "statsobj.h"
@ -106,7 +107,15 @@ struct modConfData_s {
static modConfData_t *loadModConf = NULL; /* modConf ptr for current load process */
/* module-level parameters (module(...)) */
static struct cnfparamdescr modpdescr[] = {{"listenportfilename", eCmdHdlrString, 0}, {"aborttimeout", eCmdHdlrInt, 0}};
static struct cnfparamdescr modpdescr[] = {
{"listenportfilename", eCmdHdlrString, 0},
{"aborttimeout", eCmdHdlrInt, 0},
{"mainmsgqueuetimeoutshutdown", eCmdHdlrInt, 0},
{"mainmsgqueuetimeoutenqueue", eCmdHdlrInt, 0},
{"inputshutdowntimeout", eCmdHdlrInt, 0},
{"defaultactionqueuetimeoutshutdown", eCmdHdlrInt, 0},
{"defaultactionqueuetimeoutenqueue", eCmdHdlrInt, 0},
};
static struct cnfparamblk modpblk = {CNFPARAMBLK_VERSION, sizeof(modpdescr) / sizeof(struct cnfparamdescr), modpdescr};
/* input-level parameters (input(...)) */
@ -524,6 +533,20 @@ finalize_it:
RETiRet;
}
/* Parse a non-negative long integer from a command argument string.
* Returns 1 on success (val set), 0 on parse error (non-numeric, negative, or overflow).
*/
static int parsePosLong(const uchar *const s, long *const val) {
char *endptr;
if (s == NULL || *s == '\0') return 0;
errno = 0;
*val = strtol((const char *)s, &endptr, 10);
if (errno != 0) return 0; /* overflow / underflow */
/* accept optional trailing newline/space but nothing else */
while (*endptr == ' ' || *endptr == '\r' || *endptr == '\n') ++endptr;
return (*endptr == '\0' && *val >= 0) ? 1 : 0;
}
/* Function to handle received messages. This is our core function!
* rgerhards, 2009-05-24
*/
@ -566,6 +589,50 @@ static rsRetVal ATTR_NONNULL() OnMsgReceived(tcps_sess_t *const pSess, uchar *co
CHKiRet(awaitHUPComplete(pSess));
} else if (!ustrcmp(cmdBuf, UCHAR_CONSTANT("enabledebug"))) {
CHKiRet(enableDebug(pSess));
} else if (!ustrcmp(cmdBuf, UCHAR_CONSTANT("setmainmsgqueuetimeoutshutdown"))) {
long val;
if (!parsePosLong(pszMsg, &val)) {
CHKiRet(sendResponse(pSess, "ERROR: invalid timeout value\n"));
} else if (runConf->pMsgQueue == NULL) {
CHKiRet(sendResponse(pSess, "ERROR: main queue not yet initialized\n"));
} else {
CHKiRet(qqueueSettoQShutdown(runConf->pMsgQueue, val));
CHKiRet(sendResponse(pSess, "OK\n"));
}
} else if (!ustrcmp(cmdBuf, UCHAR_CONSTANT("setmainmsgqueuetimeoutenqueue"))) {
long val;
if (!parsePosLong(pszMsg, &val)) {
CHKiRet(sendResponse(pSess, "ERROR: invalid timeout value\n"));
} else if (runConf->pMsgQueue == NULL) {
CHKiRet(sendResponse(pSess, "ERROR: main queue not yet initialized\n"));
} else {
CHKiRet(qqueueSettoEnq(runConf->pMsgQueue, val));
CHKiRet(sendResponse(pSess, "OK\n"));
}
} else if (!ustrcmp(cmdBuf, UCHAR_CONSTANT("setinputshutdowntimeout"))) {
long val;
if (!parsePosLong(pszMsg, &val)) {
CHKiRet(sendResponse(pSess, "ERROR: invalid timeout value\n"));
} else {
runConf->globals.inputTimeoutShutdown = (int)val;
CHKiRet(sendResponse(pSess, "OK\n"));
}
} else if (!ustrcmp(cmdBuf, UCHAR_CONSTANT("setdefaultactionqueuetimeoutshutdown"))) {
long val;
if (!parsePosLong(pszMsg, &val)) {
CHKiRet(sendResponse(pSess, "ERROR: invalid timeout value\n"));
} else {
runConf->globals.actq_dflt_toQShutdown = (int)val;
CHKiRet(sendResponse(pSess, "OK\n"));
}
} else if (!ustrcmp(cmdBuf, UCHAR_CONSTANT("setdefaultactionqueuetimeoutenqueue"))) {
long val;
if (!parsePosLong(pszMsg, &val)) {
CHKiRet(sendResponse(pSess, "ERROR: invalid timeout value\n"));
} else {
runConf->globals.actq_dflt_toEnq = (int)val;
CHKiRet(sendResponse(pSess, "OK\n"));
}
} else {
dbgprintf("imdiag unkown command '%s'\n", cmdBuf);
CHKiRet(sendResponse(pSess, "unkown command '%s'\n", cmdBuf));
@ -760,8 +827,19 @@ BEGINsetModCnf
CHKmalloc(loadModConf->pszLstnPortFileName = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL));
} else if (!strcmp(modpblk.descr[i].name, "aborttimeout")) {
loadModConf->abortTimeout = (int)pvals[i].val.d.n;
} else if (!strcmp(modpblk.descr[i].name, "mainmsgqueuetimeoutshutdown")) {
loadModConf->pConf->globals.mainQ.iMainMsgQtoQShutdown = (int)pvals[i].val.d.n;
} else if (!strcmp(modpblk.descr[i].name, "mainmsgqueuetimeoutenqueue")) {
loadModConf->pConf->globals.mainQ.iMainMsgQtoEnq = (int)pvals[i].val.d.n;
} else if (!strcmp(modpblk.descr[i].name, "inputshutdowntimeout")) {
loadModConf->pConf->globals.inputTimeoutShutdown = (int)pvals[i].val.d.n;
} else if (!strcmp(modpblk.descr[i].name, "defaultactionqueuetimeoutshutdown")) {
loadModConf->pConf->globals.actq_dflt_toQShutdown = (int)pvals[i].val.d.n;
} else if (!strcmp(modpblk.descr[i].name, "defaultactionqueuetimeoutenqueue")) {
loadModConf->pConf->globals.actq_dflt_toEnq = (int)pvals[i].val.d.n;
} else {
dbgprintf("imdiag: program error, non-handled param '%s' in setModCnf\n", modpblk.descr[i].name);
assert(0); /* should not happen */
}
}
loadModConf->configSetViaV2Method = 1;
@ -822,6 +900,7 @@ BEGINnewInpInst
CHKmalloc(port = (uchar *)es_str2cstr(pvals[i].val.d.estr, NULL));
} else {
dbgprintf("imdiag: program error, non-handled param '%s' in newInpInst\n", inppblk.descr[i].name);
assert(0); /* should not happen */
}
}
/* apply module-level listenportfilename to global before addTCPListener uses it */
@ -912,6 +991,7 @@ BEGINmodExit
void *dummy;
pthread_join(timeoutGuard_thrd, &dummy);
}
abortTimeout = -1; /* mark cleaned up so resetConfigVariables won't double-cancel */
}
ENDmodExit

View File

@ -1866,7 +1866,7 @@ static rsRetVal process_top_level(yaml_parser_t *parser, const char *key, const
CHKiRet(parse_singleton_obj(parser, CNFOBJ_GLOBAL, fname));
} else if (!strcmp(key, "mainqueue") || !strcmp(key, "main_queue")) {
CHKiRet(parse_singleton_obj(parser, CNFOBJ_MAINQ, fname));
} else if (!strcmp(key, "modules")) {
} else if (!strcmp(key, "modules") || !strcmp(key, "testbench_modules")) {
CHKiRet(parse_obj_sequence(parser, CNFOBJ_MODULE, fname));
} else if (!strcmp(key, "inputs")) {
CHKiRet(parse_obj_sequence(parser, CNFOBJ_INPUT, fname));

View File

@ -164,13 +164,12 @@ must validate YAML-loader behaviour or when no RainerScript is desired.
### How it works
- `generate_conf --yaml-only [instance]` writes `${TESTCONF_NM}[instance].yaml`
containing `version: 2`, `global:`, `mainqueue:`, and `modules:` (imdiag).
The `modules:` sequence is intentionally left open — no `inputs:` section is
written by the preamble.
- Tests append additional module entries as **sequence continuation items**
(2-space indent, ` - load: ...`, no top-level `modules:` key) so YAML parsers
see a single, well-formed `modules:` list. The sequence closes naturally when
the test adds a zero-indent key such as `inputs:`.
containing `version: 2`, `global:`, and `testbench_modules:` (imdiag setup).
`testbench_modules:` is a YAML key understood by rsyslogd as an alias for
`modules:` and is reserved for testbench infrastructure — it avoids any
conflict with the test's own `modules:` section.
- Tests add their own `modules:` section (and `inputs:`, `rulesets:`, etc.)
via `add_yaml_conf`.
- `add_yaml_conf 'fragment' [instance]` appends arbitrary YAML to the same file.
- `add_yaml_imdiag_input [instance]` appends the imdiag input entry
(` - type: imdiag / port: "0"`) inside an already-opened `inputs:` block.
@ -184,8 +183,11 @@ The following testbench features are **not available** in yaml-only mode:
| Feature | Reason | Workaround |
|---------|--------|-----------|
| `$MainmsgQueueTimeout*` directives | Legacy sysklogd syntax; no YAML equivalent at runtime via `add_yaml_conf` | Set `RSTB_GLOBAL_QUEUE_SHUTDOWN_TIMEOUT` / `RSTB_ACTION_DEFAULT_Q_TO_ENQUEUE` env vars *before* calling `generate_conf --yaml-only`; they are written into the `mainqueue:` section of the preamble |
| `.started` marker file | The syslogtag-based filter rule requires RainerScript/legacy syntax | `wait_startup` requires the imdiag port file (not just the PID file) in yaml-only mode, confirming config loaded and inputs are active; it fast-fails if rsyslog exits before the port file appears |
| Legacy `$` directives | Legacy syntax is not parsed by the YAML loader | Use v2 RainerScript (`module()`, `input()`) or YAML keys instead |
> **Note**: Startup detection uses the imdiag port file in both RainerScript and
> yaml-only modes. The `.started` marker file mechanism has been removed; the
> imdiag port file is the sole startup signal in all modes.
### Example test structure
```bash
@ -194,7 +196,8 @@ require_plugin imtcp
export NUMMESSAGES=100
export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines
generate_conf --yaml-only
# Continue the modules: sequence opened by the preamble (2-space indent, no modules: key)
# Test-specific modules in their own modules: section (testbench_modules: is in preamble)
add_yaml_conf 'modules:'
add_yaml_conf ' - load: "../plugins/imtcp/.libs/imtcp"'
add_yaml_conf ''
add_yaml_conf 'inputs:'

View File

@ -285,6 +285,10 @@ test_status() {
setvar_RS_HOSTNAME() {
printf '### Obtaining HOSTNAME (prerequisite, not actual test) ###\n'
# This helper uses legacy RainerScript $template syntax to capture the
# hostname; always run it in RS mode regardless of RSYSLOG_YAML_ONLY.
local _saved_yaml_only="${RSYSLOG_YAML_ONLY}"
export RSYSLOG_YAML_ONLY=0
generate_conf ""
add_conf 'module(load="../plugins/imtcp/.libs/imtcp")
input(type="imtcp" port="0" listenPortFileName="'$RSYSLOG_DYNNAME'.tcpflood_port")
@ -300,6 +304,7 @@ local0.* ./'${RSYSLOG_DYNNAME}'.HOSTNAME;hostname
export RS_HOSTNAME="$(cat ${RSYSLOG_DYNNAME}.HOSTNAME)"
rm -f "${RSYSLOG_DYNNAME}.HOSTNAME"
echo HOSTNAME is: $RS_HOSTNAME
export RSYSLOG_YAML_ONLY="${_saved_yaml_only}"
}
@ -308,34 +313,26 @@ local0.* ./'${RSYSLOG_DYNNAME}'.HOSTNAME;hostname
# finished under stress otherwise
# $1 is the instance id, if given (or --yaml-only as first arg; see below)
#
# YAML-ONLY MODE LIMITATION: In --yaml-only mode, $MainmsgQueueTimeoutEnqueue and
# $MainmsgQueueTimeoutShutdown (legacy global directives) cannot be set because the
# YAML format does not support sysklogd-style directives. Instead, mainqueue timeout
# settings are expressed via the mainqueue: section. Tests requiring custom timeout
# values should set RSTB_GLOBAL_QUEUE_SHUTDOWN_TIMEOUT / RSTB_ACTION_DEFAULT_Q_TO_SHUTDOWN
# / RSTB_ACTION_DEFAULT_Q_TO_ENQUEUE env vars before calling generate_conf --yaml-only.
# Queue timeout settings ($MainmsgQueueTimeoutEnqueue, $MainmsgQueueTimeoutShutdown,
# inputs.timeout.shutdown and default.action.queue.*) are configured via imdiag
# module parameters in the config preamble (module(load="imdiag" ...)). This avoids
# post-startup diagtalker round-trips and works identically for RainerScript and
# YAML-only modes. Tests that need a non-default value must set the relevant
# RSTB_* variable before calling generate_conf.
#
# Also, the .started marker file is not written in yaml-only mode because the
# syslogtag-based filter requires legacy/RainerScript syntax. Startup detection relies
# on the imdiag port file and the rsyslogd PID file instead.
# Startup detection relies on the imdiag port file in both RainerScript and
# yaml-only modes; no .started marker file is used.
generate_conf() {
local yaml_only=0
if [ "$1" = "--yaml-only" ]; then
yaml_only=1
shift
fi
if [ "$RSTB_GLOBAL_QUEUE_SHUTDOWN_TIMEOUT" == "" ]; then
RSTB_GLOBAL_QUEUE_SHUTDOWN_TIMEOUT="10000"
fi
if [ "$RSTB_GLOBAL_INPUT_SHUTDOWN_TIMEOUT" == "" ]; then
RSTB_GLOBAL_INPUT_SHUTDOWN_TIMEOUT="60000"
fi
if [ "$RSTB_ACTION_DEFAULT_Q_TO_SHUTDOWN" == "" ]; then
RSTB_ACTION_DEFAULT_Q_TO_SHUTDOWN="20000"
fi
if [ "$RSTB_ACTION_DEFAULT_Q_TO_ENQUEUE" == "" ]; then
RSTB_ACTION_DEFAULT_Q_TO_ENQUEUE="30000"
fi
: "${RSTB_GLOBAL_QUEUE_SHUTDOWN_TIMEOUT:=10000}"
: "${RSTB_GLOBAL_INPUT_SHUTDOWN_TIMEOUT:=60000}"
: "${RSTB_ACTION_DEFAULT_Q_TO_SHUTDOWN:=20000}"
: "${RSTB_ACTION_DEFAULT_Q_TO_ENQUEUE:=30000}"
: "${RSTB_MAIN_Q_TO_ENQUEUE:=30000}"
export TCPFLOOD_PORT="$(get_free_port)"
if [ "$1" == "" ]; then
export TESTCONF_NM="${RSYSLOG_DYNNAME}_" # this basename is also used by instance 2!
@ -358,43 +355,38 @@ generate_conf() {
fi
{
printf 'version: 2\n\nglobal:\n'
printf ' inputs.timeout.shutdown: "%s"\n' "$RSTB_GLOBAL_INPUT_SHUTDOWN_TIMEOUT"
printf ' default.action.queue.timeoutshutdown: "%s"\n' "$RSTB_ACTION_DEFAULT_Q_TO_SHUTDOWN"
printf ' default.action.queue.timeoutEnqueue: "%s"\n' "$RSTB_ACTION_DEFAULT_Q_TO_ENQUEUE"
printf ' debug.abortOnProgramError: "on"\n'
[ -n "$ipproto_line" ] && printf '%s\n' "$ipproto_line"
printf '\nmainqueue:\n'
printf ' timeoutenqueue: "%s"\n' "$RSTB_ACTION_DEFAULT_Q_TO_ENQUEUE"
printf ' timeoutshutdown: "%s"\n' "$RSTB_GLOBAL_QUEUE_SHUTDOWN_TIMEOUT"
printf '\nmodules:\n'
printf '\ntestbench_modules:\n'
printf ' - load: "../plugins/imdiag/.libs/imdiag"\n'
printf ' listenportfilename: "%s.imdiag%s.port"\n' "$RSYSLOG_DYNNAME" "$1"
printf ' aborttimeout: "%s"\n' "$TB_TEST_MAX_RUNTIME"
# The modules: sequence is intentionally left open here.
# Tests append additional ' - load: ...' items (2-space indent, no modules: key)
# which YAML parsers treat as a continuation of this sequence.
# The sequence closes when the test adds a zero-indent key (inputs:, rulesets:, etc.).
# Tests MUST include the imdiag input in their inputs: section; use the
# add_yaml_imdiag_input helper to avoid boilerplate.
printf '\n###### append test modules as continuation items ( - load: ...)\n'
printf '###### then add inputs: (include imdiag via add_yaml_imdiag_input)\n'
printf ' mainmsgqueuetimeoutshutdown: "%s"\n' "$RSTB_GLOBAL_QUEUE_SHUTDOWN_TIMEOUT"
printf ' mainmsgqueuetimeoutenqueue: "%s"\n' "$RSTB_MAIN_Q_TO_ENQUEUE"
printf ' inputshutdowntimeout: "%s"\n' "$RSTB_GLOBAL_INPUT_SHUTDOWN_TIMEOUT"
printf ' defaultactionqueuetimeoutshutdown: "%s"\n' "$RSTB_ACTION_DEFAULT_Q_TO_SHUTDOWN"
printf ' defaultactionqueuetimeoutenqueue: "%s"\n' "$RSTB_ACTION_DEFAULT_Q_TO_ENQUEUE"
printf '\n###### add modules:, inputs:, rulesets: etc. below\n'
printf '###### include imdiag input via add_yaml_imdiag_input\n'
printf '###### end of testbench instrumentation part, test conf follows:\n'
} > ${TESTCONF_NM}$1.yaml
else
export RSYSLOG_YAML_ONLY=0
export TESTCONF_EXT="conf"
echo 'module(load="../plugins/imdiag/.libs/imdiag")
global(inputs.timeout.shutdown="'$RSTB_GLOBAL_INPUT_SHUTDOWN_TIMEOUT'"
default.action.queue.timeoutshutdown="'$RSTB_ACTION_DEFAULT_Q_TO_SHUTDOWN'"
default.action.queue.timeoutEnqueue="'$RSTB_ACTION_DEFAULT_Q_TO_ENQUEUE'"
debug.abortOnProgramError="on")
# use legacy-style for the following settings so that we can override if needed
$MainmsgQueueTimeoutEnqueue '$RSTB_ACTION_DEFAULT_Q_TO_ENQUEUE'
$MainmsgQueueTimeoutShutdown '$RSTB_GLOBAL_QUEUE_SHUTDOWN_TIMEOUT'
echo 'module(load="../plugins/imdiag/.libs/imdiag"
mainmsgqueuetimeoutshutdown="'$RSTB_GLOBAL_QUEUE_SHUTDOWN_TIMEOUT'"
mainmsgqueuetimeoutenqueue="'$RSTB_MAIN_Q_TO_ENQUEUE'"
inputshutdowntimeout="'$RSTB_GLOBAL_INPUT_SHUTDOWN_TIMEOUT'"
defaultactionqueuetimeoutshutdown="'$RSTB_ACTION_DEFAULT_Q_TO_SHUTDOWN'"
defaultactionqueuetimeoutenqueue="'$RSTB_ACTION_DEFAULT_Q_TO_ENQUEUE'")
global(debug.abortOnProgramError="on")
$IMDiagListenPortFileName '$RSYSLOG_DYNNAME.imdiag$1.port'
$IMDiagServerRun 0
$IMDiagAbortTimeout '$TB_TEST_MAX_RUNTIME'
# Capture rsyslogd own messages (startup, shutdown, errors) to the .started
# file. Tests use this file to check for expected rsyslogd-internal messages.
# This rule also ensures at least one output action exists in the default
# ruleset, which is required by rsyslogd even when only inputs are configured.
:syslogtag, contains, "rsyslogd" ./'${RSYSLOG_DYNNAME}$1'.started
###### end of testbench instrumentation part, test conf follows:' > ${TESTCONF_NM}$1.conf
# Optionally enforce IPv4 for this test instance.
@ -941,47 +933,38 @@ check_rsyslog_active() {
}
# wait for rsyslogd startup ($1 is the instance)
# Startup is signalled by the imdiag port file appearing (written only after
# the imdiag input is fully active). This works for both RainerScript and
# yaml-only modes. Fast-fail if the process exits before the port file appears.
wait_startup() {
local instance=$1
local pid_file="$RSYSLOG_PIDBASE$instance.pid"
local started_file="${RSYSLOG_DYNNAME}$instance.started"
local imdiag_port_file="$RSYSLOG_DYNNAME.imdiag$instance.port"
# In yaml-only mode the .started marker is never written (the syslogtag filter
# requires RainerScript/legacy syntax). The PID file alone is insufficient because
# rsyslogd writes it before activating inputs, so a YAML config error would appear
# as a successful startup. Require the imdiag port file (written only after the
# input is fully active) instead, and fast-fail if the process exits before that.
local _imdiag_port_ready
while :; do
_imdiag_port_ready=0
[ -s "$imdiag_port_file" ] && _imdiag_port_ready=1
if [ "$RSYSLOG_YAML_ONLY" = "1" ]; then
# yaml-only: imdiag port file is the definitive startup signal
[ "$_imdiag_port_ready" = "1" ] && break
# fast-fail: process wrote PID file but is already gone (config error)
if [ -s "$imdiag_port_file" ]; then
# port file seen — quick liveness check before trusting it
if [ -s "$pid_file" ] && ! ps -p "$(cat "$pid_file" 2>/dev/null)" > /dev/null 2>&1; then
printf '%s ABORT! rsyslog exited during yaml-only startup (config error?)\n' "$(tb_timestamp)"
printf '%s ABORT! rsyslog exited immediately after writing port file\n' "$(tb_timestamp)"
error_exit 1 stacktrace
fi
else
{ [ -f "$pid_file" ] || [ -f "$started_file" ] || [ "$_imdiag_port_ready" = "1" ]; } \
&& break
break
fi
# If we are exactly at/over timeout threshold, re-check once more before aborting
# fast-fail: PID written but process already gone (config error)
if [ -s "$pid_file" ] && ! ps -p "$(cat "$pid_file" 2>/dev/null)" > /dev/null 2>&1; then
printf '%s ABORT! rsyslog exited during startup (config error?)\n' "$(tb_timestamp)"
error_exit 1 stacktrace
fi
# timeout check
if [ $(date +%s) -gt $(( TB_STARTTEST + TB_STARTUP_MAX_RUNTIME )) ]; then
[ -s "$imdiag_port_file" ] && break
if [ "$RSYSLOG_YAML_ONLY" != "1" ]; then
{ [ -f "$pid_file" ] || [ -f "$started_file" ]; } && break
fi
printf '%s ABORT! Timeout waiting startup indicator (%s or %s or %s) after %d seconds\n' "$(tb_timestamp)" "$pid_file" "$started_file" "$imdiag_port_file" $TB_STARTUP_MAX_RUNTIME
# show current file states for diagnostics
ls -l "$pid_file" "$started_file" "$imdiag_port_file" 2>/dev/null || true
# observed late creation on some CI runners; proceed softly and let subsequent waits validate
break
printf '%s ABORT! Timeout waiting for imdiag port file (%s) after %d seconds\n' \
"$(tb_timestamp)" "$imdiag_port_file" $TB_STARTUP_MAX_RUNTIME
ls -l "$pid_file" "$imdiag_port_file" 2>/dev/null || true
error_exit 1 stacktrace
fi
$TESTTOOL_DIR/msleep 50 # wait 50 milliseconds
done
# If we have a pid file, perform a quick liveness check
# quick liveness check
if [ -f "$pid_file" ]; then
$TESTTOOL_DIR/msleep 50
check_rsyslog_active $instance
@ -2320,7 +2303,7 @@ exit_test() {
rm -f work rsyslog.out.* xlate*.lkp_tbl
rm -rf test-logdir stat-file1
rm -f rsyslog.conf.tlscert stat-file1 rsyslog.empty imfile-state:*
rm -f ${TESTCONF_NM}.conf
rm -f ${TESTCONF_NM}.conf ${TESTCONF_NM}.yaml
rm -f tmp.qi nocert
rm -fr $RSYSLOG_DYNNAME* # delete all of our dynamic files
unset TCPFLOOD_EXTRA_OPTS

View File

@ -1,18 +1,13 @@
#!/bin/bash
# Tests that the YAML-only testbench mode works end-to-end:
# - generate_conf --yaml-only writes a pure YAML preamble (no RainerScript)
# - additional modules are appended as sequence continuations (no duplicate
# modules: key) so YAML parsers see a single well-formed modules: list
# - generate_conf --yaml-only writes a pure YAML preamble using
# testbench_modules: for the imdiag setup (no RainerScript)
# - test-specific modules go in a standard modules: section
# - add_yaml_imdiag_input adds the imdiag input for startup detection
# - rsyslogd starts and processes messages using only the YAML loader
#
# This test intentionally avoids any RainerScript or legacy-style directives
# so that it exercises the yaml-only testbench path introduced alongside the
# YAML configuration support.
#
# Note: queue timeout settings are expressed via mainqueue: in the YAML
# preamble (generated by generate_conf --yaml-only) because the legacy
# $MainmsgQueueTimeout* directives are not available in yaml-only mode.
# so that it exercises the yaml-only testbench path.
#
# Added 2025 by contributors, released under ASL 2.0
. ${srcdir:=.}/diag.sh init
@ -20,8 +15,9 @@ require_plugin imtcp
export NUMMESSAGES=100
export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines
generate_conf --yaml-only
# Append imtcp as a continuation item of the modules: sequence already opened
# by the preamble (2-space indent, no top-level modules: key).
# Test-specific modules go in a standard modules: section.
# Testbench infrastructure (imdiag) is in testbench_modules: written by the preamble.
add_yaml_conf 'modules:'
add_yaml_conf ' - load: "../plugins/imtcp/.libs/imtcp"'
add_yaml_conf ''
add_yaml_conf 'templates:'