From 66d1e7fa79598feec2ac21b82dc134eb271b3b71 Mon Sep 17 00:00:00 2001 From: Emil Lerch Date: Thu, 18 Dec 2025 15:01:50 -0800 Subject: [PATCH] convert mock.zig -> Mock.zig --- src/main.zig | 3 +- src/weather/Mock.zig | 85 ++++++++++++++++++++++++++++++++++++++++++++ src/weather/mock.zig | 85 -------------------------------------------- 3 files changed, 86 insertions(+), 87 deletions(-) create mode 100644 src/weather/Mock.zig delete mode 100644 src/weather/mock.zig diff --git a/src/main.zig b/src/main.zig index 72017f0..85ceae1 100644 --- a/src/main.zig +++ b/src/main.zig @@ -2,7 +2,6 @@ const std = @import("std"); const config = @import("config.zig"); const Cache = @import("cache/Cache.zig"); const MetNo = @import("weather/MetNo.zig"); -const types = @import("weather/types.zig"); const Server = @import("http/Server.zig"); const RateLimiter = @import("http/RateLimiter.zig"); const GeoIp = @import("location/GeoIp.zig"); @@ -80,7 +79,7 @@ test { std.testing.refAllDecls(@This()); _ = @import("config.zig"); _ = @import("cache/Lru.zig"); - _ = @import("weather/mock.zig"); + _ = @import("weather/Mock.zig"); _ = @import("http/RateLimiter.zig"); _ = @import("http/query.zig"); _ = @import("http/help.zig"); diff --git a/src/weather/Mock.zig b/src/weather/Mock.zig new file mode 100644 index 0000000..87566af --- /dev/null +++ b/src/weather/Mock.zig @@ -0,0 +1,85 @@ +const std = @import("std"); +const weather_provider = @import("provider.zig"); +const types = @import("types.zig"); + +const Mock = @This(); + +allocator: std.mem.Allocator, +responses: std.StringHashMap(types.WeatherData), + +pub fn init(allocator: std.mem.Allocator) !Mock { + return Mock{ + .allocator = allocator, + .responses = std.StringHashMap(types.WeatherData).init(allocator), + }; +} + +pub fn provider(self: *Mock) weather_provider.WeatherProvider { + return .{ + .ptr = self, + .vtable = &.{ + .fetch = fetch, + .deinit = deinitProvider, + }, + }; +} + +pub fn addResponse(self: *Mock, location: []const u8, data: types.WeatherData) !void { + const key = try self.allocator.dupe(u8, location); + try self.responses.put(key, data); +} + +fn fetch(ptr: *anyopaque, allocator: std.mem.Allocator, location: []const u8) !types.WeatherData { + const self: *Mock = @ptrCast(@alignCast(ptr)); + const data = self.responses.get(location) orelse return error.LocationNotFound; + + return types.WeatherData{ + .location = try allocator.dupe(u8, data.location), + .current = data.current, + .forecast = try allocator.dupe(types.ForecastDay, data.forecast), + .allocator = allocator, + }; +} + +fn deinitProvider(ptr: *anyopaque) void { + const self: *Mock = @ptrCast(@alignCast(ptr)); + self.deinit(); +} + +pub fn deinit(self: *Mock) void { + var it = self.responses.iterator(); + while (it.next()) |entry| { + self.allocator.free(entry.key_ptr.*); + } + self.responses.deinit(); +} + +test "mock weather provider" { + var mock = try Mock.init(std.testing.allocator); + defer mock.deinit(); + + const data = types.WeatherData{ + .location = "London", + .current = .{ + .temp_c = 15.0, + .temp_f = 59.0, + .condition = "Clear", + .weather_code = 113, + .humidity = 65, + .wind_kph = 10.0, + .wind_dir = "N", + .pressure_mb = 1013.0, + .precip_mm = 0.0, + }, + .forecast = &.{}, + .allocator = std.testing.allocator, + }; + + try mock.addResponse("London", data); + + const p = mock.provider(); + const result = try p.fetch(std.testing.allocator, "London"); + defer result.deinit(); + + try std.testing.expectEqual(@as(f32, 15.0), result.current.temp_c); +} diff --git a/src/weather/mock.zig b/src/weather/mock.zig deleted file mode 100644 index ed5e7a2..0000000 --- a/src/weather/mock.zig +++ /dev/null @@ -1,85 +0,0 @@ -const std = @import("std"); -const weather_provider = @import("provider.zig"); -const types = @import("types.zig"); - -pub const MockWeather = struct { - allocator: std.mem.Allocator, - responses: std.StringHashMap(types.WeatherData), - - pub fn init(allocator: std.mem.Allocator) !MockWeather { - return MockWeather{ - .allocator = allocator, - .responses = std.StringHashMap(types.WeatherData).init(allocator), - }; - } - - pub fn provider(self: *MockWeather) weather_provider.WeatherProvider { - return .{ - .ptr = self, - .vtable = &.{ - .fetch = fetch, - .deinit = deinitProvider, - }, - }; - } - - pub fn addResponse(self: *MockWeather, location: []const u8, data: types.WeatherData) !void { - const key = try self.allocator.dupe(u8, location); - try self.responses.put(key, data); - } - - fn fetch(ptr: *anyopaque, allocator: std.mem.Allocator, location: []const u8) !types.WeatherData { - const self: *MockWeather = @ptrCast(@alignCast(ptr)); - const data = self.responses.get(location) orelse return error.LocationNotFound; - - return types.WeatherData{ - .location = try allocator.dupe(u8, data.location), - .current = data.current, - .forecast = try allocator.dupe(types.ForecastDay, data.forecast), - .allocator = allocator, - }; - } - - fn deinitProvider(ptr: *anyopaque) void { - const self: *MockWeather = @ptrCast(@alignCast(ptr)); - self.deinit(); - } - - pub fn deinit(self: *MockWeather) void { - var it = self.responses.iterator(); - while (it.next()) |entry| { - self.allocator.free(entry.key_ptr.*); - } - self.responses.deinit(); - } -}; - -test "mock weather provider" { - var mock = try MockWeather.init(std.testing.allocator); - defer mock.deinit(); - - const data = types.WeatherData{ - .location = "London", - .current = .{ - .temp_c = 15.0, - .temp_f = 59.0, - .condition = "Clear", - .weather_code = 113, - .humidity = 65, - .wind_kph = 10.0, - .wind_dir = "N", - .pressure_mb = 1013.0, - .precip_mm = 0.0, - }, - .forecast = &.{}, - .allocator = std.testing.allocator, - }; - - try mock.addResponse("London", data); - - const p = mock.provider(); - const result = try p.fetch(std.testing.allocator, "London"); - defer result.deinit(); - - try std.testing.expectEqual(@as(f32, 15.0), result.current.temp_c); -}