| //===--- FileSystemTest.cpp - for swift/Basic/FileSystem.h ----------------===// |
| // |
| // This source file is part of the Swift.org open source project |
| // |
| // Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors |
| // Licensed under Apache License v2.0 with Runtime Library Exception |
| // |
| // See https://swift.org/LICENSE.txt for license information |
| // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "swift/Basic/FileSystem.h" |
| #include "swift/Basic/LLVM.h" |
| #include "llvm/Support/FileSystem.h" |
| #include "llvm/Support/Path.h" |
| #include "llvm/Support/raw_ostream.h" |
| #include "gtest/gtest.h" |
| |
| #define ASSERT_NO_ERROR(x) \ |
| do if (std::error_code ASSERT_NO_ERROR_ec = x) { \ |
| llvm::errs() << #x ": did not return errc::success.\n" \ |
| << "error number: " << ASSERT_NO_ERROR_ec.value() << "\n" \ |
| << "error message: " << ASSERT_NO_ERROR_ec.message() << "\n"; \ |
| FAIL(); \ |
| } while (0) |
| |
| using namespace llvm::sys; |
| using namespace swift; |
| |
| namespace { |
| TEST(FileSystem, MoveFileIfDifferentEmpty) { |
| // Create unique temporary directory for these tests |
| llvm::SmallString<128> dirPath; |
| ASSERT_NO_ERROR(fs::createUniqueDirectory("FileSystem-test", dirPath)); |
| |
| // Test 1: Move empty over nonexistent. |
| llvm::SmallString<128> sourceFile = dirPath; |
| path::append(sourceFile, "source.txt"); |
| { |
| std::error_code error; |
| llvm::raw_fd_ostream emptyOut(sourceFile, error, fs::F_None); |
| ASSERT_NO_ERROR(error); |
| } |
| |
| fs::UniqueID origID; |
| ASSERT_NO_ERROR(fs::getUniqueID(sourceFile, origID)); |
| |
| llvm::SmallString<128> destFile = dirPath; |
| path::append(destFile, "dest.txt"); |
| ASSERT_FALSE(fs::exists(destFile)); |
| |
| ASSERT_NO_ERROR(moveFileIfDifferent(sourceFile, destFile)); |
| ASSERT_TRUE(fs::exists(destFile)); |
| ASSERT_FALSE(fs::exists(sourceFile)); |
| |
| fs::UniqueID destID; |
| ASSERT_NO_ERROR(fs::getUniqueID(destFile, destID)); |
| ASSERT_EQ(origID, destID); |
| |
| ASSERT_NO_ERROR(fs::rename(destFile, sourceFile)); |
| |
| // Test 2: Move empty over empty. |
| { |
| std::error_code error; |
| llvm::raw_fd_ostream emptyOut(destFile, error, fs::F_None); |
| ASSERT_NO_ERROR(error); |
| } |
| |
| fs::UniqueID newID; |
| ASSERT_NO_ERROR(fs::getUniqueID(destFile, newID)); |
| ASSERT_NE(origID, newID); |
| |
| ASSERT_NO_ERROR(moveFileIfDifferent(sourceFile, destFile)); |
| ASSERT_TRUE(fs::exists(destFile)); |
| ASSERT_FALSE(fs::exists(sourceFile)); |
| |
| ASSERT_NO_ERROR(fs::getUniqueID(destFile, destID)); |
| ASSERT_EQ(newID, destID); |
| |
| ASSERT_NO_ERROR(fs::rename(destFile, sourceFile)); |
| origID = destID; |
| |
| // Test 3: Move empty over non-empty. |
| { |
| std::error_code error; |
| llvm::raw_fd_ostream nonEmptyOut(destFile, error, fs::F_None); |
| ASSERT_NO_ERROR(error); |
| nonEmptyOut << "a"; |
| } |
| |
| ASSERT_NO_ERROR(fs::getUniqueID(destFile, newID)); |
| ASSERT_NE(origID, newID); |
| |
| ASSERT_NO_ERROR(moveFileIfDifferent(sourceFile, destFile)); |
| ASSERT_TRUE(fs::exists(destFile)); |
| ASSERT_FALSE(fs::exists(sourceFile)); |
| |
| ASSERT_NO_ERROR(fs::getUniqueID(destFile, destID)); |
| ASSERT_EQ(origID, destID); |
| |
| ASSERT_NO_ERROR(fs::rename(destFile, sourceFile)); |
| |
| // Test 4: Move empty over self. |
| ASSERT_NO_ERROR(moveFileIfDifferent(sourceFile, sourceFile)); |
| ASSERT_TRUE(fs::exists(sourceFile)); |
| |
| ASSERT_NO_ERROR(fs::getUniqueID(sourceFile, newID)); |
| ASSERT_EQ(origID, newID); |
| |
| // Clean up. |
| ASSERT_NO_ERROR(fs::remove(sourceFile, false)); |
| ASSERT_NO_ERROR(fs::remove(dirPath, false)); |
| } |
| |
| TEST(FileSystem, MoveFileIfDifferentNonEmpty) { |
| // Create unique temporary directory for these tests |
| llvm::SmallString<128> dirPath; |
| ASSERT_NO_ERROR(fs::createUniqueDirectory("FileSystem-test", dirPath)); |
| |
| // Test 1: Move source over nonexistent. |
| llvm::SmallString<128> sourceFile = dirPath; |
| path::append(sourceFile, "source.txt"); |
| { |
| std::error_code error; |
| llvm::raw_fd_ostream sourceOut(sourceFile, error, fs::F_None); |
| sourceOut << "original"; |
| ASSERT_NO_ERROR(error); |
| } |
| |
| fs::UniqueID origID; |
| ASSERT_NO_ERROR(fs::getUniqueID(sourceFile, origID)); |
| |
| llvm::SmallString<128> destFile = dirPath; |
| path::append(destFile, "dest.txt"); |
| ASSERT_FALSE(fs::exists(destFile)); |
| |
| ASSERT_NO_ERROR(moveFileIfDifferent(sourceFile, destFile)); |
| ASSERT_TRUE(fs::exists(destFile)); |
| ASSERT_FALSE(fs::exists(sourceFile)); |
| |
| fs::UniqueID destID; |
| ASSERT_NO_ERROR(fs::getUniqueID(destFile, destID)); |
| ASSERT_EQ(origID, destID); |
| |
| ASSERT_NO_ERROR(fs::rename(destFile, sourceFile)); |
| |
| // Test 2: Move source over empty. |
| { |
| std::error_code error; |
| llvm::raw_fd_ostream emptyOut(destFile, error, fs::F_None); |
| ASSERT_NO_ERROR(error); |
| } |
| |
| fs::UniqueID newID; |
| ASSERT_NO_ERROR(fs::getUniqueID(destFile, newID)); |
| ASSERT_NE(origID, newID); |
| |
| ASSERT_NO_ERROR(moveFileIfDifferent(sourceFile, destFile)); |
| ASSERT_TRUE(fs::exists(destFile)); |
| ASSERT_FALSE(fs::exists(sourceFile)); |
| |
| ASSERT_NO_ERROR(fs::getUniqueID(destFile, destID)); |
| ASSERT_EQ(origID, destID); |
| |
| ASSERT_NO_ERROR(fs::rename(destFile, sourceFile)); |
| |
| // Test 3: Move source over non-empty-but-different. |
| { |
| std::error_code error; |
| llvm::raw_fd_ostream nonEmptyOut(destFile, error, fs::F_None); |
| ASSERT_NO_ERROR(error); |
| nonEmptyOut << "different"; |
| } |
| |
| ASSERT_NO_ERROR(fs::getUniqueID(destFile, newID)); |
| ASSERT_NE(origID, newID); |
| |
| ASSERT_NO_ERROR(moveFileIfDifferent(sourceFile, destFile)); |
| ASSERT_TRUE(fs::exists(destFile)); |
| ASSERT_FALSE(fs::exists(sourceFile)); |
| |
| ASSERT_NO_ERROR(fs::getUniqueID(destFile, destID)); |
| ASSERT_EQ(origID, destID); |
| |
| ASSERT_NO_ERROR(fs::rename(destFile, sourceFile)); |
| |
| // Test 4: Move source over identical. |
| { |
| std::error_code error; |
| llvm::raw_fd_ostream nonEmptyOut(destFile, error, fs::F_None); |
| ASSERT_NO_ERROR(error); |
| nonEmptyOut << "original"; |
| } |
| |
| ASSERT_NO_ERROR(fs::getUniqueID(destFile, newID)); |
| ASSERT_NE(origID, newID); |
| |
| ASSERT_NO_ERROR(moveFileIfDifferent(sourceFile, destFile)); |
| ASSERT_TRUE(fs::exists(destFile)); |
| ASSERT_FALSE(fs::exists(sourceFile)); |
| |
| ASSERT_NO_ERROR(fs::getUniqueID(destFile, destID)); |
| ASSERT_EQ(newID, destID); |
| |
| ASSERT_NO_ERROR(fs::rename(destFile, sourceFile)); |
| origID = newID; |
| |
| // Test 5: Move source over self. |
| ASSERT_NO_ERROR(moveFileIfDifferent(sourceFile, sourceFile)); |
| ASSERT_TRUE(fs::exists(sourceFile)); |
| |
| ASSERT_NO_ERROR(fs::getUniqueID(sourceFile, newID)); |
| ASSERT_EQ(origID, newID); |
| |
| // Clean up. |
| ASSERT_NO_ERROR(fs::remove(sourceFile, false)); |
| ASSERT_NO_ERROR(fs::remove(dirPath, false)); |
| } |
| |
| TEST(FileSystem, MoveFileIfDifferentNonExistent) { |
| // Create unique temporary directory for these tests |
| llvm::SmallString<128> dirPath; |
| ASSERT_NO_ERROR(fs::createUniqueDirectory("FileSystem-test", dirPath)); |
| |
| llvm::SmallString<128> sourceFile = dirPath; |
| path::append(sourceFile, "source.txt"); |
| llvm::SmallString<128> destFile = dirPath; |
| path::append(destFile, "dest.txt"); |
| |
| // Test 1: Nonexistent -> nonexistent. |
| ASSERT_TRUE((bool)moveFileIfDifferent(sourceFile, destFile)); |
| |
| { |
| std::error_code error; |
| llvm::raw_fd_ostream emptyOut(destFile, error, fs::F_None); |
| ASSERT_NO_ERROR(error); |
| } |
| |
| // Test 2: Nonexistent -> present. |
| ASSERT_TRUE((bool)moveFileIfDifferent(sourceFile, destFile)); |
| |
| // Clean up. |
| ASSERT_NO_ERROR(fs::remove(destFile)); |
| ASSERT_NO_ERROR(fs::remove(dirPath)); |
| } |
| |
| TEST(FileSystem, MoveFileIfDifferentInvalid) { |
| // Create unique temporary directory for these tests |
| llvm::SmallString<128> dirPath; |
| ASSERT_NO_ERROR(fs::createUniqueDirectory("FileSystem-test", dirPath)); |
| |
| llvm::SmallString<128> sourceFile = dirPath; |
| path::append(sourceFile, "source.txt"); |
| { |
| std::error_code error; |
| llvm::raw_fd_ostream emptyOut(sourceFile, error, fs::F_None); |
| ASSERT_NO_ERROR(error); |
| } |
| |
| // Test 1: Move a file over its parent directory. |
| ASSERT_TRUE((bool)moveFileIfDifferent(sourceFile, dirPath)); |
| |
| // Test 2: Move a file into a nonexistent directory. |
| llvm::SmallString<128> destFile = dirPath; |
| path::append(destFile, "nonexistent", "dest.txt"); |
| ASSERT_TRUE((bool)moveFileIfDifferent(sourceFile, destFile)); |
| |
| // Clean up. |
| ASSERT_NO_ERROR(fs::remove(sourceFile, false)); |
| ASSERT_NO_ERROR(fs::remove(dirPath, false)); |
| } |
| } // anonymous namespace |