I wrote a small command line argument parser and I would now like to test it. The parser takes a std.process.Args.Iterator for initialization like so:
const args: std.process.Args = .{
.vector = &.{ "--asdf", "--qwerty", "--", "-abc", "waow", "woah", "hmmm" },
};
var iter: ArgsIterator = .init(args.iterate());
Which works great… on linux. But this test can’t run on windows and some other targets because the type of .vector is different.
Is there any platform-agnostic way to create a std.process.Args instance for testing purposes?
1 Like
I think it should be somewhat manual, I was looking at the code for std.process.Args.zig
fn testIteratorWindows(cmd_line: []const u8, expected_args: []const []const u8) !void {
const cmd_line_w = try std.unicode.wtf8ToWtf16LeAllocZ(testing.allocator, cmd_line);
defer testing.allocator.free(cmd_line_w);
// next
{
var it = try Iterator.Windows.init(testing.allocator, cmd_line_w);
defer it.deinit();
...
line 669
It is extremely cheap in the grand scheme of things to allocate the args into an ArrayList at initialization time and parse a []const []const u8 instead. That allows you to pass &.{"foo", "bar"} to tests (maybe with some massaging, I’m not at a computer to verify).
For a parser I worked on, I built the logic around parsing slices, then provided an additional adapter/wrapper for consuming an iterator instead.
It seems like it would be either changing the api like that or constructing it manually as @IbrahimOuhamou mentioned.
I’m probably just gonna leave the test posix-only as it is just a part of a bigger project, not an arg-parsing library. Might have to figure out a way to auto-skip that test if I add others to not have all the tests be platform specific just because that one refuses to compile.
I think it would be better to make a small wrapper function which converts []const []const u8 to utf16 on windows, since it is apparently the only thing that needs conversion (and wasi need [*:0]const u8)
since the std code is
pub const Vector = switch (native_os) {
.windows => []const u16, // WTF-16 encoded
.wasi => switch (builtin.link_libc) {
false => void,
true => []const [*:0]const u8,
},
.freestanding, .other => void,
else => []const [*:0]const u8,
};