xref: /aosp_15_r20/external/perfetto/src/base/getopt_compat_unittest.cc (revision 6dbdd20afdafa5e3ca9b8809fa73465d530080dc)
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