1/* Copyright (c) 2015, MariaDB Corporation
2
3 Redistribution and use in source and binary forms, with or without
4 modification, are permitted provided that the following conditions are
5 met:
6
7 1. Redistributions of source code must retain the above copyright
8 notice, this list of conditions and the following disclaimer.
9
10 2. Redistributions in binary form must the following disclaimer in
11 the documentation and/or other materials provided with the
12 distribution.
13
14 THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND ANY
15 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> OR
18 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
19 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
20 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
21 USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
24 OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 SUCH DAMAGE.
26*/
27
28#include <my_global.h>
29#include <my_getopt.h>
30#include <mysys_err.h>
31#include <stdarg.h>
32#include <tap.h>
33
34ulonglong opt_ull;
35ulong opt_ul;
36int arg_c, res;
37char **arg_v, *arg_s[100];
38
39ulong mopts_num;
40char *mopts_str;
41my_bool mopts_bool;
42static struct my_option mopts_options[]=
43{
44 {"str", 0,
45 "Something numeric.",
46 &mopts_str, &mopts_str, 0, GET_STR,
47 REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
48 {"bool", 0,
49 "Something true or false",
50 &mopts_bool, &mopts_bool, 0, GET_BOOL,
51 OPT_ARG, FALSE, 0, 0, 0, 0, 0},
52 {"num", 0,
53 "Something numeric.",
54 &mopts_num, &mopts_num, 0, GET_ULONG,
55 REQUIRED_ARG, 1000000L, 1, ULONG_MAX, 0, 2, 0},
56 {"ull", 0, "ull", &opt_ull, &opt_ull,
57 0, GET_ULL, REQUIRED_ARG, 1, 0, ~0ULL, 0, 0, 0},
58 {"ul", 0, "ul", &opt_ul, &opt_ul,
59 0, GET_ULONG, REQUIRED_ARG, 1, 0, 0xFFFFFFFF, 0, 0, 0},
60 { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
61};
62
63void run(const char *arg, ...)
64{
65 va_list ap;
66 va_start(ap, arg);
67 arg_v= arg_s;
68 *arg_v++= (char*)"<skipped>";
69 while (arg)
70 {
71 *arg_v++= (char*)arg;
72 arg= va_arg(ap, char*);
73 }
74 va_end(ap);
75 arg_c= (int)(arg_v - arg_s);
76 arg_v= arg_s;
77 res= handle_options(&arg_c, &arg_v, mopts_options, 0);
78}
79
80int mopts1_argc= 4;
81const char *mopts1_argv[]= {"mopts1", "--num=123", "--str=str", "--bool"};
82void test_mopts1()
83{
84 int rc;
85 char **av= (char **)mopts1_argv;
86
87 rc= handle_options(&mopts1_argc, &av, mopts_options, NULL);
88 ok( (rc == 0), "%s", "test_mopts1 call");
89 ok( (mopts_num == 122), "%s", "test_mopts1 num");
90 ok( (strncmp(mopts_str, "str", 4) == 0), "%s", "test_mopts1 str");
91 ok( (mopts_bool == 1), "%s", "test_mopts1 bool");
92}
93
94int mopts2_argc= 4;
95const char *mopts2_argv[]= {"mopts2", "--num=123", "--num=124", "--bool=0"};
96void test_mopts2()
97{
98 int rc;
99 char **av= (char **)mopts2_argv;
100
101 rc= handle_options(&mopts2_argc, &av, mopts_options, NULL);
102 ok( (rc == 0), "%s", "test_mopts2 call");
103 ok( (mopts_num == 124), "%s", "test_mopts2 num");
104 ok( (strncmp(mopts_str, "ddd", 4) == 0), "%s", "test_mopts2 str");
105 ok( (mopts_bool == 0), "%s", "test_mopts2 bool");
106}
107
108int mopts3_argc= 4;
109const char *mopts3_argv[]= {"mopts3", "--loose-foo", "--loose-loose-foo", "--enable-bool"};
110void test_mopts3()
111{
112 int rc;
113 char **av= (char **)mopts3_argv;
114
115 rc= handle_options(&mopts3_argc, &av, mopts_options, NULL);
116 ok( (rc == 0), "%s", "test_mopts3 call");
117 ok( (mopts_num == 1000000L), "%s", "test_mopts3 num");
118 ok( (strncmp(mopts_str, "ddd", 4) == 0), "%s", "test_mopts3 str");
119 ok( (mopts_bool == 1), "%s", "test_mopts3 bool");
120}
121
122int mopts4_argc= 3;
123const char *mopts4_argv[]= {"mopts4", "--loose-str=aa", "--skip-bool"};
124void test_mopts4()
125{
126 int rc;
127 char **av= (char **)mopts4_argv;
128
129 rc= handle_options(&mopts4_argc, &av, mopts_options, NULL);
130 ok( (rc == 0), "%s", "test_mopts4 call");
131 ok( (mopts_num == 1000000L), "%s", "test_mopts4 num");
132 ok( (strncmp(mopts_str, "aa", 3) == 0), "%s", "test_mopts4 str");
133 ok( (mopts_bool == 0), "%s", "test_mopts4 bool");
134}
135
136int mopts5_argc= 2;
137const char *mopts5_argv[]= {"mopts5", "--loose-skip-bool"};
138void test_mopts5()
139{
140 int rc;
141 char **av= (char **)mopts5_argv;
142
143 rc= handle_options(&mopts5_argc, &av, mopts_options, NULL);
144 ok( (rc == 0), "%s", "test_mopts5 call");
145 ok( (mopts_num == 1000000L), "%s", "test_mopts5 num");
146 ok( (strncmp(mopts_str, "ddd", 4) == 0), "%s", "test_mopts5 str");
147 ok( (mopts_bool == 0), "%s", "test_mopts5 bool");
148}
149
150int mopts6_argc= 2;
151const char *mopts6_argv[]= {"mopts6", "--loose-skip-skip-bool"};
152void test_mopts6()
153{
154 int rc;
155 char **av= (char **)mopts6_argv;
156
157 rc= handle_options(&mopts6_argc, &av, mopts_options, NULL);
158 ok( (rc == 0), "%s", "test_mopts6 call");
159 ok( (mopts_num == 1000000L), "%s", "test_mopts6 num");
160 ok( (strncmp(mopts_str, "ddd", 4) == 0), "%s", "test_mopts6 str");
161 ok( (mopts_bool == 0), "%s", "test_mopts6 bool");
162}
163
164int mopts7_argc= 2;
165const char *mopts7_argv[]= {"mopts7", "--loose-disable-skip-bool"};
166void test_mopts7()
167{
168 int rc;
169 char **av= (char **)mopts7_argv;
170
171 rc= handle_options(&mopts7_argc, &av, mopts_options, NULL);
172 ok( (rc == 0), "%s", "test_mopts7 call");
173 ok( (mopts_num == 1000000L), "%s", "test_mopts7 num");
174 ok( (strncmp(mopts_str, "ddd", 4) == 0), "%s", "test_mopts7 str");
175 ok( (mopts_bool == 0), "%s", "test_mopts7 bool");
176}
177
178int mopts8_argc= 2;
179const char *mopts8_argv[]= {"mopts8", "--loose-disable-enable-bool"};
180void test_mopts8()
181{
182 int rc;
183 char **av= (char **)mopts8_argv;
184
185 rc= handle_options(&mopts8_argc, &av, mopts_options, NULL);
186 ok( (rc == 0), "%s", "test_mopts8 call");
187 ok( (mopts_num == 1000000L), "%s", "test_mopts7 num");
188 ok( (strncmp(mopts_str, "ddd", 4) == 0), "%s", "test_mopts7 str");
189 ok( (mopts_bool == 1), "%s", "test_mopts7 bool");
190}
191
192int mopts9_argc= 2;
193const char *mopts9_argv[]= {"mopts9", "--foo"};
194void test_mopts9()
195{
196 int rc;
197 char **av= (char **)mopts9_argv;
198
199 rc= handle_options(&mopts9_argc, &av, mopts_options, NULL);
200 ok( (rc != 0), "%s", "test_mopts9 call");
201}
202
203int mopts10_argc= 2;
204const char *mopts10_argv[]= {"mopts10", "--skip-foo"};
205void test_mopts10()
206{
207 int rc;
208 char **av= (char **)mopts10_argv;
209
210 rc= handle_options(&mopts10_argc, &av, mopts_options, NULL);
211 ok( (rc != 0), "%s", "test_mopts10 call");
212}
213
214ulong auto_num;
215static struct my_option auto_options[]=
216{
217 {"anum", 0,
218 "Something numeric.",
219 &auto_num, &auto_num, 0, GET_ULONG | GET_AUTO,
220 REQUIRED_ARG, 1000000L, 1, ULONG_MAX, 0, 1, 0},
221 {"num", 0,
222 "Something numeric.",
223 &mopts_num, &mopts_num, 0, GET_ULONG,
224 REQUIRED_ARG, 1000000L, 1, ULONG_MAX, 0, 1, 0},
225 { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
226};
227
228
229
230my_bool auto_get_one_option(int optid __attribute__((unused)),
231 const struct my_option *opt,
232 char *argument)
233{
234 if (argument == autoset_my_option)
235 {
236 *((ulong*)opt->value)= 111;
237 }
238 return FALSE;
239}
240
241int auto1_argc= 3;
242const char *auto1_argv[]= {"auto1", "--anum=123", "--autoset-anum"};
243void test_auto1()
244{
245 int rc;
246 char **av= (char **)auto1_argv;
247
248 rc= handle_options(&auto1_argc, &av, auto_options, NULL);
249 ok( (rc == EXIT_ARGUMENT_INVALID), "%s", "test_auto1 call");
250}
251
252int auto2_argc= 3;
253const char *auto2_argv[]= {"auto2", "--num=123", "--autoset-num"};
254void test_auto2()
255{
256 int rc;
257 char **av= (char **)auto2_argv;
258
259 rc= handle_options(&auto2_argc, &av, auto_options, &auto_get_one_option);
260 ok( (rc == EXIT_ARGUMENT_INVALID), "%s", "test_auto2 call");
261}
262
263int auto3_argc= 3;
264const char *auto3_argv[]= {"auto3", "--anum=123", "--autoset-anum"};
265void test_auto3()
266{
267 int rc;
268 char **av= (char **)auto3_argv;
269
270 rc= handle_options(&auto3_argc, &av, auto_options, &auto_get_one_option);
271 ok( (rc == 0), "%s", "test_auto3 call");
272 ok( (mopts_num == 1000000L), "%s", "test_auto3 num");
273 ok( (auto_num == 111), "%s", "test_auto3 anum");
274}
275
276int auto4_argc= 3;
277const char *auto4_argv[]= {"auto4", "--loose-autoset-num", "--loose-autoset-anum"};
278void test_auto4()
279{
280 int rc;
281 char **av= (char **)auto4_argv;
282
283 rc= handle_options(&auto4_argc, &av, auto_options, &auto_get_one_option);
284 ok( (rc == 0), "%s", "test_auto4 call");
285 ok( (mopts_num == 1000000L), "%s", "test_auto4 num");
286 ok( (auto_num == 111), "%s", "test_auto4 anum");
287}
288
289int auto5_argc= 3;
290const char *auto5_argv[]= {"auto5", "--autoset-loose-num", "--autoset-loose-anum"};
291void test_auto5()
292{
293 int rc;
294 char **av= (char **)auto5_argv;
295
296 rc= handle_options(&auto5_argc, &av, auto_options, &auto_get_one_option);
297 ok( (rc == 0), "%s", "test_auto5 call");
298 ok( (mopts_num == 1000000L), "%s", "test_auto5 num");
299 ok( (auto_num == 111), "%s", "test_auto5 anum");
300}
301
302int auto6_argc= 3;
303const char *auto6_argv[]= {"auto6", "--autoset-anum", "--anum=123"};
304void test_auto6()
305{
306 int rc;
307 char **av= (char **)auto6_argv;
308
309 rc= handle_options(&auto6_argc, &av, auto_options, &auto_get_one_option);
310 ok( (rc == 0), "%s", "test_auto6 call");
311 ok( (mopts_num == 1000000L), "%s", "test_auto6 num");
312 ok( (auto_num == 123), "%s", "test_auto6 anum");
313}
314
315
316ulong max_num= ULONG_MAX;
317static struct my_option max_options[]=
318{
319 {"num", 0,
320 "Something numeric.",
321 &mopts_num, &max_num, 0, GET_ULONG,
322 REQUIRED_ARG, 1000000L, 1, 1000001L, 0, 1, 0},
323 { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
324};
325
326int max1_argc= 3;
327const char *max1_argv[]= {"max1", "--num=100", "--num=200"};
328void test_max1()
329{
330 int rc;
331 char **av= (char **)max1_argv;
332
333 rc= handle_options(&max1_argc, &av, max_options, NULL);
334 ok( (rc == 0), "%s", "test_max1 call");
335 ok( (mopts_num == 200), "%s", "test_max1 num");
336 ok( (max_num == 1000001L), "%s", "test_max1 max_num");
337}
338int max2_argc= 3;
339const char *max2_argv[]= {"max2", "--maximum-num=100", "--num=200"};
340void test_max2()
341{
342 int rc;
343 char **av= (char **)max2_argv;
344
345 rc= handle_options(&max2_argc, &av, max_options, NULL);
346 ok( (rc == 0), "%s", "test_max2 call");
347 ok( (mopts_num == 200), "%s", "test_max2 num");
348 ok( (max_num == 100), "%s", "test_max2 max_num");
349}
350
351int main(int argc __attribute__((unused)), char **argv)
352{
353 MY_INIT(argv[0]);
354 plan(4*8 + 1*4 + 3*4 + 3*2 + 3);
355
356 /* gcc 4.1.2 doesn't want it in the initializer, we have to do it run-time */
357 mopts_options[0].def_value= (intptr)"ddd";
358
359 test_mopts1();
360 test_mopts2();
361 test_mopts3();
362 test_mopts4();
363 test_mopts5();
364 test_mopts6();
365 test_mopts7();
366 test_mopts8();
367
368 test_mopts9();
369 test_mopts10();
370 test_auto1();
371 test_auto2();
372
373 test_auto3();
374 test_auto4();
375 test_auto5();
376 test_auto6();
377
378 test_max1();
379 test_max2();
380
381 run("--ull=100", NULL);
382 ok(res==0 && arg_c==0 && opt_ull==100,
383 "res:%d, argc:%d, opt_ull:%llu", res, arg_c, opt_ull);
384
385 /*
386 negative numbers are wrapped. this is kinda questionable,
387 we might want to fix it eventually. but it'd be a change in behavior,
388 users might've got used to "-1" meaning "max possible value"
389 */
390 run("--ull=-100", NULL);
391 ok(res==0 && arg_c==0 && opt_ull==18446744073709551516ULL,
392 "res:%d, argc:%d, opt_ull:%llu", res, arg_c, opt_ull);
393 run("--ul=-100", NULL);
394 ok(res==0 && arg_c==0 && opt_ul==4294967295UL,
395 "res:%d, argc:%d, opt_ul:%lu", res, arg_c, opt_ul);
396
397 my_end(0);
398 return exit_status();
399}
400