Reid Kleckner | 74679a9 | 2013-04-22 19:03:55 +0000 | [diff] [blame] | 1 | //===- unittest/Support/ProgramTest.cpp -----------------------------------===// |
| 2 | // |
Chandler Carruth | 2946cd7 | 2019-01-19 08:50:56 +0000 | [diff] [blame] | 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| 4 | // See https://llvm.org/LICENSE.txt for license information. |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
Reid Kleckner | 74679a9 | 2013-04-22 19:03:55 +0000 | [diff] [blame] | 6 | // |
| 7 | //===----------------------------------------------------------------------===// |
| 8 | |
Chandler Carruth | 9a67b07 | 2017-06-06 11:06:56 +0000 | [diff] [blame] | 9 | #include "llvm/Support/Program.h" |
Nico Weber | 432a388 | 2018-04-30 14:59:11 +0000 | [diff] [blame] | 10 | #include "llvm/Config/llvm-config.h" |
Reid Kleckner | 74679a9 | 2013-04-22 19:03:55 +0000 | [diff] [blame] | 11 | #include "llvm/Support/CommandLine.h" |
Chandler Carruth | 9a67b07 | 2017-06-06 11:06:56 +0000 | [diff] [blame] | 12 | #include "llvm/Support/ConvertUTF.h" |
Rafael Espindola | e03dfd9 | 2013-06-26 05:01:35 +0000 | [diff] [blame] | 13 | #include "llvm/Support/FileSystem.h" |
Reid Kleckner | 74679a9 | 2013-04-22 19:03:55 +0000 | [diff] [blame] | 14 | #include "llvm/Support/Path.h" |
Reid Kleckner | 74679a9 | 2013-04-22 19:03:55 +0000 | [diff] [blame] | 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 | } |
Nico Weber | 712e8d2 | 2018-04-29 00:45:03 +0000 | [diff] [blame] | 29 | #elif defined(_WIN32) |
Tareq A. Siraj | d88b983 | 2013-10-01 14:28:18 +0000 | [diff] [blame] | 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 { |
Zachary Turner | 08426e1 | 2018-06-12 17:43:52 +0000 | [diff] [blame] | 62 | std::vector<StringRef> EnvTable; |
Pawel Bylica | 85ca294 | 2015-11-04 08:25:20 +0000 | [diff] [blame] | 63 | std::vector<std::string> EnvStorage; |
| 64 | |
| 65 | protected: |
| 66 | void SetUp() override { |
| 67 | auto EnvP = [] { |
Nico Weber | 712e8d2 | 2018-04-29 00:45:03 +0000 | [diff] [blame] | 68 | #if defined(_WIN32) |
Pawel Bylica | 85ca294 | 2015-11-04 08:25:20 +0000 | [diff] [blame] | 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 | |
Zachary Turner | 08426e1 | 2018-06-12 17:43:52 +0000 | [diff] [blame] | 79 | auto prepareEnvVar = [this](decltype(*EnvP) Var) -> StringRef { |
Nico Weber | 712e8d2 | 2018-04-29 00:45:03 +0000 | [diff] [blame] | 80 | #if defined(_WIN32) |
Pawel Bylica | 85ca294 | 2015-11-04 08:25:20 +0000 | [diff] [blame] | 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); |
Zachary Turner | 08426e1 | 2018-06-12 17:43:52 +0000 | [diff] [blame] | 88 | return EnvStorage.back(); |
Pawel Bylica | 85ca294 | 2015-11-04 08:25:20 +0000 | [diff] [blame] | 89 | #else |
Malcolm Parsons | 17d266b | 2017-01-13 17:12:16 +0000 | [diff] [blame] | 90 | (void)this; |
Zachary Turner | 08426e1 | 2018-06-12 17:43:52 +0000 | [diff] [blame] | 91 | return StringRef(Var); |
Pawel Bylica | 85ca294 | 2015-11-04 08:25:20 +0000 | [diff] [blame] | 92 | #endif |
| 93 | }; |
| 94 | |
| 95 | while (*EnvP != nullptr) { |
| 96 | EnvTable.emplace_back(prepareEnvVar(*EnvP)); |
| 97 | ++EnvP; |
| 98 | } |
Reid Kleckner | de0c260 | 2013-04-23 13:15:51 +0000 | [diff] [blame] | 99 | } |
Pawel Bylica | 85ca294 | 2015-11-04 08:25:20 +0000 | [diff] [blame] | 100 | |
| 101 | void TearDown() override { |
| 102 | EnvTable.clear(); |
| 103 | EnvStorage.clear(); |
| 104 | } |
| 105 | |
Zachary Turner | 08426e1 | 2018-06-12 17:43:52 +0000 | [diff] [blame] | 106 | void addEnvVar(StringRef Var) { EnvTable.emplace_back(Var); } |
Pawel Bylica | 85ca294 | 2015-11-04 08:25:20 +0000 | [diff] [blame] | 107 | |
Zachary Turner | 08426e1 | 2018-06-12 17:43:52 +0000 | [diff] [blame] | 108 | ArrayRef<StringRef> getEnviron() const { return EnvTable; } |
Pawel Bylica | 85ca294 | 2015-11-04 08:25:20 +0000 | [diff] [blame] | 109 | }; |
Reid Kleckner | de0c260 | 2013-04-23 13:15:51 +0000 | [diff] [blame] | 110 | |
Nico Weber | 712e8d2 | 2018-04-29 00:45:03 +0000 | [diff] [blame] | 111 | #ifdef _WIN32 |
Pawel Bylica | 85ca294 | 2015-11-04 08:25:20 +0000 | [diff] [blame] | 112 | TEST_F(ProgramEnvTest, CreateProcessLongPath) { |
Paul Robinson | c38deee | 2014-11-24 18:05:29 +0000 | [diff] [blame] | 113 | if (getenv("LLVM_PROGRAM_TEST_LONG_PATH")) |
| 114 | exit(0); |
| 115 | |
| 116 | // getMainExecutable returns an absolute path; prepend the long-path prefix. |
| 117 | std::string MyAbsExe = |
| 118 | sys::fs::getMainExecutable(TestMainArgv0, &ProgramTestStringArg1); |
| 119 | std::string MyExe; |
| 120 | if (!StringRef(MyAbsExe).startswith("\\\\?\\")) |
| 121 | MyExe.append("\\\\?\\"); |
| 122 | MyExe.append(MyAbsExe); |
| 123 | |
Zachary Turner | 08426e1 | 2018-06-12 17:43:52 +0000 | [diff] [blame] | 124 | StringRef ArgV[] = {MyExe, |
| 125 | "--gtest_filter=ProgramEnvTest.CreateProcessLongPath"}; |
Paul Robinson | c38deee | 2014-11-24 18:05:29 +0000 | [diff] [blame] | 126 | |
| 127 | // Add LLVM_PROGRAM_TEST_LONG_PATH to the environment of the child. |
Pawel Bylica | 85ca294 | 2015-11-04 08:25:20 +0000 | [diff] [blame] | 128 | addEnvVar("LLVM_PROGRAM_TEST_LONG_PATH=1"); |
Paul Robinson | c38deee | 2014-11-24 18:05:29 +0000 | [diff] [blame] | 129 | |
| 130 | // Redirect stdout to a long path. |
| 131 | SmallString<128> TestDirectory; |
| 132 | ASSERT_NO_ERROR( |
| 133 | fs::createUniqueDirectory("program-redirect-test", TestDirectory)); |
| 134 | SmallString<256> LongPath(TestDirectory); |
| 135 | LongPath.push_back('\\'); |
| 136 | // MAX_PATH = 260 |
| 137 | LongPath.append(260 - TestDirectory.size(), 'a'); |
Paul Robinson | c38deee | 2014-11-24 18:05:29 +0000 | [diff] [blame] | 138 | |
| 139 | std::string Error; |
| 140 | bool ExecutionFailed; |
Alexander Kornienko | 208eecd | 2017-09-13 17:03:37 +0000 | [diff] [blame] | 141 | Optional<StringRef> Redirects[] = {None, LongPath.str(), None}; |
Pawel Bylica | 85ca294 | 2015-11-04 08:25:20 +0000 | [diff] [blame] | 142 | int RC = ExecuteAndWait(MyExe, ArgV, getEnviron(), Redirects, |
Paul Robinson | c38deee | 2014-11-24 18:05:29 +0000 | [diff] [blame] | 143 | /*secondsToWait=*/ 10, /*memoryLimit=*/ 0, &Error, |
| 144 | &ExecutionFailed); |
| 145 | EXPECT_FALSE(ExecutionFailed) << Error; |
| 146 | EXPECT_EQ(0, RC); |
| 147 | |
| 148 | // Remove the long stdout. |
| 149 | ASSERT_NO_ERROR(fs::remove(Twine(LongPath))); |
| 150 | ASSERT_NO_ERROR(fs::remove(Twine(TestDirectory))); |
| 151 | } |
| 152 | #endif |
| 153 | |
Pawel Bylica | 85ca294 | 2015-11-04 08:25:20 +0000 | [diff] [blame] | 154 | TEST_F(ProgramEnvTest, CreateProcessTrailingSlash) { |
Reid Kleckner | 74679a9 | 2013-04-22 19:03:55 +0000 | [diff] [blame] | 155 | if (getenv("LLVM_PROGRAM_TEST_CHILD")) { |
| 156 | if (ProgramTestStringArg1 == "has\\\\ trailing\\" && |
| 157 | ProgramTestStringArg2 == "has\\\\ trailing\\") { |
| 158 | exit(0); // Success! The arguments were passed and parsed. |
| 159 | } |
| 160 | exit(1); |
| 161 | } |
| 162 | |
Rafael Espindola | e03dfd9 | 2013-06-26 05:01:35 +0000 | [diff] [blame] | 163 | std::string my_exe = |
| 164 | sys::fs::getMainExecutable(TestMainArgv0, &ProgramTestStringArg1); |
Zachary Turner | 08426e1 | 2018-06-12 17:43:52 +0000 | [diff] [blame] | 165 | StringRef argv[] = { |
| 166 | my_exe, |
| 167 | "--gtest_filter=ProgramEnvTest.CreateProcessTrailingSlash", |
| 168 | "-program-test-string-arg1", |
| 169 | "has\\\\ trailing\\", |
| 170 | "-program-test-string-arg2", |
| 171 | "has\\\\ trailing\\"}; |
Reid Kleckner | de0c260 | 2013-04-23 13:15:51 +0000 | [diff] [blame] | 172 | |
| 173 | // Add LLVM_PROGRAM_TEST_CHILD to the environment of the child. |
Pawel Bylica | 85ca294 | 2015-11-04 08:25:20 +0000 | [diff] [blame] | 174 | addEnvVar("LLVM_PROGRAM_TEST_CHILD=1"); |
Reid Kleckner | de0c260 | 2013-04-23 13:15:51 +0000 | [diff] [blame] | 175 | |
Reid Kleckner | 74679a9 | 2013-04-22 19:03:55 +0000 | [diff] [blame] | 176 | std::string error; |
| 177 | bool ExecutionFailed; |
| 178 | // Redirect stdout and stdin to NUL, but let stderr through. |
Nico Weber | 712e8d2 | 2018-04-29 00:45:03 +0000 | [diff] [blame] | 179 | #ifdef _WIN32 |
Rafael Espindola | 7c1023a | 2013-06-13 20:25:38 +0000 | [diff] [blame] | 180 | StringRef nul("NUL"); |
Reid Kleckner | 74679a9 | 2013-04-22 19:03:55 +0000 | [diff] [blame] | 181 | #else |
Rafael Espindola | 7c1023a | 2013-06-13 20:25:38 +0000 | [diff] [blame] | 182 | StringRef nul("/dev/null"); |
Reid Kleckner | 74679a9 | 2013-04-22 19:03:55 +0000 | [diff] [blame] | 183 | #endif |
Alexander Kornienko | 208eecd | 2017-09-13 17:03:37 +0000 | [diff] [blame] | 184 | Optional<StringRef> redirects[] = { nul, nul, None }; |
Pawel Bylica | 85ca294 | 2015-11-04 08:25:20 +0000 | [diff] [blame] | 185 | int rc = ExecuteAndWait(my_exe, argv, getEnviron(), redirects, |
Rafael Espindola | 7c1023a | 2013-06-13 20:25:38 +0000 | [diff] [blame] | 186 | /*secondsToWait=*/ 10, /*memoryLimit=*/ 0, &error, |
| 187 | &ExecutionFailed); |
Reid Kleckner | 74679a9 | 2013-04-22 19:03:55 +0000 | [diff] [blame] | 188 | EXPECT_FALSE(ExecutionFailed) << error; |
| 189 | EXPECT_EQ(0, rc); |
| 190 | } |
| 191 | |
Pawel Bylica | 85ca294 | 2015-11-04 08:25:20 +0000 | [diff] [blame] | 192 | TEST_F(ProgramEnvTest, TestExecuteNoWait) { |
Tareq A. Siraj | d88b983 | 2013-10-01 14:28:18 +0000 | [diff] [blame] | 193 | using namespace llvm::sys; |
| 194 | |
| 195 | if (getenv("LLVM_PROGRAM_TEST_EXECUTE_NO_WAIT")) { |
| 196 | sleep_for(/*seconds*/ 1); |
| 197 | exit(0); |
| 198 | } |
| 199 | |
| 200 | std::string Executable = |
| 201 | sys::fs::getMainExecutable(TestMainArgv0, &ProgramTestStringArg1); |
Zachary Turner | 08426e1 | 2018-06-12 17:43:52 +0000 | [diff] [blame] | 202 | StringRef argv[] = {Executable, |
| 203 | "--gtest_filter=ProgramEnvTest.TestExecuteNoWait"}; |
Tareq A. Siraj | d88b983 | 2013-10-01 14:28:18 +0000 | [diff] [blame] | 204 | |
| 205 | // 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] | 206 | addEnvVar("LLVM_PROGRAM_TEST_EXECUTE_NO_WAIT=1"); |
Tareq A. Siraj | d88b983 | 2013-10-01 14:28:18 +0000 | [diff] [blame] | 207 | |
| 208 | std::string Error; |
| 209 | bool ExecutionFailed; |
Alexander Kornienko | 208eecd | 2017-09-13 17:03:37 +0000 | [diff] [blame] | 210 | ProcessInfo PI1 = ExecuteNoWait(Executable, argv, getEnviron(), {}, 0, &Error, |
| 211 | &ExecutionFailed); |
Tareq A. Siraj | d88b983 | 2013-10-01 14:28:18 +0000 | [diff] [blame] | 212 | ASSERT_FALSE(ExecutionFailed) << Error; |
Reid Kleckner | c2e2311 | 2016-02-03 21:41:12 +0000 | [diff] [blame] | 213 | ASSERT_NE(PI1.Pid, ProcessInfo::InvalidPid) << "Invalid process id"; |
Tareq A. Siraj | d88b983 | 2013-10-01 14:28:18 +0000 | [diff] [blame] | 214 | |
| 215 | unsigned LoopCount = 0; |
| 216 | |
| 217 | // Test that Wait() with WaitUntilTerminates=true works. In this case, |
| 218 | // LoopCount should only be incremented once. |
| 219 | while (true) { |
| 220 | ++LoopCount; |
Zachary Turner | 07670b3 | 2016-06-29 21:48:26 +0000 | [diff] [blame] | 221 | ProcessInfo WaitResult = llvm::sys::Wait(PI1, 0, true, &Error); |
Tareq A. Siraj | d88b983 | 2013-10-01 14:28:18 +0000 | [diff] [blame] | 222 | ASSERT_TRUE(Error.empty()); |
| 223 | if (WaitResult.Pid == PI1.Pid) |
| 224 | break; |
| 225 | } |
| 226 | |
| 227 | EXPECT_EQ(LoopCount, 1u) << "LoopCount should be 1"; |
| 228 | |
Alexander Kornienko | 208eecd | 2017-09-13 17:03:37 +0000 | [diff] [blame] | 229 | ProcessInfo PI2 = ExecuteNoWait(Executable, argv, getEnviron(), {}, 0, &Error, |
| 230 | &ExecutionFailed); |
Tareq A. Siraj | d88b983 | 2013-10-01 14:28:18 +0000 | [diff] [blame] | 231 | ASSERT_FALSE(ExecutionFailed) << Error; |
Reid Kleckner | c2e2311 | 2016-02-03 21:41:12 +0000 | [diff] [blame] | 232 | ASSERT_NE(PI2.Pid, ProcessInfo::InvalidPid) << "Invalid process id"; |
Tareq A. Siraj | d88b983 | 2013-10-01 14:28:18 +0000 | [diff] [blame] | 233 | |
| 234 | // Test that Wait() with SecondsToWait=0 performs a non-blocking wait. In this |
| 235 | // cse, LoopCount should be greater than 1 (more than one increment occurs). |
| 236 | while (true) { |
| 237 | ++LoopCount; |
Zachary Turner | 07670b3 | 2016-06-29 21:48:26 +0000 | [diff] [blame] | 238 | ProcessInfo WaitResult = llvm::sys::Wait(PI2, 0, false, &Error); |
Tareq A. Siraj | d88b983 | 2013-10-01 14:28:18 +0000 | [diff] [blame] | 239 | ASSERT_TRUE(Error.empty()); |
| 240 | if (WaitResult.Pid == PI2.Pid) |
| 241 | break; |
| 242 | } |
| 243 | |
| 244 | ASSERT_GT(LoopCount, 1u) << "LoopCount should be >1"; |
| 245 | } |
| 246 | |
Pawel Bylica | 85ca294 | 2015-11-04 08:25:20 +0000 | [diff] [blame] | 247 | TEST_F(ProgramEnvTest, TestExecuteAndWaitTimeout) { |
Peter Collingbourne | ec1aaca | 2014-05-31 01:36:02 +0000 | [diff] [blame] | 248 | using namespace llvm::sys; |
| 249 | |
| 250 | if (getenv("LLVM_PROGRAM_TEST_TIMEOUT")) { |
| 251 | sleep_for(/*seconds*/ 10); |
| 252 | exit(0); |
| 253 | } |
| 254 | |
| 255 | std::string Executable = |
| 256 | sys::fs::getMainExecutable(TestMainArgv0, &ProgramTestStringArg1); |
Zachary Turner | 08426e1 | 2018-06-12 17:43:52 +0000 | [diff] [blame] | 257 | StringRef argv[] = { |
| 258 | Executable, "--gtest_filter=ProgramEnvTest.TestExecuteAndWaitTimeout"}; |
Peter Collingbourne | ec1aaca | 2014-05-31 01:36:02 +0000 | [diff] [blame] | 259 | |
| 260 | // Add LLVM_PROGRAM_TEST_TIMEOUT to the environment of the child. |
Pawel Bylica | 85ca294 | 2015-11-04 08:25:20 +0000 | [diff] [blame] | 261 | addEnvVar("LLVM_PROGRAM_TEST_TIMEOUT=1"); |
Peter Collingbourne | ec1aaca | 2014-05-31 01:36:02 +0000 | [diff] [blame] | 262 | |
| 263 | std::string Error; |
| 264 | bool ExecutionFailed; |
| 265 | int RetCode = |
Alexander Kornienko | 208eecd | 2017-09-13 17:03:37 +0000 | [diff] [blame] | 266 | ExecuteAndWait(Executable, argv, getEnviron(), {}, /*secondsToWait=*/1, 0, |
Peter Collingbourne | ec1aaca | 2014-05-31 01:36:02 +0000 | [diff] [blame] | 267 | &Error, &ExecutionFailed); |
| 268 | ASSERT_EQ(-2, RetCode); |
| 269 | } |
| 270 | |
Tareq A. Siraj | d88b983 | 2013-10-01 14:28:18 +0000 | [diff] [blame] | 271 | TEST(ProgramTest, TestExecuteNegative) { |
| 272 | std::string Executable = "i_dont_exist"; |
Zachary Turner | 08426e1 | 2018-06-12 17:43:52 +0000 | [diff] [blame] | 273 | StringRef argv[] = {Executable}; |
Tareq A. Siraj | d88b983 | 2013-10-01 14:28:18 +0000 | [diff] [blame] | 274 | |
| 275 | { |
| 276 | std::string Error; |
| 277 | bool ExecutionFailed; |
Zachary Turner | 08426e1 | 2018-06-12 17:43:52 +0000 | [diff] [blame] | 278 | int RetCode = ExecuteAndWait(Executable, argv, llvm::None, {}, 0, 0, &Error, |
Alexander Kornienko | 208eecd | 2017-09-13 17:03:37 +0000 | [diff] [blame] | 279 | &ExecutionFailed); |
Tareq A. Siraj | d88b983 | 2013-10-01 14:28:18 +0000 | [diff] [blame] | 280 | ASSERT_TRUE(RetCode < 0) << "On error ExecuteAndWait should return 0 or " |
| 281 | "positive value indicating the result code"; |
| 282 | ASSERT_TRUE(ExecutionFailed); |
| 283 | ASSERT_FALSE(Error.empty()); |
| 284 | } |
| 285 | |
| 286 | { |
| 287 | std::string Error; |
| 288 | bool ExecutionFailed; |
Zachary Turner | 08426e1 | 2018-06-12 17:43:52 +0000 | [diff] [blame] | 289 | ProcessInfo PI = ExecuteNoWait(Executable, argv, llvm::None, {}, 0, &Error, |
Alexander Kornienko | 208eecd | 2017-09-13 17:03:37 +0000 | [diff] [blame] | 290 | &ExecutionFailed); |
Reid Kleckner | c2e2311 | 2016-02-03 21:41:12 +0000 | [diff] [blame] | 291 | ASSERT_EQ(PI.Pid, ProcessInfo::InvalidPid) |
Tareq A. Siraj | d88b983 | 2013-10-01 14:28:18 +0000 | [diff] [blame] | 292 | << "On error ExecuteNoWait should return an invalid ProcessInfo"; |
| 293 | ASSERT_TRUE(ExecutionFailed); |
| 294 | ASSERT_FALSE(Error.empty()); |
| 295 | } |
Duncan P. N. Exon Smith | 91d3cfe | 2016-04-05 20:45:04 +0000 | [diff] [blame] | 296 | |
Tareq A. Siraj | d88b983 | 2013-10-01 14:28:18 +0000 | [diff] [blame] | 297 | } |
| 298 | |
Nico Weber | 712e8d2 | 2018-04-29 00:45:03 +0000 | [diff] [blame] | 299 | #ifdef _WIN32 |
Rafael Espindola | 9c35966 | 2014-09-03 20:02:00 +0000 | [diff] [blame] | 300 | const char utf16le_text[] = |
| 301 | "\x6c\x00\x69\x00\x6e\x00\x67\x00\xfc\x00\x69\x00\xe7\x00\x61\x00"; |
| 302 | const char utf16be_text[] = |
| 303 | "\x00\x6c\x00\x69\x00\x6e\x00\x67\x00\xfc\x00\x69\x00\xe7\x00\x61"; |
| 304 | #endif |
| 305 | const char utf8_text[] = "\x6c\x69\x6e\x67\xc3\xbc\x69\xc3\xa7\x61"; |
| 306 | |
| 307 | TEST(ProgramTest, TestWriteWithSystemEncoding) { |
| 308 | SmallString<128> TestDirectory; |
| 309 | ASSERT_NO_ERROR(fs::createUniqueDirectory("program-test", TestDirectory)); |
| 310 | errs() << "Test Directory: " << TestDirectory << '\n'; |
| 311 | errs().flush(); |
| 312 | SmallString<128> file_pathname(TestDirectory); |
| 313 | path::append(file_pathname, "international-file.txt"); |
| 314 | // Only on Windows we should encode in UTF16. For other systems, use UTF8 |
| 315 | ASSERT_NO_ERROR(sys::writeFileWithEncoding(file_pathname.c_str(), utf8_text, |
| 316 | sys::WEM_UTF16)); |
| 317 | int fd = 0; |
| 318 | ASSERT_NO_ERROR(fs::openFileForRead(file_pathname.c_str(), fd)); |
Nico Weber | 712e8d2 | 2018-04-29 00:45:03 +0000 | [diff] [blame] | 319 | #if defined(_WIN32) |
Rafael Espindola | 9c35966 | 2014-09-03 20:02:00 +0000 | [diff] [blame] | 320 | char buf[18]; |
| 321 | ASSERT_EQ(::read(fd, buf, 18), 18); |
| 322 | if (strncmp(buf, "\xfe\xff", 2) == 0) { // UTF16-BE |
| 323 | ASSERT_EQ(strncmp(&buf[2], utf16be_text, 16), 0); |
| 324 | } else if (strncmp(buf, "\xff\xfe", 2) == 0) { // UTF16-LE |
| 325 | ASSERT_EQ(strncmp(&buf[2], utf16le_text, 16), 0); |
| 326 | } else { |
| 327 | FAIL() << "Invalid BOM in UTF-16 file"; |
| 328 | } |
| 329 | #else |
| 330 | char buf[10]; |
| 331 | ASSERT_EQ(::read(fd, buf, 10), 10); |
| 332 | ASSERT_EQ(strncmp(buf, utf8_text, 10), 0); |
| 333 | #endif |
| 334 | ::close(fd); |
| 335 | ASSERT_NO_ERROR(fs::remove(file_pathname.str())); |
| 336 | ASSERT_NO_ERROR(fs::remove(TestDirectory.str())); |
| 337 | } |
| 338 | |
Reid Kleckner | 74679a9 | 2013-04-22 19:03:55 +0000 | [diff] [blame] | 339 | } // end anonymous namespace |