| // Copyright 2014 The Chromium OS Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include <cstdint> |
| #include <cstdio> |
| #include <sysexits.h> |
| |
| #include <base/command_line.h> |
| #include <base/macros.h> |
| #include <base/stl_util.h> |
| #include <brillo/flag_helper.h> |
| |
| #include <gtest/gtest.h> |
| |
| namespace brillo { |
| |
| class FlagHelperTest : public ::testing::Test { |
| public: |
| FlagHelperTest() {} |
| ~FlagHelperTest() override { brillo::FlagHelper::ResetForTesting(); } |
| static void SetUpTestCase() { base::CommandLine::Init(0, nullptr); } |
| }; |
| |
| // Test that the DEFINE_xxxx macros can create the respective variables |
| // correctly with the default value. |
| TEST_F(FlagHelperTest, Defaults) { |
| DEFINE_bool(bool1, true, "Test bool flag"); |
| DEFINE_bool(bool2, false, "Test bool flag"); |
| DEFINE_int32(int32_1, INT32_MIN, "Test int32 flag"); |
| DEFINE_int32(int32_2, 0, "Test int32 flag"); |
| DEFINE_int32(int32_3, INT32_MAX, "Test int32 flag"); |
| DEFINE_uint32(uint32_1, 0, "Test uint32 flag"); |
| DEFINE_uint32(uint32_2, UINT32_MAX, "Test uint32 flag"); |
| DEFINE_int64(int64_1, INT64_MIN, "Test int64 flag"); |
| DEFINE_int64(int64_2, 0, "Test int64 flag"); |
| DEFINE_int64(int64_3, INT64_MAX, "Test int64 flag"); |
| DEFINE_uint64(uint64_1, 0, "Test uint64 flag"); |
| DEFINE_uint64(uint64_2, UINT_LEAST64_MAX, "Test uint64 flag"); |
| DEFINE_double(double_1, -100.5, "Test double flag"); |
| DEFINE_double(double_2, 0, "Test double flag"); |
| DEFINE_double(double_3, 100.5, "Test double flag"); |
| DEFINE_string(string_1, "", "Test string flag"); |
| DEFINE_string(string_2, "value", "Test string flag"); |
| |
| const char* argv[] = {"test_program"}; |
| base::CommandLine command_line(base::size(argv), argv); |
| |
| brillo::FlagHelper::GetInstance()->set_command_line_for_testing( |
| &command_line); |
| brillo::FlagHelper::Init(base::size(argv), argv, "TestDefaultTrue"); |
| |
| EXPECT_TRUE(FLAGS_bool1); |
| EXPECT_FALSE(FLAGS_bool2); |
| EXPECT_EQ(FLAGS_int32_1, INT32_MIN); |
| EXPECT_EQ(FLAGS_int32_2, 0); |
| EXPECT_EQ(FLAGS_int32_3, INT32_MAX); |
| EXPECT_EQ(FLAGS_uint32_1, 0); |
| EXPECT_EQ(FLAGS_uint32_2, UINT32_MAX); |
| EXPECT_EQ(FLAGS_int64_1, INT64_MIN); |
| EXPECT_EQ(FLAGS_int64_2, 0); |
| EXPECT_EQ(FLAGS_int64_3, INT64_MAX); |
| EXPECT_EQ(FLAGS_uint64_1, 0); |
| EXPECT_EQ(FLAGS_uint64_2, UINT_LEAST64_MAX); |
| EXPECT_DOUBLE_EQ(FLAGS_double_1, -100.5); |
| EXPECT_DOUBLE_EQ(FLAGS_double_2, 0); |
| EXPECT_DOUBLE_EQ(FLAGS_double_3, 100.5); |
| EXPECT_STREQ(FLAGS_string_1.c_str(), ""); |
| EXPECT_STREQ(FLAGS_string_2.c_str(), "value"); |
| } |
| |
| // Test that command line flag values are parsed and update the flag |
| // variable values correctly when using double '--' flags |
| TEST_F(FlagHelperTest, SetValueDoubleDash) { |
| DEFINE_bool(bool1, false, "Test bool flag"); |
| DEFINE_bool(bool2, true, "Test bool flag"); |
| DEFINE_bool(bool3, false, "Test bool flag"); |
| DEFINE_bool(bool4, true, "Test bool flag"); |
| DEFINE_int32(int32_1, 1, "Test int32 flag"); |
| DEFINE_int32(int32_2, 1, "Test int32 flag"); |
| DEFINE_int32(int32_3, 1, "Test int32 flag"); |
| DEFINE_uint32(uint32_1, 1, "Test uint32 flag"); |
| DEFINE_uint32(uint32_2, 1, "Test uint32 flag"); |
| DEFINE_int64(int64_1, 1, "Test int64 flag"); |
| DEFINE_int64(int64_2, 1, "Test int64 flag"); |
| DEFINE_int64(int64_3, 1, "Test int64 flag"); |
| DEFINE_uint64(uint64_1, 1, "Test uint64 flag"); |
| DEFINE_uint64(uint64_2, 1, "Test uint64 flag"); |
| DEFINE_double(double_1, 1, "Test double flag"); |
| DEFINE_double(double_2, 1, "Test double flag"); |
| DEFINE_double(double_3, 1, "Test double flag"); |
| DEFINE_string(string_1, "default", "Test string flag"); |
| DEFINE_string(string_2, "default", "Test string flag"); |
| |
| const char* argv[] = {"test_program", |
| "--bool1", |
| "--nobool2", |
| "--bool3=true", |
| "--bool4=false", |
| "--int32_1=-2147483648", |
| "--int32_2=0", |
| "--int32_3=2147483647", |
| "--uint32_1=0", |
| "--uint32_2=4294967295", |
| "--int64_1=-9223372036854775808", |
| "--int64_2=0", |
| "--int64_3=9223372036854775807", |
| "--uint64_1=0", |
| "--uint64_2=18446744073709551615", |
| "--double_1=-100.5", |
| "--double_2=0", |
| "--double_3=100.5", |
| "--string_1=", |
| "--string_2=value"}; |
| base::CommandLine command_line(base::size(argv), argv); |
| |
| brillo::FlagHelper::GetInstance()->set_command_line_for_testing( |
| &command_line); |
| brillo::FlagHelper::Init(base::size(argv), argv, "TestDefaultTrue"); |
| |
| EXPECT_TRUE(FLAGS_bool1); |
| EXPECT_FALSE(FLAGS_bool2); |
| EXPECT_TRUE(FLAGS_bool3); |
| EXPECT_FALSE(FLAGS_bool4); |
| EXPECT_EQ(FLAGS_int32_1, INT32_MIN); |
| EXPECT_EQ(FLAGS_int32_2, 0); |
| EXPECT_EQ(FLAGS_int32_3, INT32_MAX); |
| EXPECT_EQ(FLAGS_uint32_1, 0); |
| EXPECT_EQ(FLAGS_uint32_2, UINT32_MAX); |
| EXPECT_EQ(FLAGS_int64_1, INT64_MIN); |
| EXPECT_EQ(FLAGS_int64_2, 0); |
| EXPECT_EQ(FLAGS_int64_3, INT64_MAX); |
| EXPECT_EQ(FLAGS_uint64_1, 0); |
| EXPECT_EQ(FLAGS_uint64_2, UINT_LEAST64_MAX); |
| EXPECT_DOUBLE_EQ(FLAGS_double_1, -100.5); |
| EXPECT_DOUBLE_EQ(FLAGS_double_2, 0); |
| EXPECT_DOUBLE_EQ(FLAGS_double_3, 100.5); |
| EXPECT_STREQ(FLAGS_string_1.c_str(), ""); |
| EXPECT_STREQ(FLAGS_string_2.c_str(), "value"); |
| } |
| |
| // Test that command line flag values are parsed and update the flag |
| // variable values correctly when using single '-' flags |
| TEST_F(FlagHelperTest, SetValueSingleDash) { |
| DEFINE_bool(bool1, false, "Test bool flag"); |
| DEFINE_bool(bool2, true, "Test bool flag"); |
| DEFINE_int32(int32_1, 1, "Test int32 flag"); |
| DEFINE_int32(int32_2, 1, "Test int32 flag"); |
| DEFINE_int32(int32_3, 1, "Test int32 flag"); |
| DEFINE_uint64(uint32_1, 1, "Test uint32 flag"); |
| DEFINE_uint64(uint32_2, 1, "Test uint32 flag"); |
| DEFINE_int64(int64_1, 1, "Test int64 flag"); |
| DEFINE_int64(int64_2, 1, "Test int64 flag"); |
| DEFINE_int64(int64_3, 1, "Test int64 flag"); |
| DEFINE_uint64(uint64_1, 1, "Test uint64 flag"); |
| DEFINE_uint64(uint64_2, 1, "Test uint64 flag"); |
| DEFINE_double(double_1, 1, "Test double flag"); |
| DEFINE_double(double_2, 1, "Test double flag"); |
| DEFINE_double(double_3, 1, "Test double flag"); |
| DEFINE_string(string_1, "default", "Test string flag"); |
| DEFINE_string(string_2, "default", "Test string flag"); |
| |
| const char* argv[] = {"test_program", |
| "-bool1", |
| "-nobool2", |
| "-int32_1=-2147483648", |
| "-int32_2=0", |
| "-int32_3=2147483647", |
| "-uint32_1=0", |
| "-uint32_2=4294967295", |
| "-int64_1=-9223372036854775808", |
| "-int64_2=0", |
| "-int64_3=9223372036854775807", |
| "-uint64_1=0", |
| "-uint64_2=18446744073709551615", |
| "-double_1=-100.5", |
| "-double_2=0", |
| "-double_3=100.5", |
| "-string_1=", |
| "-string_2=value"}; |
| base::CommandLine command_line(base::size(argv), argv); |
| |
| brillo::FlagHelper::GetInstance()->set_command_line_for_testing( |
| &command_line); |
| brillo::FlagHelper::Init(base::size(argv), argv, "TestDefaultTrue"); |
| |
| EXPECT_TRUE(FLAGS_bool1); |
| EXPECT_FALSE(FLAGS_bool2); |
| EXPECT_EQ(FLAGS_int32_1, INT32_MIN); |
| EXPECT_EQ(FLAGS_int32_2, 0); |
| EXPECT_EQ(FLAGS_int32_3, INT32_MAX); |
| EXPECT_EQ(FLAGS_uint32_1, 0); |
| EXPECT_EQ(FLAGS_uint32_2, UINT32_MAX); |
| EXPECT_EQ(FLAGS_int64_1, INT64_MIN); |
| EXPECT_EQ(FLAGS_int64_2, 0); |
| EXPECT_EQ(FLAGS_int64_3, INT64_MAX); |
| EXPECT_EQ(FLAGS_uint64_1, 0); |
| EXPECT_EQ(FLAGS_uint64_2, UINT_LEAST64_MAX); |
| EXPECT_DOUBLE_EQ(FLAGS_double_1, -100.5); |
| EXPECT_DOUBLE_EQ(FLAGS_double_2, 0); |
| EXPECT_DOUBLE_EQ(FLAGS_double_3, 100.5); |
| EXPECT_STREQ(FLAGS_string_1.c_str(), ""); |
| EXPECT_STREQ(FLAGS_string_2.c_str(), "value"); |
| } |
| |
| // Test that a duplicated flag on the command line picks up the last |
| // value set. |
| TEST_F(FlagHelperTest, DuplicateSetValue) { |
| DEFINE_int32(int32_1, 0, "Test in32 flag"); |
| |
| const char* argv[] = {"test_program", "--int32_1=5", "--int32_1=10"}; |
| base::CommandLine command_line(base::size(argv), argv); |
| |
| brillo::FlagHelper::GetInstance()->set_command_line_for_testing( |
| &command_line); |
| brillo::FlagHelper::Init(base::size(argv), argv, "TestDuplicateSetvalue"); |
| |
| EXPECT_EQ(FLAGS_int32_1, 10); |
| } |
| |
| // Test that flags set after the -- marker are not parsed as command line flags |
| TEST_F(FlagHelperTest, FlagTerminator) { |
| DEFINE_int32(int32_1, 0, "Test int32 flag"); |
| |
| const char* argv[] = {"test_program", "--int32_1=5", "--", "--int32_1=10"}; |
| base::CommandLine command_line(base::size(argv), argv); |
| |
| brillo::FlagHelper::GetInstance()->set_command_line_for_testing( |
| &command_line); |
| brillo::FlagHelper::Init(base::size(argv), argv, "TestFlagTerminator"); |
| |
| EXPECT_EQ(FLAGS_int32_1, 5); |
| } |
| |
| // Test that help messages are generated correctly when the --help flag |
| // is passed to the program. |
| TEST_F(FlagHelperTest, HelpMessage) { |
| DEFINE_bool(bool_1, true, "Test bool flag"); |
| DEFINE_int32(int_1, 0, "Test int flag"); |
| DEFINE_uint32(uint32_1, 0, "Test uint32 flag"); |
| DEFINE_int64(int64_1, 0, "Test int64 flag"); |
| DEFINE_uint64(uint64_1, 0, "Test uint64 flag"); |
| DEFINE_double(double_1, 0, "Test double flag"); |
| DEFINE_string(string_1, "", "Test string flag"); |
| |
| const char* argv[] = {"test_program", "--int_1=value", "--help"}; |
| base::CommandLine command_line(base::size(argv), argv); |
| |
| brillo::FlagHelper::GetInstance()->set_command_line_for_testing( |
| &command_line); |
| |
| FILE* orig = stdout; |
| stdout = stderr; |
| |
| ASSERT_EXIT( |
| brillo::FlagHelper::Init(base::size(argv), argv, "TestHelpMessage"), |
| ::testing::ExitedWithCode(EX_OK), |
| "TestHelpMessage\n\n" |
| " --bool_1 \\(Test bool flag\\) type: bool default: true\n" |
| " --double_1 \\(Test double flag\\) type: double default: 0\n" |
| " --help \\(Show this help message\\) type: bool default: false\n" |
| " --int64_1 \\(Test int64 flag\\) type: int64 default: 0\n" |
| " --int_1 \\(Test int flag\\) type: int default: 0\n" |
| " --string_1 \\(Test string flag\\) type: string default: \"\"\n" |
| " --uint32_1 \\(Test uint32 flag\\) type: uint32 default: 0\n" |
| " --uint64_1 \\(Test uint64 flag\\) type: uint64 default: 0\n"); |
| |
| stdout = orig; |
| } |
| |
| // Test that passing in unknown command line flags causes the program |
| // to exit with EX_USAGE error code and corresponding error message. |
| TEST_F(FlagHelperTest, UnknownFlag) { |
| const char* argv[] = {"test_program", "--flag=value"}; |
| base::CommandLine command_line(base::size(argv), argv); |
| |
| brillo::FlagHelper::GetInstance()->set_command_line_for_testing( |
| &command_line); |
| |
| FILE* orig = stdout; |
| stdout = stderr; |
| |
| ASSERT_EXIT(brillo::FlagHelper::Init(base::size(argv), argv, "TestIntExit"), |
| ::testing::ExitedWithCode(EX_USAGE), |
| "ERROR: unknown command line flag 'flag'"); |
| |
| stdout = orig; |
| } |
| |
| // Test that when passing an incorrect/unparsable type to a command line flag, |
| // the program exits with code EX_DATAERR and outputs a corresponding message. |
| TEST_F(FlagHelperTest, BoolParseError) { |
| DEFINE_bool(bool_1, 0, "Test bool flag"); |
| |
| const char* argv[] = {"test_program", "--bool_1=value"}; |
| base::CommandLine command_line(base::size(argv), argv); |
| |
| brillo::FlagHelper::GetInstance()->set_command_line_for_testing( |
| &command_line); |
| |
| FILE* orig = stdout; |
| stdout = stderr; |
| |
| ASSERT_EXIT( |
| brillo::FlagHelper::Init(base::size(argv), argv, "TestBoolParseError"), |
| ::testing::ExitedWithCode(EX_DATAERR), |
| "ERROR: illegal value 'value' specified for bool flag 'bool_1'"); |
| |
| stdout = orig; |
| } |
| |
| // Test that when passing an incorrect/unparsable type to a command line flag, |
| // the program exits with code EX_DATAERR and outputs a corresponding message. |
| TEST_F(FlagHelperTest, Int32ParseError) { |
| DEFINE_int32(int_1, 0, "Test int flag"); |
| |
| const char* argv[] = {"test_program", "--int_1=value"}; |
| base::CommandLine command_line(base::size(argv), argv); |
| |
| brillo::FlagHelper::GetInstance()->set_command_line_for_testing( |
| &command_line); |
| |
| FILE* orig = stdout; |
| stdout = stderr; |
| |
| ASSERT_EXIT( |
| brillo::FlagHelper::Init(base::size(argv), argv, "TestInt32ParseError"), |
| ::testing::ExitedWithCode(EX_DATAERR), |
| "ERROR: illegal value 'value' specified for int flag 'int_1'"); |
| |
| stdout = orig; |
| } |
| |
| // Test that when passing an incorrect/unparsable type to a command line flag, |
| // the program exits with code EX_DATAERR and outputs a corresponding message. |
| TEST_F(FlagHelperTest, Uint32ParseErrorUppperBound) { |
| DEFINE_uint32(uint32_1, 0, "Test uint32 flag"); |
| |
| // test with UINT32_MAX + 1 |
| const char* argv[] = {"test_program", "--uint32_1=4294967296"}; |
| base::CommandLine command_line(base::size(argv), argv); |
| |
| brillo::FlagHelper::GetInstance()->set_command_line_for_testing( |
| &command_line); |
| |
| FILE* orig = stdout; |
| stdout = stderr; |
| |
| ASSERT_EXIT( |
| brillo::FlagHelper::Init(base::size(argv), argv, "TestUint32ParseError"), |
| ::testing::ExitedWithCode(EX_DATAERR), |
| "ERROR: illegal value '4294967296' specified for uint32 flag " |
| "'uint32_1'"); |
| |
| stdout = orig; |
| } |
| |
| // Test that when passing an incorrect/unparsable type to a command line flag, |
| // the program exits with code EX_DATAERR and outputs a corresponding message. |
| TEST_F(FlagHelperTest, Uint32ParseErrorNegativeValue) { |
| DEFINE_uint32(uint32_1, 0, "Test uint32 flag"); |
| |
| const char* argv[] = {"test_program", "--uint32_1=-1"}; |
| base::CommandLine command_line(base::size(argv), argv); |
| |
| brillo::FlagHelper::GetInstance()->set_command_line_for_testing( |
| &command_line); |
| |
| FILE* orig = stdout; |
| stdout = stderr; |
| |
| ASSERT_EXIT( |
| brillo::FlagHelper::Init(base::size(argv), argv, "TestUint32ParseError"), |
| ::testing::ExitedWithCode(EX_DATAERR), |
| "ERROR: illegal value '-1' specified for uint32 flag " |
| "'uint32_1'"); |
| |
| stdout = orig; |
| } |
| |
| // Test that when passing an incorrect/unparsable type to a command line flag, |
| // the program exits with code EX_DATAERR and outputs a corresponding message. |
| TEST_F(FlagHelperTest, Int64ParseError) { |
| DEFINE_int64(int64_1, 0, "Test int64 flag"); |
| |
| const char* argv[] = {"test_program", "--int64_1=value"}; |
| base::CommandLine command_line(base::size(argv), argv); |
| |
| brillo::FlagHelper::GetInstance()->set_command_line_for_testing( |
| &command_line); |
| |
| FILE* orig = stdout; |
| stdout = stderr; |
| |
| ASSERT_EXIT( |
| brillo::FlagHelper::Init(base::size(argv), argv, "TestInt64ParseError"), |
| ::testing::ExitedWithCode(EX_DATAERR), |
| "ERROR: illegal value 'value' specified for int64 flag " |
| "'int64_1'"); |
| |
| stdout = orig; |
| } |
| |
| // Test that when passing an incorrect/unparsable type to a command line flag, |
| // the program exits with code EX_DATAERR and outputs a corresponding message. |
| TEST_F(FlagHelperTest, UInt64ParseError) { |
| DEFINE_uint64(uint64_1, 0, "Test uint64 flag"); |
| |
| const char* argv[] = {"test_program", "--uint64_1=value"}; |
| base::CommandLine command_line(base::size(argv), argv); |
| |
| brillo::FlagHelper::GetInstance()->set_command_line_for_testing( |
| &command_line); |
| |
| FILE* orig = stdout; |
| stdout = stderr; |
| |
| ASSERT_EXIT( |
| brillo::FlagHelper::Init(base::size(argv), argv, "TestUInt64ParseError"), |
| ::testing::ExitedWithCode(EX_DATAERR), |
| "ERROR: illegal value 'value' specified for uint64 flag " |
| "'uint64_1'"); |
| |
| stdout = orig; |
| } |
| |
| } // namespace brillo |