Don't expect .native() to return a string
[folly.git] / folly / experimental / test / NestedCommandLineAppTest.cpp
1 /*
2  * Copyright 2016 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/NestedCommandLineApp.h>
18
19 #include <folly/Subprocess.h>
20 #include <folly/experimental/io/FsUtil.h>
21 #include <folly/portability/GTest.h>
22 #include <glog/logging.h>
23
24 namespace folly { namespace test {
25
26 namespace {
27
28 std::string getHelperPath() {
29   const auto basename = "nested_command_line_app_test_helper";
30   auto path = fs::executable_path();
31   path.remove_filename() /= basename;
32   if (!fs::exists(path)) {
33     path = path.parent_path().parent_path() / basename / basename;
34   }
35   return path.string();
36 }
37
38 std::string callHelper(std::initializer_list<std::string> args,
39                        int expectedExitCode = 0,
40                        int stdoutFd = -1) {
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   Subprocess::Options options;
49   if (stdoutFd != -1) {
50     options.stdout(stdoutFd);
51   } else {
52     options.pipeStdout();
53   }
54   options.pipeStderr();
55
56   Subprocess proc(allArgs, options);
57   auto p = proc.communicate();
58   EXPECT_EQ(expectedExitCode, proc.wait().exitStatus());
59
60   return p.first;
61 }
62
63 }  // namespace
64
65 TEST(ProgramOptionsTest, Errors) {
66   callHelper({}, 1);
67   callHelper({"--wtf", "foo"}, 1);
68   callHelper({"qux"}, 1);
69   callHelper({"--global-foo", "x", "foo"}, 1);
70 }
71
72 TEST(ProgramOptionsTest, Help) {
73   // Not actually checking help output, just verifying that help doesn't fail
74   callHelper({"--version"});
75   callHelper({"--help"});
76   callHelper({"--help", "foo"});
77   callHelper({"--help", "bar"});
78   callHelper({"help"});
79   callHelper({"help", "foo"});
80   callHelper({"help", "bar"});
81
82   // wrong command name
83   callHelper({"--help", "qux"}, 1);
84   callHelper({"help", "qux"}, 1);
85 }
86
87 TEST(ProgramOptionsTest, DevFull) {
88   folly::File full("/dev/full", O_RDWR);
89   callHelper({"--help"}, 1, full.fd());
90 }
91
92 TEST(ProgramOptionsTest, Success) {
93   EXPECT_EQ(
94       "running foo\n"
95       "foo global-foo 42\n"
96       "foo local-foo 42\n",
97       callHelper({"foo"}));
98
99   EXPECT_EQ(
100       "running foo\n"
101       "foo global-foo 43\n"
102       "foo local-foo 44\n"
103       "foo arg a\n"
104       "foo arg b\n",
105       callHelper({"--global-foo", "43", "foo", "--local-foo", "44",
106                   "a", "b"}));
107
108   // Check that global flags can still be given after the command
109   EXPECT_EQ(
110       "running foo\n"
111       "foo global-foo 43\n"
112       "foo local-foo 44\n"
113       "foo arg a\n"
114       "foo arg b\n",
115       callHelper({"foo", "--global-foo", "43", "--local-foo", "44",
116                  "a", "b"}));
117 }
118
119 TEST(ProgramOptionsTest, Aliases) {
120   EXPECT_EQ(
121       "running foo\n"
122       "foo global-foo 43\n"
123       "foo local-foo 44\n"
124       "foo arg a\n"
125       "foo arg b\n",
126       callHelper({"--global-foo", "43", "bar", "--local-foo", "44",
127                   "a", "b"}));
128 }
129
130 }}  // namespaces