test: add decl tests
This commit is contained in:
parent
c5051f9795
commit
0d18a9b332
2 changed files with 84 additions and 55 deletions
|
|
@ -1,6 +1,6 @@
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
|
||||||
pub const Instant = @This();
|
const Instant = @This();
|
||||||
|
|
||||||
inner: *CInstant,
|
inner: *CInstant,
|
||||||
epoch: i64,
|
epoch: i64,
|
||||||
|
|
@ -28,7 +28,7 @@ pub fn from(text: []const u8) !Instant {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse an ISO 8601 UTF-16 string (Temporal.Instant.from).
|
/// Parse an ISO 8601 UTF-16 string (Temporal.Instant.from).
|
||||||
pub fn fromUtf16(text: []const u16) !Instant {
|
fn fromUtf16(text: []const u16) !Instant {
|
||||||
const view = DiplomatString16View{ .data = text.ptr, .len = text.len };
|
const view = DiplomatString16View{ .data = text.ptr, .len = text.len };
|
||||||
return wrapInstant(temporal_rs_Instant_from_utf16(view));
|
return wrapInstant(temporal_rs_Instant_from_utf16(view));
|
||||||
}
|
}
|
||||||
|
|
@ -103,7 +103,7 @@ pub fn toString(self: Instant, allocator: std.mem.Allocator, opts: ToStringOptio
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convert to string using an explicit provider.
|
/// Convert to string using an explicit provider.
|
||||||
pub fn toStringWithProvider(self: Instant, allocator: std.mem.Allocator, provider: *const Provider, opts: ToStringOptions) ![]u8 {
|
fn toStringWithProvider(self: Instant, allocator: std.mem.Allocator, provider: *const Provider, opts: ToStringOptions) ![]u8 {
|
||||||
const zone_opt = if (opts.time_zone) |z|
|
const zone_opt = if (opts.time_zone) |z|
|
||||||
TimeZone_option{ .ok = z, .is_ok = true }
|
TimeZone_option{ .ok = z, .is_ok = true }
|
||||||
else
|
else
|
||||||
|
|
@ -143,12 +143,12 @@ pub fn toZonedDateTimeISO(self: Instant, zone: TimeZone) !ZonedDateTimeHandle {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convert to ZonedDateTime using an explicit provider.
|
/// Convert to ZonedDateTime using an explicit provider.
|
||||||
pub fn toZonedDateTimeIsoWithProvider(self: Instant, zone: TimeZone, provider: *const Provider) !ZonedDateTimeHandle {
|
fn toZonedDateTimeIsoWithProvider(self: Instant, zone: TimeZone, provider: *const Provider) !ZonedDateTimeHandle {
|
||||||
return wrapZonedDateTime(temporal_rs_Instant_to_zoned_date_time_iso_with_provider(self.inner, zone, provider));
|
return wrapZonedDateTime(temporal_rs_Instant_to_zoned_date_time_iso_with_provider(self.inner, zone, provider));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Clone the underlying instant.
|
/// Clone the underlying instant.
|
||||||
pub fn clone(self: Instant) Instant {
|
fn clone(self: Instant) Instant {
|
||||||
const ptr = temporal_rs_Instant_clone(self.inner);
|
const ptr = temporal_rs_Instant_clone(self.inner);
|
||||||
return .{ .inner = ptr, .epoch = temporal_rs_Instant_epoch_milliseconds(ptr) };
|
return .{ .inner = ptr, .epoch = temporal_rs_Instant_epoch_milliseconds(ptr) };
|
||||||
}
|
}
|
||||||
|
|
@ -221,12 +221,12 @@ fn parseDuration(text: []const u8) !DurationHandle {
|
||||||
|
|
||||||
// --- Public helper types -----------------------------------------------------
|
// --- Public helper types -----------------------------------------------------
|
||||||
|
|
||||||
pub const ToStringOptions = struct {
|
const ToStringOptions = struct {
|
||||||
time_zone: ?TimeZone = null,
|
time_zone: ?TimeZone = null,
|
||||||
rounding: ?ToStringRoundingOptions = null,
|
rounding: ?ToStringRoundingOptions = null,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const DurationHandle = struct {
|
const DurationHandle = struct {
|
||||||
ptr: *Duration,
|
ptr: *Duration,
|
||||||
|
|
||||||
pub fn deinit(self: DurationHandle) void {
|
pub fn deinit(self: DurationHandle) void {
|
||||||
|
|
@ -234,7 +234,7 @@ pub const DurationHandle = struct {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const ZonedDateTimeHandle = struct {
|
const ZonedDateTimeHandle = struct {
|
||||||
ptr: *ZonedDateTime,
|
ptr: *ZonedDateTime,
|
||||||
|
|
||||||
pub fn deinit(self: ZonedDateTimeHandle) void {
|
pub fn deinit(self: ZonedDateTimeHandle) void {
|
||||||
|
|
@ -245,21 +245,21 @@ pub const ZonedDateTimeHandle = struct {
|
||||||
// --- Extern types ------------------------------------------------------------
|
// --- Extern types ------------------------------------------------------------
|
||||||
|
|
||||||
const CInstant = opaque {};
|
const CInstant = opaque {};
|
||||||
pub const Duration = opaque {};
|
const Duration = opaque {};
|
||||||
pub const ZonedDateTime = opaque {};
|
const ZonedDateTime = opaque {};
|
||||||
pub const Provider = opaque {};
|
const Provider = opaque {};
|
||||||
|
|
||||||
pub const I128Nanoseconds = extern struct { high: u64, low: u64 };
|
const I128Nanoseconds = extern struct { high: u64, low: u64 };
|
||||||
pub const I128Nanoseconds_option = extern struct { ok: I128Nanoseconds, is_ok: bool };
|
const I128Nanoseconds_option = extern struct { ok: I128Nanoseconds, is_ok: bool };
|
||||||
|
|
||||||
pub const DiplomatStringView = extern struct { data: [*c]const u8, len: usize };
|
const DiplomatStringView = extern struct { data: [*c]const u8, len: usize };
|
||||||
pub const DiplomatString16View = extern struct { data: [*c]const u16, len: usize };
|
const DiplomatString16View = extern struct { data: [*c]const u16, len: usize };
|
||||||
|
|
||||||
pub const OptionStringView = extern struct { ok: DiplomatStringView, is_ok: bool };
|
const OptionStringView = extern struct { ok: DiplomatStringView, is_ok: bool };
|
||||||
pub const OptionU8 = extern struct { ok: u8, is_ok: bool };
|
const OptionU8 = extern struct { ok: u8, is_ok: bool };
|
||||||
pub const OptionU32 = extern struct { ok: u32, is_ok: bool };
|
const OptionU32 = extern struct { ok: u32, is_ok: bool };
|
||||||
|
|
||||||
pub const DiplomatWrite = extern struct {
|
const DiplomatWrite = extern struct {
|
||||||
context: ?*anyopaque,
|
context: ?*anyopaque,
|
||||||
buf: [*c]u8,
|
buf: [*c]u8,
|
||||||
len: usize,
|
len: usize,
|
||||||
|
|
@ -269,24 +269,24 @@ pub const DiplomatWrite = extern struct {
|
||||||
grow: ?*const fn (*DiplomatWrite, usize) bool,
|
grow: ?*const fn (*DiplomatWrite, usize) bool,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const TimeZone = extern struct {
|
const TimeZone = extern struct {
|
||||||
offset_minutes: i16,
|
offset_minutes: i16,
|
||||||
resolved_id: usize,
|
resolved_id: usize,
|
||||||
normalized_id: usize,
|
normalized_id: usize,
|
||||||
is_iana_id: bool,
|
is_iana_id: bool,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const TimeZone_option = extern struct {
|
const TimeZone_option = extern struct {
|
||||||
ok: TimeZone,
|
ok: TimeZone,
|
||||||
is_ok: bool,
|
is_ok: bool,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const Precision = extern struct {
|
const Precision = extern struct {
|
||||||
is_minute: bool,
|
is_minute: bool,
|
||||||
precision: OptionU8,
|
precision: OptionU8,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const Unit = enum(c_int) {
|
const Unit = enum(c_int) {
|
||||||
Unit_Auto = 0,
|
Unit_Auto = 0,
|
||||||
Unit_Nanosecond = 1,
|
Unit_Nanosecond = 1,
|
||||||
Unit_Microsecond = 2,
|
Unit_Microsecond = 2,
|
||||||
|
|
@ -300,9 +300,9 @@ pub const Unit = enum(c_int) {
|
||||||
Unit_Year = 10,
|
Unit_Year = 10,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const Unit_option = extern struct { ok: Unit, is_ok: bool };
|
const Unit_option = extern struct { ok: Unit, is_ok: bool };
|
||||||
|
|
||||||
pub const RoundingMode = enum(c_int) {
|
const RoundingMode = enum(c_int) {
|
||||||
RoundingMode_Ceil = 0,
|
RoundingMode_Ceil = 0,
|
||||||
RoundingMode_Floor = 1,
|
RoundingMode_Floor = 1,
|
||||||
RoundingMode_Expand = 2,
|
RoundingMode_Expand = 2,
|
||||||
|
|
@ -314,29 +314,29 @@ pub const RoundingMode = enum(c_int) {
|
||||||
RoundingMode_HalfEven = 8,
|
RoundingMode_HalfEven = 8,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const RoundingMode_option = extern struct { ok: RoundingMode, is_ok: bool };
|
const RoundingMode_option = extern struct { ok: RoundingMode, is_ok: bool };
|
||||||
|
|
||||||
pub const DifferenceSettings = extern struct {
|
const DifferenceSettings = extern struct {
|
||||||
largest_unit: Unit_option,
|
largest_unit: Unit_option,
|
||||||
smallest_unit: Unit_option,
|
smallest_unit: Unit_option,
|
||||||
rounding_mode: RoundingMode_option,
|
rounding_mode: RoundingMode_option,
|
||||||
increment: OptionU32,
|
increment: OptionU32,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const RoundingOptions = extern struct {
|
const RoundingOptions = extern struct {
|
||||||
largest_unit: Unit_option,
|
largest_unit: Unit_option,
|
||||||
smallest_unit: Unit_option,
|
smallest_unit: Unit_option,
|
||||||
rounding_mode: RoundingMode_option,
|
rounding_mode: RoundingMode_option,
|
||||||
increment: OptionU32,
|
increment: OptionU32,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const ToStringRoundingOptions = extern struct {
|
const ToStringRoundingOptions = extern struct {
|
||||||
precision: Precision,
|
precision: Precision,
|
||||||
smallest_unit: Unit_option,
|
smallest_unit: Unit_option,
|
||||||
rounding_mode: RoundingMode_option,
|
rounding_mode: RoundingMode_option,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const ErrorKind = enum(c_int) {
|
const ErrorKind = enum(c_int) {
|
||||||
ErrorKind_Generic = 0,
|
ErrorKind_Generic = 0,
|
||||||
ErrorKind_Type = 1,
|
ErrorKind_Type = 1,
|
||||||
ErrorKind_Range = 2,
|
ErrorKind_Range = 2,
|
||||||
|
|
@ -344,12 +344,12 @@ pub const ErrorKind = enum(c_int) {
|
||||||
ErrorKind_Assert = 4,
|
ErrorKind_Assert = 4,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const TemporalError = extern struct {
|
const TemporalError = extern struct {
|
||||||
kind: ErrorKind,
|
kind: ErrorKind,
|
||||||
msg: OptionStringView,
|
msg: OptionStringView,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const Sign = enum(c_int) {
|
const Sign = enum(c_int) {
|
||||||
Sign_Positive = 1,
|
Sign_Positive = 1,
|
||||||
Sign_Zero = 0,
|
Sign_Zero = 0,
|
||||||
Sign_Negative = -1,
|
Sign_Negative = -1,
|
||||||
|
|
|
||||||
71
src/root.zig
71
src/root.zig
|
|
@ -10,15 +10,26 @@ pub const ZonedDateTime = @import("ZonedDateTime.zig");
|
||||||
|
|
||||||
const Temporal = @This();
|
const Temporal = @This();
|
||||||
|
|
||||||
fn assertDecls(comptime T: type, checks: anytype) !void {
|
test "Temporal" {
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
inline for (checks) |check| {
|
|
||||||
const has = @hasDecl(T, check);
|
const expected_scopes = .{
|
||||||
if (!std.mem.eql(u8, check, "valueOf")) {
|
"Duration",
|
||||||
if (!has) std.log.err("Missing {s} method: {s}", .{ @typeName(T), check });
|
"Instant",
|
||||||
|
"Now",
|
||||||
|
"PlainDate",
|
||||||
|
"PlainDateTime",
|
||||||
|
"PlainMonthDay",
|
||||||
|
"PlainTime",
|
||||||
|
"PlainYearMonth",
|
||||||
|
"ZonedDateTime",
|
||||||
|
};
|
||||||
|
|
||||||
|
inline for (expected_scopes) |scope| {
|
||||||
|
const has = @hasDecl(Temporal, scope);
|
||||||
|
if (!has) std.log.err("Missing Temporal scope: {s}", .{scope});
|
||||||
try std.testing.expect(has);
|
try std.testing.expect(has);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
test "Temporal.Duration" {
|
test "Temporal.Duration" {
|
||||||
|
|
@ -388,24 +399,42 @@ test "Temporal.ZonedDateTime" {
|
||||||
try assertDecls(ZonedDateTime, checks);
|
try assertDecls(ZonedDateTime, checks);
|
||||||
}
|
}
|
||||||
|
|
||||||
test "Temporal" {
|
fn assertDecls(comptime T: type, checks: anytype) !void {
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
const typeInfo = @typeInfo(T);
|
||||||
|
|
||||||
const expected_scopes = .{
|
// Check: all items in checks exist
|
||||||
"Duration",
|
inline for (checks) |check| {
|
||||||
"Instant",
|
const should_ignore =
|
||||||
"Now",
|
std.mem.eql(u8, check, "deinit") or
|
||||||
"PlainDate",
|
std.mem.eql(u8, check, "valueOf");
|
||||||
"PlainDateTime",
|
|
||||||
"PlainMonthDay",
|
|
||||||
"PlainTime",
|
|
||||||
"PlainYearMonth",
|
|
||||||
"ZonedDateTime",
|
|
||||||
};
|
|
||||||
|
|
||||||
inline for (expected_scopes) |scope| {
|
const has = @hasDecl(T, check);
|
||||||
const has = @hasDecl(Temporal, scope);
|
if (!should_ignore) {
|
||||||
if (!has) std.log.err("Missing Temporal scope: {s}", .{scope});
|
if (!has) std.log.err("Missing {s} decl: {s}", .{ @typeName(T), check });
|
||||||
try std.testing.expect(has);
|
try std.testing.expect(has);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check: no extraneous declarations beyond checks
|
||||||
|
if (typeInfo == .@"struct") {
|
||||||
|
const struct_info = typeInfo.@"struct";
|
||||||
|
inline for (struct_info.decls) |decl| {
|
||||||
|
// Allow deinit as extraneous
|
||||||
|
if (comptime std.mem.eql(u8, decl.name, "deinit")) continue;
|
||||||
|
|
||||||
|
var found = false;
|
||||||
|
inline for (checks) |check| {
|
||||||
|
if (std.mem.eql(u8, decl.name, check)) {
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found) {
|
||||||
|
std.log.err("Extraneous {s} decl: {s}", .{ @typeName(T), decl.name });
|
||||||
|
try std.testing.expect(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue