diff --git a/src/Config.zig b/src/Config.zig index 1a2e264..fa9a208 100644 --- a/src/Config.zig +++ b/src/Config.zig @@ -71,7 +71,7 @@ pub fn load(allocator: std.mem.Allocator, env: *const std.process.Environ.Map) ! defer allocator.free(default_cache_dir); return .{ - .listen_host = env.get("WTTR_LISTEN_HOST") orelse try allocator.dupe(u8, "0.0.0.0"), + .listen_host = try allocator.dupe(u8, env.get("WTTR_LISTEN_HOST") orelse "0.0.0.0"), .listen_port = if (env.get("WTTR_LISTEN_PORT")) |p| try std.fmt.parseInt(u16, p, 10) else @@ -181,3 +181,19 @@ test "config loads defaults" { try std.testing.expectEqual(@as(u16, 8002), cfg.listen_port); try std.testing.expectEqual(@as(usize, 10_000), cfg.cache_size); } + +test "config owns WTTR_LISTEN_HOST independently of the environment map" { + const allocator = std.testing.allocator; + var env: std.process.Environ.Map = .init(allocator); + // Declared first so it runs last, matching `main`: the config is torn down + // while the environment map is still alive, then the map frees its values. + // A config that borrowed the map's string would free it twice. + defer env.deinit(); + try env.put("WTTR_CACHE_DIR", @import("build_options").cache_dir); + try env.put("WTTR_LISTEN_HOST", "127.0.0.1"); + + const cfg = try Config.load(allocator, &env); + defer cfg.deinit(allocator); + + try std.testing.expectEqualStrings("127.0.0.1", cfg.listen_host); +}