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
34 ulonglong opt_ull;
35 ulong opt_ul;
36 int arg_c, res;
37 char **arg_v, *arg_s[100];
38
39 ulong mopts_num;
40 char *mopts_str;
41 my_bool mopts_bool;
42 static 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
dummy_get_one_option(const struct my_option * opt,const char * argument,const char * filename)63 my_bool dummy_get_one_option(const struct my_option *opt __attribute__((unused)),
64 const char *argument __attribute__((unused)),
65 const char *filename __attribute__((unused)))
66 {
67 return FALSE;
68 }
69
run(const char * arg,...)70 void run(const char *arg, ...)
71 {
72 va_list ap;
73 va_start(ap, arg);
74 arg_v= arg_s;
75 *arg_v++= (char*)"<skipped>";
76 while (arg)
77 {
78 *arg_v++= (char*)arg;
79 arg= va_arg(ap, char*);
80 }
81 va_end(ap);
82 arg_c= (int)(arg_v - arg_s);
83 arg_v= arg_s;
84 res= handle_options(&arg_c, &arg_v, mopts_options, &dummy_get_one_option);
85 }
86
87 int mopts1_argc= 4;
88 const char *mopts1_argv[]= {"mopts1", "--num=123", "--str=str", "--bool"};
test_mopts1()89 void test_mopts1()
90 {
91 int rc;
92 char **av= (char **)mopts1_argv;
93
94 rc= handle_options(&mopts1_argc, &av, mopts_options, &dummy_get_one_option);
95 ok( (rc == 0), "%s", "test_mopts1 call");
96 ok( (mopts_num == 122), "%s", "test_mopts1 num");
97 ok( (strncmp(mopts_str, "str", 4) == 0), "%s", "test_mopts1 str");
98 ok( (mopts_bool == 1), "%s", "test_mopts1 bool");
99 }
100
101 int mopts2_argc= 4;
102 const char *mopts2_argv[]= {"mopts2", "--num=123", "--num=124", "--bool=0"};
test_mopts2()103 void test_mopts2()
104 {
105 int rc;
106 char **av= (char **)mopts2_argv;
107
108 rc= handle_options(&mopts2_argc, &av, mopts_options, &dummy_get_one_option);
109 ok( (rc == 0), "%s", "test_mopts2 call");
110 ok( (mopts_num == 124), "%s", "test_mopts2 num");
111 ok( (strncmp(mopts_str, "ddd", 4) == 0), "%s", "test_mopts2 str");
112 ok( (mopts_bool == 0), "%s", "test_mopts2 bool");
113 }
114
115 int mopts3_argc= 4;
116 const char *mopts3_argv[]= {"mopts3", "--loose-foo", "--loose-loose-foo", "--enable-bool"};
test_mopts3()117 void test_mopts3()
118 {
119 int rc;
120 char **av= (char **)mopts3_argv;
121
122 rc= handle_options(&mopts3_argc, &av, mopts_options, &dummy_get_one_option);
123 ok( (rc == 0), "%s", "test_mopts3 call");
124 ok( (mopts_num == 1000000L), "%s", "test_mopts3 num");
125 ok( (strncmp(mopts_str, "ddd", 4) == 0), "%s", "test_mopts3 str");
126 ok( (mopts_bool == 1), "%s", "test_mopts3 bool");
127 }
128
129 int mopts4_argc= 3;
130 const char *mopts4_argv[]= {"mopts4", "--loose-str=aa", "--skip-bool"};
test_mopts4()131 void test_mopts4()
132 {
133 int rc;
134 char **av= (char **)mopts4_argv;
135
136 rc= handle_options(&mopts4_argc, &av, mopts_options, &dummy_get_one_option);
137 ok( (rc == 0), "%s", "test_mopts4 call");
138 ok( (mopts_num == 1000000L), "%s", "test_mopts4 num");
139 ok( (strncmp(mopts_str, "aa", 3) == 0), "%s", "test_mopts4 str");
140 ok( (mopts_bool == 0), "%s", "test_mopts4 bool");
141 }
142
143 int mopts5_argc= 2;
144 const char *mopts5_argv[]= {"mopts5", "--loose-skip-bool"};
test_mopts5()145 void test_mopts5()
146 {
147 int rc;
148 char **av= (char **)mopts5_argv;
149
150 rc= handle_options(&mopts5_argc, &av, mopts_options, &dummy_get_one_option);
151 ok( (rc == 0), "%s", "test_mopts5 call");
152 ok( (mopts_num == 1000000L), "%s", "test_mopts5 num");
153 ok( (strncmp(mopts_str, "ddd", 4) == 0), "%s", "test_mopts5 str");
154 ok( (mopts_bool == 0), "%s", "test_mopts5 bool");
155 }
156
157 int mopts6_argc= 2;
158 const char *mopts6_argv[]= {"mopts6", "--loose-skip-skip-bool"};
test_mopts6()159 void test_mopts6()
160 {
161 int rc;
162 char **av= (char **)mopts6_argv;
163
164 rc= handle_options(&mopts6_argc, &av, mopts_options, &dummy_get_one_option);
165 ok( (rc == 0), "%s", "test_mopts6 call");
166 ok( (mopts_num == 1000000L), "%s", "test_mopts6 num");
167 ok( (strncmp(mopts_str, "ddd", 4) == 0), "%s", "test_mopts6 str");
168 ok( (mopts_bool == 0), "%s", "test_mopts6 bool");
169 }
170
171 int mopts7_argc= 2;
172 const char *mopts7_argv[]= {"mopts7", "--loose-disable-skip-bool"};
test_mopts7()173 void test_mopts7()
174 {
175 int rc;
176 char **av= (char **)mopts7_argv;
177
178 rc= handle_options(&mopts7_argc, &av, mopts_options, &dummy_get_one_option);
179 ok( (rc == 0), "%s", "test_mopts7 call");
180 ok( (mopts_num == 1000000L), "%s", "test_mopts7 num");
181 ok( (strncmp(mopts_str, "ddd", 4) == 0), "%s", "test_mopts7 str");
182 ok( (mopts_bool == 0), "%s", "test_mopts7 bool");
183 }
184
185 int mopts8_argc= 2;
186 const char *mopts8_argv[]= {"mopts8", "--loose-disable-enable-bool"};
test_mopts8()187 void test_mopts8()
188 {
189 int rc;
190 char **av= (char **)mopts8_argv;
191
192 rc= handle_options(&mopts8_argc, &av, mopts_options, &dummy_get_one_option);
193 ok( (rc == 0), "%s", "test_mopts8 call");
194 ok( (mopts_num == 1000000L), "%s", "test_mopts7 num");
195 ok( (strncmp(mopts_str, "ddd", 4) == 0), "%s", "test_mopts7 str");
196 ok( (mopts_bool == 1), "%s", "test_mopts7 bool");
197 }
198
199 int mopts9_argc= 2;
200 const char *mopts9_argv[]= {"mopts9", "--foo"};
test_mopts9()201 void test_mopts9()
202 {
203 int rc;
204 char **av= (char **)mopts9_argv;
205
206 rc= handle_options(&mopts9_argc, &av, mopts_options, &dummy_get_one_option);
207 ok( (rc != 0), "%s", "test_mopts9 call");
208 }
209
210 int mopts10_argc= 2;
211 const char *mopts10_argv[]= {"mopts10", "--skip-foo"};
test_mopts10()212 void test_mopts10()
213 {
214 int rc;
215 char **av= (char **)mopts10_argv;
216
217 rc= handle_options(&mopts10_argc, &av, mopts_options, &dummy_get_one_option);
218 ok( (rc != 0), "%s", "test_mopts10 call");
219 }
220
221 ulong auto_num;
222 static struct my_option auto_options[]=
223 {
224 {"anum", 0,
225 "Something numeric.",
226 &auto_num, &auto_num, 0, GET_ULONG | GET_AUTO,
227 REQUIRED_ARG, 1000000L, 1, ULONG_MAX, 0, 1, 0},
228 {"num", 0,
229 "Something numeric.",
230 &mopts_num, &mopts_num, 0, GET_ULONG,
231 REQUIRED_ARG, 1000000L, 1, ULONG_MAX, 0, 1, 0},
232 { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
233 };
234
235
236
auto_get_one_option(const struct my_option * opt,const char * argument,const char * filename)237 my_bool auto_get_one_option(const struct my_option *opt,
238 const char *argument,
239 const char *filename __attribute__((unused)))
240 {
241 if (argument == autoset_my_option)
242 {
243 *((ulong*)opt->value)= 111;
244 }
245 return FALSE;
246 }
247
248 int auto2_argc= 3;
249 const char *auto2_argv[]= {"auto2", "--num=123", "--autoset-num"};
test_auto2()250 void test_auto2()
251 {
252 int rc;
253 char **av= (char **)auto2_argv;
254
255 rc= handle_options(&auto2_argc, &av, auto_options, &auto_get_one_option);
256 ok( (rc == EXIT_ARGUMENT_INVALID), "%s", "test_auto2 call");
257 }
258
259 int auto3_argc= 3;
260 const char *auto3_argv[]= {"auto3", "--anum=123", "--autoset-anum"};
test_auto3()261 void test_auto3()
262 {
263 int rc;
264 char **av= (char **)auto3_argv;
265
266 rc= handle_options(&auto3_argc, &av, auto_options, &auto_get_one_option);
267 ok( (rc == 0), "%s", "test_auto3 call");
268 ok( (mopts_num == 1000000L), "%s", "test_auto3 num");
269 ok( (auto_num == 111), "%s", "test_auto3 anum");
270 }
271
272 int auto4_argc= 3;
273 const char *auto4_argv[]= {"auto4", "--loose-autoset-num", "--loose-autoset-anum"};
test_auto4()274 void test_auto4()
275 {
276 int rc;
277 char **av= (char **)auto4_argv;
278
279 rc= handle_options(&auto4_argc, &av, auto_options, &auto_get_one_option);
280 ok( (rc == 0), "%s", "test_auto4 call");
281 ok( (mopts_num == 1000000L), "%s", "test_auto4 num");
282 ok( (auto_num == 111), "%s", "test_auto4 anum");
283 }
284
285 int auto5_argc= 3;
286 const char *auto5_argv[]= {"auto5", "--autoset-loose-num", "--autoset-loose-anum"};
test_auto5()287 void test_auto5()
288 {
289 int rc;
290 char **av= (char **)auto5_argv;
291
292 rc= handle_options(&auto5_argc, &av, auto_options, &auto_get_one_option);
293 ok( (rc == 0), "%s", "test_auto5 call");
294 ok( (mopts_num == 1000000L), "%s", "test_auto5 num");
295 ok( (auto_num == 111), "%s", "test_auto5 anum");
296 }
297
298 int auto6_argc= 3;
299 const char *auto6_argv[]= {"auto6", "--autoset-anum", "--anum=123"};
test_auto6()300 void test_auto6()
301 {
302 int rc;
303 char **av= (char **)auto6_argv;
304
305 rc= handle_options(&auto6_argc, &av, auto_options, &auto_get_one_option);
306 ok( (rc == 0), "%s", "test_auto6 call");
307 ok( (mopts_num == 1000000L), "%s", "test_auto6 num");
308 ok( (auto_num == 123), "%s", "test_auto6 anum");
309 }
310
311
312 ulong max_num= ULONG_MAX;
313 static struct my_option max_options[]=
314 {
315 {"num", 0,
316 "Something numeric.",
317 &mopts_num, &max_num, 0, GET_ULONG,
318 REQUIRED_ARG, 1000000L, 1, 1000001L, 0, 1, 0},
319 { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
320 };
321
322 int max1_argc= 3;
323 const char *max1_argv[]= {"max1", "--num=100", "--num=200"};
test_max1()324 void test_max1()
325 {
326 int rc;
327 char **av= (char **)max1_argv;
328
329 rc= handle_options(&max1_argc, &av, max_options, &dummy_get_one_option);
330 ok( (rc == 0), "%s", "test_max1 call");
331 ok( (mopts_num == 200), "%s", "test_max1 num");
332 ok( (max_num == 1000001L), "%s", "test_max1 max_num");
333 }
334 int max2_argc= 3;
335 const char *max2_argv[]= {"max2", "--maximum-num=100", "--num=200"};
test_max2()336 void test_max2()
337 {
338 int rc;
339 char **av= (char **)max2_argv;
340
341 rc= handle_options(&max2_argc, &av, max_options, &dummy_get_one_option);
342 ok( (rc == 0), "%s", "test_max2 call");
343 ok( (mopts_num == 200), "%s", "test_max2 num");
344 ok( (max_num == 100), "%s", "test_max2 max_num");
345 }
346
main(int argc,char ** argv)347 int main(int argc __attribute__((unused)), char **argv)
348 {
349 MY_INIT(argv[0]);
350 plan(4*8 + 1*4 + 3*4 + 3*2 + 2);
351
352 /* gcc 4.1.2 doesn't want it in the initializer, we have to do it run-time */
353 mopts_options[0].def_value= (intptr)"ddd";
354
355 test_mopts1();
356 test_mopts2();
357 test_mopts3();
358 test_mopts4();
359 test_mopts5();
360 test_mopts6();
361 test_mopts7();
362 test_mopts8();
363
364 test_mopts9();
365 test_mopts10();
366 test_auto2();
367
368 test_auto3();
369 test_auto4();
370 test_auto5();
371 test_auto6();
372
373 test_max1();
374 test_max2();
375
376 run("--ull=100", NULL);
377 ok(res==0 && arg_c==0 && opt_ull==100,
378 "res:%d, argc:%d, opt_ull:%llu", res, arg_c, opt_ull);
379
380 /*
381 negative numbers are wrapped. this is kinda questionable,
382 we might want to fix it eventually. but it'd be a change in behavior,
383 users might've got used to "-1" meaning "max possible value"
384 */
385 run("--ull=-100", NULL);
386 ok(res==0 && arg_c==0 && opt_ull==18446744073709551516ULL,
387 "res:%d, argc:%d, opt_ull:%llu", res, arg_c, opt_ull);
388 run("--ul=-100", NULL);
389 ok(res==0 && arg_c==0 && opt_ul==4294967295UL,
390 "res:%d, argc:%d, opt_ul:%lu", res, arg_c, opt_ul);
391
392 my_end(0);
393 return exit_status();
394 }
395