• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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