Skip to content

Commit 4b01f8a

Browse files
committed
[New] tests: --json-report list sort + started_epoch regressions; issue #483
[New] tests/31-json-report.bats: 3 new cases — (1) reports[] sorted by started_epoch descending across TSV + legacy passes, (2) started_epoch present as integer and matches date -d on started string, (3) legacy session entries derive started_epoch via pass-2 date fallback. [Change] CHANGELOG + CHANGELOG.RELEASE: note test coverage in v2.0.1 Bug Fixes.
1 parent 2a32ce5 commit 4b01f8a

3 files changed

Lines changed: 126 additions & 0 deletions

File tree

CHANGELOG

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,8 @@ v2.0.1 | Mar 25 2026:
334334
[New] --json-report list: reports[] entries include started_epoch integer
335335
field for machine-readable absolute timestamps; additive schema
336336
change (existing "started" string preserved); issue #483
337+
[New] tests: 3 BATS regressions for --json-report list sort order,
338+
started_epoch field, and legacy-session epoch derivation; issue #483
337339

338340
v1.6.6.1 | Feb 25 2025:
339341
[Fix] find_recentopts incorrectly escaping find options to the right of ( -mtime .. -ctime ); previously normalized by eval; issue #440, pr#442

CHANGELOG.RELEASE

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -334,3 +334,5 @@ v2.0.1 | Mar 25 2026:
334334
[New] --json-report list: reports[] entries include started_epoch integer
335335
field for machine-readable absolute timestamps; additive schema
336336
change (existing "started" string preserved); issue #483
337+
[New] tests: 3 BATS regressions for --json-report list sort order,
338+
started_epoch field, and legacy-session epoch derivation; issue #483

