2 * Copyright 2015-present Facebook, Inc.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #include <folly/experimental/NestedCommandLineApp.h>
19 #include <folly/Subprocess.h>
20 #include <folly/experimental/io/FsUtil.h>
21 #include <folly/portability/GTest.h>
22 #include <glog/logging.h>
24 namespace folly { namespace test {
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;
38 std::string callHelper(std::initializer_list<std::string> args,
39 int expectedExitCode = 0,
41 static std::string helperPath = getHelperPath();
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());
48 Subprocess::Options options;
50 options.stdoutFd(stdoutFd);
56 Subprocess proc(allArgs, options);
57 auto p = proc.communicate();
58 EXPECT_EQ(expectedExitCode, proc.wait().exitStatus());
65 TEST(ProgramOptionsTest, Errors) {
67 callHelper({"--wtf", "foo"}, 1);
68 callHelper({"qux"}, 1);
69 callHelper({"--global-foo", "x", "foo"}, 1);
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", "--", "bar"});
80 callHelper({"help", "foo"});
81 callHelper({"help", "bar"});
84 callHelper({"--help", "qux"}, 1);
85 callHelper({"help", "qux"}, 1);
87 // anything after -- is parsed as arguments
88 callHelper({"--", "help", "bar"}, 1);
91 TEST(ProgramOptionsTest, DevFull) {
92 folly::File full("/dev/full", O_RDWR);
93 callHelper({"--help"}, 1, full.fd());
96 TEST(ProgramOptionsTest, CutArguments) {
97 // anything after -- is parsed as arguments
100 "foo global-foo 43\n"
103 "foo arg --local-foo\n"
107 {"foo", "--global-foo", "43", "--", "b", "--local-foo", "44", "a"}));
110 TEST(ProgramOptionsTest, Success) {
113 "foo global-foo 42\n"
114 "foo local-foo 42\n",
115 callHelper({"foo"}));
119 "foo global-foo 43\n"
123 callHelper({"--global-foo", "43", "foo", "--local-foo", "44",
126 // Check that global flags can still be given after the command
129 "foo global-foo 43\n"
133 callHelper({"foo", "--global-foo", "43", "--local-foo", "44",
137 TEST(ProgramOptionsTest, Aliases) {
140 "foo global-foo 43\n"
144 callHelper({"--global-foo", "43", "bar", "--local-foo", "44",