Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: set Creation, LastAccess and LastWrite time for files #875

Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,14 @@ namespace System.IO.Abstractions.TestingHelpers
/// </summary>
public interface IMockFileDataAccessor : IFileSystem
{
/// <summary>
/// Adjust the times of the <paramref name="fileData"/>.
/// </summary>
/// <param name="fileData">The <see cref="MockFileData"/> for which the times should be adjusted.</param>
/// <param name="timeAdjustments">The adjustments to make on the <see cref="MockFileData"/>.</param>
/// <returns>The adjusted file.</returns>
MockFileData AdjustTimes(MockFileData fileData, TimeAdjustments timeAdjustments);
vbreuss marked this conversation as resolved.
Show resolved Hide resolved

/// <summary>
/// Gets a file.
/// </summary>
Expand Down
12 changes: 6 additions & 6 deletions src/System.IO.Abstractions.TestingHelpers/MockDirectoryInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -62,15 +62,15 @@ public override FileAttributes Attributes
/// <inheritdoc />
public override DateTime CreationTime
{
get { return GetMockFileDataForRead().CreationTime.DateTime; }
get { return GetMockFileDataForRead().CreationTime.LocalDateTime; }
set { GetMockFileDataForWrite().CreationTime = value; }
}

/// <inheritdoc />
public override DateTime CreationTimeUtc
{
get { return GetMockFileDataForRead().CreationTime.UtcDateTime; }
set { GetMockFileDataForWrite().CreationTime = value.ToLocalTime(); }
set { GetMockFileDataForWrite().CreationTime = value; }
}

/// <inheritdoc />
Expand Down Expand Up @@ -114,29 +114,29 @@ public override string FullName
/// <inheritdoc />
public override DateTime LastAccessTime
{
get { return GetMockFileDataForRead().LastAccessTime.DateTime; }
get { return GetMockFileDataForRead().LastAccessTime.LocalDateTime; }
fgreinacher marked this conversation as resolved.
Show resolved Hide resolved
set { GetMockFileDataForWrite().LastAccessTime = value; }
}

/// <inheritdoc />
public override DateTime LastAccessTimeUtc
{
get { return GetMockFileDataForRead().LastAccessTime.UtcDateTime; }
set { GetMockFileDataForWrite().LastAccessTime = value.ToLocalTime(); }
set { GetMockFileDataForWrite().LastAccessTime = value; }
}

/// <inheritdoc />
public override DateTime LastWriteTime
{
get { return GetMockFileDataForRead().LastWriteTime.DateTime; }
get { return GetMockFileDataForRead().LastWriteTime.LocalDateTime; }
set { GetMockFileDataForWrite().LastWriteTime = value; }
}

/// <inheritdoc />
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
Expand Down
44 changes: 30 additions & 14 deletions src/System.IO.Abstractions.TestingHelpers/MockFile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
Expand Down Expand Up @@ -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);
}

Expand All @@ -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);
}
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -539,6 +541,12 @@ public override Stream Open(string path, FileMode mode, FileAccess access)

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);
}
Expand Down Expand Up @@ -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();
}

/// <inheritdoc />
Expand All @@ -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();
}
Expand All @@ -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();
Expand Down Expand Up @@ -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;
}

Expand All @@ -736,6 +750,7 @@ public override void SetAttributes(string path, FileAttributes fileAttributes)
}
else
{
mockFileDataAccessor.AdjustTimes(possibleFileData, TimeAdjustments.LastAccessTime);
possibleFileData.Attributes = fileAttributes;
}
}
Expand Down Expand Up @@ -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));
}

/// <summary>
Expand Down Expand Up @@ -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)
Expand All @@ -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);
}

Expand Down
27 changes: 23 additions & 4 deletions src/System.IO.Abstractions.TestingHelpers/MockFileData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,10 @@ public class MockFileData
/// </summary>
private MockFileData()
{
// empty
var now = DateTime.UtcNow;
LastWriteTime = now;
LastAccessTime = now;
CreationTime = now;
vbreuss marked this conversation as resolved.
Show resolved Hide resolved
}