tests/31-json-report.bats

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -454,3 +454,125 @@ LEGACY
454454
[ "$elapsed" -lt 30 ]
455455
[[ "${lines[0]}" = "{" ]]
456456
}
457+
458+
# --- Test 28: --json-report list reports[] globally sorted by started_epoch ---
459+
# Regression guard for issue #483 comment 2: pre-fix code emitted TSV-index
460+
# entries before legacy entries regardless of date, producing a misordered
461+
# reports[] (e.g. Mar 29 legacy after Apr 18 TSV). The fix buffers both
462+
# passes and sorts by started_epoch descending.
463+
@test "--json-report list reports[] sorted by started_epoch descending" {
464+
local sessdir="$LMD_INSTALL/sess"
465+
# Inject a legacy session with an OLDER date than any TSV scan we'll run.
466+
local oldsid="200101-0100.88881"
467+
cat > "$sessdir/session.$oldsid" <<'LEGACY'
468+
HOST: testhost.example.com
469+
SCAN ID: 200101-0100.88881
470+
STARTED: Jan 01 2020 01:00:00 +0000
471+
COMPLETED: Jan 01 2020 01:00:05 +0000
472+
ELAPSED: 5s [find: 1s]
473+
PATH: /home/legacyuser
474+
TOTAL FILES: 10
475+
TOTAL HITS: 0
476+
TOTAL CLEANED: 0
477+
478+
FILE HIT LIST:
479+
LEGACY
480+
# Run a fresh scan — produces a TSV-indexed entry with a recent epoch.
481+
cp "$SAMPLES_DIR/eicar.com" "$TEST_DIR/"
482+
maldet -a "$TEST_DIR" || true
483+
484+
run maldet --json-report list
485+
rm -f "$sessdir/session.$oldsid"
486+
assert_success
487+
# Extract started_epoch values in emission order and verify non-increasing.
488+
# python3 is available on debian12 + rocky9; skip on images without it.
489+
if ! command -v python3 >/dev/null 2>&1; then
490+
skip "python3 not available in this image"
491+
fi
492+
local ordered
493+
ordered=$(echo "$output" | python3 -c '
494+
import sys, json
495+
d = json.load(sys.stdin)
496+
eps = [r["started_epoch"] for r in d["reports"]]
497+
print("OK" if eps == sorted(eps, reverse=True) else "FAIL: " + repr(eps))
498+
')
499+
[[ "$ordered" == "OK" ]]
500+
}
501+
502+
# --- Test 29: --json-report list reports[] include started_epoch integer ---
503+
# Regression guard for issue #483 comment 1: machine consumers need an
504+
# unambiguous absolute timestamp. Asserts the field is present, is an
505+
# integer (not a quoted string), and matches date -d on the started string.
506+
@test "--json-report list reports[] include started_epoch matching started" {
507+
cp "$SAMPLES_DIR/eicar.com" "$TEST_DIR/"
508+
maldet -a "$TEST_DIR" || true
509+
run maldet --json-report list
510+
assert_success
511+
assert_output --partial '"started_epoch"'
512+
# Integer — no quotes around the value. Matches lines like:
513+
# "started_epoch": 1744116606,
514+
[[ "$output" =~ \"started_epoch\":[[:space:]]+[0-9]+ ]]
515+
# If python3 available, cross-check epoch equals date -d on started.
516+
if command -v python3 >/dev/null 2>&1; then
517+
local check
518+
check=$(echo "$output" | python3 -c '
519+
import sys, json, subprocess
520+
d = json.load(sys.stdin)
521+
bad = []
522+
for r in d["reports"]:
523+
s, e = r.get("started"), r.get("started_epoch")
524+
if s is None or e is None or e == 0:
525+
continue
526+
p = subprocess.run(["date", "-d", s, "+%s"], capture_output=True, text=True)
527+
if p.returncode != 0:
528+
continue
529+
want = int(p.stdout.strip())
530+
if want != e:
531+
bad.append((r["scan_id"], s, e, want))
532+
print("OK" if not bad else "FAIL: " + repr(bad))
533+
')
534+
[[ "$check" == "OK" ]]
535+
fi
536+
}
537+
538+
# --- Test 30: --json-report list legacy entries carry started_epoch ---
539+
# Regression guard for issue #483: pass 2 (legacy session files not in
540+
# session.index) must derive started_epoch from scan_start_hr, not silently
541+
# omit the field. Also asserts the legacy "source" tag is still emitted.
542+
@test "--json-report list legacy session reports[] include started_epoch" {
543+
local sessdir="$LMD_INSTALL/sess"
544+
local sid="991231-2359.99990"
545+
cat > "$sessdir/session.$sid" <<'LEGACY'
546+
HOST: testhost.example.com
547+
SCAN ID: 991231-2359.99990
548+
STARTED: Dec 31 2099 23:59:59 +0000
549+
COMPLETED: Jan 01 2100 00:00:05 +0000
550+
ELAPSED: 6s [find: 1s]
551+
PATH: /home/testuser
552+
TOTAL FILES: 42
553+
TOTAL HITS: 0
554+
TOTAL CLEANED: 0
555+
556+
FILE HIT LIST:
557+
LEGACY
558+
run maldet --json-report list
559+
rm -f "$sessdir/session.$sid"
560+
assert_success
561+
assert_output --partial '"991231-2359.99990"'
562+
assert_output --partial '"source": "legacy"'
563+
# Epoch of Dec 31 2099 23:59:59 UTC = 4102444799. Non-zero value proves
564+
# pass 2 derivation ran. Loose assertion (just >= year-2099 epoch) to
565+
# avoid timezone-induced brittleness on test runners.
566+
if command -v python3 >/dev/null 2>&1; then
567+
local got
568+
got=$(echo "$output" | python3 -c '
569+
import sys, json
570+
d = json.load(sys.stdin)
571+
e = next((r["started_epoch"] for r in d["reports"]
572+
if r["scan_id"] == "991231-2359.99990"), None)
573+
print(e if e is not None else "MISSING")
574+
')
575+
[[ "$got" != "MISSING" ]]
576+
[[ "$got" -gt 4000000000 ]]
577+
fi
578+
}

0 commit comments

Comments
 (0)