[test](trx-decode-log): add unit tests for config, template resolution, and write round-trip

Cover disabled config, template date token substitution, logger
initialization, and JSON Lines write+read verification for FT8 and
APRS payloads.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
This commit is contained in:
2026-04-08 21:58:01 +02:00
parent cee84aa904
commit 7cb2b84d94
2 changed files with 132 additions and 0 deletions
+3
View File
@@ -14,3 +14,6 @@ dirs = "6"
serde = { workspace = true, features = ["derive"] }
serde_json = { workspace = true }
tracing = { workspace = true }
[dev-dependencies]
tempfile = "3"
+129
View File
@@ -224,3 +224,132 @@ impl DecoderLoggers {
self.wefax.write_payload(msg);
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn resolve_file_name_substitutes_date_tokens() {
let template = "LOG-%YYYY%-%MM%-%DD%.log";
let resolved = DecoderFileLogger::resolve_file_name(template);
// Must not contain any template tokens
assert!(!resolved.contains("%YYYY%"));
assert!(!resolved.contains("%MM%"));
assert!(!resolved.contains("%DD%"));
// Must end with .log
assert!(resolved.ends_with(".log"));
// Must start with LOG-
assert!(resolved.starts_with("LOG-"));
// Year should be 4 digits
let parts: Vec<&str> = resolved
.trim_start_matches("LOG-")
.trim_end_matches(".log")
.split('-')
.collect();
assert_eq!(parts.len(), 3);
assert_eq!(parts[0].len(), 4); // YYYY
assert_eq!(parts[1].len(), 2); // MM
assert_eq!(parts[2].len(), 2); // DD
}
#[test]
fn from_config_disabled_returns_none() {
let cfg = DecodeLogsConfig {
enabled: false,
..Default::default()
};
let result = DecoderLoggers::from_config(&cfg).unwrap();
assert!(result.is_none());
}
#[test]
fn from_config_enabled_creates_loggers() {
let dir = tempfile::tempdir().unwrap();
let cfg = DecodeLogsConfig {
enabled: true,
dir: dir.path().to_string_lossy().to_string(),
..Default::default()
};
let result = DecoderLoggers::from_config(&cfg).unwrap();
assert!(result.is_some());
}
#[test]
fn log_ft8_writes_json_line() {
let dir = tempfile::tempdir().unwrap();
let cfg = DecodeLogsConfig {
enabled: true,
dir: dir.path().to_string_lossy().to_string(),
ft8_file: "ft8-test.log".to_string(),
..Default::default()
};
let loggers = DecoderLoggers::from_config(&cfg).unwrap().unwrap();
let msg = Ft8Message {
rig_id: None,
ts_ms: 1000,
snr_db: -12.0,
dt_s: 0.1,
freq_hz: 1234.0,
message: "CQ SP2SJG JO93".to_string(),
};
loggers.log_ft8(&msg);
// Read back the log file
let log_path = dir.path().join("ft8-test.log");
let content = std::fs::read_to_string(&log_path).unwrap();
let lines: Vec<&str> = content.lines().collect();
assert_eq!(lines.len(), 1);
let parsed: serde_json::Value = serde_json::from_str(lines[0]).unwrap();
assert_eq!(parsed["decoder"], "ft8");
assert!(parsed["ts_ms"].is_number());
assert_eq!(parsed["payload"]["message"], "CQ SP2SJG JO93");
assert_eq!(parsed["payload"]["snr_db"], -12.0);
}
#[test]
fn log_aprs_writes_json_line() {
let dir = tempfile::tempdir().unwrap();
let cfg = DecodeLogsConfig {
enabled: true,
dir: dir.path().to_string_lossy().to_string(),
aprs_file: "aprs-test.log".to_string(),
..Default::default()
};
let loggers = DecoderLoggers::from_config(&cfg).unwrap().unwrap();
let pkt = AprsPacket {
rig_id: None,
ts_ms: Some(2000),
src_call: "N0CALL".to_string(),
dest_call: "APRS".to_string(),
path: "WIDE1-1".to_string(),
info: ">Test".to_string(),
info_bytes: b">Test".to_vec(),
packet_type: "Status".to_string(),
crc_ok: true,
lat: None,
lon: None,
symbol_table: None,
symbol_code: None,
};
loggers.log_aprs(&pkt);
let log_path = dir.path().join("aprs-test.log");
let content = std::fs::read_to_string(&log_path).unwrap();
let parsed: serde_json::Value = serde_json::from_str(content.trim()).unwrap();
assert_eq!(parsed["decoder"], "aprs");
assert_eq!(parsed["payload"]["src_call"], "N0CALL");
}
#[test]
fn default_config_has_template_tokens() {
let cfg = DecodeLogsConfig::default();
assert!(cfg.ft8_file.contains("%YYYY%"));
assert!(cfg.aprs_file.contains("%MM%"));
assert!(cfg.cw_file.contains("%DD%"));
assert!(!cfg.enabled);
}
}