Home | History | Annotate | Download | only in platform
      1 /* Copyright 2016 The TensorFlow Authors. All Rights Reserved.
      2 
      3 Licensed under the Apache License, Version 2.0 (the "License");
      4 you may not use this file except in compliance with the License.
      5 You may obtain a copy of the License at
      6 
      7     http://www.apache.org/licenses/LICENSE-2.0
      8 
      9 Unless required by applicable law or agreed to in writing, software
     10 distributed under the License is distributed on an "AS IS" BASIS,
     11 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12 See the License for the specific language governing permissions and
     13 limitations under the License.
     14 ==============================================================================*/
     15 
     16 #include <sys/wait.h>
     17 
     18 #include "tensorflow/core/lib/core/status_test_util.h"
     19 #include "tensorflow/core/platform/subprocess.h"
     20 #include "tensorflow/core/platform/test.h"
     21 
     22 namespace tensorflow {
     23 
     24 class SubProcessTest : public ::testing::Test {};
     25 
     26 TEST_F(SubProcessTest, NoOutputNoComm) {
     27   tensorflow::SubProcess proc;
     28   proc.SetProgram("/bin/cat", {"cat", "/dev/null"});
     29   EXPECT_TRUE(proc.Start());
     30   EXPECT_TRUE(proc.Wait());
     31 }
     32 
     33 TEST_F(SubProcessTest, NoOutput) {
     34   tensorflow::SubProcess proc;
     35   proc.SetProgram("/bin/cat", {"cat", "/dev/null"});
     36   proc.SetChannelAction(CHAN_STDOUT, ACTION_PIPE);
     37   proc.SetChannelAction(CHAN_STDERR, ACTION_PIPE);
     38   EXPECT_TRUE(proc.Start());
     39 
     40   string out, err;
     41   int status = proc.Communicate(nullptr, &out, &err);
     42   EXPECT_TRUE(WIFEXITED(status));
     43   EXPECT_EQ(0, WEXITSTATUS(status));
     44   EXPECT_EQ("", out);
     45   EXPECT_EQ("", err);
     46 }
     47 
     48 TEST_F(SubProcessTest, Stdout) {
     49   tensorflow::SubProcess proc;
     50   proc.SetProgram("/bin/echo", {"echo", "-n", "hello world"});
     51   proc.SetChannelAction(CHAN_STDOUT, ACTION_PIPE);
     52   proc.SetChannelAction(CHAN_STDERR, ACTION_PIPE);
     53   EXPECT_TRUE(proc.Start());
     54 
     55   string out, err;
     56   int status = proc.Communicate(nullptr, &out, &err);
     57   EXPECT_TRUE(WIFEXITED(status));
     58   EXPECT_EQ(0, WEXITSTATUS(status));
     59   EXPECT_EQ("hello world", out);
     60   EXPECT_EQ("", err);
     61 }
     62 
     63 TEST_F(SubProcessTest, StdoutIgnored) {
     64   tensorflow::SubProcess proc;
     65   proc.SetProgram("/bin/echo", {"echo", "-n", "hello world"});
     66   proc.SetChannelAction(CHAN_STDOUT, ACTION_PIPE);
     67   proc.SetChannelAction(CHAN_STDERR, ACTION_PIPE);
     68   EXPECT_TRUE(proc.Start());
     69 
     70   int status = proc.Communicate(nullptr, nullptr, nullptr);
     71   EXPECT_TRUE(WIFEXITED(status));
     72   EXPECT_EQ(0, WEXITSTATUS(status));
     73 }
     74 
     75 TEST_F(SubProcessTest, Stderr) {
     76   tensorflow::SubProcess proc;
     77   proc.SetProgram("/bin/cat", {"cat", "/file_does_not_exist"});
     78   proc.SetChannelAction(CHAN_STDOUT, ACTION_PIPE);
     79   proc.SetChannelAction(CHAN_STDERR, ACTION_PIPE);
     80   EXPECT_TRUE(proc.Start());
     81 
     82   string out, err;
     83   int status = proc.Communicate(nullptr, &out, &err);
     84   EXPECT_TRUE(WIFEXITED(status));
     85   EXPECT_EQ(1, WEXITSTATUS(status));
     86   EXPECT_EQ("", out);
     87   EXPECT_NE(string::npos, err.find("/file_does_not_exist"));
     88 }
     89 
     90 TEST_F(SubProcessTest, StderrIgnored) {
     91   tensorflow::SubProcess proc;
     92   proc.SetProgram("/bin/cat", {"cat", "/file_does_not_exist"});
     93   proc.SetChannelAction(CHAN_STDOUT, ACTION_PIPE);
     94   proc.SetChannelAction(CHAN_STDERR, ACTION_PIPE);
     95   EXPECT_TRUE(proc.Start());
     96 
     97   int status = proc.Communicate(nullptr, nullptr, nullptr);
     98   EXPECT_TRUE(WIFEXITED(status));
     99   EXPECT_EQ(1, WEXITSTATUS(status));
    100 }
    101 
    102 TEST_F(SubProcessTest, Stdin) {
    103   tensorflow::SubProcess proc;
    104   proc.SetProgram("/usr/bin/wc", {"wc", "-l"});
    105   proc.SetChannelAction(CHAN_STDIN, ACTION_PIPE);
    106   EXPECT_TRUE(proc.Start());
    107 
    108   string in = "foobar\nbarfoo\nhaha\n";
    109   int status = proc.Communicate(&in, nullptr, nullptr);
    110   EXPECT_TRUE(WIFEXITED(status));
    111   EXPECT_EQ(0, WEXITSTATUS(status));
    112 }
    113 
    114 TEST_F(SubProcessTest, StdinStdout) {
    115   tensorflow::SubProcess proc;
    116   proc.SetProgram("/usr/bin/wc", {"wc", "-l"});
    117   proc.SetChannelAction(CHAN_STDIN, ACTION_PIPE);
    118   proc.SetChannelAction(CHAN_STDOUT, ACTION_PIPE);
    119   EXPECT_TRUE(proc.Start());
    120 
    121   string in = "foobar\nbarfoo\nhaha\n";
    122   string out;
    123   int status = proc.Communicate(&in, &out, nullptr);
    124   EXPECT_TRUE(WIFEXITED(status));
    125   EXPECT_EQ(0, WEXITSTATUS(status));
    126   int count = stoi(out);
    127   EXPECT_EQ(3, count);
    128 }
    129 
    130 TEST_F(SubProcessTest, StdinChildExit) {
    131   tensorflow::SubProcess proc;
    132   proc.SetProgram("/bin/sleep", {"sleep", "0"});
    133   proc.SetChannelAction(CHAN_STDIN, ACTION_PIPE);
    134   EXPECT_TRUE(proc.Start());
    135 
    136   // Verify that the parent handles the child exiting immediately as the
    137   // parent is trying to write a large string to the child's stdin.
    138   string in;
    139   in.reserve(1000000);
    140   for (int i = 0; i < 100000; i++) {
    141     in += "hello xyz\n";
    142   }
    143 
    144   int status = proc.Communicate(&in, nullptr, nullptr);
    145   EXPECT_TRUE(WIFEXITED(status));
    146   EXPECT_EQ(0, WEXITSTATUS(status));
    147 }
    148 
    149 TEST_F(SubProcessTest, StdinStdoutOverlap) {
    150   tensorflow::SubProcess proc;
    151   proc.SetProgram("/bin/cat", {"cat"});
    152   proc.SetChannelAction(CHAN_STDIN, ACTION_PIPE);
    153   proc.SetChannelAction(CHAN_STDOUT, ACTION_PIPE);
    154   EXPECT_TRUE(proc.Start());
    155 
    156   // Verify that the parent handles multiplexed reading/writing to the child
    157   // process.  The string is large enough to exceed the buffering of the pipes.
    158   string in;
    159   in.reserve(1000000);
    160   for (int i = 0; i < 100000; i++) {
    161     in += "hello xyz\n";
    162   }
    163 
    164   string out;
    165   int status = proc.Communicate(&in, &out, nullptr);
    166   EXPECT_TRUE(WIFEXITED(status));
    167   EXPECT_EQ(0, WEXITSTATUS(status));
    168   EXPECT_EQ(in, out);
    169 }
    170 
    171 TEST_F(SubProcessTest, KillProc) {
    172   tensorflow::SubProcess proc;
    173   proc.SetProgram("/bin/cat", {"cat"});
    174   proc.SetChannelAction(CHAN_STDIN, ACTION_PIPE);
    175   proc.SetChannelAction(CHAN_STDOUT, ACTION_PIPE);
    176   EXPECT_TRUE(proc.Start());
    177 
    178   EXPECT_TRUE(proc.Kill(SIGKILL));
    179   EXPECT_TRUE(proc.Wait());
    180 
    181   EXPECT_FALSE(proc.Kill(SIGKILL));
    182 }
    183 
    184 }  // namespace tensorflow
    185