diff options
author | 2017-02-10 10:38:14 +0000 | |
---|---|---|
committer | 2017-02-10 15:36:03 +0000 | |
commit | d2cba292a6904d188d5a903d5baee3ba873b0ec5 (patch) | |
tree | c2c111650fe560f1cf1b3c5541c2cbfea70455f8 /src/test | |
parent | da3099a0816f3c0e206a08962e5ffd77a0aac2de (diff) |
Bazel client, Windows, tests: `rm -rf TEST_TMPDIR`
Add test helpers to recursively delete the
TEST_TMPDIR in the TearDown method of tests, to
ensure each test sees a fresh temp directory.
Also add tests for these test helpers.
--
PiperOrigin-RevId: 147135561
MOS_MIGRATED_REVID=147135561
Diffstat (limited to 'src/test')
-rw-r--r-- | src/test/cpp/util/BUILD | 39 | ||||
-rw-r--r-- | src/test/cpp/util/dummy_test.cc | 19 | ||||
-rw-r--r-- | src/test/cpp/util/file_posix_test.cc | 16 | ||||
-rw-r--r-- | src/test/cpp/util/file_windows_test.cc | 64 | ||||
-rw-r--r-- | src/test/cpp/util/windows_test_util.cc | 104 | ||||
-rw-r--r-- | src/test/cpp/util/windows_test_util.h | 37 | ||||
-rw-r--r-- | src/test/cpp/util/windows_test_util_test.cc | 62 |
7 files changed, 318 insertions, 23 deletions
diff --git a/src/test/cpp/util/BUILD b/src/test/cpp/util/BUILD index 4328bf6511..64e9e19518 100644 --- a/src/test/cpp/util/BUILD +++ b/src/test/cpp/util/BUILD @@ -20,6 +20,7 @@ cc_test( cc_test( name = "file_test", + size = "small", srcs = ["file_test.cc"] + select({ "//src:windows": [ "file_posix_test.cc", @@ -36,7 +37,17 @@ cc_test( deps = [ "//src/main/cpp/util:file", "//third_party:gtest", - ], + ] + select({ + "//src:windows": [ + "//src/main/native:windows_jni_lib", + ":windows_test_util", + ], + "//src:windows_msvc": [ + "//src/main/native:windows_jni_lib", + ":windows_test_util", + ], + "//conditions:default": [], + }), ) cc_test( @@ -69,4 +80,30 @@ cc_test( ], ) +cc_library( + name = "windows_test_util", + testonly = 1, + srcs = select({ + "//src:windows": ["windows_test_util.cc"], + "//src:windows_msvc": ["windows_test_util.cc"], + "//conditions:default": [], + }), + deps = ["//third_party:gtest"], +) + +cc_test( + name = "windows_test_util_test", + size = "small", + srcs = select({ + "//src:windows": ["windows_test_util.cc"], + "//src:windows_msvc": ["windows_test_util.cc"], + "//conditions:default": ["dummy_test.cc"], + }), + deps = select({ + "//src:windows": ["//third_party:gtest"], + "//src:windows_msvc": ["//third_party:gtest"], + "//conditions:default": [], + }), +) + test_suite(name = "all_tests") diff --git a/src/test/cpp/util/dummy_test.cc b/src/test/cpp/util/dummy_test.cc new file mode 100644 index 0000000000..388e986a81 --- /dev/null +++ b/src/test/cpp/util/dummy_test.cc @@ -0,0 +1,19 @@ +// Copyright 2017 The Bazel Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#include <stdio.h> + +int main(int, char**) { + printf("INFO: This test is empty on this platform.\n"); + return 0; +} diff --git a/src/test/cpp/util/file_posix_test.cc b/src/test/cpp/util/file_posix_test.cc index b100016076..e8d553bbde 100644 --- a/src/test/cpp/util/file_posix_test.cc +++ b/src/test/cpp/util/file_posix_test.cc @@ -45,7 +45,7 @@ static bool CreateEmptyFile(const string& path) { return close(fd) == 0; } -TEST(FileTest, TestDirname) { +TEST(FilePosixTest, TestDirname) { // The Posix version of SplitPath (thus Dirname too, which is implemented on // top of it) is not aware of Windows paths. ASSERT_EQ("", Dirname("")); @@ -68,7 +68,7 @@ TEST(FileTest, TestDirname) { ASSERT_EQ("", Dirname("\\\\?\\c:\\foo")); } -TEST(FileTest, TestBasename) { +TEST(FilePosixTest, TestBasename) { // The Posix version of SplitPath (thus Basename too, which is implemented on // top of it) is not aware of Windows paths. ASSERT_EQ("", Basename("")); @@ -92,7 +92,7 @@ TEST(FileTest, TestBasename) { ASSERT_EQ("\\\\?\\c:\\foo", Basename("\\\\?\\c:\\foo")); } -TEST(FileTest, JoinPath) { +TEST(FilePosixTest, JoinPath) { std::string path = JoinPath("", ""); ASSERT_EQ("", path); @@ -132,7 +132,7 @@ void MockDirectoryListingFunction(const string& path, } } -TEST(FileTest, GetAllFilesUnder) { +TEST(FilePosixTest, GetAllFilesUnder) { vector<string> result; _GetAllFilesUnder("root", &result, &MockDirectoryListingFunction); std::sort(result.begin(), result.end()); @@ -142,7 +142,7 @@ TEST(FileTest, GetAllFilesUnder) { ASSERT_EQ(expected, result); } -TEST(FileTest, MakeDirectories) { +TEST(FilePosixTest, MakeDirectories) { const char* tmp_dir = getenv("TEST_TMPDIR"); ASSERT_STRNE(tmp_dir, NULL); const char* test_src_dir = getenv("TEST_SRCDIR"); @@ -203,7 +203,7 @@ TEST(FileTest, MakeDirectories) { ASSERT_EQ(EACCES, errno); } -TEST(FileTest, HammerMakeDirectories) { +TEST(FilePosixTest, HammerMakeDirectories) { const char* tmp_dir = getenv("TEST_TMPDIR"); ASSERT_STRNE(tmp_dir, NULL); @@ -402,7 +402,7 @@ TEST(FilePosixTest, ForEachDirectoryEntry) { rmdir(root.c_str()); } -TEST(FileTest, IsAbsolute) { +TEST(FilePosixTest, IsAbsolute) { ASSERT_FALSE(IsAbsolute("")); ASSERT_TRUE(IsAbsolute("/")); ASSERT_TRUE(IsAbsolute("/foo")); @@ -416,7 +416,7 @@ TEST(FileTest, IsAbsolute) { ASSERT_FALSE(IsAbsolute("\\\\?\\c:\\foo")); } -TEST(FileTest, IsRootDirectory) { +TEST(FilePosixTest, IsRootDirectory) { ASSERT_FALSE(IsRootDirectory("")); ASSERT_TRUE(IsRootDirectory("/")); ASSERT_FALSE(IsRootDirectory("/foo")); diff --git a/src/test/cpp/util/file_windows_test.cc b/src/test/cpp/util/file_windows_test.cc index 76af446f31..0e777d88fd 100644 --- a/src/test/cpp/util/file_windows_test.cc +++ b/src/test/cpp/util/file_windows_test.cc @@ -15,9 +15,15 @@ #include <string.h> #include <windows.h> +#include <algorithm> +#include <memory> +#include <string> + +#include "gtest/gtest.h" #include "src/main/cpp/util/file.h" #include "src/main/cpp/util/file_platform.h" -#include "gtest/gtest.h" +#include "src/main/native/windows_util.h" +#include "src/test/cpp/util/windows_test_util.h" #if !defined(COMPILER_MSVC) && !defined(__CYGWIN__) #error("This test should only be run on Windows") @@ -26,6 +32,7 @@ namespace blaze_util { using std::string; +using std::unique_ptr; using std::wstring; // Methods defined in file_windows.cc that are only visible for testing. @@ -33,6 +40,11 @@ bool AsWindowsPath(const string& path, wstring* result); void ResetMsysRootForTesting(); string NormalizeWindowsPath(string path); +class FileWindowsTest : public ::testing::Test { + public: + void TearDown() override { DeleteAllUnder(GetTestTmpDirW()); } +}; + // This is a macro so the assertions will have the correct line number. #define GET_TEST_TMPDIR(/* string& */ result) \ { \ @@ -42,7 +54,31 @@ string NormalizeWindowsPath(string path); ASSERT_GT(result.size(), 0); \ } -TEST(FileTest, TestNormalizeWindowsPath) { +// Asserts that dir1 can be created with some content, and dir2 doesn't exist. +static void AssertTearDown(const WCHAR* dir1, const WCHAR* dir2) { + wstring wtmpdir(GetTestTmpDirW()); + wstring dir1str(wtmpdir + L"\\" + dir1); + wstring subdir(dir1str + L"\\subdir"); + wstring wfile(subdir + L"\\hello.txt"); + EXPECT_TRUE(::CreateDirectoryW(dir1str.c_str(), NULL)); + EXPECT_TRUE(::CreateDirectoryW(subdir.c_str(), NULL)); + EXPECT_TRUE(CreateDummyFile(wfile)); + EXPECT_NE(::GetFileAttributesW(wfile.c_str()), INVALID_FILE_ATTRIBUTES); + ASSERT_EQ(::GetFileAttributesW((wtmpdir + L"\\" + dir2).c_str()), + INVALID_FILE_ATTRIBUTES); +} + +// One half of the teardown test: assert that test.teardown.b was cleaned up. +TEST_F(FileWindowsTest, TestTearDownA) { + AssertTearDown(L"test.teardown.a", L"test.teardown.b"); +} + +// Other half of the teardown test: assert that test.teardown.a was cleaned up. +TEST_F(FileWindowsTest, TestTearDownB) { + AssertTearDown(L"test.teardown.b", L"test.teardown.a"); +} + +TEST_F(FileWindowsTest, TestNormalizeWindowsPath) { ASSERT_EQ(string(""), NormalizeWindowsPath("")); ASSERT_EQ(string(""), NormalizeWindowsPath(".")); ASSERT_EQ(string("foo"), NormalizeWindowsPath("foo")); @@ -56,7 +92,7 @@ TEST(FileTest, TestNormalizeWindowsPath) { ASSERT_EQ(string("c:\\foo\\bar"), NormalizeWindowsPath("c:\\..//foo/./bar/")); } -TEST(FileTest, TestDirname) { +TEST_F(FileWindowsTest, TestDirname) { ASSERT_EQ("", Dirname("")); ASSERT_EQ("/", Dirname("/")); ASSERT_EQ("", Dirname("foo")); @@ -77,7 +113,7 @@ TEST(FileTest, TestDirname) { ASSERT_EQ("\\\\?\\c:\\", Dirname("\\\\?\\c:\\foo")); } -TEST(FileTest, TestBasename) { +TEST_F(FileWindowsTest, TestBasename) { ASSERT_EQ("", Basename("")); ASSERT_EQ("", Basename("/")); ASSERT_EQ("foo", Basename("foo")); @@ -98,7 +134,7 @@ TEST(FileTest, TestBasename) { ASSERT_EQ("foo", Basename("\\\\?\\c:\\foo")); } -TEST(FileTest, IsAbsolute) { +TEST_F(FileWindowsTest, IsAbsolute) { ASSERT_FALSE(IsAbsolute("")); ASSERT_TRUE(IsAbsolute("/")); ASSERT_TRUE(IsAbsolute("/foo")); @@ -112,7 +148,7 @@ TEST(FileTest, IsAbsolute) { ASSERT_TRUE(IsAbsolute("\\\\?\\c:\\foo")); } -TEST(FileTest, IsRootDirectory) { +TEST_F(FileWindowsTest, IsRootDirectory) { ASSERT_FALSE(IsRootDirectory("")); ASSERT_TRUE(IsRootDirectory("/")); ASSERT_FALSE(IsRootDirectory("/foo")); @@ -126,7 +162,7 @@ TEST(FileTest, IsRootDirectory) { ASSERT_FALSE(IsRootDirectory("\\\\?\\c:\\foo")); } -TEST(FileTest, TestAsWindowsPath) { +TEST_F(FileWindowsTest, TestAsWindowsPath) { SetEnvironmentVariableA("BAZEL_SH", "c:\\msys\\some\\long\\path\\bash.exe"); ResetMsysRootForTesting(); wstring actual; @@ -188,7 +224,7 @@ TEST(FileTest, TestAsWindowsPath) { ASSERT_EQ(wlongpath, actual); } -TEST(FileTest, TestAsShortWindowsPath) { +TEST_F(FileWindowsTest, TestAsShortWindowsPath) { string actual; ASSERT_TRUE(AsShortWindowsPath("/dev/null", &actual)); ASSERT_EQ(string("NUL"), actual); @@ -212,7 +248,7 @@ TEST(FileTest, TestAsShortWindowsPath) { ASSERT_EQ(0, rmdir(dirname.c_str())); } -TEST(FileTest, TestMsysRootRetrieval) { +TEST_F(FileWindowsTest, TestMsysRootRetrieval) { wstring actual; SetEnvironmentVariableA("BAZEL_SH", "c:/foo/msys/bar/qux.exe"); @@ -262,7 +298,7 @@ static void RunCommand(const string& cmdline) { ASSERT_EQ(0, exit_code); } -TEST(FileTest, TestPathExistsWindows) { +TEST_F(FileWindowsTest, TestPathExistsWindows) { ASSERT_FALSE(PathExists("")); ASSERT_TRUE(PathExists(".")); ASSERT_FALSE(PathExists("non.existent")); @@ -307,7 +343,7 @@ TEST(FileTest, TestPathExistsWindows) { ASSERT_FALSE(PathExists(JoinPath(tmpdir, "junc2"))); } -TEST(FileTest, TestIsDirectory) { +TEST_F(FileWindowsTest, TestIsDirectory) { ASSERT_FALSE(IsDirectory("")); ASSERT_FALSE(IsDirectory("/dev/null")); ASSERT_FALSE(IsDirectory("Nul")); @@ -345,7 +381,7 @@ TEST(FileTest, TestIsDirectory) { ASSERT_EQ(0, rmdir(junc1.c_str())); } -TEST(FileTest, TestUnlinkPath) { +TEST_F(FileWindowsTest, TestUnlinkPath) { ASSERT_FALSE(UnlinkPath("/dev/null")); ASSERT_FALSE(UnlinkPath("Nul")); @@ -378,7 +414,7 @@ TEST(FileTest, TestUnlinkPath) { ASSERT_EQ(0, rmdir(dir1.c_str())); } -TEST(FileTest, TestMakeDirectories) { +TEST_F(FileWindowsTest, TestMakeDirectories) { string tmpdir; GET_TEST_TMPDIR(tmpdir); ASSERT_LT(0, tmpdir.size()); @@ -411,7 +447,7 @@ TEST(FileTest, TestMakeDirectories) { ASSERT_EQ(0, rmdir(JoinPath(tmpdir, "dir4").c_str())); } -TEST(FileTest, CanAccess) { +TEST_F(FileWindowsTest, CanAccess) { ASSERT_FALSE(CanReadFile("C:/windows/this/should/not/exist/mkay")); ASSERT_FALSE(CanExecuteFile("C:/this/should/not/exist/mkay")); ASSERT_FALSE(CanAccessDirectory("C:/this/should/not/exist/mkay")); diff --git a/src/test/cpp/util/windows_test_util.cc b/src/test/cpp/util/windows_test_util.cc new file mode 100644 index 0000000000..dfea7b05bb --- /dev/null +++ b/src/test/cpp/util/windows_test_util.cc @@ -0,0 +1,104 @@ +// Copyright 2016 The Bazel Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#include <windows.h> + +#include <algorithm> +#include <memory> +#include <string> + +#include "src/test/cpp/util/windows_test_util.h" + +#if !defined(COMPILER_MSVC) && !defined(__CYGWIN__) +#error("This test should only be run on Windows") +#endif // !defined(COMPILER_MSVC) && !defined(__CYGWIN__) + +namespace blaze_util { + +using std::unique_ptr; +using std::wstring; + +wstring GetTestTmpDirW() { + DWORD size = ::GetEnvironmentVariableW(L"TEST_TMPDIR", NULL, 0); + unique_ptr<WCHAR[]> buf(new WCHAR[size]); + ::GetEnvironmentVariableW(L"TEST_TMPDIR", buf.get(), size); + wstring result(buf.get()); + std::replace(result.begin(), result.end(), '/', '\\'); + return result; +} + +bool DeleteAllUnder(wstring path) { + static const wstring kDot(L"."); + static const wstring kDotDot(L".."); + + // Prepend UNC prefix if the path doesn't have it already. Don't bother + // checking if the path is shorter than MAX_PATH, let's just do it + // unconditionally; this is a test after all, performance isn't paramount. + if (path.find(L"\\\\?\\") != 0) { + path = wstring(L"\\\\?\\") + path; + } + // Append "\" if necessary. + if (path.back() != '\\') { + path.push_back('\\'); + } + + WIN32_FIND_DATAW metadata; + HANDLE handle = FindFirstFileW((path + L"*").c_str(), &metadata); + if (handle == INVALID_HANDLE_VALUE) { + return true; // directory doesn't exist + } + + bool result = true; + do { + wstring childname = metadata.cFileName; + if (kDot != childname && kDotDot != childname) { + wstring childpath = path + childname; + if ((metadata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0) { + // If this is not a junction, delete its contents recursively. + // Finally delete this directory/junction too. + if (((metadata.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) == 0 && + !DeleteAllUnder(childpath)) || + !::RemoveDirectoryW(childpath.c_str())) { + result = false; + break; + } + } else { + if (!::DeleteFileW(childpath.c_str())) { + result = false; + break; + } + } + } + } while (FindNextFileW(handle, &metadata)); + FindClose(handle); + return result; +} + +bool CreateDummyFile(const wstring& path) { + HANDLE handle = + ::CreateFileW(path.c_str(), GENERIC_WRITE, FILE_SHARE_READ, NULL, + CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + if (handle == INVALID_HANDLE_VALUE) { + return false; + } + bool result = true; + DWORD actually_written = 0; + if (!::WriteFile(handle, "hello", 5, &actually_written, NULL) && + actually_written != 5) { + result = false; + } + CloseHandle(handle); + return result; +} + +} // namespace blaze_util diff --git a/src/test/cpp/util/windows_test_util.h b/src/test/cpp/util/windows_test_util.h new file mode 100644 index 0000000000..2ec5844e41 --- /dev/null +++ b/src/test/cpp/util/windows_test_util.h @@ -0,0 +1,37 @@ +// Copyright 2016 The Bazel Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#ifndef BAZEL_SRC_TEST_CPP_UTIL_WINDOWS_TEST_UTIL_H_ +#define BAZEL_SRC_TEST_CPP_UTIL_WINDOWS_TEST_UTIL_H_ + +#include <string> + +namespace blaze_util { + +using std::wstring; + +// Returns $TEST_TMPDIR as a wstring. +// The result will have backslashes as directory separators (but no UNC prefix). +wstring GetTestTmpDirW(); + +// Deletes all files and directories under `path`. +// `path` must be a valid Windows path, but doesn't need to have a UNC prefix. +bool DeleteAllUnder(wstring path); + +// Creates a dummy file under `path`. +// `path` must be a valid Windows path, and have a UNC prefix if necessary. +bool CreateDummyFile(const wstring& path); + +} // namespace blaze_util + +#endif // BAZEL_SRC_TEST_CPP_UTIL_WINDOWS_TEST_UTIL_H_ diff --git a/src/test/cpp/util/windows_test_util_test.cc b/src/test/cpp/util/windows_test_util_test.cc new file mode 100644 index 0000000000..e408246bcc --- /dev/null +++ b/src/test/cpp/util/windows_test_util_test.cc @@ -0,0 +1,62 @@ +// Copyright 2016 The Bazel Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#include <windows.h> + +#include <string> + +#include "gtest/gtest.h" +#include "src/test/cpp/util/windows_test_util.h" + +#if !defined(COMPILER_MSVC) && !defined(__CYGWIN__) +#error("This test should only be run on Windows") +#endif // !defined(COMPILER_MSVC) && !defined(__CYGWIN__) + +namespace blaze_util { + +using std::wstring; + +class WindowsTestUtilTest : public ::testing::Test { + public: + void SetUp() override { ::CreateDirectoryW(GetTestTmpDirW().c_str(), NULL); } + void TearDown() override { DeleteAllUnder(GetTestTmpDirW()); } +}; + +TEST_F(WindowsTestUtilTest, TestGetTestTempDirW) { + wstring actual = GetTestTmpDirW(); + ASSERT_EQ(actual.find(L":\\"), 1); + ASSERT_EQ(actual.find(L"/"), wstring::npos); +} + +TEST_F(WindowsTestUtilTest, TestCreateDummyFile) { + wstring wtemp = GetTestTmpDirW(); + EXPECT_FALSE(wtemp.empty()); + wstring file1 = wstring(L"\\\\?\\") + wtemp + L"\\file1.txt"; + ASSERT_TRUE(CreateDummyFile(file1)); + DWORD attr = ::GetFileAttributesW(file1.c_str()); + ASSERT_NE(attr, INVALID_FILE_ATTRIBUTES); +} + +TEST_F(WindowsTestUtilTest, TestDeleteAllUnder) { + wstring wtemp = GetTestTmpDirW(); + EXPECT_FALSE(wtemp.empty()); + wstring dir1 = wstring(L"\\\\?\\") + wtemp + L"\\dir1"; + EXPECT_TRUE(::CreateDirectoryW(dir1.c_str(), NULL)); + EXPECT_TRUE(CreateDummyFile(dir1 + L"\\file1.txt")); + wstring dir2 = dir1 + L"\\dir2"; + EXPECT_TRUE(::CreateDirectoryW(dir2.c_str(), NULL)); + EXPECT_TRUE(CreateDummyFile(dir2 + L"\\file2.txt")); + ASSERT_TRUE(DeleteAllUnder(dir1)); +} + +} // namespace blaze_util |