Make gflags and boost::program_options play nice with each other
[folly.git] / folly / experimental / test / ProgramOptionsTest.cpp
1 /*
2  * Copyright 2015 Facebook, Inc.
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  *   http://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
17 #include <folly/experimental/ProgramOptions.h>
18
19 #include <folly/FileUtil.h>
20 #include <folly/Subprocess.h>
21 #include <folly/experimental/io/FsUtil.h>
22 #include <glog/logging.h>
23 #include <gtest/gtest.h>
24
25 namespace folly { namespace test {
26
27 namespace {
28
29 std::string getHelperPath() {
30   auto path = fs::executable_path();
31   path.remove_filename() /= "program_options_test_helper";
32   return path.native();
33 }
34
35 std::string callHelper(ProgramOptionsStyle style,
36                        std::initializer_list<std::string> args) {
37   static std::string helperPath = getHelperPath();
38
39   std::vector<std::string> allArgs;
40   allArgs.reserve(args.size() + 1);
41   allArgs.push_back(helperPath);
42   allArgs.insert(allArgs.end(), args.begin(), args.end());
43
44   std::vector<std::string> env;
45   switch (style) {
46   case ProgramOptionsStyle::GNU:
47     env.push_back("PROGRAM_OPTIONS_TEST_STYLE=GNU");
48     break;
49   case ProgramOptionsStyle::GFLAGS:
50     env.push_back("PROGRAM_OPTIONS_TEST_STYLE=GFLAGS");
51     break;
52   }
53
54   Subprocess proc(allArgs, Subprocess::pipeStdout(), nullptr, &env);
55   auto p = proc.communicate();
56   EXPECT_EQ(0, proc.wait().exitStatus());
57
58   return p.first;
59 }
60
61 }  // namespace
62
63 // name value
64
65 TEST(ProgramOptionsTest, GFlagsStyleDefaultValues) {
66   EXPECT_EQ(
67       "flag_bool_true 1\n"
68       "flag_bool_false 0\n"
69       "flag_int 42\n"
70       "flag_string foo\n",
71       callHelper(ProgramOptionsStyle::GFLAGS, {}));
72 }
73
74 TEST(ProgramOptionsTest, GFlagsStyleFlagsSet) {
75   EXPECT_EQ(
76       "flag_bool_true 1\n"
77       "flag_bool_false 1\n"
78       "flag_int 43\n"
79       "flag_string bar\n",
80       callHelper(ProgramOptionsStyle::GFLAGS, {
81           "--flag_bool_true",
82           "--flag_bool_false",
83           "--flag_int", "43",
84           "--flag_string", "bar"}));
85 }
86
87 TEST(ProgramOptionsTest, GFlagsStyleBoolFlagsNegation) {
88   EXPECT_EQ(
89       "flag_bool_true 0\n"
90       "flag_bool_false 0\n"
91       "flag_int 42\n"
92       "flag_string foo\n",
93       callHelper(ProgramOptionsStyle::GFLAGS, {
94           "--noflag_bool_true",
95           "--noflag_bool_false"}));
96 }
97
98 TEST(ProgramOptionsTest, GNUStyleDefaultValues) {
99   EXPECT_EQ(
100       "flag-bool-true 1\n"
101       "flag-bool-false 0\n"
102       "flag-int 42\n"
103       "flag-string foo\n",
104       callHelper(ProgramOptionsStyle::GNU, {}));
105 }
106
107 TEST(ProgramOptionsTest, GNUStyleFlagsSet) {
108   EXPECT_EQ(
109       "flag-bool-true 1\n"
110       "flag-bool-false 1\n"
111       "flag-int 43\n"
112       "flag-string bar\n",
113       callHelper(ProgramOptionsStyle::GNU, {
114           "--flag-bool-true",
115           "--flag-bool-false",
116           "--flag-int", "43",
117           "--flag-string", "bar"}));
118 }
119
120 TEST(ProgramOptionsTest, GNUStyleBoolFlagsNegation) {
121   EXPECT_EQ(
122       "flag-bool-true 0\n"
123       "flag-bool-false 0\n"
124       "flag-int 42\n"
125       "flag-string foo\n",
126       callHelper(ProgramOptionsStyle::GNU, {
127           "--no-flag-bool-true",
128           "--no-flag-bool-false"}));
129 }
130
131 TEST(ProgramOptionsTest, GNUStyleSubCommand) {
132   EXPECT_EQ(
133       "flag-bool-true 1\n"
134       "flag-bool-false 1\n"
135       "flag-int 43\n"
136       "flag-string foo\n"
137       "command hello\n"
138       "arg --wtf\n"
139       "arg 100\n"
140       "arg -x\n"
141       "arg -xy\n",
142       callHelper(ProgramOptionsStyle::GNU, {
143           "--flag-bool-false",
144           "hello",
145           "--wtf",
146           "--flag-int", "43",
147           "100",
148           "-x",
149           "-xy"}));
150 }
151
152 TEST(ProgramOptionsTest, GNUStyleSubCommandUnrecognizedOptionFirst) {
153   EXPECT_EQ(
154       "flag-bool-true 1\n"
155       "flag-bool-false 1\n"
156       "flag-int 43\n"
157       "flag-string foo\n"
158       "arg --wtf\n"
159       "arg hello\n"
160       "arg 100\n"
161       "arg -x\n"
162       "arg -xy\n",
163       callHelper(ProgramOptionsStyle::GNU, {
164           "--flag-bool-false",
165           "--wtf",
166           "hello",
167           "--flag-int", "43",
168           "100",
169           "-x",
170           "-xy"}));
171 }
172
173 }}  // namespaces