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 15namespace brillo { 16 17class FlagHelperTest : public ::testing::Test { 18 public: 19 FlagHelperTest() {} 20 ~FlagHelperTest() override { brillo::FlagHelper::ResetForTesting(); } 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. 26TEST_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 69TEST_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 133TEST_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. 191TEST_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 205TEST_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. 220TEST_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. 254TEST_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. 273TEST_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. 295TEST_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. 318TEST_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. 341TEST_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