blob: 64ba11d7c032a92b8b69223637e8fef35c902e8d [file] [log] [blame]
// Copyright (c) 2018 The Chromium 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 "net/third_party/quic/platform/api/quic_flags.h"
#include "base/optional.h"
#include "base/stl_util.h"
#include "base/strings/strcat.h"
#include "base/strings/string16.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "net/third_party/quic/platform/api/quic_logging.h"
#include "net/third_party/quic/platform/api/quic_string.h"
#include "net/third_party/quic/platform/api/quic_test.h"
#include "net/third_party/quic/platform/impl/quic_flags_impl.h"
DEFINE_QUIC_COMMAND_LINE_FLAG(bool, foo, false, "An old silent pond...");
DEFINE_QUIC_COMMAND_LINE_FLAG(int32_t, bar, 123, "A frog jumps into the pond,");
DEFINE_QUIC_COMMAND_LINE_FLAG(quic::QuicString,
baz,
"splash!",
"Silence again.");
namespace quic {
namespace test {
class QuicCommandLineFlagTest : public QuicTest {
protected:
void SetUp() override { QuicFlagRegistry::GetInstance().ResetFlags(); }
static QuicParseCommandLineFlagsResult QuicParseCommandLineFlagsForTest(
const char* usage,
int argc,
const char* const* argv) {
base::CommandLine::StringVector v;
FillCommandLineArgs(argc, argv, &v);
return QuicParseCommandLineFlagsHelper(usage, base::CommandLine(v));
}
private:
// Overload for platforms where base::CommandLine::StringType == std::string.
static void FillCommandLineArgs(int argc,
const char* const* argv,
std::vector<std::string>* v) {
for (int i = 0; i < argc; ++i) {
v->push_back(argv[i]);
}
}
// Overload for platforms where base::CommandLine::StringType ==
// base::string16.
static void FillCommandLineArgs(int argc,
const char* const* argv,
std::vector<base::string16>* v) {
for (int i = 0; i < argc; ++i) {
v->push_back(base::UTF8ToUTF16(argv[i]));
}
}
};
TEST_F(QuicCommandLineFlagTest, DefaultValues) {
EXPECT_EQ(false, GetQuicFlag(FLAGS_foo));
EXPECT_EQ(123, GetQuicFlag(FLAGS_bar));
EXPECT_EQ("splash!", GetQuicFlag(FLAGS_baz));
}
TEST_F(QuicCommandLineFlagTest, NotSpecified) {
const char* argv[]{"one", "two", "three"};
auto parse_result =
QuicParseCommandLineFlagsForTest("usage message", base::size(argv), argv);
EXPECT_FALSE(parse_result.exit_status.has_value());
std::vector<QuicString> expected_args{"two", "three"};
EXPECT_EQ(expected_args, parse_result.non_flag_args);
EXPECT_EQ(false, GetQuicFlag(FLAGS_foo));
EXPECT_EQ(123, GetQuicFlag(FLAGS_bar));
EXPECT_EQ("splash!", GetQuicFlag(FLAGS_baz));
}
TEST_F(QuicCommandLineFlagTest, BoolFlag) {
for (const char* s :
{"--foo", "--foo=1", "--foo=t", "--foo=True", "--foo=Y", "--foo=yes"}) {
SetQuicFlag(&FLAGS_foo, false);
const char* argv[]{"argv0", s};
auto parse_result = QuicParseCommandLineFlagsForTest(
"usage message", base::size(argv), argv);
EXPECT_FALSE(parse_result.exit_status.has_value());
EXPECT_TRUE(parse_result.non_flag_args.empty());
EXPECT_TRUE(GetQuicFlag(FLAGS_foo));
}
for (const char* s :
{"--foo=0", "--foo=f", "--foo=False", "--foo=N", "--foo=no"}) {
SetQuicFlag(&FLAGS_foo, true);
const char* argv[]{"argv0", s};
auto parse_result = QuicParseCommandLineFlagsForTest(
"usage message", base::size(argv), argv);
EXPECT_FALSE(parse_result.exit_status.has_value());
EXPECT_TRUE(parse_result.non_flag_args.empty());
EXPECT_FALSE(GetQuicFlag(FLAGS_foo));
}
for (const char* s : {"--foo=7", "--foo=abc", "--foo=trueish"}) {
SetQuicFlag(&FLAGS_foo, false);
const char* argv[]{"argv0", s};
testing::internal::CaptureStderr();
auto parse_result = QuicParseCommandLineFlagsForTest(
"usage message", base::size(argv), argv);
std::string captured_stderr = testing::internal::GetCapturedStderr();
EXPECT_TRUE(parse_result.exit_status.has_value());
EXPECT_EQ(1, *parse_result.exit_status);
EXPECT_THAT(captured_stderr,
testing::ContainsRegex("Invalid value.*for flag --foo"));
EXPECT_TRUE(parse_result.non_flag_args.empty());
EXPECT_FALSE(GetQuicFlag(FLAGS_foo));
}
}
TEST_F(QuicCommandLineFlagTest, Int32Flag) {
for (const int i : {-1, 0, 100, 38239832}) {
SetQuicFlag(&FLAGS_bar, 0);
std::string flag_str = base::StringPrintf("--bar=%d", i);
const char* argv[]{"argv0", flag_str.c_str()};
auto parse_result = QuicParseCommandLineFlagsForTest(
"usage message", base::size(argv), argv);
EXPECT_FALSE(parse_result.exit_status.has_value());
EXPECT_TRUE(parse_result.non_flag_args.empty());
EXPECT_EQ(i, GetQuicFlag(FLAGS_bar));
}
for (const char* s : {"--bar", "--bar=a", "--bar=9999999999999"}) {
SetQuicFlag(&FLAGS_bar, 0);
const char* argv[]{"argv0", s};
testing::internal::CaptureStderr();
auto parse_result = QuicParseCommandLineFlagsForTest(
"usage message", base::size(argv), argv);
std::string captured_stderr = testing::internal::GetCapturedStderr();
EXPECT_TRUE(parse_result.exit_status.has_value());
EXPECT_EQ(1, *parse_result.exit_status);
EXPECT_THAT(captured_stderr,
testing::ContainsRegex("Invalid value.*for flag --bar"));
EXPECT_TRUE(parse_result.non_flag_args.empty());
EXPECT_EQ(0, GetQuicFlag(FLAGS_bar));
}
}
TEST_F(QuicCommandLineFlagTest, StringFlag) {
{
SetQuicFlag(&FLAGS_baz, "whee");
const char* argv[]{"argv0", "--baz"};
auto parse_result = QuicParseCommandLineFlagsForTest(
"usage message", base::size(argv), argv);
EXPECT_FALSE(parse_result.exit_status.has_value());
EXPECT_TRUE(parse_result.non_flag_args.empty());
EXPECT_EQ("", GetQuicFlag(FLAGS_baz));
}
for (const char* s : {"", "12345", "abcdefg"}) {
SetQuicFlag(&FLAGS_baz, "qux");
std::string flag_str = base::StrCat({"--baz=", s});
const char* argv[]{"argv0", flag_str.c_str()};
auto parse_result = QuicParseCommandLineFlagsForTest(
"usage message", base::size(argv), argv);
EXPECT_FALSE(parse_result.exit_status.has_value());
EXPECT_TRUE(parse_result.non_flag_args.empty());
EXPECT_EQ(s, GetQuicFlag(FLAGS_baz));
}
}
TEST_F(QuicCommandLineFlagTest, PrintHelp) {
testing::internal::CaptureStdout();
QuicPrintCommandLineFlagHelp("usage message");
std::string captured_stdout = testing::internal::GetCapturedStdout();
EXPECT_THAT(captured_stdout, testing::HasSubstr("usage message"));
EXPECT_THAT(captured_stdout,
testing::ContainsRegex("--help +Print this help message."));
EXPECT_THAT(captured_stdout,
testing::ContainsRegex("--foo +An old silent pond..."));
EXPECT_THAT(captured_stdout,
testing::ContainsRegex("--bar +A frog jumps into the pond,"));
EXPECT_THAT(captured_stdout, testing::ContainsRegex("--baz +Silence again."));
}
} // namespace test
} // namespace quic