From f4e53cd6149ed4dcbfd8b81a6427b1b652d0a472 Mon Sep 17 00:00:00 2001 From: Jimmi HC Date: Thu, 31 May 2018 16:00:44 +0200 Subject: Started work on the proper structure for the lib --- tests/core.zig | 134 ++++++++++++++++++++++++++++++ tests/extended.zig | 234 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 368 insertions(+) create mode 100644 tests/core.zig create mode 100644 tests/extended.zig (limited to 'tests') diff --git a/tests/core.zig b/tests/core.zig new file mode 100644 index 0000000..a6a705e --- /dev/null +++ b/tests/core.zig @@ -0,0 +1,134 @@ +const std = @import("std"); +const clap = @import("../index.zig"); + +const debug = std.debug; +const mem = std.mem; +const core = clap.core; + +const assert = debug.assert; + +const ArgSliceIterator = core.ArgSliceIterator; +const Names = core.Names; +const Param = core.Param; +const Clap = core.Clap; + +fn testNoErr(params: []const Param(u8), args: []const []const u8, ids: []const u8, values: []const ?[]const u8) void { + var arg_iter = ArgSliceIterator.init(args); + var iter = Clap(u8).init(params, &arg_iter.iter, debug.global_allocator); + + var i: usize = 0; + while (iter.next() catch unreachable) |arg| : (i += 1) { + debug.assert(ids[i] == arg.id); + const expected_value = values[i] ?? { + debug.assert(arg.value == null); + continue; + }; + const actual_value = arg.value ?? unreachable; + + debug.assert(mem.eql(u8, expected_value, actual_value)); + } +} + +test "clap.core: short" { + const params = []Param(u8) { + Param(u8).init(0, false, Names.short('a')), + Param(u8).init(1, false, Names.short('b')), + Param(u8).init(2, true, Names.short('c')), + }; + + testNoErr(params, [][]const u8 { "-a" }, []u8{0}, []?[]const u8{null}); + testNoErr(params, [][]const u8 { "-a", "-b" }, []u8{0,1}, []?[]const u8{null,null}); + testNoErr(params, [][]const u8 { "-ab" }, []u8{0,1}, []?[]const u8{null,null}); + testNoErr(params, [][]const u8 { "-c=100" }, []u8{2}, []?[]const u8{"100"}); + testNoErr(params, [][]const u8 { "-c100" }, []u8{2}, []?[]const u8{"100"}); + testNoErr(params, [][]const u8 { "-c", "100" }, []u8{2}, []?[]const u8{"100"}); + testNoErr(params, [][]const u8 { "-abc", "100" }, []u8{0,1,2}, []?[]const u8{null,null,"100"}); + testNoErr(params, [][]const u8 { "-abc=100" }, []u8{0,1,2}, []?[]const u8{null,null,"100"}); + testNoErr(params, [][]const u8 { "-abc100" }, []u8{0,1,2}, []?[]const u8{null,null,"100"}); +} + +test "clap.core: long" { + const params = []Param(u8) { + Param(u8).init(0, false, Names.long("aa")), + Param(u8).init(1, false, Names.long("bb")), + Param(u8).init(2, true, Names.long("cc")), + }; + + testNoErr(params, [][]const u8 { "--aa" }, []u8{0}, []?[]const u8{null}); + testNoErr(params, [][]const u8 { "--aa", "--bb" }, []u8{0,1}, []?[]const u8{null,null}); + testNoErr(params, [][]const u8 { "--cc=100" }, []u8{2}, []?[]const u8{"100"}); + testNoErr(params, [][]const u8 { "--cc", "100" }, []u8{2}, []?[]const u8{"100"}); +} + +test "clap.core: bare" { + const params = []Param(u8) { + Param(u8).init(0, false, Names.bare("aa")), + Param(u8).init(1, false, Names.bare("bb")), + Param(u8).init(2, true, Names.bare("cc")), + }; + + testNoErr(params, [][]const u8 { "aa" }, []u8{0}, []?[]const u8{null}); + testNoErr(params, [][]const u8 { "aa", "bb" }, []u8{0,1}, []?[]const u8{null,null}); + testNoErr(params, [][]const u8 { "cc=100" }, []u8{2}, []?[]const u8{"100"}); + testNoErr(params, [][]const u8 { "cc", "100" }, []u8{2}, []?[]const u8{"100"}); +} + +test "clap.core: none" { + const params = []Param(u8) { + Param(u8).init(0, true, Names.none()), + }; + + testNoErr(params, [][]const u8 { "aa" }, []u8{0}, []?[]const u8{"aa"}); +} + +test "clap.core: all" { + const params = []Param(u8) { + Param(u8).init( + 0, + false, + Names{ + .bare = "aa", + .short = 'a', + .long = "aa", + } + ), + Param(u8).init( + 1, + false, + Names{ + .bare = "bb", + .short = 'b', + .long = "bb", + } + ), + Param(u8).init( + 2, + true, + Names{ + .bare = "cc", + .short = 'c', + .long = "cc", + } + ), + Param(u8).init(3, true, Names.none()), + }; + + testNoErr(params, [][]const u8 { "-a" }, []u8{0}, []?[]const u8{null}); + testNoErr(params, [][]const u8 { "-a", "-b" }, []u8{0,1}, []?[]const u8{null,null}); + testNoErr(params, [][]const u8 { "-ab" }, []u8{0,1}, []?[]const u8{null,null}); + testNoErr(params, [][]const u8 { "-c=100" }, []u8{2}, []?[]const u8{"100"}); + testNoErr(params, [][]const u8 { "-c100" }, []u8{2}, []?[]const u8{"100"}); + testNoErr(params, [][]const u8 { "-c", "100" }, []u8{2}, []?[]const u8{"100"}); + testNoErr(params, [][]const u8 { "-abc", "100" }, []u8{0,1,2}, []?[]const u8{null,null,"100"}); + testNoErr(params, [][]const u8 { "-abc=100" }, []u8{0,1,2}, []?[]const u8{null,null,"100"}); + testNoErr(params, [][]const u8 { "-abc100" }, []u8{0,1,2}, []?[]const u8{null,null,"100"}); + testNoErr(params, [][]const u8 { "--aa" }, []u8{0}, []?[]const u8{null}); + testNoErr(params, [][]const u8 { "--aa", "--bb" }, []u8{0,1}, []?[]const u8{null,null}); + testNoErr(params, [][]const u8 { "--cc=100" }, []u8{2}, []?[]const u8{"100"}); + testNoErr(params, [][]const u8 { "--cc", "100" }, []u8{2}, []?[]const u8{"100"}); + testNoErr(params, [][]const u8 { "aa" }, []u8{0}, []?[]const u8{null}); + testNoErr(params, [][]const u8 { "aa", "bb" }, []u8{0,1}, []?[]const u8{null,null}); + testNoErr(params, [][]const u8 { "cc=100" }, []u8{2}, []?[]const u8{"100"}); + testNoErr(params, [][]const u8 { "cc", "100" }, []u8{2}, []?[]const u8{"100"}); + testNoErr(params, [][]const u8 { "dd" }, []u8{3}, []?[]const u8{"dd"}); +} diff --git a/tests/extended.zig b/tests/extended.zig new file mode 100644 index 0000000..8f722e4 --- /dev/null +++ b/tests/extended.zig @@ -0,0 +1,234 @@ +const std = @import("std"); +const clap = @import("../index.zig"); + +const debug = std.debug; +const mem = std.mem; +const core = clap.core; +const extended = clap.extended; + +const assert = debug.assert; + +const ArgSliceIterator = core.ArgSliceIterator; +const Command = extended.Command; +const Param = extended.Param; +const Parser = extended.Parser; + +const Options = struct { + str: []const u8, + int: i64, + uint: u64, + a: bool, + b: bool, + cc: bool, + sub: &const SubOptions, + + pub fn with(op: &const Options, comptime field: []const u8, value: var) Options { + var res = op.*; + @field(res, field) = value; + return res; + } +}; + +const SubOptions = struct { + a: bool, + b: u64, + qq: bool, + + pub fn with(op: &const SubOptions, comptime field: []const u8, value: var) SubOptions { + var res = op.*; + @field(res, field) = value; + return res; + } +}; + +const default = Options { + .str = "", + .int = 0, + .uint = 0, + .a = false, + .b = false, + .cc = false, + .sub = SubOptions{ + .a = false, + .b = 0, + .qq = false, + }, +}; + +fn testNoErr(comptime command: &const Command, args: []const []const u8, expected: &const command.Result) void { + var arg_iter = ArgSliceIterator.init(args); + const actual = command.parse(debug.global_allocator, &arg_iter.iter) catch unreachable; + assert(mem.eql(u8, expected.str, actual.str)); + assert(expected.int == actual.int); + assert(expected.uint == actual.uint); + assert(expected.a == actual.a); + assert(expected.b == actual.b); + assert(expected.cc == actual.cc); + assert(expected.sub.a == actual.sub.a); + assert(expected.sub.b == actual.sub.b); +} + +fn testErr(comptime command: &const Command, args: []const []const u8, expected: error) void { + var arg_iter = ArgSliceIterator.init(args); + if (command.parse(debug.global_allocator, &arg_iter.iter)) |actual| { + unreachable; + } else |err| { + assert(err == expected); + } +} + +test "clap.extended: short" { + const command = comptime Command.init( + "", + Options, + default, + []Param { + Param.smart("a"), + Param.smart("b"), + Param.smart("int") + .with("short", 'i') + .with("takes_value", Parser.int(i64, 10)), + }, + []Command{}, + ); + + testNoErr(command, [][]const u8 { "-a" }, default.with("a", true)); + testNoErr(command, [][]const u8 { "-a", "-b" }, default.with("a", true).with("b", true)); + testNoErr(command, [][]const u8 { "-i=100" }, default.with("int", 100)); + testNoErr(command, [][]const u8 { "-i100" }, default.with("int", 100)); + testNoErr(command, [][]const u8 { "-i", "100" }, default.with("int", 100)); + testNoErr(command, [][]const u8 { "-ab" }, default.with("a", true).with("b", true)); + testNoErr(command, [][]const u8 { "-abi", "100" }, default.with("a", true).with("b", true).with("int", 100)); + testNoErr(command, [][]const u8 { "-abi=100" }, default.with("a", true).with("b", true).with("int", 100)); + testNoErr(command, [][]const u8 { "-abi100" }, default.with("a", true).with("b", true).with("int", 100)); +} + +test "clap.extended: long" { + const command = comptime Command.init( + "", + Options, + default, + []Param { + Param.smart("cc"), + Param.smart("int").with("takes_value", Parser.int(i64, 10)), + Param.smart("uint").with("takes_value", Parser.int(u64, 10)), + Param.smart("str").with("takes_value", Parser.string), + }, + []Command{}, + ); + + testNoErr(command, [][]const u8 { "--cc" }, default.with("cc", true)); + testNoErr(command, [][]const u8 { "--int", "100" }, default.with("int", 100)); +} + +test "clap.extended: value bool" { + const command = comptime Command.init( + "", + Options, + default, + []Param { + Param.smart("a"), + }, + []Command{}, + ); + + testNoErr(command, [][]const u8 { "-a" }, default.with("a", true)); +} + +test "clap.extended: value str" { + const command = comptime Command.init( + "", + Options, + default, + []Param { + Param.smart("str").with("takes_value", Parser.string), + }, + []Command{}, + ); + + testNoErr(command, [][]const u8 { "--str", "Hello World!" }, default.with("str", "Hello World!")); +} + +test "clap.extended: value int" { + const command = comptime Command.init( + "", + Options, + default, + []Param { + Param.smart("int").with("takes_value", Parser.int(i64, 10)), + }, + []Command{}, + ); + + testNoErr(command, [][]const u8 { "--int", "100" }, default.with("int", 100)); +} + +test "clap.extended: position" { + const command = comptime Command.init( + "", + Options, + default, + []Param { + Param.smart("a").with("position", 0), + Param.smart("b").with("position", 1), + }, + []Command{}, + ); + + testNoErr(command, [][]const u8 { "-a", "-b" }, default.with("a", true).with("b", true)); + testErr(command, [][]const u8 { "-b", "-a" }, error.InvalidArgument); +} + +test "clap.extended: sub fields" { + const B = struct { + a: bool, + }; + const A = struct { + b: B, + }; + + const command = comptime Command.init( + "", + A, + A { .b = B { .a = false } }, + []Param { + Param.short('a') + .with("field", "b.a"), + }, + []Command{}, + ); + + var arg_iter = ArgSliceIterator.init([][]const u8{ "-a" }); + const res = command.parse(debug.global_allocator, &arg_iter.iter) catch unreachable; + debug.assert(res.b.a == true); +} + +test "clap.extended: sub commands" { + const command = comptime Command.init( + "", + Options, + default, + []Param { + Param.smart("a"), + Param.smart("b"), + }, + []Command{ + Command.init( + "sub", + SubOptions, + default.sub, + []Param { + Param.smart("a"), + Param.smart("b") + .with("takes_value", Parser.int(u64, 10)), + }, + []Command{}, + ), + }, + ); + + testNoErr(command, [][]const u8 { "sub", "-a" }, default.with("sub", default.sub.with("a", true))); + testNoErr(command, [][]const u8 { "sub", "-b", "100" }, default.with("sub", default.sub.with("b", 100))); + testNoErr(command, [][]const u8 { "-a", "sub", "-a" }, default.with("a", true).with("sub", default.sub.with("a", true))); + testErr(command, [][]const u8 { "-qq", "sub" }, error.InvalidArgument); +} -- cgit v1.2.3