ProgramTest.cpp revision 0af5493701f9982d7451c8b3c1b7699cc84ac94c
1a09ec19a332de34de493b2c4da2b89b46fadc370Barry Warsaw//===- unittest/Support/ProgramTest.cpp -----------------------------------===//
2cd112f5546256a752f56b3bf6ce0ff19ff30a981Fred Drake//
3cd112f5546256a752f56b3bf6ce0ff19ff30a981Fred Drake//                     The LLVM Compiler Infrastructure
404f357cffef6d764f2f0ff2671dabde75ec250d1Barry Warsaw//
5cd112f5546256a752f56b3bf6ce0ff19ff30a981Fred Drake// This file is distributed under the University of Illinois Open Source
6fd163f92cee2aa8189879bd43670782f4cfd2cf8Armin Rigo// License. See LICENSE.TXT for details.
7fd163f92cee2aa8189879bd43670782f4cfd2cf8Armin Rigo//
8fd163f92cee2aa8189879bd43670782f4cfd2cf8Armin Rigo//===----------------------------------------------------------------------===//
9fd163f92cee2aa8189879bd43670782f4cfd2cf8Armin Rigo
10fd163f92cee2aa8189879bd43670782f4cfd2cf8Armin Rigo#include "llvm/Support/CommandLine.h"
11fd163f92cee2aa8189879bd43670782f4cfd2cf8Armin Rigo#include "llvm/Support/Path.h"
12fd163f92cee2aa8189879bd43670782f4cfd2cf8Armin Rigo#include "llvm/Support/Program.h"
13fd163f92cee2aa8189879bd43670782f4cfd2cf8Armin Rigo#include "gtest/gtest.h"
14fd163f92cee2aa8189879bd43670782f4cfd2cf8Armin Rigo
15fd163f92cee2aa8189879bd43670782f4cfd2cf8Armin Rigo#include <stdlib.h>
16fd163f92cee2aa8189879bd43670782f4cfd2cf8Armin Rigo
17fd163f92cee2aa8189879bd43670782f4cfd2cf8Armin Rigonamespace {
18fd163f92cee2aa8189879bd43670782f4cfd2cf8Armin Rigo
19fd163f92cee2aa8189879bd43670782f4cfd2cf8Armin Rigousing namespace llvm;
20fd163f92cee2aa8189879bd43670782f4cfd2cf8Armin Rigousing namespace sys;
21fd163f92cee2aa8189879bd43670782f4cfd2cf8Armin Rigo
22fd163f92cee2aa8189879bd43670782f4cfd2cf8Armin Rigostatic cl::opt<std::string>
23fd163f92cee2aa8189879bd43670782f4cfd2cf8Armin RigoProgramTestStringArg1("program-test-string-arg1");
24fd163f92cee2aa8189879bd43670782f4cfd2cf8Armin Rigostatic cl::opt<std::string>
25fd163f92cee2aa8189879bd43670782f4cfd2cf8Armin RigoProgramTestStringArg2("program-test-string-arg2");
26fd163f92cee2aa8189879bd43670782f4cfd2cf8Armin Rigo
27fd163f92cee2aa8189879bd43670782f4cfd2cf8Armin Rigostatic void CopyEnvironment(std::vector<const char *> &out) {
28fd163f92cee2aa8189879bd43670782f4cfd2cf8Armin Rigo  // environ appears to be pretty portable.
29fd163f92cee2aa8189879bd43670782f4cfd2cf8Armin Rigo  char **envp = environ;
30fd163f92cee2aa8189879bd43670782f4cfd2cf8Armin Rigo  while (*envp != 0) {
31fd163f92cee2aa8189879bd43670782f4cfd2cf8Armin Rigo    out.push_back(*envp);
32fd163f92cee2aa8189879bd43670782f4cfd2cf8Armin Rigo    ++envp;
33fd163f92cee2aa8189879bd43670782f4cfd2cf8Armin Rigo  }
34cd112f5546256a752f56b3bf6ce0ff19ff30a981Fred Drake}
35cd112f5546256a752f56b3bf6ce0ff19ff30a981Fred Drake
36cd112f5546256a752f56b3bf6ce0ff19ff30a981Fred DrakeTEST(ProgramTest, CreateProcessTrailingSlash) {
37bb9c739806b9f0251fa4a564986e2cb5e92e766eWalter Dörwald  if (getenv("LLVM_PROGRAM_TEST_CHILD")) {
38bb9c739806b9f0251fa4a564986e2cb5e92e766eWalter Dörwald    if (ProgramTestStringArg1 == "has\\\\ trailing\\" &&
39cd112f5546256a752f56b3bf6ce0ff19ff30a981Fred Drake        ProgramTestStringArg2 == "has\\\\ trailing\\") {
40cd112f5546256a752f56b3bf6ce0ff19ff30a981Fred Drake      exit(0);  // Success!  The arguments were passed and parsed.
41cd112f5546256a752f56b3bf6ce0ff19ff30a981Fred Drake    }
42cd112f5546256a752f56b3bf6ce0ff19ff30a981Fred Drake    exit(1);
43cd112f5546256a752f56b3bf6ce0ff19ff30a981Fred Drake  }
44cd112f5546256a752f56b3bf6ce0ff19ff30a981Fred Drake
45cd112f5546256a752f56b3bf6ce0ff19ff30a981Fred Drake  // FIXME: Hardcoding argv0 here since I don't know a good cross-platform way
46cd112f5546256a752f56b3bf6ce0ff19ff30a981Fred Drake  // to get it.  Maybe ParseCommandLineOptions() should save it?
47bb9c739806b9f0251fa4a564986e2cb5e92e766eWalter Dörwald  Path my_exe = Path::GetMainExecutable("SupportTests", &ProgramTestStringArg1);
48bb9c739806b9f0251fa4a564986e2cb5e92e766eWalter Dörwald  const char *argv[] = {
49cd112f5546256a752f56b3bf6ce0ff19ff30a981Fred Drake    my_exe.c_str(),
50cd112f5546256a752f56b3bf6ce0ff19ff30a981Fred Drake    "--gtest_filter=ProgramTest.CreateProcessTrailingSlashChild",
51cd112f5546256a752f56b3bf6ce0ff19ff30a981Fred Drake    "-program-test-string-arg1", "has\\\\ trailing\\",
52cd112f5546256a752f56b3bf6ce0ff19ff30a981Fred Drake    "-program-test-string-arg2", "has\\\\ trailing\\",
53cd112f5546256a752f56b3bf6ce0ff19ff30a981Fred Drake    0
54cd112f5546256a752f56b3bf6ce0ff19ff30a981Fred Drake  };
55cd112f5546256a752f56b3bf6ce0ff19ff30a981Fred Drake
56cd112f5546256a752f56b3bf6ce0ff19ff30a981Fred Drake  // Add LLVM_PROGRAM_TEST_CHILD to the environment of the child.
57bb9c739806b9f0251fa4a564986e2cb5e92e766eWalter Dörwald  std::vector<const char *> envp;
58bb9c739806b9f0251fa4a564986e2cb5e92e766eWalter Dörwald  CopyEnvironment(envp);
59bb9c739806b9f0251fa4a564986e2cb5e92e766eWalter Dörwald  envp.push_back("LLVM_PROGRAM_TEST_CHILD=1");
60bb9c739806b9f0251fa4a564986e2cb5e92e766eWalter Dörwald  envp.push_back(0);
61bb9c739806b9f0251fa4a564986e2cb5e92e766eWalter Dörwald
62cd112f5546256a752f56b3bf6ce0ff19ff30a981Fred Drake  std::string error;
63cd112f5546256a752f56b3bf6ce0ff19ff30a981Fred Drake  bool ExecutionFailed;
64cd112f5546256a752f56b3bf6ce0ff19ff30a981Fred Drake  // Redirect stdout and stdin to NUL, but let stderr through.
65cd112f5546256a752f56b3bf6ce0ff19ff30a981Fred Drake#ifdef LLVM_ON_WIN32
66cd112f5546256a752f56b3bf6ce0ff19ff30a981Fred Drake  Path nul("NUL");
67cd112f5546256a752f56b3bf6ce0ff19ff30a981Fred Drake#else
68cd112f5546256a752f56b3bf6ce0ff19ff30a981Fred Drake  Path nul("/dev/null");
69cd112f5546256a752f56b3bf6ce0ff19ff30a981Fred Drake#endif
70bb9c739806b9f0251fa4a564986e2cb5e92e766eWalter Dörwald  const Path *redirects[] = { &nul, &nul, 0 };
71bb9c739806b9f0251fa4a564986e2cb5e92e766eWalter Dörwald  int rc = Program::ExecuteAndWait(my_exe, argv, &envp[0], redirects,
72bb9c739806b9f0251fa4a564986e2cb5e92e766eWalter Dörwald                                   /*secondsToWait=*/10, /*memoryLimit=*/0,
73bb9c739806b9f0251fa4a564986e2cb5e92e766eWalter Dörwald                                   &error, &ExecutionFailed);
74bb9c739806b9f0251fa4a564986e2cb5e92e766eWalter Dörwald  EXPECT_FALSE(ExecutionFailed) << error;
75cd112f5546256a752f56b3bf6ce0ff19ff30a981Fred Drake  EXPECT_EQ(0, rc);
76cd112f5546256a752f56b3bf6ce0ff19ff30a981Fred Drake}
77cd112f5546256a752f56b3bf6ce0ff19ff30a981Fred Drake
78cd112f5546256a752f56b3bf6ce0ff19ff30a981Fred Drake} // end anonymous namespace
79cd112f5546256a752f56b3bf6ce0ff19ff30a981Fred Drake