summaryrefslogtreecommitdiffstats
path: root/unittest/mysys/my_getopt-t.c
blob: 4b50468ac3fbfc2fef2ee91de73da0e0501c8e50 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
/* Copyright (c) 2015, MariaDB Corporation

   Redistribution and use in source and binary forms, with or without
   modification, are permitted provided that the following conditions are
   met:

   1. Redistributions of source code must retain the above copyright
   notice, this list of conditions and the following disclaimer.

   2. Redistributions in binary form must the following disclaimer in
     the documentation and/or other materials provided with the
     distribution.

   THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND ANY
   EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> OR
   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   SUCH DAMAGE.
*/

#include <my_global.h>
#include <my_getopt.h>
#include <mysys_err.h>
#include <stdarg.h>
#include <tap.h>

ulonglong opt_ull;
ulong opt_ul;
int arg_c, res;
char **arg_v, *arg_s[100];

ulong mopts_num;
char *mopts_str;
my_bool mopts_bool;
static struct my_option mopts_options[]=
{
  {"str", 0,
    "Something numeric.",
    &mopts_str, &mopts_str, 0, GET_STR,
    REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
  {"bool", 0,
    "Something true or false",
    &mopts_bool, &mopts_bool, 0, GET_BOOL,
    OPT_ARG, FALSE, 0, 0, 0, 0, 0},
  {"num", 0,
   "Something numeric.",
   &mopts_num, &mopts_num, 0, GET_ULONG,
   REQUIRED_ARG, 1000000L, 1, ULONG_MAX, 0, 2, 0},
  {"ull", 0, "ull", &opt_ull, &opt_ull,
   0, GET_ULL, REQUIRED_ARG, 1, 0, ~0ULL, 0, 0, 0},
  {"ul", 0, "ul", &opt_ul, &opt_ul,
   0, GET_ULONG, REQUIRED_ARG, 1, 0, 0xFFFFFFFF, 0, 0, 0},
  { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
};

my_bool dummy_get_one_option(const struct my_option *opt __attribute__((unused)),
                             const char *argument __attribute__((unused)),
                             const char *filename __attribute__((unused)))
{
  return FALSE;
}

void run(const char *arg, ...)
{
  va_list ap;
  va_start(ap, arg);
  arg_v= arg_s;
  *arg_v++= (char*)"<skipped>";
  while (arg)
  {
    *arg_v++= (char*)arg;
    arg= va_arg(ap, char*);
  }
  va_end(ap);
  arg_c= (int)(arg_v - arg_s);
  arg_v= arg_s;
  res= handle_options(&arg_c, &arg_v, mopts_options, &dummy_get_one_option);
}

int mopts1_argc= 4;
const char *mopts1_argv[]= {"mopts1", "--num=123", "--str=str", "--bool"};
void test_mopts1()
{
  int rc;
  char **av= (char **)mopts1_argv;

  rc= handle_options(&mopts1_argc, &av, mopts_options, &dummy_get_one_option);
  ok( (rc == 0), "%s", "test_mopts1 call");
  ok( (mopts_num == 122), "%s", "test_mopts1 num");
  ok( (strncmp(mopts_str, "str", 4) == 0), "%s", "test_mopts1 str");
  ok( (mopts_bool == 1), "%s", "test_mopts1 bool");
}

int mopts2_argc= 4;
const char *mopts2_argv[]= {"mopts2", "--num=123", "--num=124", "--bool=0"};
void test_mopts2()
{
  int rc;
  char **av= (char **)mopts2_argv;

  rc= handle_options(&mopts2_argc, &av, mopts_options, &dummy_get_one_option);
  ok( (rc == 0), "%s", "test_mopts2 call");
  ok( (mopts_num == 124), "%s", "test_mopts2 num");
  ok( (strncmp(mopts_str, "ddd", 4) == 0), "%s", "test_mopts2 str");
  ok( (mopts_bool == 0), "%s", "test_mopts2 bool");
}

int mopts3_argc= 4;
const char *mopts3_argv[]= {"mopts3", "--loose-foo", "--loose-loose-foo", "--enable-bool"};
void test_mopts3()
{
  int rc;
  char **av= (char **)mopts3_argv;

  rc= handle_options(&mopts3_argc, &av, mopts_options, &dummy_get_one_option);
  ok( (rc == 0), "%s", "test_mopts3 call");
  ok( (mopts_num == 1000000L), "%s", "test_mopts3 num");
  ok( (strncmp(mopts_str, "ddd", 4) == 0), "%s", "test_mopts3 str");
  ok( (mopts_bool == 1), "%s", "test_mopts3 bool");
}

int mopts4_argc= 3;
const char *mopts4_argv[]= {"mopts4", "--loose-str=aa", "--skip-bool"};
void test_mopts4()
{
  int rc;
  char **av= (char **)mopts4_argv;

  rc= handle_options(&mopts4_argc, &av, mopts_options, &dummy_get_one_option);
  ok( (rc == 0), "%s", "test_mopts4 call");
  ok( (mopts_num == 1000000L), "%s", "test_mopts4 num");
  ok( (strncmp(mopts_str, "aa", 3) == 0), "%s", "test_mopts4 str");
  ok( (mopts_bool == 0), "%s", "test_mopts4 bool");
}

int mopts5_argc= 2;
const char *mopts5_argv[]= {"mopts5", "--loose-skip-bool"};
void test_mopts5()
{
  int rc;
  char **av= (char **)mopts5_argv;

  rc= handle_options(&mopts5_argc, &av, mopts_options, &dummy_get_one_option);
  ok( (rc == 0), "%s", "test_mopts5 call");
  ok( (mopts_num == 1000000L), "%s", "test_mopts5 num");
  ok( (strncmp(mopts_str, "ddd", 4) == 0), "%s", "test_mopts5 str");
  ok( (mopts_bool == 0), "%s", "test_mopts5 bool");
}

int mopts6_argc= 2;
const char *mopts6_argv[]= {"mopts6", "--loose-skip-skip-bool"};
void test_mopts6()
{
  int rc;
  char **av= (char **)mopts6_argv;

  rc= handle_options(&mopts6_argc, &av, mopts_options, &dummy_get_one_option);
  ok( (rc == 0), "%s", "test_mopts6 call");
  ok( (mopts_num == 1000000L), "%s", "test_mopts6 num");
  ok( (strncmp(mopts_str, "ddd", 4) == 0), "%s", "test_mopts6 str");
  ok( (mopts_bool == 0), "%s", "test_mopts6 bool");
}

int mopts7_argc= 2;
const char *mopts7_argv[]= {"mopts7", "--loose-disable-skip-bool"};
void test_mopts7()
{
  int rc;
  char **av= (char **)mopts7_argv;

  rc= handle_options(&mopts7_argc, &av, mopts_options, &dummy_get_one_option);
  ok( (rc == 0), "%s", "test_mopts7 call");
  ok( (mopts_num == 1000000L), "%s", "test_mopts7 num");
  ok( (strncmp(mopts_str, "ddd", 4) == 0), "%s", "test_mopts7 str");
  ok( (mopts_bool == 0), "%s", "test_mopts7 bool");
}

int mopts8_argc= 2;
const char *mopts8_argv[]= {"mopts8", "--loose-disable-enable-bool"};
void test_mopts8()
{
  int rc;
  char **av= (char **)mopts8_argv;

  rc= handle_options(&mopts8_argc, &av, mopts_options, &dummy_get_one_option);
  ok( (rc == 0), "%s", "test_mopts8 call");
  ok( (mopts_num == 1000000L), "%s", "test_mopts7 num");
  ok( (strncmp(mopts_str, "ddd", 4) == 0), "%s", "test_mopts7 str");
  ok( (mopts_bool == 1), "%s", "test_mopts7 bool");
}

int mopts9_argc= 2;
const char *mopts9_argv[]= {"mopts9", "--foo"};
void test_mopts9()
{
  int rc;
  char **av= (char **)mopts9_argv;

  rc= handle_options(&mopts9_argc, &av, mopts_options, &dummy_get_one_option);
  ok( (rc != 0), "%s", "test_mopts9 call");
}

int mopts10_argc= 2;
const char *mopts10_argv[]= {"mopts10", "--skip-foo"};
void test_mopts10()
{
  int rc;
  char **av= (char **)mopts10_argv;

  rc= handle_options(&mopts10_argc, &av, mopts_options, &dummy_get_one_option);
  ok( (rc != 0), "%s", "test_mopts10 call");
}

ulong auto_num;
static struct my_option auto_options[]=
{
  {"anum", 0,
   "Something numeric.",
   &auto_num, &auto_num, 0, GET_ULONG | GET_AUTO,
   REQUIRED_ARG, 1000000L, 1, ULONG_MAX, 0, 1, 0},
  {"num", 0,
   "Something numeric.",
   &mopts_num, &mopts_num, 0, GET_ULONG,
   REQUIRED_ARG, 1000000L, 1, ULONG_MAX, 0, 1, 0},
  { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
};



my_bool auto_get_one_option(const struct my_option *opt,
                            const char *argument,
                            const char *filename __attribute__((unused)))
{
  if (argument == autoset_my_option)
  {
    *((ulong*)opt->value)= 111;
  }
  return FALSE;
}

int auto2_argc= 3;
const char *auto2_argv[]= {"auto2", "--num=123", "--autoset-num"};
void test_auto2()
{
  int rc;
  char **av= (char **)auto2_argv;

  rc= handle_options(&auto2_argc, &av, auto_options, &auto_get_one_option);
  ok( (rc == EXIT_ARGUMENT_INVALID), "%s", "test_auto2 call");
}

int auto3_argc= 3;
const char *auto3_argv[]= {"auto3", "--anum=123", "--autoset-anum"};
void test_auto3()
{
  int rc;
  char **av= (char **)auto3_argv;

  rc= handle_options(&auto3_argc, &av, auto_options, &auto_get_one_option);
  ok( (rc == 0), "%s", "test_auto3 call");
  ok( (mopts_num == 1000000L), "%s", "test_auto3 num");
  ok( (auto_num == 111), "%s", "test_auto3 anum");
}

int auto4_argc= 3;
const char *auto4_argv[]= {"auto4", "--loose-autoset-num", "--loose-autoset-anum"};
void test_auto4()
{
  int rc;
  char **av= (char **)auto4_argv;

  rc= handle_options(&auto4_argc, &av, auto_options, &auto_get_one_option);
  ok( (rc == 0), "%s", "test_auto4 call");
  ok( (mopts_num == 1000000L), "%s", "test_auto4 num");
  ok( (auto_num == 111), "%s", "test_auto4 anum");
}

int auto5_argc= 3;
const char *auto5_argv[]= {"auto5", "--autoset-loose-num", "--autoset-loose-anum"};
void test_auto5()
{
  int rc;
  char **av= (char **)auto5_argv;

  rc= handle_options(&auto5_argc, &av, auto_options, &auto_get_one_option);
  ok( (rc == 0), "%s", "test_auto5 call");
  ok( (mopts_num == 1000000L), "%s", "test_auto5 num");
  ok( (auto_num == 111), "%s", "test_auto5 anum");
}

int auto6_argc= 3;
const char *auto6_argv[]= {"auto6", "--autoset-anum", "--anum=123"};
void test_auto6()
{
  int rc;
  char **av= (char **)auto6_argv;

  rc= handle_options(&auto6_argc, &av, auto_options, &auto_get_one_option);
  ok( (rc == 0), "%s", "test_auto6 call");
  ok( (mopts_num == 1000000L), "%s", "test_auto6 num");
  ok( (auto_num == 123), "%s", "test_auto6 anum");
}


ulong max_num= ULONG_MAX;
static struct my_option max_options[]=
{
  {"num", 0,
   "Something numeric.",
   &mopts_num, &max_num, 0, GET_ULONG,
   REQUIRED_ARG, 1000000L, 1, 1000001L, 0, 1, 0},
  { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
};

int max1_argc= 3;
const char *max1_argv[]= {"max1", "--num=100", "--num=200"};
void test_max1()
{
  int rc;
  char **av= (char **)max1_argv;

  rc= handle_options(&max1_argc, &av, max_options, &dummy_get_one_option);
  ok( (rc == 0), "%s", "test_max1 call");
  ok( (mopts_num == 200), "%s", "test_max1 num");
  ok( (max_num == 1000001L), "%s", "test_max1 max_num");
}
int max2_argc= 3;
const char *max2_argv[]= {"max2", "--maximum-num=100", "--num=200"};
void test_max2()
{
  int rc;
  char **av= (char **)max2_argv;

  rc= handle_options(&max2_argc, &av, max_options, &dummy_get_one_option);
  ok( (rc == 0), "%s", "test_max2 call");
  ok( (mopts_num == 200), "%s", "test_max2 num");
  ok( (max_num == 100), "%s", "test_max2 max_num");
}

int main(int argc __attribute__((unused)), char **argv)
{
  MY_INIT(argv[0]);
  plan(4*8 + 1*4 + 3*4 + 3*2 + 2);

  /* gcc 4.1.2 doesn't want it in the initializer, we have to do it run-time */
  mopts_options[0].def_value= (intptr)"ddd";

  test_mopts1();
  test_mopts2();
  test_mopts3();
  test_mopts4();
  test_mopts5();
  test_mopts6();
  test_mopts7();
  test_mopts8();

  test_mopts9();
  test_mopts10();
  test_auto2();

  test_auto3();
  test_auto4();
  test_auto5();
  test_auto6();

  test_max1();
  test_max2();

  run("--ull=100", NULL);
  ok(res==0 && arg_c==0 && opt_ull==100,
     "res:%d, argc:%d, opt_ull:%llu", res, arg_c, opt_ull);

  /*
    negative numbers are wrapped. this is kinda questionable,
    we might want to fix it eventually. but it'd be a change in behavior,
    users might've got used to "-1" meaning "max possible value"
  */
  run("--ull=-100", NULL);
  ok(res==0 && arg_c==0 && opt_ull==18446744073709551516ULL,
     "res:%d, argc:%d, opt_ull:%llu", res, arg_c, opt_ull);
  run("--ul=-100", NULL);
  ok(res==0 && arg_c==0 && opt_ul==4294967295UL,
     "res:%d, argc:%d, opt_ul:%lu", res, arg_c, opt_ul);

  my_end(0);
  return exit_status();
}