summaryrefslogtreecommitdiff
path: root/tests/extended.zig
diff options
context:
space:
mode:
Diffstat (limited to 'tests/extended.zig')
-rw-r--r--tests/extended.zig234
1 files changed, 234 insertions, 0 deletions
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 @@
1const std = @import("std");
2const clap = @import("../index.zig");
3
4const debug = std.debug;
5const mem = std.mem;
6const core = clap.core;
7const extended = clap.extended;
8
9const assert = debug.assert;
10
11const ArgSliceIterator = core.ArgSliceIterator;
12const Command = extended.Command;
13const Param = extended.Param;
14const Parser = extended.Parser;
15
16const Options = struct {
17 str: []const u8,
18 int: i64,
19 uint: u64,
20 a: bool,
21 b: bool,
22 cc: bool,
23 sub: &const SubOptions,
24
25 pub fn with(op: &const Options, comptime field: []const u8, value: var) Options {
26 var res = op.*;
27 @field(res, field) = value;
28 return res;
29 }
30};
31
32const SubOptions = struct {
33 a: bool,
34 b: u64,
35 qq: bool,
36
37 pub fn with(op: &const SubOptions, comptime field: []const u8, value: var) SubOptions {
38 var res = op.*;
39 @field(res, field) = value;
40 return res;
41 }
42};
43
44const default = Options {
45 .str = "",
46 .int = 0,
47 .uint = 0,
48 .a = false,
49 .b = false,
50 .cc = false,
51 .sub = SubOptions{
52 .a = false,
53 .b = 0,
54 .qq = false,
55 },
56};
57
58fn testNoErr(comptime command: &const Command, args: []const []const u8, expected: &const command.Result) void {
59 var arg_iter = ArgSliceIterator.init(args);
60 const actual = command.parse(debug.global_allocator, &arg_iter.iter) catch unreachable;
61 assert(mem.eql(u8, expected.str, actual.str));
62 assert(expected.int == actual.int);
63 assert(expected.uint == actual.uint);
64 assert(expected.a == actual.a);
65 assert(expected.b == actual.b);
66 assert(expected.cc == actual.cc);
67 assert(expected.sub.a == actual.sub.a);
68 assert(expected.sub.b == actual.sub.b);
69}
70
71fn testErr(comptime command: &const Command, args: []const []const u8, expected: error) void {
72 var arg_iter = ArgSliceIterator.init(args);
73 if (command.parse(debug.global_allocator, &arg_iter.iter)) |actual| {
74 unreachable;
75 } else |err| {
76 assert(err == expected);
77 }
78}
79
80test "clap.extended: short" {
81 const command = comptime Command.init(
82 "",
83 Options,
84 default,
85 []Param {
86 Param.smart("a"),
87 Param.smart("b"),
88 Param.smart("int")
89 .with("short", 'i')
90 .with("takes_value", Parser.int(i64, 10)),
91 },
92 []Command{},
93 );
94
95 testNoErr(command, [][]const u8 { "-a" }, default.with("a", true));
96 testNoErr(command, [][]const u8 { "-a", "-b" }, default.with("a", true).with("b", true));
97 testNoErr(command, [][]const u8 { "-i=100" }, default.with("int", 100));
98 testNoErr(command, [][]const u8 { "-i100" }, default.with("int", 100));
99 testNoErr(command, [][]const u8 { "-i", "100" }, default.with("int", 100));
100 testNoErr(command, [][]const u8 { "-ab" }, default.with("a", true).with("b", true));
101 testNoErr(command, [][]const u8 { "-abi", "100" }, default.with("a", true).with("b", true).with("int", 100));
102 testNoErr(command, [][]const u8 { "-abi=100" }, default.with("a", true).with("b", true).with("int", 100));
103 testNoErr(command, [][]const u8 { "-abi100" }, default.with("a", true).with("b", true).with("int", 100));
104}
105
106test "clap.extended: long" {
107 const command = comptime Command.init(
108 "",
109 Options,
110 default,
111 []Param {
112 Param.smart("cc"),
113 Param.smart("int").with("takes_value", Parser.int(i64, 10)),
114 Param.smart("uint").with("takes_value", Parser.int(u64, 10)),
115 Param.smart("str").with("takes_value", Parser.string),
116 },
117 []Command{},
118 );
119
120 testNoErr(command, [][]const u8 { "--cc" }, default.with("cc", true));
121 testNoErr(command, [][]const u8 { "--int", "100" }, default.with("int", 100));
122}
123
124test "clap.extended: value bool" {
125 const command = comptime Command.init(
126 "",
127 Options,
128 default,
129 []Param {
130 Param.smart("a"),
131 },
132 []Command{},
133 );
134
135 testNoErr(command, [][]const u8 { "-a" }, default.with("a", true));
136}
137
138test "clap.extended: value str" {
139 const command = comptime Command.init(
140 "",
141 Options,
142 default,
143 []Param {
144 Param.smart("str").with("takes_value", Parser.string),
145 },
146 []Command{},
147 );
148
149 testNoErr(command, [][]const u8 { "--str", "Hello World!" }, default.with("str", "Hello World!"));
150}
151
152test "clap.extended: value int" {
153 const command = comptime Command.init(
154 "",
155 Options,
156 default,
157 []Param {
158 Param.smart("int").with("takes_value", Parser.int(i64, 10)),
159 },
160 []Command{},
161 );
162
163 testNoErr(command, [][]const u8 { "--int", "100" }, default.with("int", 100));
164}
165
166test "clap.extended: position" {
167 const command = comptime Command.init(
168 "",
169 Options,
170 default,
171 []Param {
172 Param.smart("a").with("position", 0),
173 Param.smart("b").with("position", 1),
174 },
175 []Command{},
176 );
177
178 testNoErr(command, [][]const u8 { "-a", "-b" }, default.with("a", true).with("b", true));
179 testErr(command, [][]const u8 { "-b", "-a" }, error.InvalidArgument);
180}
181
182test "clap.extended: sub fields" {
183 const B = struct {
184 a: bool,
185 };
186 const A = struct {
187 b: B,
188 };
189
190 const command = comptime Command.init(
191 "",
192 A,
193 A { .b = B { .a = false } },
194 []Param {
195 Param.short('a')
196 .with("field", "b.a"),
197 },
198 []Command{},
199 );
200
201 var arg_iter = ArgSliceIterator.init([][]const u8{ "-a" });
202 const res = command.parse(debug.global_allocator, &arg_iter.iter) catch unreachable;
203 debug.assert(res.b.a == true);
204}
205
206test "clap.extended: sub commands" {
207 const command = comptime Command.init(
208 "",
209 Options,
210 default,
211 []Param {
212 Param.smart("a"),
213 Param.smart("b"),
214 },
215 []Command{
216 Command.init(
217 "sub",
218 SubOptions,
219 default.sub,
220 []Param {
221 Param.smart("a"),
222 Param.smart("b")
223 .with("takes_value", Parser.int(u64, 10)),
224 },
225 []Command{},
226 ),
227 },
228 );
229
230 testNoErr(command, [][]const u8 { "sub", "-a" }, default.with("sub", default.sub.with("a", true)));
231 testNoErr(command, [][]const u8 { "sub", "-b", "100" }, default.with("sub", default.sub.with("b", 100)));
232 testNoErr(command, [][]const u8 { "-a", "sub", "-a" }, default.with("a", true).with("sub", default.sub.with("a", true)));
233 testErr(command, [][]const u8 { "-qq", "sub" }, error.InvalidArgument);
234}