public void DeleteDirectoryContents() { string rootDir = GetFullPath("Directory"); Directory.CreateDirectory(rootDir); Directory.CreateDirectory(Path.Combine(rootDir, "subdir1")); Directory.CreateDirectory(Path.Combine(rootDir, "subdir2")); // Create a readonly file string nestedFile = Path.Combine(rootDir, "subdir1", "File.txt"); File.WriteAllText(nestedFile, "asdf"); File.SetAttributes(nestedFile, FileAttributes.ReadOnly); // And a normal file File.WriteAllText(Path.Combine(rootDir, "File.txt"), "asdf"); string exeLink = Path.Combine(rootDir, "hardlink"); XAssert.IsTrue(CreateHardLinkIfSupported(link: exeLink, linkTarget: DummyWaiter.GetDummyWaiterExeLocation())); // Add a hardlink using (var waiter = DummyWaiter.RunAndWait()) { FileUtilities.DeleteDirectoryContents(rootDir); } XAssert.AreEqual(0, Directory.GetFileSystemEntries(rootDir).Length); }
public void TrivialDeleteFailsForLinkToRunningExecutable() { string exeLink = GetFullPath("DummyWaiterLink"); XAssert.IsTrue(CreateHardLinkIfSupported(link: exeLink, linkTarget: DummyWaiter.GetDummyWaiterExeLocation())); using (var waiter = DummyWaiter.RunAndWait()) { try { File.Delete(exeLink); XAssert.Fail("Expected deletion to fail due to the executable being loaded and running."); } catch (UnauthorizedAccessException) { // expected. } catch (IOException) { // expected. } } // Should succeed when the executable is no longer running. File.Delete(exeLink); }
public void CanDeleteRunningExecutableLink() { string exeLink = GetFullPath("DummyWaiterLink"); XAssert.IsTrue(CreateHardLinkIfSupported(link: exeLink, linkTarget: DummyWaiter.GetDummyWaiterExeLocation())); using (var waiter = DummyWaiter.RunAndWait()) { XAssert.IsTrue(File.Exists(exeLink)); FileUtilities.DeleteFile(exeLink); XAssert.IsFalse(File.Exists(exeLink)); } }
public void CreateReplacementFileCanReplaceRunningExecutableLink() { string exeLink = GetFullPath("DummyWaiterLink"); XAssert.IsTrue(CreateHardLinkIfSupported(link: exeLink, linkTarget: DummyWaiter.GetDummyWaiterExeLocation())); using (var waiter = DummyWaiter.RunAndWait()) { using (FileStream fs = FileUtilities.CreateReplacementFile(exeLink, FileShare.Delete)) { XAssert.AreEqual(0, fs.Length); } } }
public void MoveTempDeletionCanReplaceRunningExecutable() { // Make a copy of DummyWaiter.exe to use as the test subject for deleting a running executable. // Keep the copy in the same directory as the original since it will need runtime dlls string dummyWaiterLocation = DummyWaiter.GetDummyWaiterExeLocation(); string exeCopy = dummyWaiterLocation + ".copy.exe"; File.Copy(dummyWaiterLocation, exeCopy); using (var waiter = DummyWaiter.RunAndWait(exeCopy)) { BuildXLException caughtException = null; try { FileUtilities.DeleteFile(exeCopy); } catch (BuildXLException ex) { caughtException = ex; } XAssert.IsNotNull(caughtException, "Expected deletion without a tempCleaner to fail"); XAssert.IsTrue(File.Exists(exeCopy)); caughtException = null; try { FileUtilities.DeleteFile(exeCopy, tempDirectoryCleaner: MoveDeleteCleaner); } catch (BuildXLException ex) { caughtException = ex; } XAssert.IsNull(caughtException, "Expected deletion with a MoveDeleteCleaner to succeed"); XAssert.IsFalse(File.Exists(exeCopy)); } }
public void DeleteDirectoryContentsLongPath() { string originalRoot = GetFullPath("testRoot"); // Create a directory with a path that's too long to normally delete StringBuilder sb = new StringBuilder(); for (int i = 0; i < 100; i++) { sb.Append("a"); } string rootDir = @"\\?\" + originalRoot; XAssert.IsTrue(CreateDirectoryW(rootDir, IntPtr.Zero)); rootDir = rootDir + "\\" + sb.ToString(); XAssert.IsTrue(CreateDirectoryW(rootDir, IntPtr.Zero)); rootDir = rootDir + "\\" + sb.ToString(); XAssert.IsTrue(CreateDirectoryW(rootDir, IntPtr.Zero)); // Write some files in the directory. Set their attributes as readonly to exercise the related logic in DeleteFile string shorterPath = Path.Combine(originalRoot, "myFile.txt"); File.WriteAllText(shorterPath, "foo"); File.SetAttributes(shorterPath, FileAttributes.ReadOnly); // And a file with a filename longer than maxpath string longerPath = rootDir + @"\myFile.txt"; SafeFileHandle fileHandle; var result = FileUtilities.TryCreateOrOpenFile( longerPath, FileDesiredAccess.GenericWrite, FileShare.Delete, FileMode.Create, FileFlagsAndAttributes.FileAttributeNormal, out fileHandle); XAssert.IsTrue(result.Succeeded); using (FileStream stream = new FileStream(fileHandle, FileAccess.Write)) { stream.WriteByte(255); } FileUtilities.SetFileAttributes(longerPath, FileAttributes.ReadOnly); string exeLink = Path.Combine(rootDir, "hardlink"); XAssert.IsTrue(CreateHardLinkIfSupported(link: exeLink, linkTarget: DummyWaiter.GetDummyWaiterExeLocation())); // Add a hardlink. Perform deletion attempts while the hardlink target is in use using (var waiter = DummyWaiter.RunAndWait()) { // Attempt to delete with the managed API. This should fail because it contains nested paths that are too long bool isPathTooLong = false; try { Directory.Delete(rootDir, recursive: true); } catch (PathTooLongException) { isPathTooLong = true; } XAssert.IsTrue(isPathTooLong, "Expected to encounter a PathTooLongException. If no exception is thrown by the System.IO method, this test isn't validating anything"); // Now use the native API. This should succeed FileUtilities.DeleteDirectoryContents(originalRoot); } XAssert.IsTrue(Directory.Exists(originalRoot)); XAssert.AreEqual(0, Directory.GetFileSystemEntries(originalRoot).Length); }