42 #define WIN32_LEAN_AND_MEAN
48 #include <sys/types.h>
65 const char kUtf8Text[] = {
68 static_cast<char>(0xd0),
static_cast<char>(0x9f),
70 static_cast<char>(0xd1),
static_cast<char>(0x80),
72 static_cast<char>(0xd0),
static_cast<char>(0xb8),
74 static_cast<char>(0xd0),
static_cast<char>(0xb2),
76 static_cast<char>(0xd0),
static_cast<char>(0xb5),
78 static_cast<char>(0xd1),
static_cast<char>(0x82), 0
81 const wchar_t kUtf16Text[] = {
83 L
'\x41f', L
'\x440', L
'\x438', L
'\x432', L
'\x435', L
'\x442', 0
98 WCHAR working_directory[MAX_PATH];
103 #define ASSERT_INITIALIZED \
105 EXPECT_FALSE(test_tmpdir.empty()); \
106 EXPECT_FALSE(wtest_tmpdir.empty()); \
110 void StripTrailingSlashes(
string*
str) {
111 int i =
str->size() - 1;
112 for (;
i >= 0 && ((*str)[
i] ==
'/' || (*str)[
i] ==
'\\'); --
i) {}
116 bool GetEnvVarAsUtf8(
const WCHAR*
name,
string* result) {
117 DWORD
size = ::GetEnvironmentVariableW(
name,
nullptr, 0);
118 if (
size > 0 && GetLastError() != ERROR_ENVVAR_NOT_FOUND) {
119 std::unique_ptr<WCHAR[]> wcs(
new WCHAR[
size]);
120 ::GetEnvironmentVariableW(
name, wcs.get(),
size);
126 return strings::wcs_to_utf8(wcs.get(), result);
132 bool GetCwdAsUtf8(
string* result) {
133 DWORD
size = ::GetCurrentDirectoryW(0,
nullptr);
135 std::unique_ptr<WCHAR[]> wcs(
new WCHAR[
size]);
136 ::GetCurrentDirectoryW(
size, wcs.get());
142 return strings::wcs_to_utf8(wcs.get(), result);
150 void IoWin32Test::SetUp() {
152 wtest_tmpdir.clear();
153 EXPECT_GT(::GetCurrentDirectoryW(MAX_PATH, working_directory), 0);
159 ok = GetEnvVarAsUtf8(L
"TEST_TMPDIR", &tmp);
163 ok = GetEnvVarAsUtf8(L
"TEMP", &tmp);
167 ok = GetEnvVarAsUtf8(L
"TMP", &tmp);
171 ok = GetCwdAsUtf8(&tmp);
173 if (!ok || tmp.empty()) {
174 FAIL() <<
"Cannot find a temp directory.";
177 StripTrailingSlashes(&tmp);
178 std::stringstream result;
183 static unsigned int counter = 0;
184 result << tmp <<
"\\w32tst" << counter++ <<
".tmp";
185 test_tmpdir = result.str();
186 wtest_tmpdir = testonly_utf8_to_winpath(test_tmpdir.c_str());
192 void IoWin32Test::TearDown() {
193 if (!wtest_tmpdir.empty()) {
194 DeleteAllUnder(wtest_tmpdir);
196 ::SetCurrentDirectoryW(working_directory);
203 if (
path.find(L
"\\\\?\\") != 0) {
206 if (::CreateDirectoryW(
path.c_str(),
nullptr) ||
207 GetLastError() == ERROR_ALREADY_EXISTS ||
208 GetLastError() == ERROR_ACCESS_DENIED) {
211 if (GetLastError() == ERROR_PATH_NOT_FOUND) {
212 size_t pos =
path.find_last_of(L
'\\');
213 if (pos != wstring::npos) {
215 if (CreateAllUnder(parent) && CreateDirectoryW(
path.c_str(),
nullptr)) {
224 static const wstring kDot(L
".");
225 static const wstring kDotDot(L
"..");
230 if (
path.find(L
"\\\\?\\") != 0) {
234 if (
path[
path.size() - 1] != L
'\\') {
235 path.push_back(L
'\\');
240 if (handle == INVALID_HANDLE_VALUE) {
247 if (kDot != childname && kDotDot != childname) {
249 if ((
metadata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0) {
252 if (((
metadata.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) == 0 &&
253 !DeleteAllUnder(childpath)) ||
254 !::RemoveDirectoryW(childpath.c_str())) {
259 if (!::DeleteFileW(childpath.c_str())) {
265 }
while (::FindNextFileW(handle, &
metadata));
270 TEST_F(IoWin32Test, AccessTest) {
273 string path = test_tmpdir;
274 while (
path.size() < MAX_PATH - 30) {
275 path +=
"\\accesstest";
278 string file =
path +
"\\file.txt";
279 int fd = open(file.c_str(), O_CREAT | O_WRONLY, 0644);
295 EXPECT_EQ(
access((test_tmpdir +
"/accesstest").c_str(), F_OK | W_OK), 0);
296 ASSERT_EQ(
access((test_tmpdir +
"/./normalize_me/.././accesstest").c_str(),
299 EXPECT_NE(
access(
"io_win32_unittest.AccessTest.nonexistent", F_OK), 0);
300 EXPECT_NE(
access(
"io_win32_unittest.AccessTest.nonexistent", W_OK), 0);
310 TEST_F(IoWin32Test, OpenTest) {
313 string path = test_tmpdir;
314 while (
path.size() < MAX_PATH) {
315 path +=
"\\opentest";
318 string file =
path +
"\\file.txt";
319 int fd = open(file.c_str(), O_CREAT | O_WRONLY, 0644);
327 ASSERT_EQ(open(
"c:bad.txt", O_CREAT | O_WRONLY, 0644), -1);
329 ASSERT_EQ(open(
"/tmp/bad.txt", O_CREAT | O_WRONLY, 0644), -1);
331 ASSERT_EQ(open(
"\\bad.txt", O_CREAT | O_WRONLY, 0644), -1);
335 TEST_F(IoWin32Test, MkdirTest) {
338 string path = test_tmpdir;
340 path +=
"\\mkdirtest";
342 }
while (
path.size() <= MAX_PATH);
352 TEST_F(IoWin32Test, MkdirTestNonAscii) {
357 EXPECT_TRUE(CreateDirectoryW((wtest_tmpdir + L
"\\1").c_str(),
nullptr));
358 EXPECT_TRUE(CreateDirectoryW((wtest_tmpdir + L
"\\1\\" + kUtf16Text).c_str(),
nullptr));
362 EXPECT_EQ(mkdir((test_tmpdir +
"\\2").c_str(), 0644), 0);
363 EXPECT_EQ(mkdir((test_tmpdir +
"\\2\\" + kUtf8Text).c_str(), 0644), 0);
366 TEST_F(IoWin32Test, ChdirTest) {
378 path = test_tmpdir +
"/foo.";
384 TEST_F(IoWin32Test, ChdirTestNonAscii) {
388 wstring wNonAscii(wtest_tmpdir + L
"\\" + kUtf16Text);
390 EXPECT_TRUE(strings::wcs_to_utf8(wNonAscii.c_str(), &nonAscii));
391 EXPECT_TRUE(CreateDirectoryW(wNonAscii.c_str(),
nullptr));
395 EXPECT_TRUE(SetCurrentDirectoryW(wNonAscii.c_str()));
404 TEST_F(IoWin32Test, AsWindowsPathTest) {
405 DWORD
size = GetCurrentDirectoryW(0,
nullptr);
406 std::unique_ptr<wchar_t[]> cwd_str(
new wchar_t[
size]);
410 ASSERT_EQ(testonly_utf8_to_winpath(
"relative_mkdirtest"),
411 cwd + L
"\\relative_mkdirtest");
412 ASSERT_EQ(testonly_utf8_to_winpath(
"preserve//\\trailing///"),
413 cwd + L
"\\preserve\\trailing\\");
414 ASSERT_EQ(testonly_utf8_to_winpath(
"./normalize_me\\/../blah"),
416 std::ostringstream relpath;
417 for (
wchar_t*
p = cwd_str.get(); *
p; ++
p) {
418 if (*
p ==
'/' || *
p ==
'\\') {
422 relpath <<
".\\/../\\./beyond-toplevel";
423 ASSERT_EQ(testonly_utf8_to_winpath(relpath.str().c_str()),
424 wstring(L
"\\\\?\\") + cwd_str.get()[0] + L
":\\beyond-toplevel");
429 ASSERT_EQ(testonly_utf8_to_winpath(
"/absolute/unix/path"), L
"");
431 ASSERT_EQ(testonly_utf8_to_winpath(
"\\driveless\\absolute"), L
"");
433 ASSERT_EQ(testonly_utf8_to_winpath(
"c:foo"), L
"");
434 ASSERT_EQ(testonly_utf8_to_winpath(
"c:/foo"), L
"\\\\?\\c:\\foo");
435 ASSERT_EQ(testonly_utf8_to_winpath(
"\\\\?\\C:\\foo"), L
"\\\\?\\C:\\foo");
438 TEST_F(IoWin32Test, Utf8Utf16ConversionTest) {
441 ASSERT_TRUE(strings::utf8_to_wcs(kUtf8Text, &wcs));
442 ASSERT_TRUE(strings::wcs_to_utf8(kUtf16Text, &mbs));
453 #endif // defined(_WIN32)