1*6dbdd20aSAndroid Build Coastguard Worker /*
2*6dbdd20aSAndroid Build Coastguard Worker * Copyright (C) 2021 The Android Open Source Project
3*6dbdd20aSAndroid Build Coastguard Worker *
4*6dbdd20aSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*6dbdd20aSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*6dbdd20aSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*6dbdd20aSAndroid Build Coastguard Worker *
8*6dbdd20aSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*6dbdd20aSAndroid Build Coastguard Worker *
10*6dbdd20aSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*6dbdd20aSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*6dbdd20aSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*6dbdd20aSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*6dbdd20aSAndroid Build Coastguard Worker * limitations under the License.
15*6dbdd20aSAndroid Build Coastguard Worker */
16*6dbdd20aSAndroid Build Coastguard Worker
17*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/ext/base/getopt_compat.h"
18*6dbdd20aSAndroid Build Coastguard Worker
19*6dbdd20aSAndroid Build Coastguard Worker // This test has two roles:
20*6dbdd20aSAndroid Build Coastguard Worker // 1. In Windows builds it's a plain unittest for our getopt_compat.cc
21*6dbdd20aSAndroid Build Coastguard Worker // 2. On other builds it also checks that the behavior of our getopt_compat.cc
22*6dbdd20aSAndroid Build Coastguard Worker // is the same of <getopt.h> (for the options we support).
23*6dbdd20aSAndroid Build Coastguard Worker // It does so creating a gtest typed test, and defining two structs that inject
24*6dbdd20aSAndroid Build Coastguard Worker // getopt functions and global variables like optind.
25*6dbdd20aSAndroid Build Coastguard Worker
26*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/base/build_config.h"
27*6dbdd20aSAndroid Build Coastguard Worker
28*6dbdd20aSAndroid Build Coastguard Worker #if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
29*6dbdd20aSAndroid Build Coastguard Worker #include <getopt.h>
30*6dbdd20aSAndroid Build Coastguard Worker #endif
31*6dbdd20aSAndroid Build Coastguard Worker
32*6dbdd20aSAndroid Build Coastguard Worker #include <initializer_list>
33*6dbdd20aSAndroid Build Coastguard Worker
34*6dbdd20aSAndroid Build Coastguard Worker #include "test/gtest_and_gmock.h"
35*6dbdd20aSAndroid Build Coastguard Worker
36*6dbdd20aSAndroid Build Coastguard Worker using testing::ElementsAre;
37*6dbdd20aSAndroid Build Coastguard Worker using testing::ElementsAreArray;
38*6dbdd20aSAndroid Build Coastguard Worker
39*6dbdd20aSAndroid Build Coastguard Worker namespace perfetto {
40*6dbdd20aSAndroid Build Coastguard Worker namespace base {
41*6dbdd20aSAndroid Build Coastguard Worker namespace {
42*6dbdd20aSAndroid Build Coastguard Worker
43*6dbdd20aSAndroid Build Coastguard Worker struct OurGetopt {
44*6dbdd20aSAndroid Build Coastguard Worker using LongOptionType = getopt_compat::option;
45*6dbdd20aSAndroid Build Coastguard Worker using GetoptFn = decltype(&getopt_compat::getopt);
46*6dbdd20aSAndroid Build Coastguard Worker using GetoptLongFn = decltype(&getopt_compat::getopt_long);
47*6dbdd20aSAndroid Build Coastguard Worker GetoptFn getopt = &getopt_compat::getopt;
48*6dbdd20aSAndroid Build Coastguard Worker GetoptLongFn getopt_long = &getopt_compat::getopt_long;
49*6dbdd20aSAndroid Build Coastguard Worker int& optind = getopt_compat::optind;
50*6dbdd20aSAndroid Build Coastguard Worker int& optopt = getopt_compat::optopt;
51*6dbdd20aSAndroid Build Coastguard Worker int& opterr = getopt_compat::opterr;
52*6dbdd20aSAndroid Build Coastguard Worker char*& optarg = getopt_compat::optarg;
53*6dbdd20aSAndroid Build Coastguard Worker };
54*6dbdd20aSAndroid Build Coastguard Worker
55*6dbdd20aSAndroid Build Coastguard Worker #if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
56*6dbdd20aSAndroid Build Coastguard Worker struct SystemGetopt {
57*6dbdd20aSAndroid Build Coastguard Worker using LongOptionType = ::option;
58*6dbdd20aSAndroid Build Coastguard Worker using GetoptFn = decltype(&::getopt);
59*6dbdd20aSAndroid Build Coastguard Worker using GetoptLongFn = decltype(&::getopt_long);
60*6dbdd20aSAndroid Build Coastguard Worker GetoptFn getopt = &::getopt;
61*6dbdd20aSAndroid Build Coastguard Worker GetoptLongFn getopt_long = &::getopt_long;
62*6dbdd20aSAndroid Build Coastguard Worker int& optind = ::optind;
63*6dbdd20aSAndroid Build Coastguard Worker int& optopt = ::optopt;
64*6dbdd20aSAndroid Build Coastguard Worker int& opterr = ::opterr;
65*6dbdd20aSAndroid Build Coastguard Worker char*& optarg = ::optarg;
66*6dbdd20aSAndroid Build Coastguard Worker };
67*6dbdd20aSAndroid Build Coastguard Worker #endif
68*6dbdd20aSAndroid Build Coastguard Worker
69*6dbdd20aSAndroid Build Coastguard Worker template <typename T>
70*6dbdd20aSAndroid Build Coastguard Worker class GetoptCompatTest : public testing::Test {
71*6dbdd20aSAndroid Build Coastguard Worker public:
SetCmdline(std::initializer_list<const char * > arg_list)72*6dbdd20aSAndroid Build Coastguard Worker inline void SetCmdline(std::initializer_list<const char*> arg_list) {
73*6dbdd20aSAndroid Build Coastguard Worker // Reset the getopt() state.
74*6dbdd20aSAndroid Build Coastguard Worker // When calling getopt() several times, MacOS requires that optind is reset
75*6dbdd20aSAndroid Build Coastguard Worker // to 1, while Linux requires optind to be reset to 0. Also MacOS requires
76*6dbdd20aSAndroid Build Coastguard Worker // optreset to be set as well.
77*6dbdd20aSAndroid Build Coastguard Worker #if PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
78*6dbdd20aSAndroid Build Coastguard Worker impl.optind = 1;
79*6dbdd20aSAndroid Build Coastguard Worker optreset = 1; // It has no corresponding variable in other OSes.
80*6dbdd20aSAndroid Build Coastguard Worker #else
81*6dbdd20aSAndroid Build Coastguard Worker impl.optind = 0;
82*6dbdd20aSAndroid Build Coastguard Worker #endif
83*6dbdd20aSAndroid Build Coastguard Worker argc = static_cast<int>(arg_list.size());
84*6dbdd20aSAndroid Build Coastguard Worker for (char*& arg : argv)
85*6dbdd20aSAndroid Build Coastguard Worker arg = nullptr;
86*6dbdd20aSAndroid Build Coastguard Worker size_t i = 0;
87*6dbdd20aSAndroid Build Coastguard Worker for (const char* arg : arg_list)
88*6dbdd20aSAndroid Build Coastguard Worker argv[i++] = const_cast<char*>(arg);
89*6dbdd20aSAndroid Build Coastguard Worker }
90*6dbdd20aSAndroid Build Coastguard Worker int argc;
91*6dbdd20aSAndroid Build Coastguard Worker char* argv[32]; // We don't use more than 32 entries on our tests.
92*6dbdd20aSAndroid Build Coastguard Worker T impl;
93*6dbdd20aSAndroid Build Coastguard Worker };
94*6dbdd20aSAndroid Build Coastguard Worker
95*6dbdd20aSAndroid Build Coastguard Worker #if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
96*6dbdd20aSAndroid Build Coastguard Worker using GetoptTestTypes = ::testing::Types<OurGetopt>;
97*6dbdd20aSAndroid Build Coastguard Worker #else
98*6dbdd20aSAndroid Build Coastguard Worker using GetoptTestTypes = ::testing::Types<OurGetopt, SystemGetopt>;
99*6dbdd20aSAndroid Build Coastguard Worker #endif
100*6dbdd20aSAndroid Build Coastguard Worker TYPED_TEST_SUITE(GetoptCompatTest, GetoptTestTypes, /* trailing ',' for GCC*/);
101*6dbdd20aSAndroid Build Coastguard Worker
TYPED_TEST(GetoptCompatTest,ShortOptions)102*6dbdd20aSAndroid Build Coastguard Worker TYPED_TEST(GetoptCompatTest, ShortOptions) {
103*6dbdd20aSAndroid Build Coastguard Worker auto& t = this->impl;
104*6dbdd20aSAndroid Build Coastguard Worker
105*6dbdd20aSAndroid Build Coastguard Worker const char* sops = "";
106*6dbdd20aSAndroid Build Coastguard Worker this->SetCmdline({"argv0"});
107*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.getopt(this->argc, this->argv, sops), -1);
108*6dbdd20aSAndroid Build Coastguard Worker
109*6dbdd20aSAndroid Build Coastguard Worker sops = "h";
110*6dbdd20aSAndroid Build Coastguard Worker this->SetCmdline({"argv0"});
111*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.getopt(this->argc, this->argv, sops), -1);
112*6dbdd20aSAndroid Build Coastguard Worker
113*6dbdd20aSAndroid Build Coastguard Worker sops = "h";
114*6dbdd20aSAndroid Build Coastguard Worker this->SetCmdline({"argv0", "-h"});
115*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.getopt(this->argc, this->argv, sops), 'h');
116*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.optind, 2);
117*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.getopt(this->argc, this->argv, sops), -1);
118*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.optind, 2);
119*6dbdd20aSAndroid Build Coastguard Worker
120*6dbdd20aSAndroid Build Coastguard Worker sops = "h";
121*6dbdd20aSAndroid Build Coastguard Worker this->SetCmdline({"argv0", "positional1", "positional2"});
122*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.getopt(this->argc, this->argv, sops), -1);
123*6dbdd20aSAndroid Build Coastguard Worker
124*6dbdd20aSAndroid Build Coastguard Worker sops = "h";
125*6dbdd20aSAndroid Build Coastguard Worker this->SetCmdline({"argv0", "--", "positional1", "positional2"});
126*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.getopt(this->argc, this->argv, sops), -1);
127*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.optind, 2);
128*6dbdd20aSAndroid Build Coastguard Worker
129*6dbdd20aSAndroid Build Coastguard Worker sops = "h";
130*6dbdd20aSAndroid Build Coastguard Worker this->SetCmdline({"argv0", "-h"});
131*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.getopt(this->argc, this->argv, sops), 'h');
132*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.optind, 2);
133*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.getopt(this->argc, this->argv, sops), -1);
134*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.optind, 2);
135*6dbdd20aSAndroid Build Coastguard Worker
136*6dbdd20aSAndroid Build Coastguard Worker sops = "abc";
137*6dbdd20aSAndroid Build Coastguard Worker this->SetCmdline({"argv0", "-c", "-a", "-b"});
138*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.getopt(this->argc, this->argv, sops), 'c');
139*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.optind, 2);
140*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.getopt(this->argc, this->argv, sops), 'a');
141*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.optind, 3);
142*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.getopt(this->argc, this->argv, sops), 'b');
143*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.optind, 4);
144*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.getopt(this->argc, this->argv, sops), -1);
145*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.optind, 4);
146*6dbdd20aSAndroid Build Coastguard Worker
147*6dbdd20aSAndroid Build Coastguard Worker sops = "abc";
148*6dbdd20aSAndroid Build Coastguard Worker this->SetCmdline({"argv0", "-c", "-a", "--", "nonopt"});
149*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.getopt(this->argc, this->argv, sops), 'c');
150*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.optind, 2);
151*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.getopt(this->argc, this->argv, sops), 'a');
152*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.optind, 3);
153*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.getopt(this->argc, this->argv, sops), -1);
154*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.optind, 4);
155*6dbdd20aSAndroid Build Coastguard Worker
156*6dbdd20aSAndroid Build Coastguard Worker sops = "abc";
157*6dbdd20aSAndroid Build Coastguard Worker this->SetCmdline({"argv0", "-cb"});
158*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.getopt(this->argc, this->argv, sops), 'c');
159*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.optind, 1);
160*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.getopt(this->argc, this->argv, sops), 'b');
161*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.optind, 2);
162*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.getopt(this->argc, this->argv, sops), -1);
163*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.optind, 2);
164*6dbdd20aSAndroid Build Coastguard Worker
165*6dbdd20aSAndroid Build Coastguard Worker sops = "abc";
166*6dbdd20aSAndroid Build Coastguard Worker this->SetCmdline({"argv0", "-aa", "-c"});
167*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.getopt(this->argc, this->argv, sops), 'a');
168*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.optind, 1);
169*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.getopt(this->argc, this->argv, sops), 'a');
170*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.optind, 2);
171*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.getopt(this->argc, this->argv, sops), 'c');
172*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.optind, 3);
173*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.getopt(this->argc, this->argv, sops), -1);
174*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.optind, 3);
175*6dbdd20aSAndroid Build Coastguard Worker
176*6dbdd20aSAndroid Build Coastguard Worker sops = "a:bc";
177*6dbdd20aSAndroid Build Coastguard Worker // The semantic here is `-a b -c`
178*6dbdd20aSAndroid Build Coastguard Worker this->SetCmdline({"argv0", "-ab", "-c"});
179*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.getopt(this->argc, this->argv, sops), 'a');
180*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.optind, 2);
181*6dbdd20aSAndroid Build Coastguard Worker EXPECT_STREQ(t.optarg, "b");
182*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.getopt(this->argc, this->argv, sops), 'c');
183*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.optind, 3);
184*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.getopt(this->argc, this->argv, sops), -1);
185*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.optind, 3);
186*6dbdd20aSAndroid Build Coastguard Worker
187*6dbdd20aSAndroid Build Coastguard Worker sops = "a:bc";
188*6dbdd20aSAndroid Build Coastguard Worker this->SetCmdline({"argv0", "-ab", "--", "-c"});
189*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.getopt(this->argc, this->argv, sops), 'a');
190*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.optind, 2);
191*6dbdd20aSAndroid Build Coastguard Worker EXPECT_STREQ(t.optarg, "b");
192*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.getopt(this->argc, this->argv, sops), -1);
193*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.optind, 3);
194*6dbdd20aSAndroid Build Coastguard Worker
195*6dbdd20aSAndroid Build Coastguard Worker sops = "a:b:c:";
196*6dbdd20aSAndroid Build Coastguard Worker this->SetCmdline({"argv0", "-a", "arg1", "-b", "--", "-c", "-carg"});
197*6dbdd20aSAndroid Build Coastguard Worker // This is sbutle, the "--" is an arg value for "-b", not a separator.
198*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.getopt(this->argc, this->argv, sops), 'a');
199*6dbdd20aSAndroid Build Coastguard Worker EXPECT_STREQ(t.optarg, "arg1");
200*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.optind, 3);
201*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.getopt(this->argc, this->argv, sops), 'b');
202*6dbdd20aSAndroid Build Coastguard Worker EXPECT_STREQ(t.optarg, "--");
203*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.optind, 5);
204*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.getopt(this->argc, this->argv, sops), 'c');
205*6dbdd20aSAndroid Build Coastguard Worker EXPECT_STREQ(t.optarg, "-carg");
206*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.optind, 7);
207*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.getopt(this->argc, this->argv, sops), -1);
208*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.optind, 7);
209*6dbdd20aSAndroid Build Coastguard Worker
210*6dbdd20aSAndroid Build Coastguard Worker sops = "a";
211*6dbdd20aSAndroid Build Coastguard Worker this->SetCmdline({"argv0", "-q"});
212*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.getopt(this->argc, this->argv, sops), '?');
213*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.optind, 2);
214*6dbdd20aSAndroid Build Coastguard Worker }
215*6dbdd20aSAndroid Build Coastguard Worker
TYPED_TEST(GetoptCompatTest,LongOptions)216*6dbdd20aSAndroid Build Coastguard Worker TYPED_TEST(GetoptCompatTest, LongOptions) {
217*6dbdd20aSAndroid Build Coastguard Worker auto& t = this->impl;
218*6dbdd20aSAndroid Build Coastguard Worker using LongOptionType = typename decltype(this->impl)::LongOptionType;
219*6dbdd20aSAndroid Build Coastguard Worker
220*6dbdd20aSAndroid Build Coastguard Worker {
221*6dbdd20aSAndroid Build Coastguard Worker LongOptionType lopts[]{
222*6dbdd20aSAndroid Build Coastguard Worker {nullptr, 0, nullptr, 0},
223*6dbdd20aSAndroid Build Coastguard Worker };
224*6dbdd20aSAndroid Build Coastguard Worker const char* sops = "";
225*6dbdd20aSAndroid Build Coastguard Worker this->SetCmdline({"argv0"});
226*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.getopt_long(this->argc, this->argv, sops, lopts, nullptr), -1);
227*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.optind, 1);
228*6dbdd20aSAndroid Build Coastguard Worker }
229*6dbdd20aSAndroid Build Coastguard Worker
230*6dbdd20aSAndroid Build Coastguard Worker {
231*6dbdd20aSAndroid Build Coastguard Worker LongOptionType lopts[]{
232*6dbdd20aSAndroid Build Coastguard Worker {nullptr, 0, nullptr, 0},
233*6dbdd20aSAndroid Build Coastguard Worker };
234*6dbdd20aSAndroid Build Coastguard Worker const char* sops = "";
235*6dbdd20aSAndroid Build Coastguard Worker this->SetCmdline({"argv0", "--unknown"});
236*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.getopt_long(this->argc, this->argv, sops, lopts, nullptr), '?');
237*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.optind, 2);
238*6dbdd20aSAndroid Build Coastguard Worker }
239*6dbdd20aSAndroid Build Coastguard Worker
240*6dbdd20aSAndroid Build Coastguard Worker {
241*6dbdd20aSAndroid Build Coastguard Worker LongOptionType lopts[]{
242*6dbdd20aSAndroid Build Coastguard Worker {"one", 0 /*no_argument*/, nullptr, 1},
243*6dbdd20aSAndroid Build Coastguard Worker {"two", 0 /*no_argument*/, nullptr, 2},
244*6dbdd20aSAndroid Build Coastguard Worker {nullptr, 0, nullptr, 0},
245*6dbdd20aSAndroid Build Coastguard Worker };
246*6dbdd20aSAndroid Build Coastguard Worker const char* sops = "";
247*6dbdd20aSAndroid Build Coastguard Worker this->SetCmdline({"argv0", "--two", "--one"});
248*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.getopt_long(this->argc, this->argv, sops, lopts, nullptr), 2);
249*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.optind, 2);
250*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.getopt_long(this->argc, this->argv, sops, lopts, nullptr), 1);
251*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.optind, 3);
252*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.getopt_long(this->argc, this->argv, sops, lopts, nullptr), -1);
253*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.optind, 3);
254*6dbdd20aSAndroid Build Coastguard Worker }
255*6dbdd20aSAndroid Build Coastguard Worker
256*6dbdd20aSAndroid Build Coastguard Worker {
257*6dbdd20aSAndroid Build Coastguard Worker LongOptionType lopts[]{
258*6dbdd20aSAndroid Build Coastguard Worker {"one", 0 /*no_argument*/, nullptr, 1},
259*6dbdd20aSAndroid Build Coastguard Worker {"two", 0 /*no_argument*/, nullptr, 2},
260*6dbdd20aSAndroid Build Coastguard Worker {nullptr, 0, nullptr, 0},
261*6dbdd20aSAndroid Build Coastguard Worker };
262*6dbdd20aSAndroid Build Coastguard Worker const char* sops = "";
263*6dbdd20aSAndroid Build Coastguard Worker this->SetCmdline({"argv0", "--two", "--one", "--not-an-opt"});
264*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.getopt_long(this->argc, this->argv, sops, lopts, nullptr), 2);
265*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.optind, 2);
266*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.getopt_long(this->argc, this->argv, sops, lopts, nullptr), 1);
267*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.optind, 3);
268*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.getopt_long(this->argc, this->argv, sops, lopts, nullptr), '?');
269*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.optind, 4);
270*6dbdd20aSAndroid Build Coastguard Worker }
271*6dbdd20aSAndroid Build Coastguard Worker
272*6dbdd20aSAndroid Build Coastguard Worker {
273*6dbdd20aSAndroid Build Coastguard Worker LongOptionType lopts[]{
274*6dbdd20aSAndroid Build Coastguard Worker {"one", 0 /*no_argument*/, nullptr, 1},
275*6dbdd20aSAndroid Build Coastguard Worker {"two", 0 /*no_argument*/, nullptr, 2},
276*6dbdd20aSAndroid Build Coastguard Worker {nullptr, 0, nullptr, 0},
277*6dbdd20aSAndroid Build Coastguard Worker };
278*6dbdd20aSAndroid Build Coastguard Worker const char* sops = "";
279*6dbdd20aSAndroid Build Coastguard Worker this->SetCmdline({"argv0", "--two", "--one", "--", "--not-an-opt"});
280*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.getopt_long(this->argc, this->argv, sops, lopts, nullptr), 2);
281*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.optind, 2);
282*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.getopt_long(this->argc, this->argv, sops, lopts, nullptr), 1);
283*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.optind, 3);
284*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.getopt_long(this->argc, this->argv, sops, lopts, nullptr), -1);
285*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.optind, 4);
286*6dbdd20aSAndroid Build Coastguard Worker }
287*6dbdd20aSAndroid Build Coastguard Worker
288*6dbdd20aSAndroid Build Coastguard Worker {
289*6dbdd20aSAndroid Build Coastguard Worker LongOptionType lopts[]{
290*6dbdd20aSAndroid Build Coastguard Worker {"no1", 0 /*no_argument*/, nullptr, 1},
291*6dbdd20aSAndroid Build Coastguard Worker {"req2", 1 /*required_argument*/, nullptr, 2},
292*6dbdd20aSAndroid Build Coastguard Worker {"req3", 1 /*required_argument*/, nullptr, 3},
293*6dbdd20aSAndroid Build Coastguard Worker {nullptr, 0, nullptr, 0},
294*6dbdd20aSAndroid Build Coastguard Worker };
295*6dbdd20aSAndroid Build Coastguard Worker const char* sops = "";
296*6dbdd20aSAndroid Build Coastguard Worker // This is subtle: the "--" really is an argument for req2, not an argument
297*6dbdd20aSAndroid Build Coastguard Worker // separator. The first positional arg is "!!!".
298*6dbdd20aSAndroid Build Coastguard Worker this->SetCmdline({"argv0", "--req3", "-", "--no1", "--req2", "--", "!!!"});
299*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.getopt_long(this->argc, this->argv, sops, lopts, nullptr), 3);
300*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.optind, 3);
301*6dbdd20aSAndroid Build Coastguard Worker EXPECT_STREQ(t.optarg, "-");
302*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.getopt_long(this->argc, this->argv, sops, lopts, nullptr), 1);
303*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.optind, 4);
304*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.getopt_long(this->argc, this->argv, sops, lopts, nullptr), 2);
305*6dbdd20aSAndroid Build Coastguard Worker EXPECT_STREQ(t.optarg, "--");
306*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.optind, 6);
307*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.getopt_long(this->argc, this->argv, sops, lopts, nullptr), -1);
308*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.optind, 6);
309*6dbdd20aSAndroid Build Coastguard Worker }
310*6dbdd20aSAndroid Build Coastguard Worker
311*6dbdd20aSAndroid Build Coastguard Worker {
312*6dbdd20aSAndroid Build Coastguard Worker LongOptionType lopts[]{
313*6dbdd20aSAndroid Build Coastguard Worker {"no1", 0 /*no_argument*/, nullptr, 1},
314*6dbdd20aSAndroid Build Coastguard Worker {"req2", 1 /*required_argument*/, nullptr, 2},
315*6dbdd20aSAndroid Build Coastguard Worker {nullptr, 0, nullptr, 0},
316*6dbdd20aSAndroid Build Coastguard Worker };
317*6dbdd20aSAndroid Build Coastguard Worker const char* sops = "";
318*6dbdd20aSAndroid Build Coastguard Worker this->SetCmdline({"argv0", "--req2", "foo", "--", "--no1"});
319*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.getopt_long(this->argc, this->argv, sops, lopts, nullptr), 2);
320*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.optind, 3);
321*6dbdd20aSAndroid Build Coastguard Worker EXPECT_STREQ(t.optarg, "foo");
322*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.getopt_long(this->argc, this->argv, sops, lopts, nullptr), -1);
323*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.optind, 4);
324*6dbdd20aSAndroid Build Coastguard Worker }
325*6dbdd20aSAndroid Build Coastguard Worker }
326*6dbdd20aSAndroid Build Coastguard Worker
TYPED_TEST(GetoptCompatTest,ShortAndLongOptions)327*6dbdd20aSAndroid Build Coastguard Worker TYPED_TEST(GetoptCompatTest, ShortAndLongOptions) {
328*6dbdd20aSAndroid Build Coastguard Worker auto& t = this->impl;
329*6dbdd20aSAndroid Build Coastguard Worker using LongOptionType = typename decltype(this->impl)::LongOptionType;
330*6dbdd20aSAndroid Build Coastguard Worker
331*6dbdd20aSAndroid Build Coastguard Worker {
332*6dbdd20aSAndroid Build Coastguard Worker LongOptionType lopts[]{
333*6dbdd20aSAndroid Build Coastguard Worker {"one", 0 /*no_argument*/, nullptr, 1},
334*6dbdd20aSAndroid Build Coastguard Worker {"two", 0 /*no_argument*/, nullptr, 2},
335*6dbdd20aSAndroid Build Coastguard Worker {"three", 0 /*no_argument*/, nullptr, 3},
336*6dbdd20aSAndroid Build Coastguard Worker {nullptr, 0, nullptr, 0},
337*6dbdd20aSAndroid Build Coastguard Worker };
338*6dbdd20aSAndroid Build Coastguard Worker const char* sops = "123";
339*6dbdd20aSAndroid Build Coastguard Worker
340*6dbdd20aSAndroid Build Coastguard Worker this->SetCmdline({"argv0"});
341*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.getopt_long(this->argc, this->argv, sops, lopts, nullptr), -1);
342*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.optind, 1);
343*6dbdd20aSAndroid Build Coastguard Worker
344*6dbdd20aSAndroid Build Coastguard Worker this->SetCmdline({"argv0", "-13", "--two", "--three", "--", "--one"});
345*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.getopt_long(this->argc, this->argv, sops, lopts, nullptr), '1');
346*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.optind, 1);
347*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.getopt_long(this->argc, this->argv, sops, lopts, nullptr), '3');
348*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.optind, 2);
349*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.getopt_long(this->argc, this->argv, sops, lopts, nullptr), 2);
350*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.optind, 3);
351*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.getopt_long(this->argc, this->argv, sops, lopts, nullptr), 3);
352*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.optind, 4);
353*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.getopt_long(this->argc, this->argv, sops, lopts, nullptr), -1);
354*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.optind, 5);
355*6dbdd20aSAndroid Build Coastguard Worker
356*6dbdd20aSAndroid Build Coastguard Worker this->SetCmdline({"argv0", "--two", "-1", "--two", "-13"});
357*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.getopt_long(this->argc, this->argv, sops, lopts, nullptr), 2);
358*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.optind, 2);
359*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.getopt_long(this->argc, this->argv, sops, lopts, nullptr), '1');
360*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.optind, 3);
361*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.getopt_long(this->argc, this->argv, sops, lopts, nullptr), 2);
362*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.optind, 4);
363*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.getopt_long(this->argc, this->argv, sops, lopts, nullptr), '1');
364*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.optind, 4);
365*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.getopt_long(this->argc, this->argv, sops, lopts, nullptr), '3');
366*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.optind, 5);
367*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.getopt_long(this->argc, this->argv, sops, lopts, nullptr), -1);
368*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.optind, 5);
369*6dbdd20aSAndroid Build Coastguard Worker }
370*6dbdd20aSAndroid Build Coastguard Worker }
371*6dbdd20aSAndroid Build Coastguard Worker
TYPED_TEST(GetoptCompatTest,OpterrHandling)372*6dbdd20aSAndroid Build Coastguard Worker TYPED_TEST(GetoptCompatTest, OpterrHandling) {
373*6dbdd20aSAndroid Build Coastguard Worker auto& t = this->impl;
374*6dbdd20aSAndroid Build Coastguard Worker t.opterr = 0; // Make errors silent.
375*6dbdd20aSAndroid Build Coastguard Worker
376*6dbdd20aSAndroid Build Coastguard Worker const char* sops = "ab:";
377*6dbdd20aSAndroid Build Coastguard Worker this->SetCmdline({"argv0", "-a", "-c", "-b"});
378*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.getopt(this->argc, this->argv, sops), 'a');
379*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.getopt(this->argc, this->argv, sops), '?');
380*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.optopt, 'c');
381*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.getopt(this->argc, this->argv, sops), '?');
382*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.optopt, 'b');
383*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.getopt(this->argc, this->argv, sops), -1);
384*6dbdd20aSAndroid Build Coastguard Worker
385*6dbdd20aSAndroid Build Coastguard Worker using LongOptionType = typename decltype(this->impl)::LongOptionType;
386*6dbdd20aSAndroid Build Coastguard Worker LongOptionType lopts[]{
387*6dbdd20aSAndroid Build Coastguard Worker {"requires_arg", 1 /*required_argument*/, nullptr, 42},
388*6dbdd20aSAndroid Build Coastguard Worker {nullptr, 0, nullptr, 0},
389*6dbdd20aSAndroid Build Coastguard Worker };
390*6dbdd20aSAndroid Build Coastguard Worker this->SetCmdline({"argv0", "-a", "--unkonwn", "--requires_arg"});
391*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.getopt_long(this->argc, this->argv, sops, lopts, nullptr), 'a');
392*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.getopt_long(this->argc, this->argv, sops, lopts, nullptr), '?');
393*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.getopt_long(this->argc, this->argv, sops, lopts, nullptr), '?');
394*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.optopt, 42);
395*6dbdd20aSAndroid Build Coastguard Worker EXPECT_EQ(t.getopt_long(this->argc, this->argv, sops, lopts, nullptr), -1);
396*6dbdd20aSAndroid Build Coastguard Worker }
397*6dbdd20aSAndroid Build Coastguard Worker
398*6dbdd20aSAndroid Build Coastguard Worker } // namespace
399*6dbdd20aSAndroid Build Coastguard Worker } // namespace base
400*6dbdd20aSAndroid Build Coastguard Worker } // namespace perfetto
401