1 /* vim: set ts=8 sts=4 sw=4 tw=80 noet: */
2 /*======================================================================
3 Copyright (C) 2004,2005,2009 Walter Doekes <walter+tthsum@wjd.nu>
4 This file is part of tthsum.
5
6 tthsum is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10
11 tthsum is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with tthsum. If not, see <http://www.gnu.org/licenses/>.
18 ======================================================================*/
19 #include "getopt.h"
20
21 #include "test.h"
22 #include <string.h>
23
24
25 static int argc;
26 static const char* argv[64];
27
reset_getopt(const char * const args[])28 static void reset_getopt(const char* const args[]) {
29 for (argc = 0; args[argc]; ++argc)
30 argv[argc] = args[argc];
31 #if !defined(USE_MY_GETOPT) \
32 && (defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__))
33 optind = 1;
34 optreset = 1;
35 #else /* USE_MY_GETOPT || !__*BSD__ */
36 optind = 0;
37 optopt = '\0';
38 #endif /* USE_MY_GETOPT || !__*BSD__ */
39 opterr = 1;
40 }
41
test_getopt_counts_and_order()42 static int test_getopt_counts_and_order() {
43 const char* const args[] = {
44 #ifdef USE_BSD_GETOPT
45 /* BSD getopt semantics means that no options are allowed after
46 * non-options. (Also available through POSIXLY_CORRECT.) */
47 "test_getopt", "-o", "-4", "-ghi", "abc.txt", "De\xff.txt", 0
48 #else /* !USE_BSD_GETOPT */
49 "test_getopt", "abc.txt", "-o", "-4", "De\xff.txt", "-ghi", 0
50 #endif /* !USE_BSD_GETOPT */
51 };
52 int ret;
53 int good_option_count = 0;
54 int bad_option_count = 0;
55 reset_getopt(args);
56 opterr = 0;
57 while ((ret = getopt(argc, (char* const*)argv, "Vbg")) >= 0) {
58 switch(ret) {
59 case 'g':
60 /* expected good option */
61 TEST_PASS(good_option_count == 0 && bad_option_count == 2,
62 "getopt returned option 'g' too soon or too late");
63 ++good_option_count;
64 break;
65 case '?':
66 /* expected bad options */
67 if ((optopt == 'o' && bad_option_count == 0)
68 || (optopt == '4' && bad_option_count == 1)
69 || (optopt == 'h' && bad_option_count == 2)
70 || (optopt == 'i' && bad_option_count == 3)) {
71 ++bad_option_count;
72 break;
73 }
74 FAIL3("getopt returned unexpected bad option character: %c (%i/%i)",
75 optopt, good_option_count, bad_option_count);
76 default:
77 FAIL3("getopt returned unexpected option character: %c (%i/%i)",
78 ret, good_option_count, bad_option_count);
79 }
80 }
81 TEST_PASS(good_option_count == 1, "got too many or too few good options");
82 TEST_PASS(bad_option_count == 4, "got too many or too few bad options");
83 TEST_PASS1(optind + 2 == argc, "%i arguments found", argc - optind);
84 TEST_PASS1(strcmp(argv[optind], "abc.txt") == 0, "abc.txt != %s",
85 argv[optind]);
86 TEST_PASS(strcmp(argv[optind+1], "De\xff.txt") == 0, "De?.txt mismatch");
87 return 0;
88 }
89
test_getopt_missing_argument()90 static int test_getopt_missing_argument() {
91 const char* const args[] = {"test_getopt", "-o", 0};
92 int ret;
93 reset_getopt(args);
94 opterr = 0;
95 while ((ret = getopt(argc, (char* const*)argv, "o:")) >= 0) {
96 switch(ret) {
97 case 'o':
98 FAIL("getopt returned 'o' even though we lack arguments");
99 case '?':
100 if (optopt == 'o')
101 /* missing option argument */
102 break;
103 default:
104 FAIL2("fell through switch: ret=%i optopt=%i", ret, optopt);
105 }
106 }
107 return 0;
108 }
109
test_getopt_double_dash()110 static int test_getopt_double_dash() {
111 const char* const args[] = {"test_getopt", "-o", "--", "-o", "--", 0};
112 int ret;
113 int opts = 0;
114 reset_getopt(args);
115 opterr = 0;
116 while ((ret = getopt(argc, (char* const*)argv, "o")) >= 0) {
117 switch(ret) {
118 case 'o':
119 case '?':
120 ++opts;
121 break;
122 default:
123 FAIL2("fell through switch: ret=%i optopt=%i", ret, optopt);
124 }
125 }
126 TEST_PASS(opts == 1, "got too many or too few options");
127 TEST_PASS1(optind + 2 == argc, "%i arguments found", argc - optind);
128 TEST_PASS1(strcmp(argv[optind], "-o") == 0, "-o != %s",
129 argv[optind]);
130 TEST_PASS1(strcmp(argv[optind+1], "--") == 0, "-- != %s",
131 argv[optind+1]);
132 return 0;
133 }
134
135
136 TESTS(getopt_test)
137 TEST(test_getopt_counts_and_order);
138 TEST(test_getopt_missing_argument);
139 TEST(test_getopt_double_dash);
140 ENDTESTS
141