xref: /aosp_15_r20/external/libbrillo/brillo/flag_helper_test.cc (revision 1a96fba65179ea7d3f56207137718607415c5953)
1 // Copyright 2014 The Chromium OS Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include <cstdint>
6 #include <cstdio>
7 #include <sysexits.h>
8 
9 #include <base/command_line.h>
10 #include <base/macros.h>
11 #include <base/stl_util.h>
12 #include <brillo/flag_helper.h>
13 
14 #include <gtest/gtest.h>
15 
16 namespace brillo {
17 
18 class FlagHelperTest : public ::testing::Test {
19  public:
FlagHelperTest()20   FlagHelperTest() {}
~FlagHelperTest()21   ~FlagHelperTest() override { brillo::FlagHelper::ResetForTesting(); }
SetUpTestCase()22   static void SetUpTestCase() { base::CommandLine::Init(0, nullptr); }
23 };
24 
25 // Test that the DEFINE_xxxx macros can create the respective variables
26 // correctly with the default value.
TEST_F(FlagHelperTest,Defaults)27 TEST_F(FlagHelperTest, Defaults) {
28   DEFINE_bool(bool1, true, "Test bool flag");
29   DEFINE_bool(bool2, false, "Test bool flag");
30   DEFINE_int32(int32_1, INT32_MIN, "Test int32 flag");
31   DEFINE_int32(int32_2, 0, "Test int32 flag");
32   DEFINE_int32(int32_3, INT32_MAX, "Test int32 flag");
33   DEFINE_uint32(uint32_1, 0, "Test uint32 flag");
34   DEFINE_uint32(uint32_2, UINT32_MAX, "Test uint32 flag");
35   DEFINE_int64(int64_1, INT64_MIN, "Test int64 flag");
36   DEFINE_int64(int64_2, 0, "Test int64 flag");
37   DEFINE_int64(int64_3, INT64_MAX, "Test int64 flag");
38   DEFINE_uint64(uint64_1, 0, "Test uint64 flag");
39   DEFINE_uint64(uint64_2, UINT_LEAST64_MAX, "Test uint64 flag");
40   DEFINE_double(double_1, -100.5, "Test double flag");
41   DEFINE_double(double_2, 0, "Test double flag");
42   DEFINE_double(double_3, 100.5, "Test double flag");
43   DEFINE_string(string_1, "", "Test string flag");
44   DEFINE_string(string_2, "value", "Test string flag");
45 
46   const char* argv[] = {"test_program"};
47   base::CommandLine command_line(base::size(argv), argv);
48 
49   brillo::FlagHelper::GetInstance()->set_command_line_for_testing(
50       &command_line);
51   brillo::FlagHelper::Init(base::size(argv), argv, "TestDefaultTrue");
52 
53   EXPECT_TRUE(FLAGS_bool1);
54   EXPECT_FALSE(FLAGS_bool2);
55   EXPECT_EQ(FLAGS_int32_1, INT32_MIN);
56   EXPECT_EQ(FLAGS_int32_2, 0);
57   EXPECT_EQ(FLAGS_int32_3, INT32_MAX);
58   EXPECT_EQ(FLAGS_uint32_1, 0);
59   EXPECT_EQ(FLAGS_uint32_2, UINT32_MAX);
60   EXPECT_EQ(FLAGS_int64_1, INT64_MIN);
61   EXPECT_EQ(FLAGS_int64_2, 0);
62   EXPECT_EQ(FLAGS_int64_3, INT64_MAX);
63   EXPECT_EQ(FLAGS_uint64_1, 0);
64   EXPECT_EQ(FLAGS_uint64_2, UINT_LEAST64_MAX);
65   EXPECT_DOUBLE_EQ(FLAGS_double_1, -100.5);
66   EXPECT_DOUBLE_EQ(FLAGS_double_2, 0);
67   EXPECT_DOUBLE_EQ(FLAGS_double_3, 100.5);
68   EXPECT_STREQ(FLAGS_string_1.c_str(), "");
69   EXPECT_STREQ(FLAGS_string_2.c_str(), "value");
70 }
71 
72 // Test that command line flag values are parsed and update the flag
73 // variable values correctly when using double '--' flags
TEST_F(FlagHelperTest,SetValueDoubleDash)74 TEST_F(FlagHelperTest, SetValueDoubleDash) {
75   DEFINE_bool(bool1, false, "Test bool flag");
76   DEFINE_bool(bool2, true, "Test bool flag");
77   DEFINE_bool(bool3, false, "Test bool flag");
78   DEFINE_bool(bool4, true, "Test bool flag");
79   DEFINE_int32(int32_1, 1, "Test int32 flag");
80   DEFINE_int32(int32_2, 1, "Test int32 flag");
81   DEFINE_int32(int32_3, 1, "Test int32 flag");
82   DEFINE_uint32(uint32_1, 1, "Test uint32 flag");
83   DEFINE_uint32(uint32_2, 1, "Test uint32 flag");
84   DEFINE_int64(int64_1, 1, "Test int64 flag");
85   DEFINE_int64(int64_2, 1, "Test int64 flag");
86   DEFINE_int64(int64_3, 1, "Test int64 flag");
87   DEFINE_uint64(uint64_1, 1, "Test uint64 flag");
88   DEFINE_uint64(uint64_2, 1, "Test uint64 flag");
89   DEFINE_double(double_1, 1, "Test double flag");
90   DEFINE_double(double_2, 1, "Test double flag");
91   DEFINE_double(double_3, 1, "Test double flag");
92   DEFINE_string(string_1, "default", "Test string flag");
93   DEFINE_string(string_2, "default", "Test string flag");
94 
95   const char* argv[] = {"test_program",
96                         "--bool1",
97                         "--nobool2",
98                         "--bool3=true",
99                         "--bool4=false",
100                         "--int32_1=-2147483648",
101                         "--int32_2=0",
102                         "--int32_3=2147483647",
103                         "--uint32_1=0",
104                         "--uint32_2=4294967295",
105                         "--int64_1=-9223372036854775808",
106                         "--int64_2=0",
107                         "--int64_3=9223372036854775807",
108                         "--uint64_1=0",
109                         "--uint64_2=18446744073709551615",
110                         "--double_1=-100.5",
111                         "--double_2=0",
112                         "--double_3=100.5",
113                         "--string_1=",
114                         "--string_2=value"};
115   base::CommandLine command_line(base::size(argv), argv);
116 
117   brillo::FlagHelper::GetInstance()->set_command_line_for_testing(
118       &command_line);
119   brillo::FlagHelper::Init(base::size(argv), argv, "TestDefaultTrue");
120 
121   EXPECT_TRUE(FLAGS_bool1);
122   EXPECT_FALSE(FLAGS_bool2);
123   EXPECT_TRUE(FLAGS_bool3);
124   EXPECT_FALSE(FLAGS_bool4);
125   EXPECT_EQ(FLAGS_int32_1, INT32_MIN);
126   EXPECT_EQ(FLAGS_int32_2, 0);
127   EXPECT_EQ(FLAGS_int32_3, INT32_MAX);
128   EXPECT_EQ(FLAGS_uint32_1, 0);
129   EXPECT_EQ(FLAGS_uint32_2, UINT32_MAX);
130   EXPECT_EQ(FLAGS_int64_1, INT64_MIN);
131   EXPECT_EQ(FLAGS_int64_2, 0);
132   EXPECT_EQ(FLAGS_int64_3, INT64_MAX);
133   EXPECT_EQ(FLAGS_uint64_1, 0);
134   EXPECT_EQ(FLAGS_uint64_2, UINT_LEAST64_MAX);
135   EXPECT_DOUBLE_EQ(FLAGS_double_1, -100.5);
136   EXPECT_DOUBLE_EQ(FLAGS_double_2, 0);
137   EXPECT_DOUBLE_EQ(FLAGS_double_3, 100.5);
138   EXPECT_STREQ(FLAGS_string_1.c_str(), "");
139   EXPECT_STREQ(FLAGS_string_2.c_str(), "value");
140 }
141 
142 // Test that command line flag values are parsed and update the flag
143 // variable values correctly when using single '-' flags
TEST_F(FlagHelperTest,SetValueSingleDash)144 TEST_F(FlagHelperTest, SetValueSingleDash) {
145   DEFINE_bool(bool1, false, "Test bool flag");
146   DEFINE_bool(bool2, true, "Test bool flag");
147   DEFINE_int32(int32_1, 1, "Test int32 flag");
148   DEFINE_int32(int32_2, 1, "Test int32 flag");
149   DEFINE_int32(int32_3, 1, "Test int32 flag");
150   DEFINE_uint64(uint32_1, 1, "Test uint32 flag");
151   DEFINE_uint64(uint32_2, 1, "Test uint32 flag");
152   DEFINE_int64(int64_1, 1, "Test int64 flag");
153   DEFINE_int64(int64_2, 1, "Test int64 flag");
154   DEFINE_int64(int64_3, 1, "Test int64 flag");
155   DEFINE_uint64(uint64_1, 1, "Test uint64 flag");
156   DEFINE_uint64(uint64_2, 1, "Test uint64 flag");
157   DEFINE_double(double_1, 1, "Test double flag");
158   DEFINE_double(double_2, 1, "Test double flag");
159   DEFINE_double(double_3, 1, "Test double flag");
160   DEFINE_string(string_1, "default", "Test string flag");
161   DEFINE_string(string_2, "default", "Test string flag");
162 
163   const char* argv[] = {"test_program",
164                         "-bool1",
165                         "-nobool2",
166                         "-int32_1=-2147483648",
167                         "-int32_2=0",
168                         "-int32_3=2147483647",
169                         "-uint32_1=0",
170                         "-uint32_2=4294967295",
171                         "-int64_1=-9223372036854775808",
172                         "-int64_2=0",
173                         "-int64_3=9223372036854775807",
174                         "-uint64_1=0",
175                         "-uint64_2=18446744073709551615",
176                         "-double_1=-100.5",
177                         "-double_2=0",
178                         "-double_3=100.5",
179                         "-string_1=",
180                         "-string_2=value"};
181   base::CommandLine command_line(base::size(argv), argv);
182 
183   brillo::FlagHelper::GetInstance()->set_command_line_for_testing(
184       &command_line);
185   brillo::FlagHelper::Init(base::size(argv), argv, "TestDefaultTrue");
186 
187   EXPECT_TRUE(FLAGS_bool1);
188   EXPECT_FALSE(FLAGS_bool2);
189   EXPECT_EQ(FLAGS_int32_1, INT32_MIN);
190   EXPECT_EQ(FLAGS_int32_2, 0);
191   EXPECT_EQ(FLAGS_int32_3, INT32_MAX);
192   EXPECT_EQ(FLAGS_uint32_1, 0);
193   EXPECT_EQ(FLAGS_uint32_2, UINT32_MAX);
194   EXPECT_EQ(FLAGS_int64_1, INT64_MIN);
195   EXPECT_EQ(FLAGS_int64_2, 0);
196   EXPECT_EQ(FLAGS_int64_3, INT64_MAX);
197   EXPECT_EQ(FLAGS_uint64_1, 0);
198   EXPECT_EQ(FLAGS_uint64_2, UINT_LEAST64_MAX);
199   EXPECT_DOUBLE_EQ(FLAGS_double_1, -100.5);
200   EXPECT_DOUBLE_EQ(FLAGS_double_2, 0);
201   EXPECT_DOUBLE_EQ(FLAGS_double_3, 100.5);
202   EXPECT_STREQ(FLAGS_string_1.c_str(), "");
203   EXPECT_STREQ(FLAGS_string_2.c_str(), "value");
204 }
205 
206 // Test that a duplicated flag on the command line picks up the last
207 // value set.
TEST_F(FlagHelperTest,DuplicateSetValue)208 TEST_F(FlagHelperTest, DuplicateSetValue) {
209   DEFINE_int32(int32_1, 0, "Test in32 flag");
210 
211   const char* argv[] = {"test_program", "--int32_1=5", "--int32_1=10"};
212   base::CommandLine command_line(base::size(argv), argv);
213 
214   brillo::FlagHelper::GetInstance()->set_command_line_for_testing(
215       &command_line);
216   brillo::FlagHelper::Init(base::size(argv), argv, "TestDuplicateSetvalue");
217 
218   EXPECT_EQ(FLAGS_int32_1, 10);
219 }
220 
221 // Test that flags set after the -- marker are not parsed as command line flags
TEST_F(FlagHelperTest,FlagTerminator)222 TEST_F(FlagHelperTest, FlagTerminator) {
223   DEFINE_int32(int32_1, 0, "Test int32 flag");
224 
225   const char* argv[] = {"test_program", "--int32_1=5", "--", "--int32_1=10"};
226   base::CommandLine command_line(base::size(argv), argv);
227 
228   brillo::FlagHelper::GetInstance()->set_command_line_for_testing(
229       &command_line);
230   brillo::FlagHelper::Init(base::size(argv), argv, "TestFlagTerminator");
231 
232   EXPECT_EQ(FLAGS_int32_1, 5);
233 }
234 
235 // Test that help messages are generated correctly when the --help flag
236 // is passed to the program.
TEST_F(FlagHelperTest,HelpMessage)237 TEST_F(FlagHelperTest, HelpMessage) {
238   DEFINE_bool(bool_1, true, "Test bool flag");
239   DEFINE_int32(int_1, 0, "Test int flag");
240   DEFINE_uint32(uint32_1, 0, "Test uint32 flag");
241   DEFINE_int64(int64_1, 0, "Test int64 flag");
242   DEFINE_uint64(uint64_1, 0, "Test uint64 flag");
243   DEFINE_double(double_1, 0, "Test double flag");
244   DEFINE_string(string_1, "", "Test string flag");
245 
246   const char* argv[] = {"test_program", "--int_1=value", "--help"};
247   base::CommandLine command_line(base::size(argv), argv);
248 
249   brillo::FlagHelper::GetInstance()->set_command_line_for_testing(
250       &command_line);
251 
252   FILE* orig = stdout;
253   stdout = stderr;
254 
255   ASSERT_EXIT(
256       brillo::FlagHelper::Init(base::size(argv), argv, "TestHelpMessage"),
257       ::testing::ExitedWithCode(EX_OK),
258       "TestHelpMessage\n\n"
259       "  --bool_1  \\(Test bool flag\\)  type: bool  default: true\n"
260       "  --double_1  \\(Test double flag\\)  type: double  default: 0\n"
261       "  --help  \\(Show this help message\\)  type: bool  default: false\n"
262       "  --int64_1  \\(Test int64 flag\\)  type: int64  default: 0\n"
263       "  --int_1  \\(Test int flag\\)  type: int  default: 0\n"
264       "  --string_1  \\(Test string flag\\)  type: string  default: \"\"\n"
265       "  --uint32_1  \\(Test uint32 flag\\)  type: uint32  default: 0\n"
266       "  --uint64_1  \\(Test uint64 flag\\)  type: uint64  default: 0\n");
267 
268   stdout = orig;
269 }
270 
271 // Test that passing in unknown command line flags causes the program
272 // to exit with EX_USAGE error code and corresponding error message.
TEST_F(FlagHelperTest,UnknownFlag)273 TEST_F(FlagHelperTest, UnknownFlag) {
274   const char* argv[] = {"test_program", "--flag=value"};
275   base::CommandLine command_line(base::size(argv), argv);
276 
277   brillo::FlagHelper::GetInstance()->set_command_line_for_testing(
278       &command_line);
279 
280   FILE* orig = stdout;
281   stdout = stderr;
282 
283   ASSERT_EXIT(brillo::FlagHelper::Init(base::size(argv), argv, "TestIntExit"),
284               ::testing::ExitedWithCode(EX_USAGE),
285               "ERROR: unknown command line flag 'flag'");
286 
287   stdout = orig;
288 }
289 
290 // Test that when passing an incorrect/unparsable type to a command line flag,
291 // the program exits with code EX_DATAERR and outputs a corresponding message.
TEST_F(FlagHelperTest,BoolParseError)292 TEST_F(FlagHelperTest, BoolParseError) {
293   DEFINE_bool(bool_1, 0, "Test bool flag");
294 
295   const char* argv[] = {"test_program", "--bool_1=value"};
296   base::CommandLine command_line(base::size(argv), argv);
297 
298   brillo::FlagHelper::GetInstance()->set_command_line_for_testing(
299       &command_line);
300 
301   FILE* orig = stdout;
302   stdout = stderr;
303 
304   ASSERT_EXIT(
305       brillo::FlagHelper::Init(base::size(argv), argv, "TestBoolParseError"),
306       ::testing::ExitedWithCode(EX_DATAERR),
307       "ERROR: illegal value 'value' specified for bool flag 'bool_1'");
308 
309   stdout = orig;
310 }
311 
312 // Test that when passing an incorrect/unparsable type to a command line flag,
313 // the program exits with code EX_DATAERR and outputs a corresponding message.
TEST_F(FlagHelperTest,Int32ParseError)314 TEST_F(FlagHelperTest, Int32ParseError) {
315   DEFINE_int32(int_1, 0, "Test int flag");
316 
317   const char* argv[] = {"test_program", "--int_1=value"};
318   base::CommandLine command_line(base::size(argv), argv);
319 
320   brillo::FlagHelper::GetInstance()->set_command_line_for_testing(
321       &command_line);
322 
323   FILE* orig = stdout;
324   stdout = stderr;
325 
326   ASSERT_EXIT(
327       brillo::FlagHelper::Init(base::size(argv), argv, "TestInt32ParseError"),
328       ::testing::ExitedWithCode(EX_DATAERR),
329       "ERROR: illegal value 'value' specified for int flag 'int_1'");
330 
331   stdout = orig;
332 }
333 
334 // Test that when passing an incorrect/unparsable type to a command line flag,
335 // the program exits with code EX_DATAERR and outputs a corresponding message.
TEST_F(FlagHelperTest,Uint32ParseErrorUppperBound)336 TEST_F(FlagHelperTest, Uint32ParseErrorUppperBound) {
337   DEFINE_uint32(uint32_1, 0, "Test uint32 flag");
338 
339   // test with UINT32_MAX + 1
340   const char* argv[] = {"test_program", "--uint32_1=4294967296"};
341   base::CommandLine command_line(base::size(argv), argv);
342 
343   brillo::FlagHelper::GetInstance()->set_command_line_for_testing(
344       &command_line);
345 
346   FILE* orig = stdout;
347   stdout = stderr;
348 
349   ASSERT_EXIT(
350       brillo::FlagHelper::Init(base::size(argv), argv, "TestUint32ParseError"),
351       ::testing::ExitedWithCode(EX_DATAERR),
352       "ERROR: illegal value '4294967296' specified for uint32 flag "
353       "'uint32_1'");
354 
355   stdout = orig;
356 }
357 
358 // Test that when passing an incorrect/unparsable type to a command line flag,
359 // the program exits with code EX_DATAERR and outputs a corresponding message.
TEST_F(FlagHelperTest,Uint32ParseErrorNegativeValue)360 TEST_F(FlagHelperTest, Uint32ParseErrorNegativeValue) {
361   DEFINE_uint32(uint32_1, 0, "Test uint32 flag");
362 
363   const char* argv[] = {"test_program", "--uint32_1=-1"};
364   base::CommandLine command_line(base::size(argv), argv);
365 
366   brillo::FlagHelper::GetInstance()->set_command_line_for_testing(
367       &command_line);
368 
369   FILE* orig = stdout;
370   stdout = stderr;
371 
372   ASSERT_EXIT(
373       brillo::FlagHelper::Init(base::size(argv), argv, "TestUint32ParseError"),
374       ::testing::ExitedWithCode(EX_DATAERR),
375       "ERROR: illegal value '-1' specified for uint32 flag "
376       "'uint32_1'");
377 
378   stdout = orig;
379 }
380 
381 // Test that when passing an incorrect/unparsable type to a command line flag,
382 // the program exits with code EX_DATAERR and outputs a corresponding message.
TEST_F(FlagHelperTest,Int64ParseError)383 TEST_F(FlagHelperTest, Int64ParseError) {
384   DEFINE_int64(int64_1, 0, "Test int64 flag");
385 
386   const char* argv[] = {"test_program", "--int64_1=value"};
387   base::CommandLine command_line(base::size(argv), argv);
388 
389   brillo::FlagHelper::GetInstance()->set_command_line_for_testing(
390       &command_line);
391 
392   FILE* orig = stdout;
393   stdout = stderr;
394 
395   ASSERT_EXIT(
396       brillo::FlagHelper::Init(base::size(argv), argv, "TestInt64ParseError"),
397       ::testing::ExitedWithCode(EX_DATAERR),
398       "ERROR: illegal value 'value' specified for int64 flag "
399       "'int64_1'");
400 
401   stdout = orig;
402 }
403 
404 // Test that when passing an incorrect/unparsable type to a command line flag,
405 // the program exits with code EX_DATAERR and outputs a corresponding message.
TEST_F(FlagHelperTest,UInt64ParseError)406 TEST_F(FlagHelperTest, UInt64ParseError) {
407   DEFINE_uint64(uint64_1, 0, "Test uint64 flag");
408 
409   const char* argv[] = {"test_program", "--uint64_1=value"};
410   base::CommandLine command_line(base::size(argv), argv);
411 
412   brillo::FlagHelper::GetInstance()->set_command_line_for_testing(
413       &command_line);
414 
415   FILE* orig = stdout;
416   stdout = stderr;
417 
418   ASSERT_EXIT(
419       brillo::FlagHelper::Init(base::size(argv), argv, "TestUInt64ParseError"),
420       ::testing::ExitedWithCode(EX_DATAERR),
421       "ERROR: illegal value 'value' specified for uint64 flag "
422       "'uint64_1'");
423 
424   stdout = orig;
425 }
426 
427 }  // namespace brillo
428