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/Gen.h"
24 #include "folly/experimental/FileGen.h"
25 #include "folly/experimental/StringGen.h"
27 using namespace folly;
29 TEST(SimpleSubprocessTest, ExitsSuccessfully) {
30 Subprocess proc(std::vector<std::string>{ "/bin/true" });
31 EXPECT_EQ(0, proc.wait().exitStatus());
34 TEST(SimpleSubprocessTest, ExitsSuccessfullyChecked) {
35 Subprocess proc(std::vector<std::string>{ "/bin/true" });
39 TEST(SimpleSubprocessTest, ExitsWithError) {
40 Subprocess proc(std::vector<std::string>{ "/bin/false" });
41 EXPECT_EQ(1, proc.wait().exitStatus());
44 TEST(SimpleSubprocessTest, ExitsWithErrorChecked) {
45 Subprocess proc(std::vector<std::string>{ "/bin/false" });
46 EXPECT_THROW(proc.waitChecked(), CalledProcessError);
49 TEST(SimpleSubprocessTest, ShellExitsSuccesssfully) {
50 Subprocess proc("true");
51 EXPECT_EQ(0, proc.wait().exitStatus());
54 TEST(SimpleSubprocessTest, ShellExitsWithError) {
55 Subprocess proc("false");
56 EXPECT_EQ(1, proc.wait().exitStatus());
59 TEST(PopenSubprocessTest, PopenRead) {
60 Subprocess proc("ls /", Subprocess::pipeStdout());
62 gen::byLine(proc.stdout()) | gen::eachAs<StringPiece>() |
63 [&] (StringPiece line) {
64 if (line == "etc" || line == "bin" || line == "usr") {
72 TEST(CommunicateSubprocessTest, SimpleRead) {
73 Subprocess proc(std::vector<std::string>{ "/bin/echo", "-n", "foo", "bar"},
74 Subprocess::pipeStdout());
75 auto p = proc.communicate();
76 EXPECT_EQ("foo bar", p.first);
80 TEST(CommunicateSubprocessTest, BigWrite) {
81 const int numLines = 1 << 20;
82 std::string line("hello\n");
84 data.reserve(numLines * line.size());
85 for (int i = 0; i < numLines; ++i) {
89 Subprocess proc("wc -l", Subprocess::pipeStdin() | Subprocess::pipeStdout());
90 auto p = proc.communicate(Subprocess::writeStdin() | Subprocess::readStdout(),
92 EXPECT_EQ(folly::format("{}\n", numLines).str(), p.first);
96 TEST(CommunicateSubprocessTest, Duplex) {
97 // Take 10MB of data and pass them through a filter.
98 // One line, as tr is line-buffered
99 const int bytes = 10 << 20;
100 std::string line(bytes, 'x');
102 Subprocess proc("tr a-z A-Z",
103 Subprocess::pipeStdin() | Subprocess::pipeStdout());
104 auto p = proc.communicate(Subprocess::writeStdin() | Subprocess::readStdout(),
106 EXPECT_EQ(bytes, p.first.size());
107 EXPECT_EQ(std::string::npos, p.first.find_first_not_of('X'));