Fix PipeClosedWhenNotRedirectedTest.

When checking for a file descriptor open on the child, we now execute a
simple test program that just runs fstat on that file descriptor. This
is more reliable than calling sh on different platforms.

Bug: 26955860
TEST=Ran unittests on edison-eng and Chromium OS.

Change-Id: I5d5d87095564159df1a75e78b0aed29c16bc7eb8
diff --git a/Android.mk b/Android.mk
index 8084b71..26ed6e6 100644
--- a/Android.mk
+++ b/Android.mk
@@ -808,6 +808,26 @@
     $(bsdiff_static_libs)
 include $(BUILD_EXECUTABLE)
 
+# test_subprocess (type: executable)
+# ========================================================
+# Test helper subprocess program.
+include $(CLEAR_VARS)
+LOCAL_MODULE := test_subprocess
+ifdef BRILLO
+  LOCAL_MODULE_TAGS := eng
+endif
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_NATIVE_TESTS)/update_engine_unittests
+LOCAL_MODULE_CLASS := EXECUTABLES
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_CLANG := true
+LOCAL_CFLAGS := $(ue_common_cflags)
+LOCAL_CPPFLAGS := $(ue_common_cppflags)
+LOCAL_LDFLAGS := $(ue_common_ldflags)
+LOCAL_C_INCLUDES := $(ue_common_c_includes)
+LOCAL_SHARED_LIBRARIES := $(ue_common_shared_libraries)
+LOCAL_SRC_FILES := test_subprocess.cc
+include $(BUILD_EXECUTABLE)
+
 # update_engine_unittests (type: executable)
 # ========================================================
 # Main unittest file.
@@ -817,6 +837,8 @@
   LOCAL_MODULE_TAGS := eng
 endif
 LOCAL_REQUIRED_MODULES := \
+    test_http_server \
+    test_subprocess \
     ue_unittest_bsdiff \
     ue_unittest_delta_generator \
     ue_unittest_disk_ext2_1k.img \
diff --git a/common/subprocess_unittest.cc b/common/subprocess_unittest.cc
index 5ca44e8..cc1f353 100644
--- a/common/subprocess_unittest.cc
+++ b/common/subprocess_unittest.cc
@@ -171,13 +171,15 @@
 // Test that a pipe file descriptor open in the parent is not open in the child.
 TEST_F(SubprocessTest, PipeClosedWhenNotRedirectedTest) {
   brillo::ScopedPipe pipe;
-  const vector<string> cmd = {kBinPath "/sh", "-c",
-     base::StringPrintf("echo on pipe >/proc/self/fd/%d", pipe.writer)};
+
+  // test_subprocess will return with the errno of fstat, which should be EBADF
+  // if the passed file descriptor is closed in the child.
+  const vector<string> cmd = {
+      test_utils::GetBuildArtifactsPath("test_subprocess"),
+      "fstat",
+      std::to_string(pipe.writer)};
   EXPECT_TRUE(subprocess_.ExecFlags(
-      cmd,
-      0,
-      {},
-      base::Bind(&ExpectedResults, 1, "")));
+      cmd, 0, {}, base::Bind(&ExpectedResults, EBADF, "")));
   loop_.Run();
 }
 
diff --git a/test_subprocess.cc b/test_subprocess.cc
new file mode 100644
index 0000000..c7f4a37
--- /dev/null
+++ b/test_subprocess.cc
@@ -0,0 +1,59 @@
+//
+// Copyright (C) 2012 The Android Open Source Project
+//
+// 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.
+//
+
+// This is a simple program used to test interaction with update_engine when
+// executing other programs. This program receives pre-programmed actions in the
+// command line and executes them in order.
+
+#include <errno.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <string>
+
+#define EX_USAGE_ERROR 100
+
+void usage(const char* program, const char* error) {
+  if (error)
+    fprintf(stderr, "ERROR: %s\n", error);
+  fprintf(stderr, "Usage: %s <cmd> [args..]\n", program);
+  exit(EX_USAGE_ERROR);
+}
+
+int main(int argc, char** argv, char** envp) {
+  if (argc < 2)
+    usage(argv[0], "No command passed");
+
+  std::string cmd(argv[1]);
+  if (cmd == "fstat") {
+    // Call fstat on the passed file descriptor number
+    if (argc < 3)
+      usage(argv[0], "No fd passed to fstat");
+    int fd = atoi(argv[2]);
+    struct stat buf;
+    int rc = fstat(fd, &buf);
+    if (rc < 0) {
+      int ret = errno;
+      perror("fstat");
+      return ret;
+    }
+    return 0;
+  }
+
+  usage(argv[0], "Unknown command");
+}
diff --git a/update_engine.gyp b/update_engine.gyp
index a0fc447..40d6314 100644
--- a/update_engine.gyp
+++ b/update_engine.gyp
@@ -457,6 +457,14 @@
             'test_http_server.cc',
           ],
         },
+        # Test subprocess helper.
+        {
+          'target_name': 'test_subprocess',
+          'type': 'executable',
+          'sources': [
+            'test_subprocess.cc',
+          ],
+        },
         # Main unittest file.
         {
           'target_name': 'update_engine_unittests',