2 * Copyright 2012 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/Subprocess.h"
19 #include <glog/logging.h>
20 #include <gtest/gtest.h>
22 #include "folly/Format.h"
23 #include "folly/experimental/io/Stream.h"
25 using namespace folly;
27 TEST(SimpleSubprocessTest, ExitsSuccessfully) {
28 Subprocess proc(std::vector<std::string>{ "/bin/true" });
29 EXPECT_EQ(0, proc.wait().exitStatus());
32 TEST(SimpleSubprocessTest, ExitsSuccessfullyChecked) {
33 Subprocess proc(std::vector<std::string>{ "/bin/true" });
37 TEST(SimpleSubprocessTest, ExitsWithError) {
38 Subprocess proc(std::vector<std::string>{ "/bin/false" });
39 EXPECT_EQ(1, proc.wait().exitStatus());
42 TEST(SimpleSubprocessTest, ExitsWithErrorChecked) {
43 Subprocess proc(std::vector<std::string>{ "/bin/false" });
44 EXPECT_THROW(proc.waitChecked(), CalledProcessError);
47 TEST(SimpleSubprocessTest, ShellExitsSuccesssfully) {
48 Subprocess proc("true");
49 EXPECT_EQ(0, proc.wait().exitStatus());
52 TEST(SimpleSubprocessTest, ShellExitsWithError) {
53 Subprocess proc("false");
54 EXPECT_EQ(1, proc.wait().exitStatus());
57 TEST(PopenSubprocessTest, PopenRead) {
58 Subprocess proc("ls /", Subprocess::pipeStdout());
60 for (auto bline : byLine(proc.stdout())) {
61 StringPiece line(bline);
62 if (line == "etc" || line == "bin" || line == "usr") {
70 TEST(CommunicateSubprocessTest, SimpleRead) {
71 Subprocess proc(std::vector<std::string>{ "/bin/echo", "-n", "foo", "bar"},
72 Subprocess::pipeStdout());
73 auto p = proc.communicate();
74 EXPECT_EQ("foo bar", p.first);
78 TEST(CommunicateSubprocessTest, BigWrite) {
79 const int numLines = 1 << 20;
80 std::string line("hello\n");
82 data.reserve(numLines * line.size());
83 for (int i = 0; i < numLines; ++i) {
87 Subprocess proc("wc -l", Subprocess::pipeStdin() | Subprocess::pipeStdout());
88 auto p = proc.communicate(Subprocess::writeStdin() | Subprocess::readStdout(),
90 EXPECT_EQ(folly::format("{}\n", numLines).str(), p.first);
94 TEST(CommunicateSubprocessTest, Duplex) {
95 // Take 10MB of data and pass them through a filter.
96 // One line, as tr is line-buffered
97 const int bytes = 10 << 20;
98 std::string line(bytes, 'x');
100 Subprocess proc("tr a-z A-Z",
101 Subprocess::pipeStdin() | Subprocess::pipeStdout());
102 auto p = proc.communicate(Subprocess::writeStdin() | Subprocess::readStdout(),
104 EXPECT_EQ(bytes, p.first.size());
105 EXPECT_EQ(std::string::npos, p.first.find_first_not_of('X'));