/// <summary>
Expand Down Expand Up @@ -78,6 +81,7 @@ public MockFileData(string textContents, Encoding encoding)
/// <param name="contents">The actual content.</param>
/// <exception cref="ArgumentNullException">Thrown if <paramref name="contents"/> is <see langword="null" />.</exception>
public MockFileData(byte[] contents)
: this()
{
Contents = contents ?? throw new ArgumentNullException(nameof(contents));
}
Expand Down Expand Up @@ -126,17 +130,32 @@ public string TextContents
/// <summary>
/// Gets or sets the date and time the <see cref="MockFileData"/> was created.
/// </summary>
public DateTimeOffset CreationTime { get; set; } = new DateTimeOffset(2010, 01, 02, 00, 00, 00, TimeSpan.FromHours(4));
vbreuss marked this conversation as resolved.
Show resolved Hide resolved
public DateTimeOffset CreationTime
{
get { return creationTime; }
set{ creationTime = value.ToUniversalTime(); }
}
private DateTimeOffset creationTime;

/// <summary>
/// Gets or sets the date and time of the <see cref="MockFileData"/> was last accessed to.
/// </summary>
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;

/// <summary>
/// Gets or sets the date and time of the <see cref="MockFileData"/> was last written to.
/// </summary>
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
/// <summary>
Expand Down
10 changes: 5 additions & 5 deletions src/System.IO.Abstractions.TestingHelpers/MockFileInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ public override DateTime CreationTime
get
{
var mockFileData = GetMockFileDataForRead();
return mockFileData.CreationTime.DateTime;
return mockFileData.CreationTime.LocalDateTime;
}
set
{
Expand All @@ -80,7 +80,7 @@ public override DateTime CreationTimeUtc
set
{
var mockFileData = GetMockFileDataForWrite();
mockFileData.CreationTime = value.ToLocalTime();
mockFileData.CreationTime = value;
}
}

Expand Down Expand Up @@ -117,7 +117,7 @@ public override DateTime LastAccessTime
get
{
var mockFileData = GetMockFileDataForRead();
return mockFileData.LastAccessTime.DateTime;
return mockFileData.LastAccessTime.LocalDateTime;
}
set
{
Expand Down Expand Up @@ -147,7 +147,7 @@ public override DateTime LastWriteTime
get
{
var mockFileData = GetMockFileDataForRead();
return mockFileData.LastWriteTime.DateTime;
return mockFileData.LastWriteTime.LocalDateTime;
}
set
{
Expand All @@ -167,7 +167,7 @@ public override DateTime LastWriteTimeUtc
set
{
var mockFileData = GetMockFileDataForWrite();
mockFileData.LastWriteTime = value.ToLocalTime();
mockFileData.LastWriteTime = value;
}
}

Expand Down
36 changes: 33 additions & 3 deletions src/System.IO.Abstractions.TestingHelpers/MockFileStream.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ public class MockFileStream : MemoryStream
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 &&
Expand All @@ -60,7 +62,8 @@ public class MockFileStream : MemoryStream
}

fileData = new MockFileData(new byte[] { });
fileData.CreationTime = fileData.LastWriteTime = fileData.LastAccessTime = DateTime.Now;
mockFileDataAccessor.AdjustTimes(fileData,
TimeAdjustments.CreationTime | TimeAdjustments.LastAccessTime);
vbreuss marked this conversation as resolved.
Show resolved Hide resolved
mockFileDataAccessor.AddFile(path, fileData);
}

Expand All @@ -76,14 +79,16 @@ public class MockFileStream : MemoryStream
/// <inheritdoc />
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);
}

/// <inheritdoc />
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);
}

Expand Down Expand Up @@ -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;
}
}
}
}