1 //
2 // Copyright 2019 The Abseil Authors.
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 // https://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15
16 #include "absl/flags/internal/commandlineflag.h"
17
18 #include <memory>
19 #include <string>
20
21 #include "gtest/gtest.h"
22 #include "absl/flags/flag.h"
23 #include "absl/flags/internal/registry.h"
24 #include "absl/flags/usage_config.h"
25 #include "absl/memory/memory.h"
26 #include "absl/strings/match.h"
27 #include "absl/strings/str_cat.h"
28 #include "absl/strings/string_view.h"
29
30 ABSL_FLAG(int, int_flag, 201, "int_flag help");
31 ABSL_FLAG(std::string, string_flag, "dflt",
32 absl::StrCat("string_flag", " help"));
33 ABSL_RETIRED_FLAG(bool, bool_retired_flag, false, "bool_retired_flag help");
34
35 namespace {
36
37 namespace flags = absl::flags_internal;
38
39 class CommandLineFlagTest : public testing::Test {
40 protected:
SetUpTestSuite()41 static void SetUpTestSuite() {
42 // Install a function to normalize filenames before this test is run.
43 absl::FlagsUsageConfig default_config;
44 default_config.normalize_filename = &CommandLineFlagTest::NormalizeFileName;
45 absl::SetFlagsUsageConfig(default_config);
46 }
47
SetUp()48 void SetUp() override { flag_saver_ = absl::make_unique<flags::FlagSaver>(); }
TearDown()49 void TearDown() override { flag_saver_.reset(); }
50
51 private:
NormalizeFileName(absl::string_view fname)52 static std::string NormalizeFileName(absl::string_view fname) {
53 #ifdef _WIN32
54 std::string normalized(fname);
55 std::replace(normalized.begin(), normalized.end(), '\\', '/');
56 fname = normalized;
57 #endif
58 return std::string(fname);
59 }
60
61 std::unique_ptr<flags::FlagSaver> flag_saver_;
62 };
63
TEST_F(CommandLineFlagTest,TestAttributesAccessMethods)64 TEST_F(CommandLineFlagTest, TestAttributesAccessMethods) {
65 auto* flag_01 = flags::FindCommandLineFlag("int_flag");
66
67 ASSERT_TRUE(flag_01);
68 EXPECT_EQ(flag_01->Name(), "int_flag");
69 EXPECT_EQ(flag_01->Help(), "int_flag help");
70 EXPECT_EQ(flag_01->Typename(), "");
71 EXPECT_TRUE(!flag_01->IsRetired());
72 EXPECT_TRUE(flag_01->IsOfType<int>());
73 EXPECT_TRUE(
74 absl::EndsWith(flag_01->Filename(),
75 "absl/flags/internal/commandlineflag_test.cc"))
76 << flag_01->Filename();
77
78 auto* flag_02 = flags::FindCommandLineFlag("string_flag");
79
80 ASSERT_TRUE(flag_02);
81 EXPECT_EQ(flag_02->Name(), "string_flag");
82 EXPECT_EQ(flag_02->Help(), "string_flag help");
83 EXPECT_EQ(flag_02->Typename(), "");
84 EXPECT_TRUE(!flag_02->IsRetired());
85 EXPECT_TRUE(flag_02->IsOfType<std::string>());
86 EXPECT_TRUE(
87 absl::EndsWith(flag_02->Filename(),
88 "absl/flags/internal/commandlineflag_test.cc"))
89 << flag_02->Filename();
90
91 auto* flag_03 = flags::FindRetiredFlag("bool_retired_flag");
92
93 ASSERT_TRUE(flag_03);
94 EXPECT_EQ(flag_03->Name(), "bool_retired_flag");
95 EXPECT_EQ(flag_03->Help(), "");
96 EXPECT_EQ(flag_03->Typename(), "");
97 EXPECT_TRUE(flag_03->IsRetired());
98 EXPECT_TRUE(flag_03->IsOfType<bool>());
99 EXPECT_EQ(flag_03->Filename(), "RETIRED");
100 }
101
102 // --------------------------------------------------------------------
103
TEST_F(CommandLineFlagTest,TestValueAccessMethods)104 TEST_F(CommandLineFlagTest, TestValueAccessMethods) {
105 absl::SetFlag(&FLAGS_int_flag, 301);
106 auto* flag_01 = flags::FindCommandLineFlag("int_flag");
107
108 ASSERT_TRUE(flag_01);
109 EXPECT_EQ(flag_01->CurrentValue(), "301");
110 EXPECT_EQ(flag_01->DefaultValue(), "201");
111
112 absl::SetFlag(&FLAGS_string_flag, "new_str_value");
113 auto* flag_02 = flags::FindCommandLineFlag("string_flag");
114
115 ASSERT_TRUE(flag_02);
116 EXPECT_EQ(flag_02->CurrentValue(), "new_str_value");
117 EXPECT_EQ(flag_02->DefaultValue(), "dflt");
118 }
119
120 // --------------------------------------------------------------------
121
TEST_F(CommandLineFlagTest,TestSetFromStringCurrentValue)122 TEST_F(CommandLineFlagTest, TestSetFromStringCurrentValue) {
123 std::string err;
124
125 auto* flag_01 = flags::FindCommandLineFlag("int_flag");
126 EXPECT_FALSE(flag_01->IsSpecifiedOnCommandLine());
127
128 EXPECT_TRUE(flag_01->SetFromString("11", flags::SET_FLAGS_VALUE,
129 flags::kProgrammaticChange, &err));
130 EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 11);
131 EXPECT_FALSE(flag_01->IsSpecifiedOnCommandLine());
132
133 EXPECT_TRUE(flag_01->SetFromString("-123", flags::SET_FLAGS_VALUE,
134 flags::kProgrammaticChange, &err));
135 EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), -123);
136 EXPECT_FALSE(flag_01->IsSpecifiedOnCommandLine());
137
138 EXPECT_TRUE(!flag_01->SetFromString("xyz", flags::SET_FLAGS_VALUE,
139 flags::kProgrammaticChange, &err));
140 EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), -123);
141 EXPECT_EQ(err, "Illegal value 'xyz' specified for flag 'int_flag'");
142 EXPECT_FALSE(flag_01->IsSpecifiedOnCommandLine());
143
144 EXPECT_TRUE(!flag_01->SetFromString("A1", flags::SET_FLAGS_VALUE,
145 flags::kProgrammaticChange, &err));
146 EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), -123);
147 EXPECT_EQ(err, "Illegal value 'A1' specified for flag 'int_flag'");
148 EXPECT_FALSE(flag_01->IsSpecifiedOnCommandLine());
149
150 EXPECT_TRUE(flag_01->SetFromString("0x10", flags::SET_FLAGS_VALUE,
151 flags::kProgrammaticChange, &err));
152 EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 16);
153 EXPECT_FALSE(flag_01->IsSpecifiedOnCommandLine());
154
155 EXPECT_TRUE(flag_01->SetFromString("011", flags::SET_FLAGS_VALUE,
156 flags::kCommandLine, &err));
157 EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 11);
158 EXPECT_TRUE(flag_01->IsSpecifiedOnCommandLine());
159
160 EXPECT_TRUE(!flag_01->SetFromString("", flags::SET_FLAGS_VALUE,
161 flags::kProgrammaticChange, &err));
162 EXPECT_EQ(err, "Illegal value '' specified for flag 'int_flag'");
163
164 auto* flag_02 = flags::FindCommandLineFlag("string_flag");
165 EXPECT_TRUE(flag_02->SetFromString("xyz", flags::SET_FLAGS_VALUE,
166 flags::kProgrammaticChange, &err));
167 EXPECT_EQ(absl::GetFlag(FLAGS_string_flag), "xyz");
168
169 EXPECT_TRUE(flag_02->SetFromString("", flags::SET_FLAGS_VALUE,
170 flags::kProgrammaticChange, &err));
171 EXPECT_EQ(absl::GetFlag(FLAGS_string_flag), "");
172 }
173
174 // --------------------------------------------------------------------
175
TEST_F(CommandLineFlagTest,TestSetFromStringDefaultValue)176 TEST_F(CommandLineFlagTest, TestSetFromStringDefaultValue) {
177 std::string err;
178
179 auto* flag_01 = flags::FindCommandLineFlag("int_flag");
180
181 EXPECT_TRUE(flag_01->SetFromString("111", flags::SET_FLAGS_DEFAULT,
182 flags::kProgrammaticChange, &err));
183 EXPECT_EQ(flag_01->DefaultValue(), "111");
184
185 auto* flag_02 = flags::FindCommandLineFlag("string_flag");
186
187 EXPECT_TRUE(flag_02->SetFromString("abc", flags::SET_FLAGS_DEFAULT,
188 flags::kProgrammaticChange, &err));
189 EXPECT_EQ(flag_02->DefaultValue(), "abc");
190 }
191
192 // --------------------------------------------------------------------
193
TEST_F(CommandLineFlagTest,TestSetFromStringIfDefault)194 TEST_F(CommandLineFlagTest, TestSetFromStringIfDefault) {
195 std::string err;
196
197 auto* flag_01 = flags::FindCommandLineFlag("int_flag");
198
199 EXPECT_TRUE(flag_01->SetFromString("22", flags::SET_FLAG_IF_DEFAULT,
200 flags::kProgrammaticChange, &err))
201 << err;
202 EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 22);
203
204 EXPECT_TRUE(flag_01->SetFromString("33", flags::SET_FLAG_IF_DEFAULT,
205 flags::kProgrammaticChange, &err));
206 EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 22);
207 // EXPECT_EQ(err, "ERROR: int_flag is already set to 22");
208
209 // Reset back to default value
210 EXPECT_TRUE(flag_01->SetFromString("201", flags::SET_FLAGS_VALUE,
211 flags::kProgrammaticChange, &err));
212
213 EXPECT_TRUE(flag_01->SetFromString("33", flags::SET_FLAG_IF_DEFAULT,
214 flags::kProgrammaticChange, &err));
215 EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 201);
216 // EXPECT_EQ(err, "ERROR: int_flag is already set to 201");
217 }
218
219 } // namespace
220