wttr/src/weather/Mock.zig

85 lines
2.3 KiB
Zig

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);
}