avoid output under test

This commit is contained in:
Emil Lerch 2026-05-19 13:44:37 -07:00
parent 9211fcf773
commit 8c4d7e6de3
Signed by: lobo
GPG key ID: A7B62D657EF764F8

View file

@ -10,11 +10,24 @@
/// - Success rate for a given spending level
/// - Percentile bands of portfolio value at each year (for charting)
const std = @import("std");
const builtin = @import("builtin");
const log = std.log.scoped(.projections);
const shiller = @import("../data/shiller.zig");
const srf = @import("srf");
const Date = @import("../Date.zig");
/// `log.warn` wrapper that no-ops under `zig build test`. Used for
/// validation warnings emitted while parsing user-supplied
/// `projections.srf` records: the test suite intentionally feeds
/// invalid inputs to `validRetirementTarget` and the config-loader
/// to verify they're rejected, but the resulting stderr noise
/// pollutes test output. Keep using `log.warn` directly when the
/// warning is interesting in tests too.
fn warnUser(comptime fmt: []const u8, args: anytype) void {
if (builtin.is_test) return;
log.warn(fmt, args);
}
// Life events
/// A resolved event ready for the simulation loop. All age-based timing
@ -522,7 +535,7 @@ pub fn parseProjectionsConfig(data: ?[]const u8) UserConfig {
if (amt >= 0) {
config.annual_contribution = amt;
} else {
log.warn("projections: annual_contribution must be >= 0 (got {d}); ignoring record", .{amt});
warnUser("projections: annual_contribution must be >= 0 (got {d}); ignoring record", .{amt});
}
}
if (c.contribution_inflation_adjusted) |b| {
@ -532,7 +545,7 @@ pub fn parseProjectionsConfig(data: ?[]const u8) UserConfig {
if (amt >= 0) {
config.target_spending = amt;
} else {
log.warn("projections: target_spending must be >= 0 (got {d}); ignoring record", .{amt});
warnUser("projections: target_spending must be >= 0 (got {d}); ignoring record", .{amt});
}
}
if (c.target_spending_inflation_adjusted) |b| {
@ -580,7 +593,7 @@ pub fn parseProjectionsConfig(data: ?[]const u8) UserConfig {
// fall back to the default rule. Logged as a warning so the
// user knows their override was ignored.
if (annotation_count > 1) {
log.warn("projections: retirement_target set on multiple horizons; ignoring all annotations and using default promotion rule", .{});
warnUser("projections: retirement_target set on multiple horizons; ignoring all annotations and using default promotion rule", .{});
config.horizon_targets = @splat(0);
config.horizon_age_targets = @splat(0);
}
@ -596,7 +609,7 @@ pub fn parseProjectionsConfig(data: ?[]const u8) UserConfig {
fn validRetirementTarget(raw: ?u8) ?u8 {
const v = raw orelse return null;
if (v == 90 or v == 95 or v == 99) return v;
log.warn("projections: retirement_target must be 90, 95, or 99 (got {d}); annotation ignored", .{v});
warnUser("projections: retirement_target must be 90, 95, or 99 (got {d}); annotation ignored", .{v});
return null;
}