From a53bd9a7660d0518713378b9d7afeb75c9d41ce3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Valentin=20Breu=C3=9F?= Date: Fri, 16 Sep 2022 17:04:53 +0200 Subject: [PATCH] feat: set Creation, LastAccess and LastWrite time for files (#875) Implements #872 Adjust `CreationTime`, `LastAccessTime` and `LastWriteTime` when interacting with files in the `MockFileSystem`. Provides a means to mock the used DateTime by calling e.g. ```csharp var fixedTime = new DateTime(2022, 01, 01); var fileSystem = new MockFileSystem().MockTime(() => fixedTime); // All times will now be set to the fixedTime. ``` Implementes the following logic in MockFile: *All these cases are covered by unit tests in MockFileAdjustTimesTest* - When creating files CreationTime, LastAccessTime and LastWriteTime are set to the current time - When changing files (`WriteAllText`, `WriteAllBytes`, `AppendAllText`, `OpenWrite`, `Open`) LastAccessTime and LastWriteTime are set to the current time CreationTime is left unchanged - When reading files (`ReadAllText`, `ReadAllLines`, `ReadAllBytes`, `OpenRead`) LastAccessTime is set to the current time CreationTime and LastWriteTime are left unchanged - When setting attributes or ACLs (`SetAttributes`, `SetAccessControl`) LastAccessTime is set to the current time CreationTime and LastWriteTime are left unchanged - When moving files (`Move`) LastAccessTime is set to the current time CreationTime and LastWriteTime are left unchanged - When copying files (`Copy`) CreationTime and LastAccessTime of the copied file in the destination directory is set to the current time LastWriteTime and all times of the source file are left unchanged --- .../IMockFileDataAccessor.cs | 8 + .../MockDirectoryInfo.cs | 12 +- .../MockFile.cs | 44 ++- .../MockFileData.cs | 27 +- .../MockFileInfo.cs | 29 +- .../MockFileStream.cs | 36 ++- .../MockFileSystem.cs | 51 ++- .../TimeAdjustments.cs | 30 ++ .../MockDirectoryInfoTests.cs | 10 +- .../MockDirectoryTests.cs | 15 +- .../MockFileAdjustTimesTest.cs | 303 ++++++++++++++++++ .../MockFileGetCreationTimeTests.cs | 14 + .../MockFileGetCreationTimeUtcTests.cs | 14 + .../MockFileGetLastAccessTimeTests.cs | 14 + .../MockFileGetLastAccessTimeUtcTests.cs | 14 + .../MockFileGetLastWriteTimeTests.cs | 14 + .../MockFileGetLastWriteTimeUtcTests.cs | 14 + .../MockFileInfoTests.cs | 104 +++++- 18 files changed, 703 insertions(+), 50 deletions(-) create mode 100644 src/System.IO.Abstractions.TestingHelpers/TimeAdjustments.cs create mode 100644 tests/System.IO.Abstractions.TestingHelpers.Tests/MockFileAdjustTimesTest.cs diff --git a/src/System.IO.Abstractions.TestingHelpers/IMockFileDataAccessor.cs b/src/System.IO.Abstractions.TestingHelpers/IMockFileDataAccessor.cs index 1aeeb89d2..533e28be0 100644 --- a/src/System.IO.Abstractions.TestingHelpers/IMockFileDataAccessor.cs +++ b/src/System.IO.Abstractions.TestingHelpers/IMockFileDataAccessor.cs @@ -8,6 +8,14 @@ namespace System.IO.Abstractions.TestingHelpers /// public interface IMockFileDataAccessor : IFileSystem { + /// + /// Adjust the times of the . + /// + /// The for which the times should be adjusted. + /// The adjustments to make on the . + /// The adjusted file. + MockFileData AdjustTimes(MockFileData fileData, TimeAdjustments timeAdjustments); + /// /// Gets a file. /// diff --git a/src/System.IO.Abstractions.TestingHelpers/MockDirectoryInfo.cs b/src/System.IO.Abstractions.TestingHelpers/MockDirectoryInfo.cs index eb70a3a10..6ff27e344 100644 --- a/src/System.IO.Abstractions.TestingHelpers/MockDirectoryInfo.cs +++ b/src/System.IO.Abstractions.TestingHelpers/MockDirectoryInfo.cs @@ -62,7 +62,7 @@ public override FileAttributes Attributes /// public override DateTime CreationTime { - get { return GetMockFileDataForRead().CreationTime.DateTime; } + get { return GetMockFileDataForRead().CreationTime.LocalDateTime; } set { GetMockFileDataForWrite().CreationTime = value; } } @@ -70,7 +70,7 @@ public override DateTime CreationTime public override DateTime CreationTimeUtc { get { return GetMockFileDataForRead().CreationTime.UtcDateTime; } - set { GetMockFileDataForWrite().CreationTime = value.ToLocalTime(); } + set { GetMockFileDataForWrite().CreationTime = value; } } /// @@ -114,7 +114,7 @@ public override string FullName /// public override DateTime LastAccessTime { - get { return GetMockFileDataForRead().LastAccessTime.DateTime; } + get { return GetMockFileDataForRead().LastAccessTime.LocalDateTime; } set { GetMockFileDataForWrite().LastAccessTime = value; } } @@ -122,13 +122,13 @@ public override DateTime LastAccessTime public override DateTime LastAccessTimeUtc { get { return GetMockFileDataForRead().LastAccessTime.UtcDateTime; } - set { GetMockFileDataForWrite().LastAccessTime = value.ToLocalTime(); } + set { GetMockFileDataForWrite().LastAccessTime = value; } } /// public override DateTime LastWriteTime { - get { return GetMockFileDataForRead().LastWriteTime.DateTime; } + get { return GetMockFileDataForRead().LastWriteTime.LocalDateTime; } set { GetMockFileDataForWrite().LastWriteTime = value; } } @@ -136,7 +136,7 @@ public override DateTime LastWriteTime public override DateTime LastWriteTimeUtc { get { return GetMockFileDataForRead().LastWriteTime.UtcDateTime; } - set { GetMockFileDataForWrite().LastWriteTime = value.ToLocalTime(); } + set { GetMockFileDataForWrite().LastWriteTime = value; } } #if FEATURE_FILE_SYSTEM_INFO_LINK_TARGET diff --git a/src/System.IO.Abstractions.TestingHelpers/MockFile.cs b/src/System.IO.Abstractions.TestingHelpers/MockFile.cs index 32b52a871..ed534ae2c 100644 --- a/src/System.IO.Abstractions.TestingHelpers/MockFile.cs +++ b/src/System.IO.Abstractions.TestingHelpers/MockFile.cs @@ -55,12 +55,13 @@ public override void AppendAllText(string path, string contents, Encoding encodi if (!mockFileDataAccessor.FileExists(path)) { VerifyDirectoryExists(path); - mockFileDataAccessor.AddFile(path, new MockFileData(contents, encoding)); + mockFileDataAccessor.AddFile(path, mockFileDataAccessor.AdjustTimes(new MockFileData(contents, encoding), TimeAdjustments.All)); } else { var file = mockFileDataAccessor.GetFile(path); file.CheckFileAccess(path, FileAccess.Write); + mockFileDataAccessor.AdjustTimes(file, TimeAdjustments.LastAccessTime | TimeAdjustments.LastWriteTime); var bytesToAppend = encoding.GetBytes(contents); file.Contents = file.Contents.Concat(bytesToAppend).ToArray(); } @@ -124,7 +125,7 @@ public override void Copy(string sourceFileName, string destFileName, bool overw var sourceFileData = mockFileDataAccessor.GetFile(sourceFileName); sourceFileData.CheckFileAccess(sourceFileName, FileAccess.Read); var destFileData = new MockFileData(sourceFileData); - destFileData.CreationTime = destFileData.LastAccessTime = DateTime.Now; + mockFileDataAccessor.AdjustTimes(destFileData, TimeAdjustments.CreationTime | TimeAdjustments.LastAccessTime); mockFileDataAccessor.AddFile(destFileName, destFileData); } @@ -151,6 +152,7 @@ private Stream CreateInternal(string path, FileAccess access, FileOptions option VerifyDirectoryExists(path); var mockFileData = new MockFileData(new byte[0]); + mockFileDataAccessor.AdjustTimes(mockFileData, TimeAdjustments.All); mockFileDataAccessor.AddFile(path, mockFileData); return OpenInternal(path, FileMode.Open, access, options); } @@ -188,7 +190,7 @@ public override IFileSystemInfo CreateSymbolicLink(string path, string pathToTar var sourceFileData = mockFileDataAccessor.GetFile(pathToTarget); sourceFileData.CheckFileAccess(pathToTarget, FileAccess.Read); var destFileData = new MockFileData(new byte[0]); - destFileData.CreationTime = destFileData.LastAccessTime = DateTime.Now; + mockFileDataAccessor.AdjustTimes(destFileData, TimeAdjustments.CreationTime | TimeAdjustments.LastAccessTime); destFileData.LinkTarget = pathToTarget; mockFileDataAccessor.AddFile(path, destFileData); @@ -436,7 +438,7 @@ public override void Move(string sourceFileName, string destFileName) VerifyDirectoryExists(destFileName); mockFileDataAccessor.RemoveFile(sourceFileName); - mockFileDataAccessor.AddFile(destFileName, new MockFileData(sourceFile)); + mockFileDataAccessor.AddFile(destFileName, mockFileDataAccessor.AdjustTimes(new MockFileData(sourceFile), TimeAdjustments.LastAccessTime)); } #if FEATURE_FILE_MOVE_WITH_OVERWRITE @@ -480,9 +482,9 @@ public override void Move(string sourceFileName, string destFileName, bool overw throw CommonExceptions.ProcessCannotAccessFileInUse(); } VerifyDirectoryExists(destFileName); - + mockFileDataAccessor.RemoveFile(sourceFileName); - mockFileDataAccessor.AddFile(destFileName, new MockFileData(sourceFile)); + mockFileDataAccessor.AddFile(destFileName, mockFileDataAccessor.AdjustTimes(new MockFileData(sourceFile), TimeAdjustments.LastAccessTime)); } #endif @@ -539,6 +541,12 @@ private Stream OpenInternal( var mockFileData = mockFileDataAccessor.GetFile(path); mockFileData.CheckFileAccess(path, access); + var timeAdjustments = TimeAdjustments.LastAccessTime; + if (access.HasFlag(FileAccess.Write)) + { + timeAdjustments |= TimeAdjustments.LastWriteTime; + } + mockFileDataAccessor.AdjustTimes(mockFileData, timeAdjustments); return new MockFileStream(mockFileDataAccessor, path, mode, access, options); } @@ -578,7 +586,9 @@ public override byte[] ReadAllBytes(string path) throw CommonExceptions.FileNotFound(path); } mockFileDataAccessor.GetFile(path).CheckFileAccess(path, FileAccess.Read); - return mockFileDataAccessor.GetFile(path).Contents.ToArray(); + var fileData = mockFileDataAccessor.GetFile(path); + mockFileDataAccessor.AdjustTimes(fileData, TimeAdjustments.LastAccessTime); + return fileData.Contents.ToArray(); } /// @@ -590,10 +600,11 @@ public override string[] ReadAllLines(string path) { throw CommonExceptions.FileNotFound(path); } - mockFileDataAccessor.GetFile(path).CheckFileAccess(path, FileAccess.Read); + var fileData = mockFileDataAccessor.GetFile(path); + fileData.CheckFileAccess(path, FileAccess.Read); + mockFileDataAccessor.AdjustTimes(fileData, TimeAdjustments.LastAccessTime); - return mockFileDataAccessor - .GetFile(path) + return fileData .TextContents .SplitLines(); } @@ -613,9 +624,11 @@ public override string[] ReadAllLines(string path, Encoding encoding) throw CommonExceptions.FileNotFound(path); } - mockFileDataAccessor.GetFile(path).CheckFileAccess(path, FileAccess.Read); + var fileData = mockFileDataAccessor.GetFile(path); + fileData.CheckFileAccess(path, FileAccess.Read); + mockFileDataAccessor.AdjustTimes(fileData, TimeAdjustments.LastAccessTime); - using (var ms = new MemoryStream(mockFileDataAccessor.GetFile(path).Contents)) + using (var ms = new MemoryStream(fileData.Contents)) using (var sr = new StreamReader(ms, encoding)) { return sr.ReadToEnd().SplitLines(); @@ -713,6 +726,7 @@ public override void SetAccessControl(string path, FileSecurity fileSecurity) } var fileData = mockFileDataAccessor.GetFile(path); + mockFileDataAccessor.AdjustTimes(fileData, TimeAdjustments.LastAccessTime); fileData.AccessControl = fileSecurity; } @@ -736,6 +750,7 @@ public override void SetAttributes(string path, FileAttributes fileAttributes) } else { + mockFileDataAccessor.AdjustTimes(possibleFileData, TimeAdjustments.LastAccessTime); possibleFileData.Attributes = fileAttributes; } } @@ -824,7 +839,7 @@ public override void WriteAllBytes(string path, byte[] bytes) mockFileDataAccessor.PathVerifier.IsLegalAbsoluteOrRelative(path, "path"); VerifyDirectoryExists(path); - mockFileDataAccessor.AddFile(path, new MockFileData(bytes.ToArray())); + mockFileDataAccessor.AddFile(path, mockFileDataAccessor.AdjustTimes(new MockFileData(bytes.ToArray()), TimeAdjustments.All)); } /// @@ -1094,7 +1109,7 @@ public override void WriteAllText(string path, string contents, Encoding encodin VerifyDirectoryExists(path); MockFileData data = contents == null ? new MockFileData(new byte[0]) : new MockFileData(contents, encoding); - mockFileDataAccessor.AddFile(path, data); + mockFileDataAccessor.AddFile(path, mockFileDataAccessor.AdjustTimes(data, TimeAdjustments.All)); } internal static string ReadAllBytes(byte[] contents, Encoding encoding) @@ -1110,6 +1125,7 @@ private string ReadAllTextInternal(string path, Encoding encoding) { var mockFileData = mockFileDataAccessor.GetFile(path); mockFileData.CheckFileAccess(path, FileAccess.Read); + mockFileDataAccessor.AdjustTimes(mockFileData, TimeAdjustments.LastAccessTime); return ReadAllBytes(mockFileData.Contents, encoding); } diff --git a/src/System.IO.Abstractions.TestingHelpers/MockFileData.cs b/src/System.IO.Abstractions.TestingHelpers/MockFileData.cs index 0fe04c386..1c59dba63 100644 --- a/src/System.IO.Abstractions.TestingHelpers/MockFileData.cs +++ b/src/System.IO.Abstractions.TestingHelpers/MockFileData.cs @@ -49,7 +49,10 @@ public class MockFileData /// private MockFileData() { - // empty + var now = DateTime.UtcNow; + LastWriteTime = now; + LastAccessTime = now; + CreationTime = now; } /// @@ -78,6 +81,7 @@ public MockFileData(string textContents, Encoding encoding) /// The actual content. /// Thrown if is . public MockFileData(byte[] contents) + : this() { Contents = contents ?? throw new ArgumentNullException(nameof(contents)); } @@ -126,17 +130,32 @@ public string TextContents /// /// Gets or sets the date and time the was created. /// - public DateTimeOffset CreationTime { get; set; } = new DateTimeOffset(2010, 01, 02, 00, 00, 00, TimeSpan.FromHours(4)); + public DateTimeOffset CreationTime + { + get { return creationTime; } + set{ creationTime = value.ToUniversalTime(); } + } + private DateTimeOffset creationTime; /// /// Gets or sets the date and time of the was last accessed to. /// - public DateTimeOffset LastAccessTime { get; set; } = new DateTimeOffset(2010, 02, 04, 00, 00, 00, TimeSpan.FromHours(4)); + public DateTimeOffset LastAccessTime + { + get { return lastAccessTime; } + set { lastAccessTime = value.ToUniversalTime(); } + } + private DateTimeOffset lastAccessTime; /// /// Gets or sets the date and time of the was last written to. /// - public DateTimeOffset LastWriteTime { get; set; } = new DateTimeOffset(2010, 01, 04, 00, 00, 00, TimeSpan.FromHours(4)); + public DateTimeOffset LastWriteTime + { + get { return lastWriteTime; } + set { lastWriteTime = value.ToUniversalTime(); } + } + private DateTimeOffset lastWriteTime; #if FEATURE_FILE_SYSTEM_INFO_LINK_TARGET /// diff --git a/src/System.IO.Abstractions.TestingHelpers/MockFileInfo.cs b/src/System.IO.Abstractions.TestingHelpers/MockFileInfo.cs index 66105a5bb..96096a95d 100644 --- a/src/System.IO.Abstractions.TestingHelpers/MockFileInfo.cs +++ b/src/System.IO.Abstractions.TestingHelpers/MockFileInfo.cs @@ -1,6 +1,5 @@ using System.Runtime.Versioning; using System.Security.AccessControl; -using System.Text; namespace System.IO.Abstractions.TestingHelpers { @@ -60,12 +59,12 @@ public override DateTime CreationTime get { var mockFileData = GetMockFileDataForRead(); - return mockFileData.CreationTime.DateTime; + return mockFileData.CreationTime.LocalDateTime; } set { var mockFileData = GetMockFileDataForWrite(); - mockFileData.CreationTime = value; + mockFileData.CreationTime = AdjustUnspecifiedKind(value, DateTimeKind.Local); } } @@ -80,7 +79,7 @@ public override DateTime CreationTimeUtc set { var mockFileData = GetMockFileDataForWrite(); - mockFileData.CreationTime = value.ToLocalTime(); + mockFileData.CreationTime = AdjustUnspecifiedKind(value, DateTimeKind.Utc); } } @@ -117,12 +116,12 @@ public override DateTime LastAccessTime get { var mockFileData = GetMockFileDataForRead(); - return mockFileData.LastAccessTime.DateTime; + return mockFileData.LastAccessTime.LocalDateTime; } set { var mockFileData = GetMockFileDataForWrite(); - mockFileData.LastAccessTime = value; + mockFileData.LastAccessTime = AdjustUnspecifiedKind(value, DateTimeKind.Local); } } @@ -137,7 +136,7 @@ public override DateTime LastAccessTimeUtc set { var mockFileData = GetMockFileDataForWrite(); - mockFileData.LastAccessTime = value; + mockFileData.LastAccessTime = AdjustUnspecifiedKind(value, DateTimeKind.Utc); } } @@ -147,12 +146,12 @@ public override DateTime LastWriteTime get { var mockFileData = GetMockFileDataForRead(); - return mockFileData.LastWriteTime.DateTime; + return mockFileData.LastWriteTime.LocalDateTime; } set { var mockFileData = GetMockFileDataForWrite(); - mockFileData.LastWriteTime = value; + mockFileData.LastWriteTime = AdjustUnspecifiedKind(value, DateTimeKind.Local); } } @@ -167,7 +166,7 @@ public override DateTime LastWriteTimeUtc set { var mockFileData = GetMockFileDataForWrite(); - mockFileData.LastWriteTime = value.ToLocalTime(); + mockFileData.LastWriteTime = AdjustUnspecifiedKind(value, DateTimeKind.Utc); } } @@ -381,6 +380,16 @@ public override string ToString() return originalPath; } + private static DateTime AdjustUnspecifiedKind(DateTime time, DateTimeKind fallbackKind) + { + if (time.Kind == DateTimeKind.Unspecified) + { + return DateTime.SpecifyKind(time, fallbackKind); + } + + return time; + } + private MockFileData GetMockFileDataForRead() { if (refreshOnNextRead) diff --git a/src/System.IO.Abstractions.TestingHelpers/MockFileStream.cs b/src/System.IO.Abstractions.TestingHelpers/MockFileStream.cs index 6b0c39303..64bc5f4e3 100644 --- a/src/System.IO.Abstractions.TestingHelpers/MockFileStream.cs +++ b/src/System.IO.Abstractions.TestingHelpers/MockFileStream.cs @@ -34,6 +34,8 @@ public MockFileStream( fileData = mockFileDataAccessor.GetFile(path); fileData.CheckFileAccess(path, access); + var timeAdjustments = GetTimeAdjustmentsForFileStreamWhenFileExists(mode, access); + mockFileDataAccessor.AdjustTimes(fileData, timeAdjustments); var existingContents = fileData.Contents; var keepExistingContents = existingContents?.Length > 0 && @@ -60,7 +62,8 @@ public MockFileStream( } fileData = new MockFileData(new byte[] { }); - fileData.CreationTime = fileData.LastWriteTime = fileData.LastAccessTime = DateTime.Now; + mockFileDataAccessor.AdjustTimes(fileData, + TimeAdjustments.CreationTime | TimeAdjustments.LastAccessTime); mockFileDataAccessor.AddFile(path, fileData); } @@ -76,14 +79,16 @@ public MockFileStream( /// public override int Read(byte[] buffer, int offset, int count) { - fileData.LastAccessTime = DateTime.Now; + mockFileDataAccessor.AdjustTimes(fileData, + TimeAdjustments.LastAccessTime); return base.Read(buffer, offset, count); } /// public override void Write(byte[] buffer, int offset, int count) { - fileData.LastWriteTime = fileData.LastAccessTime = DateTime.Now; + mockFileDataAccessor.AdjustTimes(fileData, + TimeAdjustments.LastAccessTime | TimeAdjustments.LastWriteTime); base.Write(buffer, offset, count); } @@ -136,5 +141,30 @@ private void OnClose() mockFileDataAccessor.FileInfo.FromFileName(path).Encrypt(); } } + + private TimeAdjustments GetTimeAdjustmentsForFileStreamWhenFileExists(FileMode mode, FileAccess access) + { + switch (mode) + { + case FileMode.Append: + case FileMode.CreateNew: + if (access.HasFlag(FileAccess.Read)) + { + return TimeAdjustments.LastAccessTime; + } + return TimeAdjustments.None; + case FileMode.Create: + case FileMode.Truncate: + if (access.HasFlag(FileAccess.Write)) + { + return TimeAdjustments.LastAccessTime | TimeAdjustments.LastWriteTime; + } + return TimeAdjustments.LastAccessTime; + case FileMode.Open: + case FileMode.OpenOrCreate: + default: + return TimeAdjustments.None; + } + } } } \ No newline at end of file diff --git a/src/System.IO.Abstractions.TestingHelpers/MockFileSystem.cs b/src/System.IO.Abstractions.TestingHelpers/MockFileSystem.cs index fa3203ac9..f8d78b74d 100644 --- a/src/System.IO.Abstractions.TestingHelpers/MockFileSystem.cs +++ b/src/System.IO.Abstractions.TestingHelpers/MockFileSystem.cs @@ -1,6 +1,7 @@ -using System.Collections.Generic; +using System.Collections.Generic; using System.Linq; using System.Reflection; +using System.Runtime.Serialization; namespace System.IO.Abstractions.TestingHelpers { @@ -15,6 +16,9 @@ public class MockFileSystem : FileSystemBase, IMockFileDataAccessor private readonly IDictionary files; private readonly PathVerifier pathVerifier; + [NonSerialized] + private Func dateTimeProvider = defaultDateTimeProvider; + private static Func defaultDateTimeProvider = () => DateTime.UtcNow; /// public MockFileSystem() : this(null) { } @@ -88,6 +92,19 @@ public MockFileSystem(IDictionary files, string currentDir /// public PathVerifier PathVerifier => pathVerifier; + /// + /// Replaces the time provider with a mocked instance. This allows to influence the used time in tests. + /// + /// If not set, the default implementation returns . + /// + /// The function that returns the current . + /// + public MockFileSystem MockTime(Func dateTimeProvider) + { + this.dateTimeProvider = dateTimeProvider ?? defaultDateTimeProvider; + return this; + } + private string FixPath(string path, bool checkCaps = false) { if (path == null) @@ -124,6 +141,28 @@ private string GetPathWithCorrectDirectoryCapitalization(string fullPath) return fullPath.TrimSlashes(); } + /// + public MockFileData AdjustTimes(MockFileData fileData, TimeAdjustments timeAdjustments) + { + var now = dateTimeProvider(); + if (timeAdjustments.HasFlag(TimeAdjustments.CreationTime)) + { + fileData.CreationTime = now; + } + + if (timeAdjustments.HasFlag(TimeAdjustments.LastAccessTime)) + { + fileData.LastAccessTime = now; + } + + if (timeAdjustments.HasFlag(TimeAdjustments.LastWriteTime)) + { + fileData.LastWriteTime = now; + } + + return fileData; + } + /// public MockFileData GetFile(string path) { @@ -143,6 +182,7 @@ public void AddFile(string path, MockFileData mockFile) var fixedPath = FixPath(path, true); lock (files) { + mockFile ??= new MockFileData(string.Empty); var file = GetFile(fixedPath); if (file != null) @@ -155,6 +195,7 @@ public void AddFile(string path, MockFileData mockFile) throw CommonExceptions.AccessDenied(path); } file.CheckFileAccess(fixedPath, FileAccess.Write); + mockFile.CreationTime = file.CreationTime; } var directoryPath = Path.GetDirectoryName(fixedPath); @@ -164,7 +205,7 @@ public void AddFile(string path, MockFileData mockFile) AddDirectory(directoryPath); } - SetEntry(fixedPath, mockFile ?? new MockFileData(string.Empty)); + SetEntry(fixedPath, mockFile); } } @@ -374,6 +415,12 @@ public IEnumerable AllDirectories } } + [OnDeserializing] + private void OnDeserializing(StreamingContext c) + { + dateTimeProvider = defaultDateTimeProvider; + } + private bool AnyFileIsReadOnly(string path) { return Directory.GetFiles(path).Any(file => FileIsReadOnly(file)); diff --git a/src/System.IO.Abstractions.TestingHelpers/TimeAdjustments.cs b/src/System.IO.Abstractions.TestingHelpers/TimeAdjustments.cs new file mode 100644 index 000000000..321de416e --- /dev/null +++ b/src/System.IO.Abstractions.TestingHelpers/TimeAdjustments.cs @@ -0,0 +1,30 @@ +namespace System.IO.Abstractions.TestingHelpers +{ + /// + /// Flags indicating which times to adjust for a . + /// + [Flags] + public enum TimeAdjustments + { + /// + /// Adjusts no times on the + /// + None = 0, + /// + /// Adjusts the + /// + CreationTime = 1 << 0, + /// + /// Adjusts the + /// + LastAccessTime = 1 << 1, + /// + /// Adjusts the + /// + LastWriteTime = 1 << 2, + /// + /// Adjusts all times on the + /// + All = ~0 + } +} diff --git a/tests/System.IO.Abstractions.TestingHelpers.Tests/MockDirectoryInfoTests.cs b/tests/System.IO.Abstractions.TestingHelpers.Tests/MockDirectoryInfoTests.cs index d347b633f..b7aafc785 100644 --- a/tests/System.IO.Abstractions.TestingHelpers.Tests/MockDirectoryInfoTests.cs +++ b/tests/System.IO.Abstractions.TestingHelpers.Tests/MockDirectoryInfoTests.cs @@ -542,7 +542,7 @@ public void MockDirectoryInfo_CreationTime_ShouldReturnDefaultTimeForNonExisting var result = directoryInfo.CreationTime; - Assert.That(result, Is.EqualTo(MockFileData.DefaultDateTimeOffset.UtcDateTime)); + Assert.That(result, Is.EqualTo(MockFileData.DefaultDateTimeOffset.LocalDateTime)); } [Test] @@ -551,9 +551,9 @@ public void MockDirectoryInfo_LastAccessTime_ShouldReturnDefaultTimeForNonExisti var fileSystem = new MockFileSystem(); var directoryInfo = new MockDirectoryInfo(fileSystem, XFS.Path(@"c:\non\existing")); - var result = directoryInfo.LastAccessTimeUtc; + var result = directoryInfo.LastAccessTime; - Assert.That(result, Is.EqualTo(MockFileData.DefaultDateTimeOffset.UtcDateTime)); + Assert.That(result, Is.EqualTo(MockFileData.DefaultDateTimeOffset.LocalDateTime)); } [Test] @@ -562,9 +562,9 @@ public void MockDirectoryInfo_LastWriteTime_ShouldReturnDefaultTimeForNonExistin var fileSystem = new MockFileSystem(); var directoryInfo = new MockDirectoryInfo(fileSystem, XFS.Path(@"c:\non\existing")); - var result = directoryInfo.LastWriteTimeUtc; + var result = directoryInfo.LastWriteTime; - Assert.That(result, Is.EqualTo(MockFileData.DefaultDateTimeOffset.UtcDateTime)); + Assert.That(result, Is.EqualTo(MockFileData.DefaultDateTimeOffset.LocalDateTime)); } [Test] diff --git a/tests/System.IO.Abstractions.TestingHelpers.Tests/MockDirectoryTests.cs b/tests/System.IO.Abstractions.TestingHelpers.Tests/MockDirectoryTests.cs index 5b3bfdfc0..3da98b588 100644 --- a/tests/System.IO.Abstractions.TestingHelpers.Tests/MockDirectoryTests.cs +++ b/tests/System.IO.Abstractions.TestingHelpers.Tests/MockDirectoryTests.cs @@ -411,7 +411,7 @@ public void MockDirectory_GetFiles_ShouldFilterForFilesWithNoExtensionsAndFilter Assert.That(result, Is.EquivalentTo(expected)); } - private void ExecuteTimeAttributeTest(Action setter, Func getter) + private void ExecuteTimeAttributeTest(DateTime time, Action setter, Func getter) { string path = XFS.Path(@"c:\something\demo.txt"); var fileSystem = new MockFileSystem(new Dictionary @@ -420,7 +420,6 @@ private void ExecuteTimeAttributeTest(Action sett }); // Act - var time = new DateTime(2010, 6, 4, 13, 26, 42); setter(fileSystem, path, time); var result = getter(fileSystem, path); @@ -432,6 +431,7 @@ private void ExecuteTimeAttributeTest(Action sett public void MockDirectory_GetCreationTime_ShouldReturnCreationTimeFromFile() { ExecuteTimeAttributeTest( + new DateTime(2010, 6, 4, 13, 26, 42), (fs, p, d) => fs.File.SetCreationTime(p, d), (fs, p) => fs.Directory.GetCreationTime(p)); } @@ -440,6 +440,7 @@ public void MockDirectory_GetCreationTime_ShouldReturnCreationTimeFromFile() public void MockDirectory_GetCreationTimeUtc_ShouldReturnCreationTimeUtcFromFile() { ExecuteTimeAttributeTest( + new DateTime(2010, 6, 4, 13, 26, 42, DateTimeKind.Utc), (fs, p, d) => fs.File.SetCreationTimeUtc(p, d), (fs, p) => fs.Directory.GetCreationTimeUtc(p)); } @@ -448,6 +449,7 @@ public void MockDirectory_GetCreationTimeUtc_ShouldReturnCreationTimeUtcFromFile public void MockDirectory_GetLastAccessTime_ShouldReturnLastAccessTimeFromFile() { ExecuteTimeAttributeTest( + new DateTime(2010, 6, 4, 13, 26, 42), (fs, p, d) => fs.File.SetLastAccessTime(p, d), (fs, p) => fs.Directory.GetLastAccessTime(p)); } @@ -456,6 +458,7 @@ public void MockDirectory_GetLastAccessTime_ShouldReturnLastAccessTimeFromFile() public void MockDirectory_GetLastAccessTimeUtc_ShouldReturnLastAccessTimeUtcFromFile() { ExecuteTimeAttributeTest( + new DateTime(2010, 6, 4, 13, 26, 42, DateTimeKind.Utc), (fs, p, d) => fs.File.SetLastAccessTimeUtc(p, d), (fs, p) => fs.Directory.GetLastAccessTimeUtc(p)); } @@ -464,6 +467,7 @@ public void MockDirectory_GetLastAccessTimeUtc_ShouldReturnLastAccessTimeUtcFrom public void MockDirectory_GetLastWriteTime_ShouldReturnLastWriteTimeFromFile() { ExecuteTimeAttributeTest( + new DateTime(2010, 6, 4, 13, 26, 42), (fs, p, d) => fs.File.SetLastWriteTime(p, d), (fs, p) => fs.Directory.GetLastWriteTime(p)); } @@ -472,6 +476,7 @@ public void MockDirectory_GetLastWriteTime_ShouldReturnLastWriteTimeFromFile() public void MockDirectory_GetLastWriteTimeUtc_ShouldReturnLastWriteTimeUtcFromFile() { ExecuteTimeAttributeTest( + new DateTime(2010, 6, 4, 13, 26, 42, DateTimeKind.Utc), (fs, p, d) => fs.File.SetLastWriteTimeUtc(p, d), (fs, p) => fs.Directory.GetLastWriteTimeUtc(p)); } @@ -480,6 +485,7 @@ public void MockDirectory_GetLastWriteTimeUtc_ShouldReturnLastWriteTimeUtcFromFi public void MockDirectory_SetCreationTime_ShouldSetCreationTimeOnFile() { ExecuteTimeAttributeTest( + new DateTime(2010, 6, 4, 13, 26, 42), (fs, p, d) => fs.Directory.SetCreationTime(p, d), (fs, p) => fs.File.GetCreationTime(p)); } @@ -488,6 +494,7 @@ public void MockDirectory_SetCreationTime_ShouldSetCreationTimeOnFile() public void MockDirectory_SetCreationTimeUtc_ShouldSetCreationTimeUtcOnFile() { ExecuteTimeAttributeTest( + new DateTime(2010, 6, 4, 13, 26, 42, DateTimeKind.Utc), (fs, p, d) => fs.Directory.SetCreationTimeUtc(p, d), (fs, p) => fs.File.GetCreationTimeUtc(p)); } @@ -496,6 +503,7 @@ public void MockDirectory_SetCreationTimeUtc_ShouldSetCreationTimeUtcOnFile() public void MockDirectory_SetLastAccessTime_ShouldSetLastAccessTimeOnFile() { ExecuteTimeAttributeTest( + new DateTime(2010, 6, 4, 13, 26, 42), (fs, p, d) => fs.Directory.SetLastAccessTime(p, d), (fs, p) => fs.File.GetLastAccessTime(p)); } @@ -504,6 +512,7 @@ public void MockDirectory_SetLastAccessTime_ShouldSetLastAccessTimeOnFile() public void MockDirectory_SetLastAccessTimeUtc_ShouldSetLastAccessTimeUtcOnFile() { ExecuteTimeAttributeTest( + new DateTime(2010, 6, 4, 13, 26, 42, DateTimeKind.Utc), (fs, p, d) => fs.Directory.SetLastAccessTimeUtc(p, d), (fs, p) => fs.File.GetLastAccessTimeUtc(p)); } @@ -512,6 +521,7 @@ public void MockDirectory_SetLastAccessTimeUtc_ShouldSetLastAccessTimeUtcOnFile( public void MockDirectory_SetLastWriteTime_ShouldSetLastWriteTimeOnFile() { ExecuteTimeAttributeTest( + new DateTime(2010, 6, 4, 13, 26, 42), (fs, p, d) => fs.Directory.SetLastWriteTime(p, d), (fs, p) => fs.File.GetLastWriteTime(p)); } @@ -520,6 +530,7 @@ public void MockDirectory_SetLastWriteTime_ShouldSetLastWriteTimeOnFile() public void MockDirectory_SetLastWriteTimeUtc_ShouldSetLastWriteTimeUtcOnFile() { ExecuteTimeAttributeTest( + new DateTime(2010, 6, 4, 13, 26, 42, DateTimeKind.Utc), (fs, p, d) => fs.Directory.SetLastWriteTimeUtc(p, d), (fs, p) => fs.File.GetLastWriteTimeUtc(p)); } diff --git a/tests/System.IO.Abstractions.TestingHelpers.Tests/MockFileAdjustTimesTest.cs b/tests/System.IO.Abstractions.TestingHelpers.Tests/MockFileAdjustTimesTest.cs new file mode 100644 index 000000000..e9feb27ab --- /dev/null +++ b/tests/System.IO.Abstractions.TestingHelpers.Tests/MockFileAdjustTimesTest.cs @@ -0,0 +1,303 @@ +using System.Runtime.Versioning; +using System.Security.AccessControl; +using System.Text; +using NUnit.Framework; + +namespace System.IO.Abstractions.TestingHelpers.Tests +{ + [TestFixture] + public class MockFileAdjustTimesTest + { + [Test] + public void MockFile_AfterAppendAllText_ShouldUpdateLastAccessAndLastWriteTime() + { + var creationTime = DateTime.UtcNow.AddDays(10); + var updateTime = creationTime.AddDays(10); + var fileSystem = new MockFileSystem() + .MockTime(() => creationTime); + fileSystem.File.WriteAllText("foo.txt", "abc"); + fileSystem.MockTime(() => updateTime); + fileSystem.File.AppendAllText("foo.txt", "xyz"); + + var actualCreationTime = fileSystem.File.GetCreationTimeUtc("foo.txt"); + var actualLastAccessTime = fileSystem.File.GetLastAccessTimeUtc("foo.txt"); + var actualLastWriteTime = fileSystem.File.GetLastWriteTimeUtc("foo.txt"); + + Assert.That(actualCreationTime, Is.EqualTo(creationTime)); + Assert.That(actualLastAccessTime, Is.EqualTo(updateTime)); + Assert.That(actualLastWriteTime, Is.EqualTo(updateTime)); + } + + [Test] + public void MockFile_AfterCopy_ShouldUpdateCreationAndLastAccessTimeOfDestination() + { + var creationTime = DateTime.UtcNow.AddDays(10); + var updateTime = creationTime.AddDays(10); + var fileSystem = new MockFileSystem() + .MockTime(() => creationTime); + fileSystem.File.WriteAllText("foo.txt", "abc"); + fileSystem.MockTime(() => updateTime); + fileSystem.File.Copy("foo.txt", "bar.txt"); + + var actualSourceCreationTime = fileSystem.File.GetCreationTimeUtc("foo.txt"); + var actualDestinationCreationTime = fileSystem.File.GetCreationTimeUtc("bar.txt"); + var actualSourceLastAccessTime = fileSystem.File.GetLastAccessTimeUtc("foo.txt"); + var actualDestinationLastAccessTime = fileSystem.File.GetLastAccessTimeUtc("bar.txt"); + var actualSourceLastWriteTime = fileSystem.File.GetLastWriteTimeUtc("foo.txt"); + var actualDestinationLastWriteTime = fileSystem.File.GetLastWriteTimeUtc("bar.txt"); + + Assert.That(actualSourceCreationTime, Is.EqualTo(creationTime)); + Assert.That(actualDestinationCreationTime, Is.EqualTo(updateTime)); + Assert.That(actualSourceLastAccessTime, Is.EqualTo(creationTime)); + Assert.That(actualDestinationLastAccessTime, Is.EqualTo(updateTime)); + Assert.That(actualSourceLastWriteTime, Is.EqualTo(creationTime)); + Assert.That(actualDestinationLastWriteTime, Is.EqualTo(creationTime)); + } + + [Test] + public void MockFile_AfterMove_ShouldUpdateLastAccessTime() + { + var creationTime = DateTime.UtcNow.AddDays(10); + var updateTime = creationTime.AddDays(10); + var fileSystem = new MockFileSystem() + .MockTime(() => creationTime); + fileSystem.File.WriteAllText("foo.txt", "abc"); + fileSystem.MockTime(() => updateTime); + fileSystem.File.Move("foo.txt", "bar.txt"); + + var actualCreationTime = fileSystem.File.GetCreationTimeUtc("bar.txt"); + var actualLastAccessTime = fileSystem.File.GetLastAccessTimeUtc("bar.txt"); + var actualLastWriteTime = fileSystem.File.GetLastWriteTimeUtc("bar.txt"); + + Assert.That(actualCreationTime, Is.EqualTo(creationTime)); + Assert.That(actualLastAccessTime, Is.EqualTo(updateTime)); + Assert.That(actualLastWriteTime, Is.EqualTo(creationTime)); + } + + [TestCase(FileMode.Open, FileAccess.ReadWrite)] + [TestCase(FileMode.OpenOrCreate, FileAccess.Write)] + [TestCase(FileMode.Append, FileAccess.ReadWrite)] + public void MockFile_AfterOpen_WithWriteAccess_ShouldUpdateLastAccessAndLastWriteTime(FileMode fileMode, FileAccess fileAccess) + { + var creationTime = DateTime.UtcNow.AddDays(10); + var updateTime = creationTime.AddDays(10); + var fileSystem = new MockFileSystem() + .MockTime(() => creationTime); + fileSystem.File.WriteAllText("foo.txt", "abc"); + fileSystem.MockTime(() => updateTime); + fileSystem.File.Open("foo.txt", fileMode, fileAccess); + + var actualCreationTime = fileSystem.File.GetCreationTimeUtc("foo.txt"); + var actualLastAccessTime = fileSystem.File.GetLastAccessTimeUtc("foo.txt"); + var actualLastWriteTime = fileSystem.File.GetLastWriteTimeUtc("foo.txt"); + + Assert.That(actualCreationTime, Is.EqualTo(creationTime)); + Assert.That(actualLastAccessTime, Is.EqualTo(updateTime)); + Assert.That(actualLastWriteTime, Is.EqualTo(updateTime)); + } + + [TestCase(FileMode.Open, FileAccess.Read)] + [TestCase(FileMode.OpenOrCreate, FileAccess.Read)] + [TestCase(FileMode.Append, FileAccess.Read)] + public void MockFile_AfterOpen_WithReadOnlyAccess_ShouldUpdateLastAccessTime(FileMode fileMode, FileAccess fileAccess) + { + var creationTime = DateTime.UtcNow.AddDays(10); + var updateTime = creationTime.AddDays(10); + var fileSystem = new MockFileSystem() + .MockTime(() => creationTime); + fileSystem.File.WriteAllText("foo.txt", "abc"); + fileSystem.MockTime(() => updateTime); + fileSystem.File.Open("foo.txt", fileMode, fileAccess); + + var actualCreationTime = fileSystem.File.GetCreationTimeUtc("foo.txt"); + var actualLastAccessTime = fileSystem.File.GetLastAccessTimeUtc("foo.txt"); + var actualLastWriteTime = fileSystem.File.GetLastWriteTimeUtc("foo.txt"); + + Assert.That(actualCreationTime, Is.EqualTo(creationTime)); + Assert.That(actualLastAccessTime, Is.EqualTo(updateTime)); + Assert.That(actualLastWriteTime, Is.EqualTo(creationTime)); + } + + [Test] + public void MockFile_AfterReadAllBytes_ShouldUpdateLastAccessTime() + { + var creationTime = DateTime.UtcNow.AddDays(10); + var updateTime = creationTime.AddDays(10); + var fileSystem = new MockFileSystem() + .MockTime(() => creationTime); + fileSystem.File.WriteAllText("foo.txt", "abc"); + fileSystem.MockTime(() => updateTime); + fileSystem.File.ReadAllBytes("foo.txt"); + + var actualCreationTime = fileSystem.File.GetCreationTimeUtc("foo.txt"); + var actualLastAccessTime = fileSystem.File.GetLastAccessTimeUtc("foo.txt"); + var actualLastWriteTime = fileSystem.File.GetLastWriteTimeUtc("foo.txt"); + + Assert.That(actualCreationTime, Is.EqualTo(creationTime)); + Assert.That(actualLastAccessTime, Is.EqualTo(updateTime)); + Assert.That(actualLastWriteTime, Is.EqualTo(creationTime)); + } + + [Test] + public void MockFile_AfterReadAllLines_ShouldUpdateLastAccessTime() + { + var creationTime = DateTime.UtcNow.AddDays(10); + var updateTime = creationTime.AddDays(10); + var fileSystem = new MockFileSystem() + .MockTime(() => creationTime); + fileSystem.File.WriteAllText("foo.txt", "abc"); + fileSystem.MockTime(() => updateTime); + fileSystem.File.ReadAllLines("foo.txt"); + + var actualCreationTime = fileSystem.File.GetCreationTimeUtc("foo.txt"); + var actualLastAccessTime = fileSystem.File.GetLastAccessTimeUtc("foo.txt"); + var actualLastWriteTime = fileSystem.File.GetLastWriteTimeUtc("foo.txt"); + + Assert.That(actualCreationTime, Is.EqualTo(creationTime)); + Assert.That(actualLastAccessTime, Is.EqualTo(updateTime)); + Assert.That(actualLastWriteTime, Is.EqualTo(creationTime)); + } + + [Test] + public void MockFile_AfterReadAllText_ShouldUpdateLastAccessTime() + { + var creationTime = DateTime.UtcNow.AddDays(10); + var updateTime = creationTime.AddDays(10); + var fileSystem = new MockFileSystem() + .MockTime(() => creationTime); + fileSystem.File.WriteAllText("foo.txt", "abc"); + fileSystem.MockTime(() => updateTime); + fileSystem.File.ReadAllText("foo.txt"); + + var actualCreationTime = fileSystem.File.GetCreationTimeUtc("foo.txt"); + var actualLastAccessTime = fileSystem.File.GetLastAccessTimeUtc("foo.txt"); + var actualLastWriteTime = fileSystem.File.GetLastWriteTimeUtc("foo.txt"); + + Assert.That(actualCreationTime, Is.EqualTo(creationTime)); + Assert.That(actualLastAccessTime, Is.EqualTo(updateTime)); + Assert.That(actualLastWriteTime, Is.EqualTo(creationTime)); + } + + [Test] + public void MockFile_AfterSetAttributes_ShouldUpdateLastAccessTime() + { + var creationTime = DateTime.UtcNow.AddDays(10); + var updateTime = creationTime.AddDays(10); + var fileSystem = new MockFileSystem() + .MockTime(() => creationTime); + fileSystem.File.WriteAllText("foo.txt", "abc"); + fileSystem.MockTime(() => updateTime); + fileSystem.File.SetAttributes("foo.txt", FileAttributes.Hidden); + + var actualCreationTime = fileSystem.File.GetCreationTimeUtc("foo.txt"); + var actualLastAccessTime = fileSystem.File.GetLastAccessTimeUtc("foo.txt"); + var actualLastWriteTime = fileSystem.File.GetLastWriteTimeUtc("foo.txt"); + + Assert.That(actualCreationTime, Is.EqualTo(creationTime)); + Assert.That(actualLastAccessTime, Is.EqualTo(updateTime)); + Assert.That(actualLastWriteTime, Is.EqualTo(creationTime)); + } + + [Test] + [SupportedOSPlatform("windows")] + [WindowsOnly(WindowsSpecifics.AccessControlLists)] + public void MockFile_AfterSetAccessControl_ShouldUpdateLastAccessTime() + { + var creationTime = DateTime.UtcNow.AddDays(10); + var updateTime = creationTime.AddDays(10); + var fileSystem = new MockFileSystem() + .MockTime(() => creationTime); + fileSystem.File.WriteAllText("foo.txt", "abc"); + fileSystem.MockTime(() => updateTime); + fileSystem.File.SetAccessControl("foo.txt", new FileSecurity()); + + var actualCreationTime = fileSystem.File.GetCreationTimeUtc("foo.txt"); + var actualLastAccessTime = fileSystem.File.GetLastAccessTimeUtc("foo.txt"); + var actualLastWriteTime = fileSystem.File.GetLastWriteTimeUtc("foo.txt"); + + Assert.That(actualCreationTime, Is.EqualTo(creationTime)); + Assert.That(actualLastAccessTime, Is.EqualTo(updateTime)); + Assert.That(actualLastWriteTime, Is.EqualTo(creationTime)); + } + + [Test] + public void MockFile_AfterWriteAllBytes_ShouldUpdateLastAccessAndLastWriteTime() + { + var creationTime = DateTime.UtcNow.AddDays(10); + var updateTime = creationTime.AddDays(10); + var fileSystem = new MockFileSystem() + .MockTime(() => creationTime); + fileSystem.File.WriteAllText("foo.txt", "abc"); + fileSystem.MockTime(() => updateTime); + fileSystem.File.WriteAllBytes("foo.txt", Encoding.UTF8.GetBytes("xyz")); + + var actualCreationTime = fileSystem.File.GetCreationTimeUtc("foo.txt"); + var actualLastAccessTime = fileSystem.File.GetLastAccessTimeUtc("foo.txt"); + var actualLastWriteTime = fileSystem.File.GetLastWriteTimeUtc("foo.txt"); + + Assert.That(actualCreationTime, Is.EqualTo(creationTime)); + Assert.That(actualLastAccessTime, Is.EqualTo(updateTime)); + Assert.That(actualLastWriteTime, Is.EqualTo(updateTime)); + } + + [Test] + public void MockFile_AfterWriteAllText_ShouldUpdateLastAccessAndLastWriteTime() + { + var creationTime = DateTime.UtcNow.AddDays(10); + var updateTime = creationTime.AddDays(10); + var fileSystem = new MockFileSystem() + .MockTime(() => creationTime); + fileSystem.File.WriteAllText("foo.txt", "abc"); + fileSystem.MockTime(() => updateTime); + fileSystem.File.WriteAllText("foo.txt", "xyz"); + + var actualCreationTime = fileSystem.File.GetCreationTimeUtc("foo.txt"); + var actualLastAccessTime = fileSystem.File.GetLastAccessTimeUtc("foo.txt"); + var actualLastWriteTime = fileSystem.File.GetLastWriteTimeUtc("foo.txt"); + + Assert.That(actualCreationTime, Is.EqualTo(creationTime)); + Assert.That(actualLastAccessTime, Is.EqualTo(updateTime)); + Assert.That(actualLastWriteTime, Is.EqualTo(updateTime)); + } + + [Test] + public void MockFileStream_OpenRead_ShouldUpdateLastAccessTime() + { + var creationTime = DateTime.UtcNow.AddDays(10); + var updateTime = creationTime.AddDays(10); + var fileSystem = new MockFileSystem() + .MockTime(() => creationTime); + fileSystem.File.WriteAllText("foo.txt", "abc"); + fileSystem.MockTime(() => updateTime); + _ = fileSystem.File.OpenRead("foo.txt"); + + var actualCreationTime = fileSystem.File.GetCreationTimeUtc("foo.txt"); + var actualLastAccessTime = fileSystem.File.GetLastAccessTimeUtc("foo.txt"); + var actualLastWriteTime = fileSystem.File.GetLastWriteTimeUtc("foo.txt"); + + Assert.That(actualCreationTime, Is.EqualTo(creationTime)); + Assert.That(actualLastAccessTime, Is.EqualTo(updateTime)); + Assert.That(actualLastWriteTime, Is.EqualTo(creationTime)); + } + + [Test] + public void MockFileStream_OpenWrite_ShouldUpdateLastAccessAndLastWriteTime() + { + var creationTime = DateTime.UtcNow.AddDays(10); + var updateTime = creationTime.AddDays(10); + var fileSystem = new MockFileSystem() + .MockTime(() => creationTime); + fileSystem.File.WriteAllText("foo.txt", "abc"); + fileSystem.MockTime(() => updateTime); + _ = fileSystem.File.OpenWrite("foo.txt"); + + var actualCreationTime = fileSystem.File.GetCreationTimeUtc("foo.txt"); + var actualLastAccessTime = fileSystem.File.GetLastAccessTimeUtc("foo.txt"); + var actualLastWriteTime = fileSystem.File.GetLastWriteTimeUtc("foo.txt"); + + Assert.That(actualCreationTime, Is.EqualTo(creationTime)); + Assert.That(actualLastAccessTime, Is.EqualTo(updateTime)); + Assert.That(actualLastWriteTime, Is.EqualTo(updateTime)); + } + } +} diff --git a/tests/System.IO.Abstractions.TestingHelpers.Tests/MockFileGetCreationTimeTests.cs b/tests/System.IO.Abstractions.TestingHelpers.Tests/MockFileGetCreationTimeTests.cs index 285948272..1d213924d 100644 --- a/tests/System.IO.Abstractions.TestingHelpers.Tests/MockFileGetCreationTimeTests.cs +++ b/tests/System.IO.Abstractions.TestingHelpers.Tests/MockFileGetCreationTimeTests.cs @@ -32,5 +32,19 @@ public void MockFile_GetCreationTime_ShouldReturnDefaultTimeIfFileDoesNotExist() // Assert Assert.AreEqual(new DateTime(1601, 01, 01, 00, 00, 00, DateTimeKind.Utc).ToLocalTime(), actualCreationTime); } + + [Test] + public void MockFile_GetCreationTime_ShouldBeSet() + { + var now = DateTime.Now.AddDays(10); + var fileSystem = new MockFileSystem() + .MockTime(() => now); + fileSystem.File.WriteAllText("foo.txt", "xyz"); + + var result = fileSystem.File.GetCreationTime("foo.txt"); + + Assert.That(result.Kind, Is.EqualTo(DateTimeKind.Local)); + Assert.That(result, Is.EqualTo(now.ToLocalTime())); + } } } diff --git a/tests/System.IO.Abstractions.TestingHelpers.Tests/MockFileGetCreationTimeUtcTests.cs b/tests/System.IO.Abstractions.TestingHelpers.Tests/MockFileGetCreationTimeUtcTests.cs index 98f80fd8f..30cb6e1d5 100644 --- a/tests/System.IO.Abstractions.TestingHelpers.Tests/MockFileGetCreationTimeUtcTests.cs +++ b/tests/System.IO.Abstractions.TestingHelpers.Tests/MockFileGetCreationTimeUtcTests.cs @@ -32,5 +32,19 @@ public void MockFile_GetCreationTimeUtc_ShouldReturnDefaultTimeIfFileDoesNotExis // Assert Assert.AreEqual(new DateTime(1601, 01, 01, 00, 00, 00, DateTimeKind.Utc), actualCreationTime); } + + [Test] + public void MockFile_GetCreationTimeUtc_ShouldBeSet() + { + var now = DateTime.Now.AddDays(10); + var fileSystem = new MockFileSystem() + .MockTime(() => now); + fileSystem.File.WriteAllText("foo.txt", "xyz"); + + var result = fileSystem.File.GetCreationTimeUtc("foo.txt"); + + Assert.That(result.Kind, Is.EqualTo(DateTimeKind.Utc)); + Assert.That(result, Is.EqualTo(now.ToUniversalTime())); + } } } diff --git a/tests/System.IO.Abstractions.TestingHelpers.Tests/MockFileGetLastAccessTimeTests.cs b/tests/System.IO.Abstractions.TestingHelpers.Tests/MockFileGetLastAccessTimeTests.cs index 8b74d23d8..fbf3ef09f 100644 --- a/tests/System.IO.Abstractions.TestingHelpers.Tests/MockFileGetLastAccessTimeTests.cs +++ b/tests/System.IO.Abstractions.TestingHelpers.Tests/MockFileGetLastAccessTimeTests.cs @@ -32,5 +32,19 @@ public void MockFile_GetLastAccessTime_ShouldReturnDefaultTimeIfFileDoesNotExist // Assert Assert.AreEqual(new DateTime(1601, 01, 01, 00, 00, 00, DateTimeKind.Utc).ToLocalTime(), actualLastAccessTime); } + + [Test] + public void MockFile_GetLastAccessTime_ShouldBeSet() + { + var now = DateTime.Now.AddDays(10); + var fileSystem = new MockFileSystem() + .MockTime(() => now); + fileSystem.File.WriteAllText("foo.txt", "xyz"); + + var result = fileSystem.File.GetLastAccessTime("foo.txt"); + + Assert.That(result.Kind, Is.EqualTo(DateTimeKind.Local)); + Assert.That(result, Is.EqualTo(now.ToLocalTime())); + } } } diff --git a/tests/System.IO.Abstractions.TestingHelpers.Tests/MockFileGetLastAccessTimeUtcTests.cs b/tests/System.IO.Abstractions.TestingHelpers.Tests/MockFileGetLastAccessTimeUtcTests.cs index b72ff9adf..c42bc6c44 100644 --- a/tests/System.IO.Abstractions.TestingHelpers.Tests/MockFileGetLastAccessTimeUtcTests.cs +++ b/tests/System.IO.Abstractions.TestingHelpers.Tests/MockFileGetLastAccessTimeUtcTests.cs @@ -32,5 +32,19 @@ public void MockFile_GetLastAccessTimeUtc_ShouldReturnDefaultTimeIfFileDoesNotEx // Assert Assert.AreEqual(new DateTime(1601, 01, 01, 00, 00, 00, DateTimeKind.Utc), actualLastAccessTime); } + + [Test] + public void MockFile_GetLastAccessTimeUtc_ShouldBeSet() + { + var now = DateTime.Now.AddDays(10); + var fileSystem = new MockFileSystem() + .MockTime(() => now); + fileSystem.File.WriteAllText("foo.txt", "xyz"); + + var result = fileSystem.File.GetLastAccessTimeUtc("foo.txt"); + + Assert.That(result.Kind, Is.EqualTo(DateTimeKind.Utc)); + Assert.That(result, Is.EqualTo(now.ToUniversalTime())); + } } } diff --git a/tests/System.IO.Abstractions.TestingHelpers.Tests/MockFileGetLastWriteTimeTests.cs b/tests/System.IO.Abstractions.TestingHelpers.Tests/MockFileGetLastWriteTimeTests.cs index c6e519583..5ceaf25f7 100644 --- a/tests/System.IO.Abstractions.TestingHelpers.Tests/MockFileGetLastWriteTimeTests.cs +++ b/tests/System.IO.Abstractions.TestingHelpers.Tests/MockFileGetLastWriteTimeTests.cs @@ -32,5 +32,19 @@ public void MockFile_GetLastWriteTime_ShouldReturnDefaultTimeIfFileDoesNotExist( // Assert Assert.AreEqual(new DateTime(1601, 01, 01, 00, 00, 00, DateTimeKind.Utc).ToLocalTime(), actualLastWriteTime); } + + [Test] + public void MockFile_GetLastWriteTime_ShouldBeSet() + { + var now = DateTime.Now.AddDays(10); + var fileSystem = new MockFileSystem() + .MockTime(() => now); + fileSystem.File.WriteAllText("foo.txt", "xyz"); + + var result = fileSystem.File.GetLastWriteTime("foo.txt"); + + Assert.That(result.Kind, Is.EqualTo(DateTimeKind.Local)); + Assert.That(result, Is.EqualTo(now.ToLocalTime())); + } } } diff --git a/tests/System.IO.Abstractions.TestingHelpers.Tests/MockFileGetLastWriteTimeUtcTests.cs b/tests/System.IO.Abstractions.TestingHelpers.Tests/MockFileGetLastWriteTimeUtcTests.cs index 5a14d41d9..4783e7e7f 100644 --- a/tests/System.IO.Abstractions.TestingHelpers.Tests/MockFileGetLastWriteTimeUtcTests.cs +++ b/tests/System.IO.Abstractions.TestingHelpers.Tests/MockFileGetLastWriteTimeUtcTests.cs @@ -31,5 +31,19 @@ public void MockFile_GetLastWriteTimeUtc_ShouldReturnDefaultTimeIfFileDoesNotExi // Assert Assert.AreEqual(new DateTime(1601, 01, 01, 00, 00, 00, DateTimeKind.Utc), actualLastWriteTime); } + + [Test] + public void MockFile_GetLastWriteTimeUtc_ShouldBeSet() + { + var now = DateTime.Now.AddDays(10); + var fileSystem = new MockFileSystem() + .MockTime(() => now); + fileSystem.File.WriteAllText("foo.txt", "xyz"); + + var result = fileSystem.File.GetLastWriteTimeUtc("foo.txt"); + + Assert.That(result.Kind, Is.EqualTo(DateTimeKind.Utc)); + Assert.That(result, Is.EqualTo(now.ToUniversalTime())); + } } } \ No newline at end of file diff --git a/tests/System.IO.Abstractions.TestingHelpers.Tests/MockFileInfoTests.cs b/tests/System.IO.Abstractions.TestingHelpers.Tests/MockFileInfoTests.cs index fbaa47307..2c413ef57 100644 --- a/tests/System.IO.Abstractions.TestingHelpers.Tests/MockFileInfoTests.cs +++ b/tests/System.IO.Abstractions.TestingHelpers.Tests/MockFileInfoTests.cs @@ -180,7 +180,7 @@ public void MockFileInfo_CreationTime_ShouldReturnDefaultTimeForNonExistingFile( var result = fileInfo.CreationTime; - Assert.AreEqual(MockFileData.DefaultDateTimeOffset.DateTime, result); + Assert.AreEqual(MockFileData.DefaultDateTimeOffset.LocalDateTime, result); } [Test] @@ -400,7 +400,7 @@ public void MockFileInfo_LastWriteTime_ShouldReturnDefaultTimeForNonExistingFile var result = fileInfo.LastWriteTime; - Assert.AreEqual(MockFileData.DefaultDateTimeOffset.DateTime, result); + Assert.AreEqual(MockFileData.DefaultDateTimeOffset.LocalDateTime, result); } [Test] @@ -442,9 +442,9 @@ public void MockFileInfo_LastWriteTimeUtc_ShouldSetLastWriteTimeUtcOfFileInMemor var fileInfo = new MockFileInfo(fileSystem, XFS.Path(@"c:\a.txt")); var newUtcTime = DateTime.UtcNow; - fileInfo.LastWriteTime = newUtcTime; + fileInfo.LastWriteTimeUtc = newUtcTime; - Assert.AreEqual(newUtcTime, fileInfo.LastWriteTime); + Assert.AreEqual(newUtcTime, fileInfo.LastWriteTimeUtc); } [Test] @@ -879,5 +879,101 @@ public void MockFileInfo_Delete_ShouldThrowIfFileAccessShareHasNoWriteOrDeleteAc Assert.Throws(typeof(System.IO.IOException), () => fi.Delete()); } + + [Test] + public void MockFileInfo_LastAccessTimeUtcWithUnspecifiedDateTimeKind_ShouldSetLastAccessTimeUtcOfFileInFileSystem() + { + var date = DateTime.SpecifyKind(DateTime.Now.AddHours(-4), DateTimeKind.Unspecified); + var fileSystem = new MockFileSystem(); + fileSystem.Directory.CreateDirectory(@"c:\test"); + fileSystem.File.WriteAllText(@"c:\test\a.txt", "Demo text content"); + var fileInfo = new MockFileInfo(fileSystem, @"c:\test\a.txt") + { + LastAccessTimeUtc = date + }; + + Assert.AreEqual(date, fileInfo.LastAccessTimeUtc); + Assert.AreNotEqual(DateTimeKind.Unspecified, fileInfo.LastAccessTimeUtc); + } + + [Test] + public void MockFileInfo_LastAccessTimeWithUnspecifiedDateTimeKind_ShouldSetLastAccessTimeOfFileInFileSystem() + { + var date = DateTime.SpecifyKind(DateTime.Now.AddHours(-4), DateTimeKind.Unspecified); + var fileSystem = new MockFileSystem(); + fileSystem.Directory.CreateDirectory(@"c:\test"); + fileSystem.File.WriteAllText(@"c:\test\a.txt", "Demo text content"); + var fileInfo = new MockFileInfo(fileSystem, @"c:\test\a.txt") + { + LastAccessTime = date + }; + + Assert.AreEqual(date, fileInfo.LastAccessTime); + Assert.AreNotEqual(DateTimeKind.Unspecified, fileInfo.LastAccessTime); + } + + [Test] + public void MockFileInfo_CreationTimeUtcWithUnspecifiedDateTimeKind_ShouldSetCreationTimeUtcOfFileInFileSystem() + { + var date = DateTime.SpecifyKind(DateTime.Now.AddHours(-4), DateTimeKind.Unspecified); + var fileSystem = new MockFileSystem(); + fileSystem.Directory.CreateDirectory(@"c:\test"); + fileSystem.File.WriteAllText(@"c:\test\a.txt", "Demo text content"); + var fileInfo = new MockFileInfo(fileSystem, @"c:\test\a.txt") + { + CreationTimeUtc = date + }; + + Assert.AreEqual(date, fileInfo.CreationTimeUtc); + Assert.AreNotEqual(DateTimeKind.Unspecified, fileInfo.CreationTimeUtc); + } + + [Test] + public void MockFileInfo_CreationTimeWithUnspecifiedDateTimeKind_ShouldSetCreationTimeOfFileInFileSystem() + { + var date = DateTime.SpecifyKind(DateTime.Now.AddHours(-4), DateTimeKind.Unspecified); + var fileSystem = new MockFileSystem(); + fileSystem.Directory.CreateDirectory(@"c:\test"); + fileSystem.File.WriteAllText(@"c:\test\a.txt", "Demo text content"); + var fileInfo = new MockFileInfo(fileSystem, @"c:\test\a.txt") + { + CreationTime = date + }; + + Assert.AreEqual(date, fileInfo.CreationTime); + Assert.AreNotEqual(DateTimeKind.Unspecified, fileInfo.CreationTime); + } + + [Test] + public void MockFileInfo_LastWriteTimeUtcWithUnspecifiedDateTimeKind_ShouldSetLastWriteTimeUtcOfFileInFileSystem() + { + var date = DateTime.SpecifyKind(DateTime.Now.AddHours(-4), DateTimeKind.Unspecified); + var fileSystem = new MockFileSystem(); + fileSystem.Directory.CreateDirectory(@"c:\test"); + fileSystem.File.WriteAllText(@"c:\test\a.txt", "Demo text content"); + var fileInfo = new MockFileInfo(fileSystem, @"c:\test\a.txt") + { + LastWriteTimeUtc = date + }; + + Assert.AreEqual(date, fileInfo.LastWriteTimeUtc); + Assert.AreNotEqual(DateTimeKind.Unspecified, fileInfo.LastWriteTimeUtc); + } + + [Test] + public void MockFileInfo_LastWriteTimeWithUnspecifiedDateTimeKind_ShouldSetLastWriteTimeOfFileInFileSystem() + { + var date = DateTime.SpecifyKind(DateTime.Now.AddHours(-4), DateTimeKind.Unspecified); + var fileSystem = new MockFileSystem(); + fileSystem.Directory.CreateDirectory(@"c:\test"); + fileSystem.File.WriteAllText(@"c:\test\a.txt", "Demo text content"); + var fileInfo = new MockFileInfo(fileSystem, @"c:\test\a.txt") + { + LastWriteTime = date + }; + + Assert.AreEqual(date, fileInfo.LastWriteTime); + Assert.AreNotEqual(DateTimeKind.Unspecified, fileInfo.LastWriteTime); + } } }