1/* Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements.  See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache License, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License.  You may obtain a copy of the License at
7 *
8 *     http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "apr_errno.h"
18#include "apr_general.h"
19#include "apr_getopt.h"
20#include "apr_strings.h"
21#include "testutil.h"
22
23static void format_arg(char *str, char option, const char *arg)
24{
25    if (arg) {
26        apr_snprintf(str, 8196, "%soption: %c with %s\n", str, option, arg);
27    }
28    else {
29        apr_snprintf(str, 8196, "%soption: %c\n", str, option);
30    }
31}
32
33static void unknown_arg(void *str, const char *err, ...)
34{
35    va_list va;
36
37    va_start(va, err);
38    apr_vsnprintf(str, 8196, err, va);
39    va_end(va);
40}
41
42static void no_options_found(abts_case *tc, void *data)
43{
44    int largc = 5;
45    const char * const largv[] = {"testprog", "-a", "-b", "-c", "-d"};
46    apr_getopt_t *opt;
47    apr_status_t rv;
48    char ch;
49    const char *optarg;
50    char str[8196];
51
52    str[0] = '\0';
53    rv = apr_getopt_init(&opt, p, largc, largv);
54    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
55
56    while (apr_getopt(opt, "abcd", &ch, &optarg) == APR_SUCCESS) {
57        switch (ch) {
58            case 'a':
59            case 'b':
60            case 'c':
61            case 'd':
62            default:
63                format_arg(str, ch, optarg);
64        }
65    }
66    ABTS_STR_EQUAL(tc, "option: a\n"
67                          "option: b\n"
68                          "option: c\n"
69                          "option: d\n", str);
70}
71
72static void no_options(abts_case *tc, void *data)
73{
74    int largc = 5;
75    const char * const largv[] = {"testprog", "-a", "-b", "-c", "-d"};
76    apr_getopt_t *opt;
77    apr_status_t rv;
78    char ch;
79    const char *optarg;
80    char str[8196];
81
82    str[0] = '\0';
83    rv = apr_getopt_init(&opt, p, largc, largv);
84    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
85
86    opt->errfn = unknown_arg;
87    opt->errarg = str;
88
89    while (apr_getopt(opt, "efgh", &ch, &optarg) == APR_SUCCESS) {
90        switch (ch) {
91            case 'a':
92            case 'b':
93            case 'c':
94            case 'd':
95                format_arg(str, ch, optarg);
96                break;
97            default:
98                break;
99        }
100    }
101    ABTS_STR_EQUAL(tc, "testprog: illegal option -- a\n", str);
102}
103
104static void required_option(abts_case *tc, void *data)
105{
106    int largc = 3;
107    const char * const largv[] = {"testprog", "-a", "foo"};
108    apr_getopt_t *opt;
109    apr_status_t rv;
110    char ch;
111    const char *optarg;
112    char str[8196];
113
114    str[0] = '\0';
115    rv = apr_getopt_init(&opt, p, largc, largv);
116    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
117
118    opt->errfn = unknown_arg;
119    opt->errarg = str;
120
121    while (apr_getopt(opt, "a:", &ch, &optarg) == APR_SUCCESS) {
122        switch (ch) {
123            case 'a':
124                format_arg(str, ch, optarg);
125                break;
126            default:
127                break;
128        }
129    }
130    ABTS_STR_EQUAL(tc, "option: a with foo\n", str);
131}
132
133static void required_option_notgiven(abts_case *tc, void *data)
134{
135    int largc = 2;
136    const char * const largv[] = {"testprog", "-a"};
137    apr_getopt_t *opt;
138    apr_status_t rv;
139    char ch;
140    const char *optarg;
141    char str[8196];
142
143    str[0] = '\0';
144    rv = apr_getopt_init(&opt, p, largc, largv);
145    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
146
147    opt->errfn = unknown_arg;
148    opt->errarg = str;
149
150    while (apr_getopt(opt, "a:", &ch, &optarg) == APR_SUCCESS) {
151        switch (ch) {
152            case 'a':
153                format_arg(str, ch, optarg);
154                break;
155            default:
156                break;
157        }
158    }
159    ABTS_STR_EQUAL(tc, "testprog: option requires an argument -- a\n", str);
160}
161
162static void optional_option(abts_case *tc, void *data)
163{
164    int largc = 3;
165    const char * const largv[] = {"testprog", "-a", "foo"};
166    apr_getopt_t *opt;
167    apr_status_t rv;
168    char ch;
169    const char *optarg;
170    char str[8196];
171
172    str[0] = '\0';
173    rv = apr_getopt_init(&opt, p, largc, largv);
174    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
175
176    opt->errfn = unknown_arg;
177    opt->errarg = str;
178
179    while (apr_getopt(opt, "a::", &ch, &optarg) == APR_SUCCESS) {
180        switch (ch) {
181            case 'a':
182                format_arg(str, ch, optarg);
183                break;
184            default:
185                break;
186        }
187    }
188    ABTS_STR_EQUAL(tc, "option: a with foo\n", str);
189}
190
191static void optional_option_notgiven(abts_case *tc, void *data)
192{
193    int largc = 2;
194    const char * const largv[] = {"testprog", "-a"};
195    apr_getopt_t *opt;
196    apr_status_t rv;
197    char ch;
198    const char *optarg;
199    char str[8196];
200
201    str[0] = '\0';
202    rv = apr_getopt_init(&opt, p, largc, largv);
203    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
204
205    opt->errfn = unknown_arg;
206    opt->errarg = str;
207
208    while (apr_getopt(opt, "a::", &ch, &optarg) == APR_SUCCESS) {
209        switch (ch) {
210            case 'a':
211                format_arg(str, ch, optarg);
212                break;
213            default:
214                break;
215        }
216    }
217#if 0
218/*  Our version of getopt doesn't allow for optional arguments.  */
219    ABTS_STR_EQUAL(tc, "option: a\n", str);
220#endif
221    ABTS_STR_EQUAL(tc, "testprog: option requires an argument -- a\n", str);
222}
223
224abts_suite *testgetopt(abts_suite *suite)
225{
226    suite = ADD_SUITE(suite)
227
228    abts_run_test(suite, no_options, NULL);
229    abts_run_test(suite, no_options_found, NULL);
230    abts_run_test(suite, required_option, NULL);
231    abts_run_test(suite, required_option_notgiven, NULL);
232    abts_run_test(suite, optional_option, NULL);
233    abts_run_test(suite, optional_option_notgiven, NULL);
234
235    return suite;
236}
237