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