test: new syslog test to verify property based filtering

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
This commit is contained in:
Joachim Wiberg
2025-11-20 14:05:38 +01:00
parent ed6db59e68
commit 956f2b620d
6 changed files with 197 additions and 0 deletions
+3
View File
@@ -13,3 +13,6 @@
- name: Syslog Hostname Filtering
case: hostname_filter/test.py
- name: Syslog Property Filtering
case: property_filter/test.py
+1
View File
@@ -0,0 +1 @@
test.adoc
@@ -0,0 +1,25 @@
=== Syslog Property Filtering
ifdef::topdoc[:imagesdir: {topdoc}../../test/case/ietf_syslog/property_filter]
==== Description
Verify property-filter feature: filtering syslog messages based on various
message properties with different operators, case-insensitivity, and negation.
==== Topology
image::topology.svg[Syslog Property Filtering topology, align=center, scaledwidth=75%]
==== Sequence
. Set up topology and attach to target DUT
. Clean up old log files
. Configure syslog with property filters
. Send test messages
. Verify myapp log contains only myapp messages
. Verify not-error log excludes ERROR messages
. Verify case-test log matches case-insensitive 'warning'
. Verify baseline log contains all messages
+134
View File
@@ -0,0 +1,134 @@
#!/usr/bin/env python3
"""Syslog Property Filtering
Verify property-filter feature: filtering syslog messages based on various
message properties with different operators, case-insensitivity, and negation.
"""
import infamy
import time
TEST_MESSAGES = [
("myapp", "Application startup"),
("myapp", "Processing request"),
("otherapp", "Different program"),
("test", "ERROR: Connection failed"),
("test", "INFO: Normal message"),
("test", "WARNING: Check config"),
("test", "Warning: lowercase"),
]
with infamy.Test() as test:
with test.step("Set up topology and attach to target DUT"):
env = infamy.Env()
target = env.attach("target", "mgmt")
tgtssh = env.attach("target", "mgmt", "ssh")
with test.step("Clean up old log files"):
tgtssh.runsh("sudo rm -f /var/log/{myapp,not-error,case-test,baseline}")
with test.step("Configure syslog with property filters"):
target.put_config_dicts({
"ietf-syslog": {
"syslog": {
"actions": {
"file": {
"log-file": [{
"name": "file:myapp",
"infix-syslog:property-filter": {
"property": "programname",
"operator": "isequal",
"value": "myapp"
},
"facility-filter": {
"facility-list": [{
"facility": "all",
"severity": "info"
}]
}
}, {
"name": "file:not-error",
"infix-syslog:property-filter": {
"property": "msg",
"operator": "contains",
"value": "ERROR",
"negate": True
},
"facility-filter": {
"facility-list": [{
"facility": "all",
"severity": "info"
}]
}
}, {
"name": "file:case-test",
"infix-syslog:property-filter": {
"property": "msg",
"operator": "contains",
"value": "warning",
"case-insensitive": True
},
"facility-filter": {
"facility-list": [{
"facility": "all",
"severity": "info"
}]
}
}, {
"name": "file:baseline",
"facility-filter": {
"facility-list": [{
"facility": "all",
"severity": "info"
}]
}
}]
}
}
}
}
})
time.sleep(2)
with test.step("Send test messages"):
for tag, msg in TEST_MESSAGES:
tgtssh.runsh(f"logger -t {tag} -p daemon.info '{msg}'")
time.sleep(1)
with test.step("Verify myapp log contains only myapp messages"):
rc = tgtssh.runsh("grep -c 'myapp' /var/log/myapp 2>/dev/null")
count = int(rc.stdout.strip()) if rc.returncode == 0 else 0
if count != 2:
test.fail(f"Expected 2 myapp messages in /var/log/myapp, got {count}")
rc = tgtssh.runsh("grep -c 'otherapp' /var/log/myapp 2>/dev/null")
count = int(rc.stdout.strip()) if rc.returncode == 0 else 0
if count != 0:
test.fail(f"Expected 0 otherapp messages in /var/log/myapp, got {count}")
with test.step("Verify not-error log excludes ERROR messages"):
rc = tgtssh.runsh("grep -c 'test' /var/log/not-error 2>/dev/null")
count = int(rc.stdout.strip()) if rc.returncode == 0 else 0
if count != 3:
test.fail(f"Expected 3 non-ERROR messages in /var/log/not-error, got {count}")
rc = tgtssh.runsh("grep -c 'ERROR' /var/log/not-error 2>/dev/null")
count = int(rc.stdout.strip()) if rc.returncode == 0 else 0
if count != 0:
test.fail(f"Expected 0 ERROR messages in /var/log/not-error, got {count}")
with test.step("Verify case-test log matches case-insensitive 'warning'"):
rc = tgtssh.runsh("grep -c 'WARNING\\|Warning' /var/log/case-test 2>/dev/null")
count = int(rc.stdout.strip()) if rc.returncode == 0 else 0
if count != 2:
test.fail(f"Expected 2 warning messages in /var/log/case-test, got {count}")
with test.step("Verify baseline log contains all messages"):
for tag, msg in TEST_MESSAGES:
rc = tgtssh.runsh(f"grep -q '{msg}' /var/log/baseline 2>/dev/null")
if rc.returncode != 0:
test.fail(f"Expected message '{msg}' not found in /var/log/baseline")
test.succeed()
+1
View File
@@ -0,0 +1 @@
../../../infamy/topologies/1x1.dot
@@ -0,0 +1,33 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Title: 1x1 Pages: 1 -->
<svg width="424pt" height="45pt"
viewBox="0.00 0.00 424.03 45.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 41)">
<title>1x1</title>
<polygon fill="white" stroke="transparent" points="-4,4 -4,-41 420.03,-41 420.03,4 -4,4"/>
<!-- host -->
<g id="node1" class="node">
<title>host</title>
<polygon fill="none" stroke="black" points="0,-0.5 0,-36.5 100,-36.5 100,-0.5 0,-0.5"/>
<text text-anchor="middle" x="25" y="-14.8" font-family="DejaVu Sans Mono, Book" font-size="14.00">host</text>
<polyline fill="none" stroke="black" points="50,-0.5 50,-36.5 "/>
<text text-anchor="middle" x="75" y="-14.8" font-family="DejaVu Sans Mono, Book" font-size="14.00">mgmt</text>
</g>
<!-- target -->
<g id="node2" class="node">
<title>target</title>
<polygon fill="none" stroke="black" points="300.03,-0.5 300.03,-36.5 416.03,-36.5 416.03,-0.5 300.03,-0.5"/>
<text text-anchor="middle" x="325.03" y="-14.8" font-family="DejaVu Sans Mono, Book" font-size="14.00">mgmt</text>
<polyline fill="none" stroke="black" points="350.03,-0.5 350.03,-36.5 "/>
<text text-anchor="middle" x="383.03" y="-14.8" font-family="DejaVu Sans Mono, Book" font-size="14.00">target</text>
</g>
<!-- host&#45;&#45;target -->
<g id="edge1" class="edge">
<title>host:mgmt&#45;&#45;target:mgmt</title>
<path fill="none" stroke="lightgray" stroke-width="2" d="M100,-18.5C100,-18.5 300.03,-18.5 300.03,-18.5"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB