ProgramTest.cpp revision 268adf2a03cf352593b632c5249c83f4fc56956f
1//===- unittest/Support/ProgramTest.cpp -----------------------------------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "llvm/Support/CommandLine.h"
11#include "llvm/Support/Path.h"
12#include "llvm/Support/Program.h"
13#include "gtest/gtest.h"
14
15#include <stdlib.h>
16#if defined(__APPLE__)
17# include <crt_externs.h>
18#elif !defined(_MSC_VER)
19// Forward declare environ in case it's not provided by stdlib.h.
20extern char **environ;
21#endif
22
23namespace {
24
25using namespace llvm;
26using namespace sys;
27
28static cl::opt<std::string>
29ProgramTestStringArg1("program-test-string-arg1");
30static cl::opt<std::string>
31ProgramTestStringArg2("program-test-string-arg2");
32
33static void CopyEnvironment(std::vector<const char *> &out) {
34#ifdef __APPLE__
35  char **envp = *_NSGetEnviron();
36#else
37  // environ seems to work for Windows and most other Unices.
38  char **envp = environ;
39#endif
40  while (*envp != 0) {
41    out.push_back(*envp);
42    ++envp;
43  }
44}
45
46TEST(ProgramTest, CreateProcessTrailingSlash) {
47  if (getenv("LLVM_PROGRAM_TEST_CHILD")) {
48    if (ProgramTestStringArg1 == "has\\\\ trailing\\" &&
49        ProgramTestStringArg2 == "has\\\\ trailing\\") {
50      exit(0);  // Success!  The arguments were passed and parsed.
51    }
52    exit(1);
53  }
54
55  // FIXME: Hardcoding argv0 here since I don't know a good cross-platform way
56  // to get it.  Maybe ParseCommandLineOptions() should save it?
57  Path my_exe = Path::GetMainExecutable("SupportTests", &ProgramTestStringArg1);
58  const char *argv[] = {
59    my_exe.c_str(),
60    "--gtest_filter=ProgramTest.CreateProcessTrailingSlashChild",
61    "-program-test-string-arg1", "has\\\\ trailing\\",
62    "-program-test-string-arg2", "has\\\\ trailing\\",
63    0
64  };
65
66  // Add LLVM_PROGRAM_TEST_CHILD to the environment of the child.
67  std::vector<const char *> envp;
68  CopyEnvironment(envp);
69  envp.push_back("LLVM_PROGRAM_TEST_CHILD=1");
70  envp.push_back(0);
71
72  std::string error;
73  bool ExecutionFailed;
74  // Redirect stdout and stdin to NUL, but let stderr through.
75#ifdef LLVM_ON_WIN32
76  Path nul("NUL");
77#else
78  Path nul("/dev/null");
79#endif
80  const Path *redirects[] = { &nul, &nul, 0 };
81  int rc = Program::ExecuteAndWait(my_exe, argv, &envp[0], redirects,
82                                   /*secondsToWait=*/10, /*memoryLimit=*/0,
83                                   &error, &ExecutionFailed);
84  EXPECT_FALSE(ExecutionFailed) << error;
85  EXPECT_EQ(0, rc);
86}
87
88} // end anonymous namespace
89