Mercurial > hg > CbC > CbC_llvm
comparison unittests/Support/ProgramTest.cpp @ 147:c2174574ed3a
LLVM 10
author | Shinji KONO <kono@ie.u-ryukyu.ac.jp> |
---|---|
date | Wed, 14 Aug 2019 16:55:33 +0900 |
parents | 803732b1fca8 |
children |
comparison
equal
deleted
inserted
replaced
134:3a76565eade5 | 147:c2174574ed3a |
---|---|
1 //===- unittest/Support/ProgramTest.cpp -----------------------------------===// | 1 //===- unittest/Support/ProgramTest.cpp -----------------------------------===// |
2 // | 2 // |
3 // The LLVM Compiler Infrastructure | 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 // | 4 // See https://llvm.org/LICENSE.txt for license information. |
5 // This file is distributed under the University of Illinois Open Source | 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 // License. See LICENSE.TXT for details. | |
7 // | 6 // |
8 //===----------------------------------------------------------------------===// | 7 //===----------------------------------------------------------------------===// |
9 | 8 |
10 #include "llvm/Support/Program.h" | 9 #include "llvm/Support/Program.h" |
10 #include "llvm/Config/llvm-config.h" | |
11 #include "llvm/Support/CommandLine.h" | 11 #include "llvm/Support/CommandLine.h" |
12 #include "llvm/Support/ConvertUTF.h" | 12 #include "llvm/Support/ConvertUTF.h" |
13 #include "llvm/Support/FileSystem.h" | 13 #include "llvm/Support/FileSystem.h" |
14 #include "llvm/Support/Path.h" | 14 #include "llvm/Support/Path.h" |
15 #include "gtest/gtest.h" | 15 #include "gtest/gtest.h" |
24 #if defined(LLVM_ON_UNIX) | 24 #if defined(LLVM_ON_UNIX) |
25 #include <unistd.h> | 25 #include <unistd.h> |
26 void sleep_for(unsigned int seconds) { | 26 void sleep_for(unsigned int seconds) { |
27 sleep(seconds); | 27 sleep(seconds); |
28 } | 28 } |
29 #elif defined(LLVM_ON_WIN32) | 29 #elif defined(_WIN32) |
30 #include <windows.h> | 30 #include <windows.h> |
31 void sleep_for(unsigned int seconds) { | 31 void sleep_for(unsigned int seconds) { |
32 Sleep(seconds * 1000); | 32 Sleep(seconds * 1000); |
33 } | 33 } |
34 #else | 34 #else |
57 ProgramTestStringArg1("program-test-string-arg1"); | 57 ProgramTestStringArg1("program-test-string-arg1"); |
58 static cl::opt<std::string> | 58 static cl::opt<std::string> |
59 ProgramTestStringArg2("program-test-string-arg2"); | 59 ProgramTestStringArg2("program-test-string-arg2"); |
60 | 60 |
61 class ProgramEnvTest : public testing::Test { | 61 class ProgramEnvTest : public testing::Test { |
62 std::vector<const char *> EnvTable; | 62 std::vector<StringRef> EnvTable; |
63 std::vector<std::string> EnvStorage; | 63 std::vector<std::string> EnvStorage; |
64 | 64 |
65 protected: | 65 protected: |
66 void SetUp() override { | 66 void SetUp() override { |
67 auto EnvP = [] { | 67 auto EnvP = [] { |
68 #if defined(LLVM_ON_WIN32) | 68 #if defined(_WIN32) |
69 _wgetenv(L"TMP"); // Populate _wenviron, initially is null | 69 _wgetenv(L"TMP"); // Populate _wenviron, initially is null |
70 return _wenviron; | 70 return _wenviron; |
71 #elif defined(__APPLE__) | 71 #elif defined(__APPLE__) |
72 return *_NSGetEnviron(); | 72 return *_NSGetEnviron(); |
73 #else | 73 #else |
74 return environ; | 74 return environ; |
75 #endif | 75 #endif |
76 }(); | 76 }(); |
77 ASSERT_TRUE(EnvP); | 77 ASSERT_TRUE(EnvP); |
78 | 78 |
79 auto prepareEnvVar = [this](decltype(*EnvP) Var) { | 79 auto prepareEnvVar = [this](decltype(*EnvP) Var) -> StringRef { |
80 #if defined(LLVM_ON_WIN32) | 80 #if defined(_WIN32) |
81 // On Windows convert UTF16 encoded variable to UTF8 | 81 // On Windows convert UTF16 encoded variable to UTF8 |
82 auto Len = wcslen(Var); | 82 auto Len = wcslen(Var); |
83 ArrayRef<char> Ref{reinterpret_cast<char const *>(Var), | 83 ArrayRef<char> Ref{reinterpret_cast<char const *>(Var), |
84 Len * sizeof(*Var)}; | 84 Len * sizeof(*Var)}; |
85 EnvStorage.emplace_back(); | 85 EnvStorage.emplace_back(); |
86 auto convStatus = convertUTF16ToUTF8String(Ref, EnvStorage.back()); | 86 auto convStatus = convertUTF16ToUTF8String(Ref, EnvStorage.back()); |
87 EXPECT_TRUE(convStatus); | 87 EXPECT_TRUE(convStatus); |
88 return EnvStorage.back().c_str(); | 88 return EnvStorage.back(); |
89 #else | 89 #else |
90 (void)this; | 90 (void)this; |
91 return Var; | 91 return StringRef(Var); |
92 #endif | 92 #endif |
93 }; | 93 }; |
94 | 94 |
95 while (*EnvP != nullptr) { | 95 while (*EnvP != nullptr) { |
96 EnvTable.emplace_back(prepareEnvVar(*EnvP)); | 96 EnvTable.emplace_back(prepareEnvVar(*EnvP)); |
101 void TearDown() override { | 101 void TearDown() override { |
102 EnvTable.clear(); | 102 EnvTable.clear(); |
103 EnvStorage.clear(); | 103 EnvStorage.clear(); |
104 } | 104 } |
105 | 105 |
106 void addEnvVar(const char *Var) { | 106 void addEnvVar(StringRef Var) { EnvTable.emplace_back(Var); } |
107 ASSERT_TRUE(EnvTable.empty() || EnvTable.back()) << "Env table sealed"; | 107 |
108 EnvTable.emplace_back(Var); | 108 ArrayRef<StringRef> getEnviron() const { return EnvTable; } |
109 } | |
110 | |
111 const char **getEnviron() { | |
112 if (EnvTable.back() != nullptr) | |
113 EnvTable.emplace_back(nullptr); // Seal table. | |
114 return &EnvTable[0]; | |
115 } | |
116 }; | 109 }; |
117 | 110 |
118 #ifdef LLVM_ON_WIN32 | 111 #ifdef _WIN32 |
119 TEST_F(ProgramEnvTest, CreateProcessLongPath) { | 112 TEST_F(ProgramEnvTest, CreateProcessLongPath) { |
120 if (getenv("LLVM_PROGRAM_TEST_LONG_PATH")) | 113 if (getenv("LLVM_PROGRAM_TEST_LONG_PATH")) |
121 exit(0); | 114 exit(0); |
122 | 115 |
123 // getMainExecutable returns an absolute path; prepend the long-path prefix. | 116 // getMainExecutable returns an absolute path; prepend the long-path prefix. |
126 std::string MyExe; | 119 std::string MyExe; |
127 if (!StringRef(MyAbsExe).startswith("\\\\?\\")) | 120 if (!StringRef(MyAbsExe).startswith("\\\\?\\")) |
128 MyExe.append("\\\\?\\"); | 121 MyExe.append("\\\\?\\"); |
129 MyExe.append(MyAbsExe); | 122 MyExe.append(MyAbsExe); |
130 | 123 |
131 const char *ArgV[] = { | 124 StringRef ArgV[] = {MyExe, |
132 MyExe.c_str(), | 125 "--gtest_filter=ProgramEnvTest.CreateProcessLongPath"}; |
133 "--gtest_filter=ProgramEnvTest.CreateProcessLongPath", | |
134 nullptr | |
135 }; | |
136 | 126 |
137 // Add LLVM_PROGRAM_TEST_LONG_PATH to the environment of the child. | 127 // Add LLVM_PROGRAM_TEST_LONG_PATH to the environment of the child. |
138 addEnvVar("LLVM_PROGRAM_TEST_LONG_PATH=1"); | 128 addEnvVar("LLVM_PROGRAM_TEST_LONG_PATH=1"); |
139 | 129 |
140 // Redirect stdout to a long path. | 130 // Redirect stdout to a long path. |
170 exit(1); | 160 exit(1); |
171 } | 161 } |
172 | 162 |
173 std::string my_exe = | 163 std::string my_exe = |
174 sys::fs::getMainExecutable(TestMainArgv0, &ProgramTestStringArg1); | 164 sys::fs::getMainExecutable(TestMainArgv0, &ProgramTestStringArg1); |
175 const char *argv[] = { | 165 StringRef argv[] = { |
176 my_exe.c_str(), | 166 my_exe, |
177 "--gtest_filter=ProgramEnvTest.CreateProcessTrailingSlash", | 167 "--gtest_filter=ProgramEnvTest.CreateProcessTrailingSlash", |
178 "-program-test-string-arg1", "has\\\\ trailing\\", | 168 "-program-test-string-arg1", |
179 "-program-test-string-arg2", "has\\\\ trailing\\", | 169 "has\\\\ trailing\\", |
180 nullptr | 170 "-program-test-string-arg2", |
181 }; | 171 "has\\\\ trailing\\"}; |
182 | 172 |
183 // Add LLVM_PROGRAM_TEST_CHILD to the environment of the child. | 173 // Add LLVM_PROGRAM_TEST_CHILD to the environment of the child. |
184 addEnvVar("LLVM_PROGRAM_TEST_CHILD=1"); | 174 addEnvVar("LLVM_PROGRAM_TEST_CHILD=1"); |
185 | 175 |
186 std::string error; | 176 std::string error; |
187 bool ExecutionFailed; | 177 bool ExecutionFailed; |
188 // Redirect stdout and stdin to NUL, but let stderr through. | 178 // Redirect stdout and stdin to NUL, but let stderr through. |
189 #ifdef LLVM_ON_WIN32 | 179 #ifdef _WIN32 |
190 StringRef nul("NUL"); | 180 StringRef nul("NUL"); |
191 #else | 181 #else |
192 StringRef nul("/dev/null"); | 182 StringRef nul("/dev/null"); |
193 #endif | 183 #endif |
194 Optional<StringRef> redirects[] = { nul, nul, None }; | 184 Optional<StringRef> redirects[] = { nul, nul, None }; |
207 exit(0); | 197 exit(0); |
208 } | 198 } |
209 | 199 |
210 std::string Executable = | 200 std::string Executable = |
211 sys::fs::getMainExecutable(TestMainArgv0, &ProgramTestStringArg1); | 201 sys::fs::getMainExecutable(TestMainArgv0, &ProgramTestStringArg1); |
212 const char *argv[] = { | 202 StringRef argv[] = {Executable, |
213 Executable.c_str(), | 203 "--gtest_filter=ProgramEnvTest.TestExecuteNoWait"}; |
214 "--gtest_filter=ProgramEnvTest.TestExecuteNoWait", | |
215 nullptr | |
216 }; | |
217 | 204 |
218 // Add LLVM_PROGRAM_TEST_EXECUTE_NO_WAIT to the environment of the child. | 205 // Add LLVM_PROGRAM_TEST_EXECUTE_NO_WAIT to the environment of the child. |
219 addEnvVar("LLVM_PROGRAM_TEST_EXECUTE_NO_WAIT=1"); | 206 addEnvVar("LLVM_PROGRAM_TEST_EXECUTE_NO_WAIT=1"); |
220 | 207 |
221 std::string Error; | 208 std::string Error; |
265 exit(0); | 252 exit(0); |
266 } | 253 } |
267 | 254 |
268 std::string Executable = | 255 std::string Executable = |
269 sys::fs::getMainExecutable(TestMainArgv0, &ProgramTestStringArg1); | 256 sys::fs::getMainExecutable(TestMainArgv0, &ProgramTestStringArg1); |
270 const char *argv[] = { | 257 StringRef argv[] = { |
271 Executable.c_str(), | 258 Executable, "--gtest_filter=ProgramEnvTest.TestExecuteAndWaitTimeout"}; |
272 "--gtest_filter=ProgramEnvTest.TestExecuteAndWaitTimeout", | |
273 nullptr | |
274 }; | |
275 | 259 |
276 // Add LLVM_PROGRAM_TEST_TIMEOUT to the environment of the child. | 260 // Add LLVM_PROGRAM_TEST_TIMEOUT to the environment of the child. |
277 addEnvVar("LLVM_PROGRAM_TEST_TIMEOUT=1"); | 261 addEnvVar("LLVM_PROGRAM_TEST_TIMEOUT=1"); |
278 | 262 |
279 std::string Error; | 263 std::string Error; |
284 ASSERT_EQ(-2, RetCode); | 268 ASSERT_EQ(-2, RetCode); |
285 } | 269 } |
286 | 270 |
287 TEST(ProgramTest, TestExecuteNegative) { | 271 TEST(ProgramTest, TestExecuteNegative) { |
288 std::string Executable = "i_dont_exist"; | 272 std::string Executable = "i_dont_exist"; |
289 const char *argv[] = { Executable.c_str(), nullptr }; | 273 StringRef argv[] = {Executable}; |
290 | 274 |
291 { | 275 { |
292 std::string Error; | 276 std::string Error; |
293 bool ExecutionFailed; | 277 bool ExecutionFailed; |
294 int RetCode = ExecuteAndWait(Executable, argv, nullptr, {}, 0, 0, &Error, | 278 int RetCode = ExecuteAndWait(Executable, argv, llvm::None, {}, 0, 0, &Error, |
295 &ExecutionFailed); | 279 &ExecutionFailed); |
296 ASSERT_TRUE(RetCode < 0) << "On error ExecuteAndWait should return 0 or " | 280 ASSERT_TRUE(RetCode < 0) << "On error ExecuteAndWait should return 0 or " |
297 "positive value indicating the result code"; | 281 "positive value indicating the result code"; |
298 ASSERT_TRUE(ExecutionFailed); | 282 ASSERT_TRUE(ExecutionFailed); |
299 ASSERT_FALSE(Error.empty()); | 283 ASSERT_FALSE(Error.empty()); |
300 } | 284 } |
301 | 285 |
302 { | 286 { |
303 std::string Error; | 287 std::string Error; |
304 bool ExecutionFailed; | 288 bool ExecutionFailed; |
305 ProcessInfo PI = ExecuteNoWait(Executable, argv, nullptr, {}, 0, &Error, | 289 ProcessInfo PI = ExecuteNoWait(Executable, argv, llvm::None, {}, 0, &Error, |
306 &ExecutionFailed); | 290 &ExecutionFailed); |
307 ASSERT_EQ(PI.Pid, ProcessInfo::InvalidPid) | 291 ASSERT_EQ(PI.Pid, ProcessInfo::InvalidPid) |
308 << "On error ExecuteNoWait should return an invalid ProcessInfo"; | 292 << "On error ExecuteNoWait should return an invalid ProcessInfo"; |
309 ASSERT_TRUE(ExecutionFailed); | 293 ASSERT_TRUE(ExecutionFailed); |
310 ASSERT_FALSE(Error.empty()); | 294 ASSERT_FALSE(Error.empty()); |
311 } | 295 } |
312 | 296 |
313 } | 297 } |
314 | 298 |
315 #ifdef LLVM_ON_WIN32 | 299 #ifdef _WIN32 |
316 const char utf16le_text[] = | 300 const char utf16le_text[] = |
317 "\x6c\x00\x69\x00\x6e\x00\x67\x00\xfc\x00\x69\x00\xe7\x00\x61\x00"; | 301 "\x6c\x00\x69\x00\x6e\x00\x67\x00\xfc\x00\x69\x00\xe7\x00\x61\x00"; |
318 const char utf16be_text[] = | 302 const char utf16be_text[] = |
319 "\x00\x6c\x00\x69\x00\x6e\x00\x67\x00\xfc\x00\x69\x00\xe7\x00\x61"; | 303 "\x00\x6c\x00\x69\x00\x6e\x00\x67\x00\xfc\x00\x69\x00\xe7\x00\x61"; |
320 #endif | 304 #endif |
330 // Only on Windows we should encode in UTF16. For other systems, use UTF8 | 314 // 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, | 315 ASSERT_NO_ERROR(sys::writeFileWithEncoding(file_pathname.c_str(), utf8_text, |
332 sys::WEM_UTF16)); | 316 sys::WEM_UTF16)); |
333 int fd = 0; | 317 int fd = 0; |
334 ASSERT_NO_ERROR(fs::openFileForRead(file_pathname.c_str(), fd)); | 318 ASSERT_NO_ERROR(fs::openFileForRead(file_pathname.c_str(), fd)); |
335 #if defined(LLVM_ON_WIN32) | 319 #if defined(_WIN32) |
336 char buf[18]; | 320 char buf[18]; |
337 ASSERT_EQ(::read(fd, buf, 18), 18); | 321 ASSERT_EQ(::read(fd, buf, 18), 18); |
338 if (strncmp(buf, "\xfe\xff", 2) == 0) { // UTF16-BE | 322 if (strncmp(buf, "\xfe\xff", 2) == 0) { // UTF16-BE |
339 ASSERT_EQ(strncmp(&buf[2], utf16be_text, 16), 0); | 323 ASSERT_EQ(strncmp(&buf[2], utf16be_text, 16), 0); |
340 } else if (strncmp(buf, "\xff\xfe", 2) == 0) { // UTF16-LE | 324 } else if (strncmp(buf, "\xff\xfe", 2) == 0) { // UTF16-LE |