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