From cfe8b42b9102ea645bfc07019c2a6d27a0551f22 Mon Sep 17 00:00:00 2001 From: Gunhan Gulsoy Date: Wed, 29 Jan 2020 11:42:14 -0800 Subject: [PATCH] Make subprocess_test platform independent. PiperOrigin-RevId: 292186297 Change-Id: I18e7a03c2038e9024da4ec5f36438fb965df6b79 --- tensorflow/core/platform/BUILD | 7 ++ tensorflow/core/platform/subprocess_test.cc | 85 +++++++++++++++---- tensorflow/core/platform/testdata/BUILD | 30 +++++++ .../core/platform/testdata/test_echo.cc | 27 ++++++ .../platform/testdata/test_echo_argv_1.cc | 22 +++++ .../core/platform/testdata/test_noop.cc | 16 ++++ .../core/platform/testdata/test_stderr.cc | 21 +++++ 7 files changed, 191 insertions(+), 17 deletions(-) create mode 100644 tensorflow/core/platform/testdata/BUILD create mode 100644 tensorflow/core/platform/testdata/test_echo.cc create mode 100644 tensorflow/core/platform/testdata/test_echo_argv_1.cc create mode 100644 tensorflow/core/platform/testdata/test_noop.cc create mode 100644 tensorflow/core/platform/testdata/test_stderr.cc diff --git a/tensorflow/core/platform/BUILD b/tensorflow/core/platform/BUILD index 6cff37d226c..b5228312901 100644 --- a/tensorflow/core/platform/BUILD +++ b/tensorflow/core/platform/BUILD @@ -890,10 +890,17 @@ tf_cc_test( name = "subprocess_test", size = "small", srcs = ["subprocess_test.cc"], + data = [ + "//tensorflow/core/platform/testdata:test_echo", + "//tensorflow/core/platform/testdata:test_echo_argv_1", + "//tensorflow/core/platform/testdata:test_noop", + "//tensorflow/core/platform/testdata:test_stderr", + ], tags = [ "no_windows", ], deps = [ + ":strcat", ":subprocess", "//tensorflow/core:test", "//tensorflow/core:test_main", diff --git a/tensorflow/core/platform/subprocess_test.cc b/tensorflow/core/platform/subprocess_test.cc index 3d58b011cb5..b982f477ad0 100644 --- a/tensorflow/core/platform/subprocess_test.cc +++ b/tensorflow/core/platform/subprocess_test.cc @@ -13,26 +13,48 @@ See the License for the specific language governing permissions and limitations under the License. ==============================================================================*/ -#include +#include "tensorflow/core/platform/subprocess.h" + +#include +#include + +#include #include "tensorflow/core/lib/core/status_test_util.h" -#include "tensorflow/core/platform/subprocess.h" +#include "tensorflow/core/platform/strcat.h" #include "tensorflow/core/platform/test.h" +#ifdef PLATFORM_WINDOWS +#define WIFEXITED(code) ((code) != 3) +#define WEXITSTATUS(code) (code) +#define SIGKILL 9 +#else +#include +#endif + +const char kEchoProgram[] = "core/platform/testdata/test_echo"; +const char kEchoArgv1Program[] = "core/platform/testdata/test_echo_argv_1"; +const char kNoopProgram[] = "core/platform/testdata/test_noop"; +const char kStdErrProgram[] = "core/platform/testdata/test_stderr"; + namespace tensorflow { class SubProcessTest : public ::testing::Test {}; TEST_F(SubProcessTest, NoOutputNoComm) { tensorflow::SubProcess proc; - proc.SetProgram("/bin/cat", {"cat", "/dev/null"}); + proc.SetProgram( + strings::StrCat(testing::TensorFlowSrcRoot(), "/", kNoopProgram).c_str(), + {kNoopProgram}); EXPECT_TRUE(proc.Start()); EXPECT_TRUE(proc.Wait()); } TEST_F(SubProcessTest, NoOutput) { tensorflow::SubProcess proc; - proc.SetProgram("/bin/cat", {"cat", "/dev/null"}); + proc.SetProgram( + strings::StrCat(testing::TensorFlowSrcRoot(), "/", kNoopProgram).c_str(), + {kNoopProgram}); proc.SetChannelAction(CHAN_STDOUT, ACTION_PIPE); proc.SetChannelAction(CHAN_STDERR, ACTION_PIPE); EXPECT_TRUE(proc.Start()); @@ -47,7 +69,11 @@ TEST_F(SubProcessTest, NoOutput) { TEST_F(SubProcessTest, Stdout) { tensorflow::SubProcess proc; - proc.SetProgram("/bin/echo", {"echo", "-n", "hello world"}); + const char test_string[] = "hello_world"; + proc.SetProgram( + strings::StrCat(testing::TensorFlowSrcRoot(), "/", kEchoArgv1Program) + .c_str(), + {kEchoArgv1Program, test_string}); proc.SetChannelAction(CHAN_STDOUT, ACTION_PIPE); proc.SetChannelAction(CHAN_STDERR, ACTION_PIPE); EXPECT_TRUE(proc.Start()); @@ -56,13 +82,17 @@ TEST_F(SubProcessTest, Stdout) { int status = proc.Communicate(nullptr, &out, &err); EXPECT_TRUE(WIFEXITED(status)); EXPECT_EQ(0, WEXITSTATUS(status)); - EXPECT_EQ("hello world", out); + EXPECT_EQ(test_string, out); EXPECT_EQ("", err); } TEST_F(SubProcessTest, StdoutIgnored) { tensorflow::SubProcess proc; - proc.SetProgram("/bin/echo", {"echo", "-n", "hello world"}); + const char test_string[] = "hello_world"; + proc.SetProgram( + strings::StrCat(testing::TensorFlowSrcRoot(), "/", kEchoArgv1Program) + .c_str(), + {kEchoArgv1Program, test_string}); proc.SetChannelAction(CHAN_STDOUT, ACTION_PIPE); proc.SetChannelAction(CHAN_STDERR, ACTION_PIPE); EXPECT_TRUE(proc.Start()); @@ -74,7 +104,11 @@ TEST_F(SubProcessTest, StdoutIgnored) { TEST_F(SubProcessTest, Stderr) { tensorflow::SubProcess proc; - proc.SetProgram("/bin/cat", {"cat", "/file_does_not_exist"}); + const char test_string[] = "muh_failure!"; + proc.SetProgram( + strings::StrCat(testing::TensorFlowSrcRoot(), "/", kStdErrProgram) + .c_str(), + {kStdErrProgram, test_string}); proc.SetChannelAction(CHAN_STDOUT, ACTION_PIPE); proc.SetChannelAction(CHAN_STDERR, ACTION_PIPE); EXPECT_TRUE(proc.Start()); @@ -84,12 +118,16 @@ TEST_F(SubProcessTest, Stderr) { EXPECT_TRUE(WIFEXITED(status)); EXPECT_EQ(1, WEXITSTATUS(status)); EXPECT_EQ("", out); - EXPECT_NE(string::npos, err.find("/file_does_not_exist")); + EXPECT_EQ(test_string, err); } TEST_F(SubProcessTest, StderrIgnored) { tensorflow::SubProcess proc; - proc.SetProgram("/bin/cat", {"cat", "/file_does_not_exist"}); + const char test_string[] = "muh_failure!"; + proc.SetProgram( + strings::StrCat(testing::TensorFlowSrcRoot(), "/", kStdErrProgram) + .c_str(), + {kStdErrProgram, test_string}); proc.SetChannelAction(CHAN_STDOUT, ACTION_PIPE); proc.SetChannelAction(CHAN_STDERR, ACTION_PIPE); EXPECT_TRUE(proc.Start()); @@ -101,7 +139,9 @@ TEST_F(SubProcessTest, StderrIgnored) { TEST_F(SubProcessTest, Stdin) { tensorflow::SubProcess proc; - proc.SetProgram("/usr/bin/wc", {"wc", "-l"}); + proc.SetProgram( + strings::StrCat(testing::TensorFlowSrcRoot(), "/", kEchoProgram).c_str(), + {kEchoProgram}); proc.SetChannelAction(CHAN_STDIN, ACTION_PIPE); EXPECT_TRUE(proc.Start()); @@ -113,7 +153,9 @@ TEST_F(SubProcessTest, Stdin) { TEST_F(SubProcessTest, StdinStdout) { tensorflow::SubProcess proc; - proc.SetProgram("/usr/bin/wc", {"wc", "-l"}); + proc.SetProgram( + strings::StrCat(testing::TensorFlowSrcRoot(), "/", kEchoProgram).c_str(), + {kEchoProgram}); proc.SetChannelAction(CHAN_STDIN, ACTION_PIPE); proc.SetChannelAction(CHAN_STDOUT, ACTION_PIPE); EXPECT_TRUE(proc.Start()); @@ -123,13 +165,16 @@ TEST_F(SubProcessTest, StdinStdout) { int status = proc.Communicate(&in, &out, nullptr); EXPECT_TRUE(WIFEXITED(status)); EXPECT_EQ(0, WEXITSTATUS(status)); - int count = stoi(out); - EXPECT_EQ(3, count); + // Sanitize out of carriage returns, because windows... + out.erase(std::remove(out.begin(), out.end(), '\r'), out.end()); + EXPECT_EQ(in, out); } TEST_F(SubProcessTest, StdinChildExit) { tensorflow::SubProcess proc; - proc.SetProgram("/bin/sleep", {"sleep", "0"}); + proc.SetProgram( + strings::StrCat(testing::TensorFlowSrcRoot(), "/", kNoopProgram).c_str(), + {kNoopProgram}); proc.SetChannelAction(CHAN_STDIN, ACTION_PIPE); EXPECT_TRUE(proc.Start()); @@ -148,7 +193,9 @@ TEST_F(SubProcessTest, StdinChildExit) { TEST_F(SubProcessTest, StdinStdoutOverlap) { tensorflow::SubProcess proc; - proc.SetProgram("/bin/cat", {"cat"}); + proc.SetProgram( + strings::StrCat(testing::TensorFlowSrcRoot(), "/", kEchoProgram).c_str(), + {kEchoProgram}); proc.SetChannelAction(CHAN_STDIN, ACTION_PIPE); proc.SetChannelAction(CHAN_STDOUT, ACTION_PIPE); EXPECT_TRUE(proc.Start()); @@ -165,12 +212,16 @@ TEST_F(SubProcessTest, StdinStdoutOverlap) { int status = proc.Communicate(&in, &out, nullptr); EXPECT_TRUE(WIFEXITED(status)); EXPECT_EQ(0, WEXITSTATUS(status)); + // Sanitize out of carriage returns, because windows... + out.erase(std::remove(out.begin(), out.end(), '\r'), out.end()); EXPECT_EQ(in, out); } TEST_F(SubProcessTest, KillProc) { tensorflow::SubProcess proc; - proc.SetProgram("/bin/cat", {"cat"}); + proc.SetProgram( + strings::StrCat(testing::TensorFlowSrcRoot(), "/", kEchoProgram).c_str(), + {kEchoProgram}); proc.SetChannelAction(CHAN_STDIN, ACTION_PIPE); proc.SetChannelAction(CHAN_STDOUT, ACTION_PIPE); EXPECT_TRUE(proc.Start()); diff --git a/tensorflow/core/platform/testdata/BUILD b/tensorflow/core/platform/testdata/BUILD new file mode 100644 index 00000000000..9f2c75957e7 --- /dev/null +++ b/tensorflow/core/platform/testdata/BUILD @@ -0,0 +1,30 @@ +# Test helper binaries to use in tests. +# These are provided to avoid linux-only binaries in tests. +# Thus helping write cross platform tests. + +package( + default_visibility = [ + "//tensorflow/core/platform:__pkg__", + ], + licenses = ["notice"], # Apache 2.0 +) + +cc_binary( + name = "test_echo", + srcs = ["test_echo.cc"], +) + +cc_binary( + name = "test_noop", + srcs = ["test_noop.cc"], +) + +cc_binary( + name = "test_echo_argv_1", + srcs = ["test_echo_argv_1.cc"], +) + +cc_binary( + name = "test_stderr", + srcs = ["test_stderr.cc"], +) diff --git a/tensorflow/core/platform/testdata/test_echo.cc b/tensorflow/core/platform/testdata/test_echo.cc new file mode 100644 index 00000000000..6e7a9971164 --- /dev/null +++ b/tensorflow/core/platform/testdata/test_echo.cc @@ -0,0 +1,27 @@ +/* Copyright 2020 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include + +int main() { + while (true) { + int c = fgetc(stdin); + if (c <= 0) { + break; + } + fputc(static_cast(c), stdout); + } + return 0; +} diff --git a/tensorflow/core/platform/testdata/test_echo_argv_1.cc b/tensorflow/core/platform/testdata/test_echo_argv_1.cc new file mode 100644 index 00000000000..e7563315ce6 --- /dev/null +++ b/tensorflow/core/platform/testdata/test_echo_argv_1.cc @@ -0,0 +1,22 @@ +/* Copyright 2020 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include +#include + +int main(int argc, char** argv) { + std::cout << argv[1]; + return 0; +} diff --git a/tensorflow/core/platform/testdata/test_noop.cc b/tensorflow/core/platform/testdata/test_noop.cc new file mode 100644 index 00000000000..8aff2f7778b --- /dev/null +++ b/tensorflow/core/platform/testdata/test_noop.cc @@ -0,0 +1,16 @@ +/* Copyright 2020 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +int main() { return 0; } diff --git a/tensorflow/core/platform/testdata/test_stderr.cc b/tensorflow/core/platform/testdata/test_stderr.cc new file mode 100644 index 00000000000..c247df20a3b --- /dev/null +++ b/tensorflow/core/platform/testdata/test_stderr.cc @@ -0,0 +1,21 @@ +/* Copyright 2020 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include + +int main(int argc, char** argv) { + std::cerr << argv[1]; + return 1; +}