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