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/usage.h"
17
18 #include <stdint.h>
19
20 #include <sstream>
21 #include <string>
22
23 #include "gtest/gtest.h"
24 #include "absl/flags/flag.h"
25 #include "absl/flags/internal/parse.h"
26 #include "absl/flags/internal/path_util.h"
27 #include "absl/flags/internal/program_name.h"
28 #include "absl/flags/reflection.h"
29 #include "absl/flags/usage.h"
30 #include "absl/flags/usage_config.h"
31 #include "absl/strings/match.h"
32 #include "absl/strings/string_view.h"
33
34 ABSL_FLAG(int, usage_reporting_test_flag_01, 101,
35 "usage_reporting_test_flag_01 help message");
36 ABSL_FLAG(bool, usage_reporting_test_flag_02, false,
37 "usage_reporting_test_flag_02 help message");
38 ABSL_FLAG(double, usage_reporting_test_flag_03, 1.03,
39 "usage_reporting_test_flag_03 help message");
40 ABSL_FLAG(int64_t, usage_reporting_test_flag_04, 1000000000000004L,
41 "usage_reporting_test_flag_04 help message");
42
43 static const char kTestUsageMessage[] = "Custom usage message";
44
45 struct UDT {
46 UDT() = default;
47 UDT(const UDT&) = default;
48 };
AbslParseFlag(absl::string_view,UDT *,std::string *)49 bool AbslParseFlag(absl::string_view, UDT*, std::string*) { return true; }
AbslUnparseFlag(const UDT &)50 std::string AbslUnparseFlag(const UDT&) { return "UDT{}"; }
51
52 ABSL_FLAG(UDT, usage_reporting_test_flag_05, {},
53 "usage_reporting_test_flag_05 help message");
54
55 ABSL_FLAG(
56 std::string, usage_reporting_test_flag_06, {},
57 "usage_reporting_test_flag_06 help message.\n"
58 "\n"
59 "Some more help.\n"
60 "Even more long long long long long long long long long long long long "
61 "help message.");
62
63 namespace {
64
65 namespace flags = absl::flags_internal;
66
NormalizeFileName(absl::string_view fname)67 static std::string NormalizeFileName(absl::string_view fname) {
68 #ifdef _WIN32
69 std::string normalized(fname);
70 std::replace(normalized.begin(), normalized.end(), '\\', '/');
71 fname = normalized;
72 #endif
73
74 auto absl_pos = fname.rfind("absl/");
75 if (absl_pos != absl::string_view::npos) {
76 fname = fname.substr(absl_pos);
77 }
78 return std::string(fname);
79 }
80
81 class UsageReportingTest : public testing::Test {
82 protected:
UsageReportingTest()83 UsageReportingTest() {
84 // Install default config for the use on this unit test.
85 // Binary may install a custom config before tests are run.
86 absl::FlagsUsageConfig default_config;
87 default_config.normalize_filename = &NormalizeFileName;
88 absl::SetFlagsUsageConfig(default_config);
89 }
~UsageReportingTest()90 ~UsageReportingTest() override {
91 flags::SetFlagsHelpMode(flags::HelpMode::kNone);
92 flags::SetFlagsHelpMatchSubstr("");
93 flags::SetFlagsHelpFormat(flags::HelpFormat::kHumanReadable);
94 }
95
96 private:
97 absl::FlagSaver flag_saver_;
98 };
99
100 // --------------------------------------------------------------------
101
102 using UsageReportingDeathTest = UsageReportingTest;
103
TEST_F(UsageReportingDeathTest,TestSetProgramUsageMessage)104 TEST_F(UsageReportingDeathTest, TestSetProgramUsageMessage) {
105 EXPECT_EQ(absl::ProgramUsageMessage(), kTestUsageMessage);
106
107 #ifndef _WIN32
108 // TODO(rogeeff): figure out why this does not work on Windows.
109 EXPECT_DEATH_IF_SUPPORTED(
110 absl::SetProgramUsageMessage("custom usage message"),
111 ".*SetProgramUsageMessage\\(\\) called twice.*");
112 #endif
113 }
114
115 // --------------------------------------------------------------------
116
TEST_F(UsageReportingTest,TestFlagHelpHRF_on_flag_01)117 TEST_F(UsageReportingTest, TestFlagHelpHRF_on_flag_01) {
118 const auto* flag = absl::FindCommandLineFlag("usage_reporting_test_flag_01");
119 std::stringstream test_buf;
120
121 flags::FlagHelp(test_buf, *flag, flags::HelpFormat::kHumanReadable);
122 EXPECT_EQ(
123 test_buf.str(),
124 R"( --usage_reporting_test_flag_01 (usage_reporting_test_flag_01 help message);
125 default: 101;
126 )");
127 }
128
TEST_F(UsageReportingTest,TestFlagHelpHRF_on_flag_02)129 TEST_F(UsageReportingTest, TestFlagHelpHRF_on_flag_02) {
130 const auto* flag = absl::FindCommandLineFlag("usage_reporting_test_flag_02");
131 std::stringstream test_buf;
132
133 flags::FlagHelp(test_buf, *flag, flags::HelpFormat::kHumanReadable);
134 EXPECT_EQ(
135 test_buf.str(),
136 R"( --usage_reporting_test_flag_02 (usage_reporting_test_flag_02 help message);
137 default: false;
138 )");
139 }
140
TEST_F(UsageReportingTest,TestFlagHelpHRF_on_flag_03)141 TEST_F(UsageReportingTest, TestFlagHelpHRF_on_flag_03) {
142 const auto* flag = absl::FindCommandLineFlag("usage_reporting_test_flag_03");
143 std::stringstream test_buf;
144
145 flags::FlagHelp(test_buf, *flag, flags::HelpFormat::kHumanReadable);
146 EXPECT_EQ(
147 test_buf.str(),
148 R"( --usage_reporting_test_flag_03 (usage_reporting_test_flag_03 help message);
149 default: 1.03;
150 )");
151 }
152
TEST_F(UsageReportingTest,TestFlagHelpHRF_on_flag_04)153 TEST_F(UsageReportingTest, TestFlagHelpHRF_on_flag_04) {
154 const auto* flag = absl::FindCommandLineFlag("usage_reporting_test_flag_04");
155 std::stringstream test_buf;
156
157 flags::FlagHelp(test_buf, *flag, flags::HelpFormat::kHumanReadable);
158 EXPECT_EQ(
159 test_buf.str(),
160 R"( --usage_reporting_test_flag_04 (usage_reporting_test_flag_04 help message);
161 default: 1000000000000004;
162 )");
163 }
164
TEST_F(UsageReportingTest,TestFlagHelpHRF_on_flag_05)165 TEST_F(UsageReportingTest, TestFlagHelpHRF_on_flag_05) {
166 const auto* flag = absl::FindCommandLineFlag("usage_reporting_test_flag_05");
167 std::stringstream test_buf;
168
169 flags::FlagHelp(test_buf, *flag, flags::HelpFormat::kHumanReadable);
170 EXPECT_EQ(
171 test_buf.str(),
172 R"( --usage_reporting_test_flag_05 (usage_reporting_test_flag_05 help message);
173 default: UDT{};
174 )");
175 }
176
177 // --------------------------------------------------------------------
178
TEST_F(UsageReportingTest,TestFlagsHelpHRF)179 TEST_F(UsageReportingTest, TestFlagsHelpHRF) {
180 std::string usage_test_flags_out =
181 R"(usage_test: Custom usage message
182
183 Flags from absl/flags/internal/usage_test.cc:
184 --usage_reporting_test_flag_01 (usage_reporting_test_flag_01 help message);
185 default: 101;
186 --usage_reporting_test_flag_02 (usage_reporting_test_flag_02 help message);
187 default: false;
188 --usage_reporting_test_flag_03 (usage_reporting_test_flag_03 help message);
189 default: 1.03;
190 --usage_reporting_test_flag_04 (usage_reporting_test_flag_04 help message);
191 default: 1000000000000004;
192 --usage_reporting_test_flag_05 (usage_reporting_test_flag_05 help message);
193 default: UDT{};
194 --usage_reporting_test_flag_06 (usage_reporting_test_flag_06 help message.
195
196 Some more help.
197 Even more long long long long long long long long long long long long help
198 message.); default: "";
199
200 Try --helpfull to get a list of all flags or --help=substring shows help for
201 flags which include specified substring in either in the name, or description or
202 path.
203 )";
204
205 std::stringstream test_buf_01;
206 flags::FlagsHelp(test_buf_01, "usage_test.cc",
207 flags::HelpFormat::kHumanReadable, kTestUsageMessage);
208 EXPECT_EQ(test_buf_01.str(), usage_test_flags_out);
209
210 std::stringstream test_buf_02;
211 flags::FlagsHelp(test_buf_02, "flags/internal/usage_test.cc",
212 flags::HelpFormat::kHumanReadable, kTestUsageMessage);
213 EXPECT_EQ(test_buf_02.str(), usage_test_flags_out);
214
215 std::stringstream test_buf_03;
216 flags::FlagsHelp(test_buf_03, "usage_test", flags::HelpFormat::kHumanReadable,
217 kTestUsageMessage);
218 EXPECT_EQ(test_buf_03.str(), usage_test_flags_out);
219
220 std::stringstream test_buf_04;
221 flags::FlagsHelp(test_buf_04, "flags/invalid_file_name.cc",
222 flags::HelpFormat::kHumanReadable, kTestUsageMessage);
223 EXPECT_EQ(test_buf_04.str(),
224 R"(usage_test: Custom usage message
225
226 No flags matched.
227
228 Try --helpfull to get a list of all flags or --help=substring shows help for
229 flags which include specified substring in either in the name, or description or
230 path.
231 )");
232
233 std::stringstream test_buf_05;
234 flags::FlagsHelp(test_buf_05, "", flags::HelpFormat::kHumanReadable,
235 kTestUsageMessage);
236 std::string test_out = test_buf_05.str();
237 absl::string_view test_out_str(test_out);
238 EXPECT_TRUE(
239 absl::StartsWith(test_out_str, "usage_test: Custom usage message"));
240 EXPECT_TRUE(absl::StrContains(
241 test_out_str, "Flags from absl/flags/internal/usage_test.cc:"));
242 EXPECT_TRUE(
243 absl::StrContains(test_out_str, "-usage_reporting_test_flag_01 "));
244 }
245
246 // --------------------------------------------------------------------
247
TEST_F(UsageReportingTest,TestNoUsageFlags)248 TEST_F(UsageReportingTest, TestNoUsageFlags) {
249 std::stringstream test_buf;
250 EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage), -1);
251 }
252
253 // --------------------------------------------------------------------
254
TEST_F(UsageReportingTest,TestUsageFlag_helpshort)255 TEST_F(UsageReportingTest, TestUsageFlag_helpshort) {
256 flags::SetFlagsHelpMode(flags::HelpMode::kShort);
257
258 std::stringstream test_buf;
259 EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage), 1);
260 EXPECT_EQ(test_buf.str(),
261 R"(usage_test: Custom usage message
262
263 Flags from absl/flags/internal/usage_test.cc:
264 --usage_reporting_test_flag_01 (usage_reporting_test_flag_01 help message);
265 default: 101;
266 --usage_reporting_test_flag_02 (usage_reporting_test_flag_02 help message);
267 default: false;
268 --usage_reporting_test_flag_03 (usage_reporting_test_flag_03 help message);
269 default: 1.03;
270 --usage_reporting_test_flag_04 (usage_reporting_test_flag_04 help message);
271 default: 1000000000000004;
272 --usage_reporting_test_flag_05 (usage_reporting_test_flag_05 help message);
273 default: UDT{};
274 --usage_reporting_test_flag_06 (usage_reporting_test_flag_06 help message.
275
276 Some more help.
277 Even more long long long long long long long long long long long long help
278 message.); default: "";
279
280 Try --helpfull to get a list of all flags or --help=substring shows help for
281 flags which include specified substring in either in the name, or description or
282 path.
283 )");
284 }
285
286 // --------------------------------------------------------------------
287
TEST_F(UsageReportingTest,TestUsageFlag_help_simple)288 TEST_F(UsageReportingTest, TestUsageFlag_help_simple) {
289 flags::SetFlagsHelpMode(flags::HelpMode::kImportant);
290
291 std::stringstream test_buf;
292 EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage), 1);
293 EXPECT_EQ(test_buf.str(),
294 R"(usage_test: Custom usage message
295
296 Flags from absl/flags/internal/usage_test.cc:
297 --usage_reporting_test_flag_01 (usage_reporting_test_flag_01 help message);
298 default: 101;
299 --usage_reporting_test_flag_02 (usage_reporting_test_flag_02 help message);
300 default: false;
301 --usage_reporting_test_flag_03 (usage_reporting_test_flag_03 help message);
302 default: 1.03;
303 --usage_reporting_test_flag_04 (usage_reporting_test_flag_04 help message);
304 default: 1000000000000004;
305 --usage_reporting_test_flag_05 (usage_reporting_test_flag_05 help message);
306 default: UDT{};
307 --usage_reporting_test_flag_06 (usage_reporting_test_flag_06 help message.
308
309 Some more help.
310 Even more long long long long long long long long long long long long help
311 message.); default: "";
312
313 Try --helpfull to get a list of all flags or --help=substring shows help for
314 flags which include specified substring in either in the name, or description or
315 path.
316 )");
317 }
318
319 // --------------------------------------------------------------------
320
TEST_F(UsageReportingTest,TestUsageFlag_help_one_flag)321 TEST_F(UsageReportingTest, TestUsageFlag_help_one_flag) {
322 flags::SetFlagsHelpMode(flags::HelpMode::kMatch);
323 flags::SetFlagsHelpMatchSubstr("usage_reporting_test_flag_06");
324
325 std::stringstream test_buf;
326 EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage), 1);
327 EXPECT_EQ(test_buf.str(),
328 R"(usage_test: Custom usage message
329
330 Flags from absl/flags/internal/usage_test.cc:
331 --usage_reporting_test_flag_06 (usage_reporting_test_flag_06 help message.
332
333 Some more help.
334 Even more long long long long long long long long long long long long help
335 message.); default: "";
336
337 Try --helpfull to get a list of all flags or --help=substring shows help for
338 flags which include specified substring in either in the name, or description or
339 path.
340 )");
341 }
342
343 // --------------------------------------------------------------------
344
TEST_F(UsageReportingTest,TestUsageFlag_help_multiple_flag)345 TEST_F(UsageReportingTest, TestUsageFlag_help_multiple_flag) {
346 flags::SetFlagsHelpMode(flags::HelpMode::kMatch);
347 flags::SetFlagsHelpMatchSubstr("test_flag");
348
349 std::stringstream test_buf;
350 EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage), 1);
351 EXPECT_EQ(test_buf.str(),
352 R"(usage_test: Custom usage message
353
354 Flags from absl/flags/internal/usage_test.cc:
355 --usage_reporting_test_flag_01 (usage_reporting_test_flag_01 help message);
356 default: 101;
357 --usage_reporting_test_flag_02 (usage_reporting_test_flag_02 help message);
358 default: false;
359 --usage_reporting_test_flag_03 (usage_reporting_test_flag_03 help message);
360 default: 1.03;
361 --usage_reporting_test_flag_04 (usage_reporting_test_flag_04 help message);
362 default: 1000000000000004;
363 --usage_reporting_test_flag_05 (usage_reporting_test_flag_05 help message);
364 default: UDT{};
365 --usage_reporting_test_flag_06 (usage_reporting_test_flag_06 help message.
366
367 Some more help.
368 Even more long long long long long long long long long long long long help
369 message.); default: "";
370
371 Try --helpfull to get a list of all flags or --help=substring shows help for
372 flags which include specified substring in either in the name, or description or
373 path.
374 )");
375 }
376
377 // --------------------------------------------------------------------
378
TEST_F(UsageReportingTest,TestUsageFlag_helppackage)379 TEST_F(UsageReportingTest, TestUsageFlag_helppackage) {
380 flags::SetFlagsHelpMode(flags::HelpMode::kPackage);
381
382 std::stringstream test_buf;
383 EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage), 1);
384 EXPECT_EQ(test_buf.str(),
385 R"(usage_test: Custom usage message
386
387 Flags from absl/flags/internal/usage_test.cc:
388 --usage_reporting_test_flag_01 (usage_reporting_test_flag_01 help message);
389 default: 101;
390 --usage_reporting_test_flag_02 (usage_reporting_test_flag_02 help message);
391 default: false;
392 --usage_reporting_test_flag_03 (usage_reporting_test_flag_03 help message);
393 default: 1.03;
394 --usage_reporting_test_flag_04 (usage_reporting_test_flag_04 help message);
395 default: 1000000000000004;
396 --usage_reporting_test_flag_05 (usage_reporting_test_flag_05 help message);
397 default: UDT{};
398 --usage_reporting_test_flag_06 (usage_reporting_test_flag_06 help message.
399
400 Some more help.
401 Even more long long long long long long long long long long long long help
402 message.); default: "";
403
404 Try --helpfull to get a list of all flags or --help=substring shows help for
405 flags which include specified substring in either in the name, or description or
406 path.
407 )");
408 }
409
410 // --------------------------------------------------------------------
411
TEST_F(UsageReportingTest,TestUsageFlag_version)412 TEST_F(UsageReportingTest, TestUsageFlag_version) {
413 flags::SetFlagsHelpMode(flags::HelpMode::kVersion);
414
415 std::stringstream test_buf;
416 EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage), 0);
417 #ifndef NDEBUG
418 EXPECT_EQ(test_buf.str(), "usage_test\nDebug build (NDEBUG not #defined)\n");
419 #else
420 EXPECT_EQ(test_buf.str(), "usage_test\n");
421 #endif
422 }
423
424 // --------------------------------------------------------------------
425
TEST_F(UsageReportingTest,TestUsageFlag_only_check_args)426 TEST_F(UsageReportingTest, TestUsageFlag_only_check_args) {
427 flags::SetFlagsHelpMode(flags::HelpMode::kOnlyCheckArgs);
428
429 std::stringstream test_buf;
430 EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage), 0);
431 EXPECT_EQ(test_buf.str(), "");
432 }
433
434 // --------------------------------------------------------------------
435
TEST_F(UsageReportingTest,TestUsageFlag_helpon)436 TEST_F(UsageReportingTest, TestUsageFlag_helpon) {
437 flags::SetFlagsHelpMode(flags::HelpMode::kMatch);
438 flags::SetFlagsHelpMatchSubstr("/bla-bla.");
439
440 std::stringstream test_buf_01;
441 EXPECT_EQ(flags::HandleUsageFlags(test_buf_01, kTestUsageMessage), 1);
442 EXPECT_EQ(test_buf_01.str(),
443 R"(usage_test: Custom usage message
444
445 No flags matched.
446
447 Try --helpfull to get a list of all flags or --help=substring shows help for
448 flags which include specified substring in either in the name, or description or
449 path.
450 )");
451
452 flags::SetFlagsHelpMatchSubstr("/usage_test.");
453
454 std::stringstream test_buf_02;
455 EXPECT_EQ(flags::HandleUsageFlags(test_buf_02, kTestUsageMessage), 1);
456 EXPECT_EQ(test_buf_02.str(),
457 R"(usage_test: Custom usage message
458
459 Flags from absl/flags/internal/usage_test.cc:
460 --usage_reporting_test_flag_01 (usage_reporting_test_flag_01 help message);
461 default: 101;
462 --usage_reporting_test_flag_02 (usage_reporting_test_flag_02 help message);
463 default: false;
464 --usage_reporting_test_flag_03 (usage_reporting_test_flag_03 help message);
465 default: 1.03;
466 --usage_reporting_test_flag_04 (usage_reporting_test_flag_04 help message);
467 default: 1000000000000004;
468 --usage_reporting_test_flag_05 (usage_reporting_test_flag_05 help message);
469 default: UDT{};
470 --usage_reporting_test_flag_06 (usage_reporting_test_flag_06 help message.
471
472 Some more help.
473 Even more long long long long long long long long long long long long help
474 message.); default: "";
475
476 Try --helpfull to get a list of all flags or --help=substring shows help for
477 flags which include specified substring in either in the name, or description or
478 path.
479 )");
480 }
481
482 // --------------------------------------------------------------------
483
484 } // namespace
485
main(int argc,char * argv[])486 int main(int argc, char* argv[]) {
487 (void)absl::GetFlag(FLAGS_undefok); // Force linking of parse.cc
488 flags::SetProgramInvocationName("usage_test");
489 absl::SetProgramUsageMessage(kTestUsageMessage);
490 ::testing::InitGoogleTest(&argc, argv);
491
492 return RUN_ALL_TESTS();
493 }
494