From b2cca2c9181c10d2d7e603ac1646badf07ad7505 Mon Sep 17 00:00:00 2001 From: Peter Baumann Date: Tue, 22 Mar 2022 18:36:53 +0100 Subject: [PATCH] fix: MockFileInfo.Exists no longer returns stale cached data In 5216e0d ("fix: make Mock{File,Directory}Info cache file attributes (#791)", 2022-01-09) a cache of the MockFileData was introduced, to mimic the behaviour that a FileInfo object will not read the data from disk but instead also remembers its internal state, which can be updated by calling its `Refresh` method. This internal (or cached state) is invalidated when calling the methods `Create`, `Delete` and `MoveTo` methods, as can be seen by the `Invalidate` calls in https://github.com/dotnet/runtime/blob/8766a1cf1ed6c3b69cef50154139699b72fb52c5/src/libraries/System.Private.CoreLib/src/System/IO/FileInfo.cs In the PR #791 it was overlooked to also invalidate the cached data in these methods. This commit fixes it by invalidating the cached data only for `Create`, `CreateText` and `Delete`. The two `MoveTo` variants are not changed as I could not manage to find any behaviour which is broken without that invalidation. Most likely reason is that the MockFileData is updated to represent the destination file ofter the move, so invalidating is not needed. Fixes #822 --- .../MockFileInfo.cs | 9 +++- .../MockFileInfoTests.cs | 43 +++++++++++++++++++ 2 files changed, 50 insertions(+), 2 deletions(-) diff --git a/src/System.IO.Abstractions.TestingHelpers/MockFileInfo.cs b/src/System.IO.Abstractions.TestingHelpers/MockFileInfo.cs index 840accb1e..4f6f7f577 100644 --- a/src/System.IO.Abstractions.TestingHelpers/MockFileInfo.cs +++ b/src/System.IO.Abstractions.TestingHelpers/MockFileInfo.cs @@ -28,6 +28,7 @@ public MockFileInfo(IMockFileDataAccessor mockFileSystem, string path) : base(mo /// public override void Delete() { + refreshOnNextRead = true; mockFile.Delete(path); } @@ -221,13 +222,17 @@ public override IFileInfo CopyTo(string destFileName, bool overwrite) /// public override Stream Create() { - return mockFile.Create(FullName); + var result = mockFile.Create(FullName); + refreshOnNextRead = true; + return result; } /// public override StreamWriter CreateText() { - return mockFile.CreateText(FullName); + var result = mockFile.CreateText(FullName); + refreshOnNextRead = true; + return result; } /// diff --git a/tests/System.IO.Abstractions.TestingHelpers.Tests/MockFileInfoTests.cs b/tests/System.IO.Abstractions.TestingHelpers.Tests/MockFileInfoTests.cs index 860615eeb..10034aab5 100644 --- a/tests/System.IO.Abstractions.TestingHelpers.Tests/MockFileInfoTests.cs +++ b/tests/System.IO.Abstractions.TestingHelpers.Tests/MockFileInfoTests.cs @@ -750,6 +750,49 @@ public void MockFileInfo_Exists_ShouldUpdateCachedDataOnRefresh() Assert.IsTrue(fileInfo.Exists); } + [Test] + public void MockFileInfo_Create_ShouldUpdateCachedDataAndReturnTrueForExists() + { + IFileSystem fileSystem = new MockFileSystem(); + var path = XFS.Path(@"c:\temp\file1.txt"); + IFileInfo fileInfo = fileSystem.FileInfo.FromFileName(path); + + // Act + fileInfo.Create().Dispose(); + + // Assert + var result = fileInfo.Exists; + Assert.IsTrue(result); + } + + [Test] + public void MockFileInfo_CreateText_ShouldUpdateCachedDataAndReturnTrueForExists() + { + IFileSystem fileSystem = new MockFileSystem(); + var path = XFS.Path(@"c:\temp\file1.txt"); + IFileInfo fileInfo = fileSystem.FileInfo.FromFileName(path); + + // Act + fileInfo.CreateText().Dispose(); + + // Assert + Assert.IsTrue(fileInfo.Exists); + } + + [Test] + public void MockFileInfo_Delete_ShouldUpdateCachedDataAndReturnFalseForExists() + { + var fileSystem = new MockFileSystem(); + var path = XFS.Path(@"c:\temp\file1.txt"); + IFileInfo fileInfo = fileSystem.FileInfo.FromFileName(path); + + // Act + fileInfo.Delete(); + + // Assert + Assert.IsFalse(fileInfo.Exists); + } + [Test] public void MockFileInfo_Delete_ShouldThrowIfFileAccessShareHasNoWriteOrDeleteAccess() {