diff --git a/tests/config-includes-glob-order/01-order.yaml b/tests/config-includes-glob-order/01-order.yaml new file mode 100644 index 0000000000..3e0397ab39 --- /dev/null +++ b/tests/config-includes-glob-order/01-order.yaml @@ -0,0 +1,3 @@ +%YAML 1.1 +--- +glob-order-seen-01: present diff --git a/tests/config-includes-glob-order/50-order.yaml b/tests/config-includes-glob-order/50-order.yaml new file mode 100644 index 0000000000..062c12643e --- /dev/null +++ b/tests/config-includes-glob-order/50-order.yaml @@ -0,0 +1,3 @@ +%YAML 1.1 +--- +glob-order-seen-50: present diff --git a/tests/config-includes-glob-order/99-order.yaml b/tests/config-includes-glob-order/99-order.yaml new file mode 100644 index 0000000000..ae0941a4d8 --- /dev/null +++ b/tests/config-includes-glob-order/99-order.yaml @@ -0,0 +1,3 @@ +%YAML 1.1 +--- +glob-order-seen-99: present diff --git a/tests/config-includes-glob-order/README.md b/tests/config-includes-glob-order/README.md new file mode 100644 index 0000000000..ece11249d4 --- /dev/null +++ b/tests/config-includes-glob-order/README.md @@ -0,0 +1,44 @@ +# config-includes-glob-order + +Verifies that a glob pattern in an `include:` directive expands to all matching +files and includes them in a deterministic (sorted) order. + +`glob.yaml` includes `*-order.yaml`, which matches three drop-in files +(`01-order.yaml`, `50-order.yaml`, `99-order.yaml`). Each file defines its own +unique marker key (`glob-order-seen-NN`). Because `glob(3)` returns matches in +sorted (lexicographic) order, the files are merged in ascending numeric-prefix +order. + +The test runs suricata against `glob.yaml` with `--dump-config` (via `command:`) +and asserts that: + +- all three matched files were included (one unique marker key per file), and +- the marker keys appear in the dump output in sorted-filename order. The + config tree preserves insertion order, so the position of each key in the + output reflects the order the files were merged. No key is defined twice, so + the test does not depend on duplicate-key override behavior. + +What this test proves is narrow: sorted glob expansion. Real users care about +that property because it makes the common numbered drop-in convention +(`01-*.yaml` .. `99-*.yaml`, as in `conf.d`-style directories) predictable, +including the case where the same key is set in more than one drop-in. This +test does not exercise any of those override scenarios. It just pins the sort +order so it cannot silently regress (for example by expanding with +`GLOB_NOSORT` or a plain directory scan). + +The glob config is kept in `glob.yaml` (not the default `suricata.yaml`) on +purpose: suricata-verify runs `suricata -c suricata.yaml --dump-config` during +test setup before the `min-version` check, so a glob `include:` in a shipped +`suricata.yaml` would break setup on Suricata builds without glob support. + +Note: this test requires the `include:` glob support added in OISF/suricata +(#15574, Redmine #8427). Until that lands, a `requires: script:` probe greps +`src/conf-yaml-loader.c` for the glob expansion code and skips the test on +builds that don't have it, so it does not fail CI runs against main or the +release branches. + +A second probe greps `src/autoconf.h` for `HAVE_GLOB_H`. Glob expansion needs +`glob(3)`, which Windows builds do not have; there an include pattern is +skipped with a warning and none of the matched files are loaded, so the checks +below could not hold. Probing the build rather than the platform keeps the test +running everywhere `glob(3)` is available, including macOS and the BSDs. diff --git a/tests/config-includes-glob-order/glob.yaml b/tests/config-includes-glob-order/glob.yaml new file mode 100644 index 0000000000..0bbfcaacd3 --- /dev/null +++ b/tests/config-includes-glob-order/glob.yaml @@ -0,0 +1,10 @@ +%YAML 1.1 +--- + +# The pattern expands to 01-order.yaml, 50-order.yaml and 99-order.yaml. +# glob(3) returns matches in sorted (lexicographic) order, so the drop-in files +# are included in ascending numeric-prefix order. Each file defines its own +# unique marker key; the order the keys appear in --dump-config output reflects +# the order the files were merged. +include: + - "*-order.yaml" diff --git a/tests/config-includes-glob-order/test.yaml b/tests/config-includes-glob-order/test.yaml new file mode 100644 index 0000000000..18b1ccb421 --- /dev/null +++ b/tests/config-includes-glob-order/test.yaml @@ -0,0 +1,49 @@ +requires: + min-version: 9 + # Glob support in include: is not merged yet (OISF/suricata#15574), so a + # min-version alone can't gate this test. Probe the source tree for the + # glob(3) expansion code instead and skip on builds that don't have it, + # the same way the eve-alert-metadata tests probe for METADATA_DEFAULTS. + # Glob expansion needs glob(3). Builds without glob.h, notably Windows, + # skip an include pattern with a warning and load none of the matched + # files, so the ordering checks below cannot hold there. Probe the build + # rather than the platform, so the test still runs anywhere glob(3) is + # available. + script: + - grep globfree src/conf-yaml-loader.c > /dev/null + - grep '^#define HAVE_GLOB_H 1' src/autoconf.h > /dev/null + +pcap: false + +# Run suricata against glob.yaml explicitly rather than shipping a suricata.yaml. +# suricata-verify always runs `suricata -c /suricata.yaml --dump-config` +# during test setup (before the min-version check), so a glob include in +# suricata.yaml would make that setup step fail on Suricata versions without +# glob support. Using a separate config exercised via `command:` keeps setup on +# the default suricata.yaml and only runs the glob config on a supported build. +command: | + ${SRCDIR}/src/suricata -c ${TEST_DIR}/glob.yaml -l ${OUTPUT_DIR} --dump-config + +checks: + # Every globbed drop-in file is included, not just one: the unique marker key + # from each of 01/50/99-order.yaml is present in the merged config. + - shell: + args: grep '^glob-order-seen-01 = present' stdout | wc -l + expect: 1 + - shell: + args: grep '^glob-order-seen-50 = present' stdout | wc -l + expect: 1 + - shell: + args: grep '^glob-order-seen-99 = present' stdout | wc -l + expect: 1 + + # Ordering is deterministic: glob(3) returns matches sorted, so the files are + # included in ascending numeric-prefix order. Include order is observable in + # --dump-config output because the config tree preserves insertion order, so + # the distinct per-file marker keys must appear in sorted-filename order. + # The test does not exercise override-on-duplicate-keys (each file uses a + # unique key on purpose). What this pins is just the sort order, which is + # what the numbered conf.d-style drop-in convention relies on in practice. + - shell: + args: grep -o '^glob-order-seen-[0-9][0-9]' stdout | tr '\n' ' ' + expect: glob-order-seen-01 glob-order-seen-50 glob-order-seen-99