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