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