Reid Kleckner | 74679a9 | 2013-04-22 19:03:55 +0000 | [diff] [blame] | 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 | |
Pawel Bylica | 85ca294 | 2015-11-04 08:25:20 +0000 | [diff] [blame] | 10 | #include "llvm/Support/ConvertUTF.h" |
Reid Kleckner | 74679a9 | 2013-04-22 19:03:55 +0000 | [diff] [blame] | 11 | #include "llvm/Support/CommandLine.h" |
Rafael Espindola | e03dfd9 | 2013-06-26 05:01:35 +0000 | [diff] [blame] | 12 | #include "llvm/Support/FileSystem.h" |
Reid Kleckner | 74679a9 | 2013-04-22 19:03:55 +0000 | [diff] [blame] | 13 | #include "llvm/Support/Path.h" |
| 14 | #include "llvm/Support/Program.h" |
| 15 | #include "gtest/gtest.h" |
Duncan P. N. Exon Smith | 91d3cfe | 2016-04-05 20:45:04 +0000 | [diff] [blame] | 16 | #include <stdlib.h> |
Reid Kleckner | 206ddd0 | 2013-04-24 17:50:30 +0000 | [diff] [blame] | 17 | #if defined(__APPLE__) |
Reid Kleckner | de0c260 | 2013-04-23 13:15:51 +0000 | [diff] [blame] | 18 | # include <crt_externs.h> |
Reid Kleckner | 206ddd0 | 2013-04-24 17:50:30 +0000 | [diff] [blame] | 19 | #elif !defined(_MSC_VER) |
Reid Kleckner | de0c260 | 2013-04-23 13:15:51 +0000 | [diff] [blame] | 20 | // Forward declare environ in case it's not provided by stdlib.h. |
| 21 | extern char **environ; |
| 22 | #endif |
Reid Kleckner | 74679a9 | 2013-04-22 19:03:55 +0000 | [diff] [blame] | 23 | |
Tareq A. Siraj | d88b983 | 2013-10-01 14:28:18 +0000 | [diff] [blame] | 24 | #if defined(LLVM_ON_UNIX) |
| 25 | #include <unistd.h> |
| 26 | void sleep_for(unsigned int seconds) { |
| 27 | sleep(seconds); |
| 28 | } |
| 29 | #elif defined(LLVM_ON_WIN32) |
| 30 | #include <windows.h> |
| 31 | void sleep_for(unsigned int seconds) { |
| 32 | Sleep(seconds * 1000); |
| 33 | } |
| 34 | #else |
| 35 | #error sleep_for is not implemented on your platform. |
| 36 | #endif |
| 37 | |
Rafael Espindola | 9c35966 | 2014-09-03 20:02:00 +0000 | [diff] [blame] | 38 | #define ASSERT_NO_ERROR(x) \ |
| 39 | if (std::error_code ASSERT_NO_ERROR_ec = x) { \ |
| 40 | SmallString<128> MessageStorage; \ |
| 41 | raw_svector_ostream Message(MessageStorage); \ |
| 42 | Message << #x ": did not return errc::success.\n" \ |
| 43 | << "error number: " << ASSERT_NO_ERROR_ec.value() << "\n" \ |
| 44 | << "error message: " << ASSERT_NO_ERROR_ec.message() << "\n"; \ |
| 45 | GTEST_FATAL_FAILURE_(MessageStorage.c_str()); \ |
| 46 | } else { \ |
| 47 | } |
Reid Kleckner | 95012aa | 2013-04-30 04:30:41 +0000 | [diff] [blame] | 48 | // From TestMain.cpp. |
| 49 | extern const char *TestMainArgv0; |
| 50 | |
Reid Kleckner | 74679a9 | 2013-04-22 19:03:55 +0000 | [diff] [blame] | 51 | namespace { |
| 52 | |
| 53 | using namespace llvm; |
| 54 | using namespace sys; |
| 55 | |
Duncan P. N. Exon Smith | 91d3cfe | 2016-04-05 20:45:04 +0000 | [diff] [blame] | 56 | static cl::opt<std::string> |
Reid Kleckner | 74679a9 | 2013-04-22 19:03:55 +0000 | [diff] [blame] | 57 | ProgramTestStringArg1("program-test-string-arg1"); |
Duncan P. N. Exon Smith | 91d3cfe | 2016-04-05 20:45:04 +0000 | [diff] [blame] | 58 | static cl::opt<std::string> |
Reid Kleckner | 74679a9 | 2013-04-22 19:03:55 +0000 | [diff] [blame] | 59 | ProgramTestStringArg2("program-test-string-arg2"); |
| 60 | |
Pawel Bylica | 85ca294 | 2015-11-04 08:25:20 +0000 | [diff] [blame] | 61 | class ProgramEnvTest : public testing::Test { |
| 62 | std::vector<const char *> EnvTable; |
| 63 | std::vector<std::string> EnvStorage; |
| 64 | |
| 65 | protected: |
| 66 | void SetUp() override { |
| 67 | auto EnvP = [] { |
| 68 | #if defined(LLVM_ON_WIN32) |
| 69 | _wgetenv(L"TMP"); // Populate _wenviron, initially is null |
| 70 | return _wenviron; |
| 71 | #elif defined(__APPLE__) |
| 72 | return *_NSGetEnviron(); |
Reid Kleckner | de0c260 | 2013-04-23 13:15:51 +0000 | [diff] [blame] | 73 | #else |
Pawel Bylica | 85ca294 | 2015-11-04 08:25:20 +0000 | [diff] [blame] | 74 | return environ; |
Reid Kleckner | de0c260 | 2013-04-23 13:15:51 +0000 | [diff] [blame] | 75 | #endif |
Pawel Bylica | 85ca294 | 2015-11-04 08:25:20 +0000 | [diff] [blame] | 76 | }(); |
| 77 | ASSERT_TRUE(EnvP); |
| 78 | |
| 79 | auto prepareEnvVar = [this](decltype(*EnvP) Var) { |
| 80 | #if defined(LLVM_ON_WIN32) |
| 81 | // On Windows convert UTF16 encoded variable to UTF8 |
| 82 | auto Len = wcslen(Var); |
| 83 | ArrayRef<char> Ref{reinterpret_cast<char const *>(Var), |
| 84 | Len * sizeof(*Var)}; |
| 85 | EnvStorage.emplace_back(); |
| 86 | auto convStatus = convertUTF16ToUTF8String(Ref, EnvStorage.back()); |
| 87 | EXPECT_TRUE(convStatus); |
| 88 | return EnvStorage.back().c_str(); |
| 89 | #else |
| 90 | return Var; |
| 91 | #endif |
| 92 | }; |
| 93 | |
| 94 | while (*EnvP != nullptr) { |
| 95 | EnvTable.emplace_back(prepareEnvVar(*EnvP)); |
| 96 | ++EnvP; |
| 97 | } |
Reid Kleckner | de0c260 | 2013-04-23 13:15:51 +0000 | [diff] [blame] | 98 | } |
Pawel Bylica | 85ca294 | 2015-11-04 08:25:20 +0000 | [diff] [blame] | 99 | |
| 100 | void TearDown() override { |
| 101 | EnvTable.clear(); |
| 102 | EnvStorage.clear(); |
| 103 | } |
| 104 | |
| 105 | void addEnvVar(const char *Var) { |
| 106 | ASSERT_TRUE(EnvTable.empty() || EnvTable.back()) << "Env table sealed"; |
| 107 | EnvTable.emplace_back(Var); |
| 108 | } |
| 109 | |
| 110 | const char **getEnviron() { |
| 111 | if (EnvTable.back() != nullptr) |
| 112 | EnvTable.emplace_back(nullptr); // Seal table. |
| 113 | return &EnvTable[0]; |
| 114 | } |
| 115 | }; |
Reid Kleckner | de0c260 | 2013-04-23 13:15:51 +0000 | [diff] [blame] | 116 | |
Paul Robinson | c38deee | 2014-11-24 18:05:29 +0000 | [diff] [blame] | 117 | #ifdef LLVM_ON_WIN32 |
Pawel Bylica | 85ca294 | 2015-11-04 08:25:20 +0000 | [diff] [blame] | 118 | TEST_F(ProgramEnvTest, CreateProcessLongPath) { |
Paul Robinson | c38deee | 2014-11-24 18:05:29 +0000 | [diff] [blame] | 119 | if (getenv("LLVM_PROGRAM_TEST_LONG_PATH")) |
| 120 | exit(0); |
| 121 | |
| 122 | // getMainExecutable returns an absolute path; prepend the long-path prefix. |
| 123 | std::string MyAbsExe = |
| 124 | sys::fs::getMainExecutable(TestMainArgv0, &ProgramTestStringArg1); |
| 125 | std::string MyExe; |
| 126 | if (!StringRef(MyAbsExe).startswith("\\\\?\\")) |
| 127 | MyExe.append("\\\\?\\"); |
| 128 | MyExe.append(MyAbsExe); |
| 129 | |
| 130 | const char *ArgV[] = { |
| 131 | MyExe.c_str(), |
Pawel Bylica | 85ca294 | 2015-11-04 08:25:20 +0000 | [diff] [blame] | 132 | "--gtest_filter=ProgramEnvTest.CreateProcessLongPath", |
Paul Robinson | c38deee | 2014-11-24 18:05:29 +0000 | [diff] [blame] | 133 | nullptr |
| 134 | }; |
| 135 | |
| 136 | // Add LLVM_PROGRAM_TEST_LONG_PATH to the environment of the child. |
Pawel Bylica | 85ca294 | 2015-11-04 08:25:20 +0000 | [diff] [blame] | 137 | addEnvVar("LLVM_PROGRAM_TEST_LONG_PATH=1"); |
Paul Robinson | c38deee | 2014-11-24 18:05:29 +0000 | [diff] [blame] | 138 | |
| 139 | // Redirect stdout to a long path. |
| 140 | SmallString<128> TestDirectory; |
| 141 | ASSERT_NO_ERROR( |
| 142 | fs::createUniqueDirectory("program-redirect-test", TestDirectory)); |
| 143 | SmallString<256> LongPath(TestDirectory); |
| 144 | LongPath.push_back('\\'); |
| 145 | // MAX_PATH = 260 |
| 146 | LongPath.append(260 - TestDirectory.size(), 'a'); |
| 147 | StringRef LongPathRef(LongPath); |
| 148 | |
| 149 | std::string Error; |
| 150 | bool ExecutionFailed; |
| 151 | const StringRef *Redirects[] = { nullptr, &LongPathRef, nullptr }; |
Pawel Bylica | 85ca294 | 2015-11-04 08:25:20 +0000 | [diff] [blame] | 152 | int RC = ExecuteAndWait(MyExe, ArgV, getEnviron(), Redirects, |
Paul Robinson | c38deee | 2014-11-24 18:05:29 +0000 | [diff] [blame] | 153 | /*secondsToWait=*/ 10, /*memoryLimit=*/ 0, &Error, |
| 154 | &ExecutionFailed); |
| 155 | EXPECT_FALSE(ExecutionFailed) << Error; |
| 156 | EXPECT_EQ(0, RC); |
| 157 | |
| 158 | // Remove the long stdout. |
| 159 | ASSERT_NO_ERROR(fs::remove(Twine(LongPath))); |
| 160 | ASSERT_NO_ERROR(fs::remove(Twine(TestDirectory))); |
| 161 | } |
| 162 | #endif |
| 163 | |
Pawel Bylica | 85ca294 | 2015-11-04 08:25:20 +0000 | [diff] [blame] | 164 | TEST_F(ProgramEnvTest, CreateProcessTrailingSlash) { |
Reid Kleckner | 74679a9 | 2013-04-22 19:03:55 +0000 | [diff] [blame] | 165 | if (getenv("LLVM_PROGRAM_TEST_CHILD")) { |
| 166 | if (ProgramTestStringArg1 == "has\\\\ trailing\\" && |
| 167 | ProgramTestStringArg2 == "has\\\\ trailing\\") { |
| 168 | exit(0); // Success! The arguments were passed and parsed. |
| 169 | } |
| 170 | exit(1); |
| 171 | } |
| 172 | |
Rafael Espindola | e03dfd9 | 2013-06-26 05:01:35 +0000 | [diff] [blame] | 173 | std::string my_exe = |
| 174 | sys::fs::getMainExecutable(TestMainArgv0, &ProgramTestStringArg1); |
Reid Kleckner | 74679a9 | 2013-04-22 19:03:55 +0000 | [diff] [blame] | 175 | const char *argv[] = { |
| 176 | my_exe.c_str(), |
Pawel Bylica | 85ca294 | 2015-11-04 08:25:20 +0000 | [diff] [blame] | 177 | "--gtest_filter=ProgramEnvTest.CreateProcessTrailingSlash", |
Reid Kleckner | 74679a9 | 2013-04-22 19:03:55 +0000 | [diff] [blame] | 178 | "-program-test-string-arg1", "has\\\\ trailing\\", |
| 179 | "-program-test-string-arg2", "has\\\\ trailing\\", |
Craig Topper | 66f09ad | 2014-06-08 22:29:17 +0000 | [diff] [blame] | 180 | nullptr |
Reid Kleckner | 74679a9 | 2013-04-22 19:03:55 +0000 | [diff] [blame] | 181 | }; |
Reid Kleckner | de0c260 | 2013-04-23 13:15:51 +0000 | [diff] [blame] | 182 | |
| 183 | // Add LLVM_PROGRAM_TEST_CHILD to the environment of the child. |
Pawel Bylica | 85ca294 | 2015-11-04 08:25:20 +0000 | [diff] [blame] | 184 | addEnvVar("LLVM_PROGRAM_TEST_CHILD=1"); |
Reid Kleckner | de0c260 | 2013-04-23 13:15:51 +0000 | [diff] [blame] | 185 | |
Reid Kleckner | 74679a9 | 2013-04-22 19:03:55 +0000 | [diff] [blame] | 186 | std::string error; |
| 187 | bool ExecutionFailed; |
| 188 | // Redirect stdout and stdin to NUL, but let stderr through. |
| 189 | #ifdef LLVM_ON_WIN32 |
Rafael Espindola | 7c1023a | 2013-06-13 20:25:38 +0000 | [diff] [blame] | 190 | StringRef nul("NUL"); |
Reid Kleckner | 74679a9 | 2013-04-22 19:03:55 +0000 | [diff] [blame] | 191 | #else |
Rafael Espindola | 7c1023a | 2013-06-13 20:25:38 +0000 | [diff] [blame] | 192 | StringRef nul("/dev/null"); |
Reid Kleckner | 74679a9 | 2013-04-22 19:03:55 +0000 | [diff] [blame] | 193 | #endif |
Craig Topper | 66f09ad | 2014-06-08 22:29:17 +0000 | [diff] [blame] | 194 | const StringRef *redirects[] = { &nul, &nul, nullptr }; |
Pawel Bylica | 85ca294 | 2015-11-04 08:25:20 +0000 | [diff] [blame] | 195 | int rc = ExecuteAndWait(my_exe, argv, getEnviron(), redirects, |
Rafael Espindola | 7c1023a | 2013-06-13 20:25:38 +0000 | [diff] [blame] | 196 | /*secondsToWait=*/ 10, /*memoryLimit=*/ 0, &error, |
| 197 | &ExecutionFailed); |
Reid Kleckner | 74679a9 | 2013-04-22 19:03:55 +0000 | [diff] [blame] | 198 | EXPECT_FALSE(ExecutionFailed) << error; |
| 199 | EXPECT_EQ(0, rc); |
| 200 | } |
| 201 | |
Pawel Bylica | 85ca294 | 2015-11-04 08:25:20 +0000 | [diff] [blame] | 202 | TEST_F(ProgramEnvTest, TestExecuteNoWait) { |
Tareq A. Siraj | d88b983 | 2013-10-01 14:28:18 +0000 | [diff] [blame] | 203 | using namespace llvm::sys; |
| 204 | |
| 205 | if (getenv("LLVM_PROGRAM_TEST_EXECUTE_NO_WAIT")) { |
| 206 | sleep_for(/*seconds*/ 1); |
| 207 | exit(0); |
| 208 | } |
| 209 | |
| 210 | std::string Executable = |
| 211 | sys::fs::getMainExecutable(TestMainArgv0, &ProgramTestStringArg1); |
| 212 | const char *argv[] = { |
| 213 | Executable.c_str(), |
Pawel Bylica | 85ca294 | 2015-11-04 08:25:20 +0000 | [diff] [blame] | 214 | "--gtest_filter=ProgramEnvTest.TestExecuteNoWait", |
Craig Topper | 66f09ad | 2014-06-08 22:29:17 +0000 | [diff] [blame] | 215 | nullptr |
Tareq A. Siraj | d88b983 | 2013-10-01 14:28:18 +0000 | [diff] [blame] | 216 | }; |
| 217 | |
| 218 | // Add LLVM_PROGRAM_TEST_EXECUTE_NO_WAIT to the environment of the child. |
Pawel Bylica | 85ca294 | 2015-11-04 08:25:20 +0000 | [diff] [blame] | 219 | addEnvVar("LLVM_PROGRAM_TEST_EXECUTE_NO_WAIT=1"); |
Tareq A. Siraj | d88b983 | 2013-10-01 14:28:18 +0000 | [diff] [blame] | 220 | |
| 221 | std::string Error; |
| 222 | bool ExecutionFailed; |
Pawel Bylica | 85ca294 | 2015-11-04 08:25:20 +0000 | [diff] [blame] | 223 | ProcessInfo PI1 = ExecuteNoWait(Executable, argv, getEnviron(), nullptr, 0, |
Craig Topper | 66f09ad | 2014-06-08 22:29:17 +0000 | [diff] [blame] | 224 | &Error, &ExecutionFailed); |
Tareq A. Siraj | d88b983 | 2013-10-01 14:28:18 +0000 | [diff] [blame] | 225 | ASSERT_FALSE(ExecutionFailed) << Error; |
Reid Kleckner | c2e2311 | 2016-02-03 21:41:12 +0000 | [diff] [blame] | 226 | ASSERT_NE(PI1.Pid, ProcessInfo::InvalidPid) << "Invalid process id"; |
Tareq A. Siraj | d88b983 | 2013-10-01 14:28:18 +0000 | [diff] [blame] | 227 | |
| 228 | unsigned LoopCount = 0; |
| 229 | |
| 230 | // Test that Wait() with WaitUntilTerminates=true works. In this case, |
| 231 | // LoopCount should only be incremented once. |
| 232 | while (true) { |
| 233 | ++LoopCount; |
Zachary Turner | 07670b3 | 2016-06-29 21:48:26 +0000 | [diff] [blame] | 234 | ProcessInfo WaitResult = llvm::sys::Wait(PI1, 0, true, &Error); |
Tareq A. Siraj | d88b983 | 2013-10-01 14:28:18 +0000 | [diff] [blame] | 235 | ASSERT_TRUE(Error.empty()); |
| 236 | if (WaitResult.Pid == PI1.Pid) |
| 237 | break; |
| 238 | } |
| 239 | |
| 240 | EXPECT_EQ(LoopCount, 1u) << "LoopCount should be 1"; |
| 241 | |
Pawel Bylica | 85ca294 | 2015-11-04 08:25:20 +0000 | [diff] [blame] | 242 | ProcessInfo PI2 = ExecuteNoWait(Executable, argv, getEnviron(), nullptr, 0, |
Craig Topper | 66f09ad | 2014-06-08 22:29:17 +0000 | [diff] [blame] | 243 | &Error, &ExecutionFailed); |
Tareq A. Siraj | d88b983 | 2013-10-01 14:28:18 +0000 | [diff] [blame] | 244 | ASSERT_FALSE(ExecutionFailed) << Error; |
Reid Kleckner | c2e2311 | 2016-02-03 21:41:12 +0000 | [diff] [blame] | 245 | ASSERT_NE(PI2.Pid, ProcessInfo::InvalidPid) << "Invalid process id"; |
Tareq A. Siraj | d88b983 | 2013-10-01 14:28:18 +0000 | [diff] [blame] | 246 | |
| 247 | // Test that Wait() with SecondsToWait=0 performs a non-blocking wait. In this |
| 248 | // cse, LoopCount should be greater than 1 (more than one increment occurs). |
| 249 | while (true) { |
| 250 | ++LoopCount; |
Zachary Turner | 07670b3 | 2016-06-29 21:48:26 +0000 | [diff] [blame] | 251 | ProcessInfo WaitResult = llvm::sys::Wait(PI2, 0, false, &Error); |
Tareq A. Siraj | d88b983 | 2013-10-01 14:28:18 +0000 | [diff] [blame] | 252 | ASSERT_TRUE(Error.empty()); |
| 253 | if (WaitResult.Pid == PI2.Pid) |
| 254 | break; |
| 255 | } |
| 256 | |
| 257 | ASSERT_GT(LoopCount, 1u) << "LoopCount should be >1"; |
| 258 | } |
| 259 | |
Pawel Bylica | 85ca294 | 2015-11-04 08:25:20 +0000 | [diff] [blame] | 260 | TEST_F(ProgramEnvTest, TestExecuteAndWaitTimeout) { |
Peter Collingbourne | ec1aaca | 2014-05-31 01:36:02 +0000 | [diff] [blame] | 261 | using namespace llvm::sys; |
| 262 | |
| 263 | if (getenv("LLVM_PROGRAM_TEST_TIMEOUT")) { |
| 264 | sleep_for(/*seconds*/ 10); |
| 265 | exit(0); |
| 266 | } |
| 267 | |
| 268 | std::string Executable = |
| 269 | sys::fs::getMainExecutable(TestMainArgv0, &ProgramTestStringArg1); |
| 270 | const char *argv[] = { |
| 271 | Executable.c_str(), |
Pawel Bylica | 85ca294 | 2015-11-04 08:25:20 +0000 | [diff] [blame] | 272 | "--gtest_filter=ProgramEnvTest.TestExecuteAndWaitTimeout", |
Craig Topper | 66f09ad | 2014-06-08 22:29:17 +0000 | [diff] [blame] | 273 | nullptr |
Peter Collingbourne | ec1aaca | 2014-05-31 01:36:02 +0000 | [diff] [blame] | 274 | }; |
| 275 | |
| 276 | // Add LLVM_PROGRAM_TEST_TIMEOUT to the environment of the child. |
Pawel Bylica | 85ca294 | 2015-11-04 08:25:20 +0000 | [diff] [blame] | 277 | addEnvVar("LLVM_PROGRAM_TEST_TIMEOUT=1"); |
Peter Collingbourne | ec1aaca | 2014-05-31 01:36:02 +0000 | [diff] [blame] | 278 | |
| 279 | std::string Error; |
| 280 | bool ExecutionFailed; |
| 281 | int RetCode = |
Pawel Bylica | 85ca294 | 2015-11-04 08:25:20 +0000 | [diff] [blame] | 282 | ExecuteAndWait(Executable, argv, getEnviron(), nullptr, /*secondsToWait=*/1, 0, |
Peter Collingbourne | ec1aaca | 2014-05-31 01:36:02 +0000 | [diff] [blame] | 283 | &Error, &ExecutionFailed); |
| 284 | ASSERT_EQ(-2, RetCode); |
| 285 | } |
| 286 | |
Tareq A. Siraj | d88b983 | 2013-10-01 14:28:18 +0000 | [diff] [blame] | 287 | TEST(ProgramTest, TestExecuteNegative) { |
| 288 | std::string Executable = "i_dont_exist"; |
Craig Topper | 66f09ad | 2014-06-08 22:29:17 +0000 | [diff] [blame] | 289 | const char *argv[] = { Executable.c_str(), nullptr }; |
Tareq A. Siraj | d88b983 | 2013-10-01 14:28:18 +0000 | [diff] [blame] | 290 | |
| 291 | { |
| 292 | std::string Error; |
| 293 | bool ExecutionFailed; |
Craig Topper | 66f09ad | 2014-06-08 22:29:17 +0000 | [diff] [blame] | 294 | int RetCode = ExecuteAndWait(Executable, argv, nullptr, nullptr, 0, 0, |
| 295 | &Error, &ExecutionFailed); |
Tareq A. Siraj | d88b983 | 2013-10-01 14:28:18 +0000 | [diff] [blame] | 296 | ASSERT_TRUE(RetCode < 0) << "On error ExecuteAndWait should return 0 or " |
| 297 | "positive value indicating the result code"; |
| 298 | ASSERT_TRUE(ExecutionFailed); |
| 299 | ASSERT_FALSE(Error.empty()); |
| 300 | } |
| 301 | |
| 302 | { |
| 303 | std::string Error; |
| 304 | bool ExecutionFailed; |
Craig Topper | 66f09ad | 2014-06-08 22:29:17 +0000 | [diff] [blame] | 305 | ProcessInfo PI = ExecuteNoWait(Executable, argv, nullptr, nullptr, 0, |
| 306 | &Error, &ExecutionFailed); |
Reid Kleckner | c2e2311 | 2016-02-03 21:41:12 +0000 | [diff] [blame] | 307 | ASSERT_EQ(PI.Pid, ProcessInfo::InvalidPid) |
Tareq A. Siraj | d88b983 | 2013-10-01 14:28:18 +0000 | [diff] [blame] | 308 | << "On error ExecuteNoWait should return an invalid ProcessInfo"; |
| 309 | ASSERT_TRUE(ExecutionFailed); |
| 310 | ASSERT_FALSE(Error.empty()); |
| 311 | } |
Duncan P. N. Exon Smith | 91d3cfe | 2016-04-05 20:45:04 +0000 | [diff] [blame] | 312 | |
Tareq A. Siraj | d88b983 | 2013-10-01 14:28:18 +0000 | [diff] [blame] | 313 | } |
| 314 | |
Rafael Espindola | 9c35966 | 2014-09-03 20:02:00 +0000 | [diff] [blame] | 315 | #ifdef LLVM_ON_WIN32 |
| 316 | const char utf16le_text[] = |
| 317 | "\x6c\x00\x69\x00\x6e\x00\x67\x00\xfc\x00\x69\x00\xe7\x00\x61\x00"; |
| 318 | const char utf16be_text[] = |
| 319 | "\x00\x6c\x00\x69\x00\x6e\x00\x67\x00\xfc\x00\x69\x00\xe7\x00\x61"; |
| 320 | #endif |
| 321 | const char utf8_text[] = "\x6c\x69\x6e\x67\xc3\xbc\x69\xc3\xa7\x61"; |
| 322 | |
| 323 | TEST(ProgramTest, TestWriteWithSystemEncoding) { |
| 324 | SmallString<128> TestDirectory; |
| 325 | ASSERT_NO_ERROR(fs::createUniqueDirectory("program-test", TestDirectory)); |
| 326 | errs() << "Test Directory: " << TestDirectory << '\n'; |
| 327 | errs().flush(); |
| 328 | SmallString<128> file_pathname(TestDirectory); |
| 329 | path::append(file_pathname, "international-file.txt"); |
| 330 | // Only on Windows we should encode in UTF16. For other systems, use UTF8 |
| 331 | ASSERT_NO_ERROR(sys::writeFileWithEncoding(file_pathname.c_str(), utf8_text, |
| 332 | sys::WEM_UTF16)); |
| 333 | int fd = 0; |
| 334 | ASSERT_NO_ERROR(fs::openFileForRead(file_pathname.c_str(), fd)); |
| 335 | #if defined(LLVM_ON_WIN32) |
| 336 | char buf[18]; |
| 337 | ASSERT_EQ(::read(fd, buf, 18), 18); |
| 338 | if (strncmp(buf, "\xfe\xff", 2) == 0) { // UTF16-BE |
| 339 | ASSERT_EQ(strncmp(&buf[2], utf16be_text, 16), 0); |
| 340 | } else if (strncmp(buf, "\xff\xfe", 2) == 0) { // UTF16-LE |
| 341 | ASSERT_EQ(strncmp(&buf[2], utf16le_text, 16), 0); |
| 342 | } else { |
| 343 | FAIL() << "Invalid BOM in UTF-16 file"; |
| 344 | } |
| 345 | #else |
| 346 | char buf[10]; |
| 347 | ASSERT_EQ(::read(fd, buf, 10), 10); |
| 348 | ASSERT_EQ(strncmp(buf, utf8_text, 10), 0); |
| 349 | #endif |
| 350 | ::close(fd); |
| 351 | ASSERT_NO_ERROR(fs::remove(file_pathname.str())); |
| 352 | ASSERT_NO_ERROR(fs::remove(TestDirectory.str())); |
| 353 | } |
| 354 | |
Reid Kleckner | 74679a9 | 2013-04-22 19:03:55 +0000 | [diff] [blame] | 355 | } // end anonymous namespace |