1 /*
2 * Copyright (c) Facebook, Inc. and its affiliates.
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 <folly/portability/GTest.h>
23
24 #include <glog/logging.h>
25
26 namespace folly {
27 namespace test {
28
29 namespace {
30
getHelperPath()31 std::string getHelperPath() {
32 const auto basename = "program_options_test_helper";
33 auto path = fs::executable_path();
34 path.remove_filename() /= basename;
35 if (!fs::exists(path)) {
36 path = path.parent_path().parent_path() / basename / basename;
37 }
38 return path.string();
39 }
40
callHelper(ProgramOptionsStyle style,std::initializer_list<std::string> args)41 std::string callHelper(
42 ProgramOptionsStyle style, std::initializer_list<std::string> args) {
43 static std::string helperPath = getHelperPath();
44
45 std::vector<std::string> allArgs;
46 allArgs.reserve(args.size() + 1);
47 allArgs.push_back(helperPath);
48 allArgs.insert(allArgs.end(), args.begin(), args.end());
49
50 std::vector<std::string> env;
51 switch (style) {
52 case ProgramOptionsStyle::GNU:
53 env.push_back("PROGRAM_OPTIONS_TEST_STYLE=GNU");
54 break;
55 case ProgramOptionsStyle::GFLAGS:
56 env.push_back("PROGRAM_OPTIONS_TEST_STYLE=GFLAGS");
57 break;
58 }
59
60 Subprocess proc(allArgs, Subprocess::Options().pipeStdout(), nullptr, &env);
61 auto p = proc.communicate();
62 EXPECT_EQ(0, proc.wait().exitStatus());
63
64 return p.first;
65 }
66
67 } // namespace
68
69 // name value
70
TEST(ProgramOptionsTest,GFlagsStyleDefaultValues)71 TEST(ProgramOptionsTest, GFlagsStyleDefaultValues) {
72 EXPECT_EQ(
73 "flag_bool_true 1\n"
74 "flag_bool_false 0\n"
75 "flag_int 42\n"
76 "flag_string foo\n",
77 callHelper(ProgramOptionsStyle::GFLAGS, {}));
78 }
79
TEST(ProgramOptionsTest,GFlagsStyleFlagsSet)80 TEST(ProgramOptionsTest, GFlagsStyleFlagsSet) {
81 EXPECT_EQ(
82 "flag_bool_true 1\n"
83 "flag_bool_false 1\n"
84 "flag_int 43\n"
85 "flag_string bar\n",
86 callHelper(
87 ProgramOptionsStyle::GFLAGS,
88 {
89 "--flag_bool_true",
90 "--flag_bool_false",
91 "--flag_int",
92 "43",
93 "--flag_string",
94 "bar",
95 }));
96 }
97
TEST(ProgramOptionsTest,GFlagsStyleBoolFlagsNegation)98 TEST(ProgramOptionsTest, GFlagsStyleBoolFlagsNegation) {
99 EXPECT_EQ(
100 "flag_bool_true 0\n"
101 "flag_bool_false 0\n"
102 "flag_int 42\n"
103 "flag_string foo\n",
104 callHelper(
105 ProgramOptionsStyle::GFLAGS,
106 {
107 "--noflag_bool_true",
108 "--noflag_bool_false",
109 }));
110 }
111
TEST(ProgramOptionsTest,GNUStyleDefaultValues)112 TEST(ProgramOptionsTest, GNUStyleDefaultValues) {
113 EXPECT_EQ(
114 "flag-bool-true 1\n"
115 "flag-bool-false 0\n"
116 "flag-int 42\n"
117 "flag-string foo\n",
118 callHelper(ProgramOptionsStyle::GNU, {}));
119 }
120
TEST(ProgramOptionsTest,GNUStyleFlagsSet)121 TEST(ProgramOptionsTest, GNUStyleFlagsSet) {
122 EXPECT_EQ(
123 "flag-bool-true 1\n"
124 "flag-bool-false 1\n"
125 "flag-int 43\n"
126 "flag-string bar\n",
127 callHelper(
128 ProgramOptionsStyle::GNU,
129 {
130 "--flag-bool-true",
131 "--flag-bool-false",
132 "--flag-int",
133 "43",
134 "--flag-string",
135 "bar",
136 }));
137 }
138
TEST(ProgramOptionsTest,GNUStyleBoolFlagsNegation)139 TEST(ProgramOptionsTest, GNUStyleBoolFlagsNegation) {
140 EXPECT_EQ(
141 "flag-bool-true 0\n"
142 "flag-bool-false 0\n"
143 "flag-int 42\n"
144 "flag-string foo\n",
145 callHelper(
146 ProgramOptionsStyle::GNU,
147 {
148 "--no-flag-bool-true",
149 "--no-flag-bool-false",
150 }));
151 }
152
TEST(ProgramOptionsTest,GNUStyleSubCommand)153 TEST(ProgramOptionsTest, GNUStyleSubCommand) {
154 EXPECT_EQ(
155 "flag-bool-true 1\n"
156 "flag-bool-false 1\n"
157 "flag-int 43\n"
158 "flag-string foo\n"
159 "command hello\n"
160 "arg --wtf\n"
161 "arg 100\n"
162 "arg -x\n"
163 "arg -xy\n",
164 callHelper(
165 ProgramOptionsStyle::GNU,
166 {
167 "--flag-bool-false",
168 "hello",
169 "--wtf",
170 "--flag-int",
171 "43",
172 "100",
173 "-x",
174 "-xy",
175 }));
176 }
177
TEST(ProgramOptionsTest,GNUStyleSubCommandUnrecognizedOptionFirst)178 TEST(ProgramOptionsTest, GNUStyleSubCommandUnrecognizedOptionFirst) {
179 EXPECT_EQ(
180 "flag-bool-true 1\n"
181 "flag-bool-false 1\n"
182 "flag-int 43\n"
183 "flag-string foo\n"
184 "arg --wtf\n"
185 "arg hello\n"
186 "arg 100\n"
187 "arg -x\n"
188 "arg -xy\n",
189 callHelper(
190 ProgramOptionsStyle::GNU,
191 {
192 "--flag-bool-false",
193 "--wtf",
194 "hello",
195 "--flag-int",
196 "43",
197 "100",
198 "-x",
199 "-xy",
200 }));
201 }
202
203 } // namespace test
204 } // namespace folly
205