diff --git a/Source/Testably.Abstractions.Testing/FileSystem/FileInfoMock.cs b/Source/Testably.Abstractions.Testing/FileSystem/FileInfoMock.cs
index f86ca07d1..21ad0f164 100644
--- a/Source/Testably.Abstractions.Testing/FileSystem/FileInfoMock.cs
+++ b/Source/Testably.Abstractions.Testing/FileSystem/FileInfoMock.cs
@@ -252,7 +252,8 @@ public IFileInfo Replace(string destinationFileName,
}
throw ExceptionFactory.DirectoryNotFound(FullName);
- }))
+ }),
+ !Execute.IsWindows)
?? throw ExceptionFactory.FileNotFound(FullName);
return _fileSystem.FileInfo.New(location.FullPath);
}
diff --git a/Source/Testably.Abstractions.Testing/Storage/InMemoryStorage.cs b/Source/Testably.Abstractions.Testing/Storage/InMemoryStorage.cs
index 36f79db62..f85f45beb 100644
--- a/Source/Testably.Abstractions.Testing/Storage/InMemoryStorage.cs
+++ b/Source/Testably.Abstractions.Testing/Storage/InMemoryStorage.cs
@@ -382,11 +382,15 @@ public IStorageContainer GetOrCreateContainer(
throw ExceptionFactory.AccessToPathDenied(source.FullPath);
}
- using (_ = sourceContainer.RequestAccess(FileAccess.ReadWrite, FileShare.None,
+ using (_ = sourceContainer.RequestAccess(
+ FileAccess.ReadWrite,
+ FileShare.None,
ignoreMetadataErrors: ignoreMetadataErrors))
{
- using (_ = destinationContainer.RequestAccess(FileAccess.ReadWrite,
- FileShare.None, ignoreMetadataErrors: ignoreMetadataErrors))
+ using (_ = destinationContainer.RequestAccess(
+ FileAccess.ReadWrite,
+ FileShare.None,
+ ignoreMetadataErrors: ignoreMetadataErrors))
{
if (_containers.TryRemove(destination,
out IStorageContainer? existingDestinationContainer))
@@ -412,8 +416,17 @@ public IStorageContainer GetOrCreateContainer(
Execute.OnWindowsIf(sourceContainer.Type == FileSystemTypes.File,
() =>
{
- existingSourceContainer.Attributes |=
+ FileAttributes targetAttributes =
+ existingDestinationContainer.Attributes |
FileAttributes.Archive;
+ if (existingSourceContainer.Attributes.HasFlag(FileAttributes
+ .ReadOnly))
+ {
+ targetAttributes |= FileAttributes.ReadOnly;
+ }
+
+ existingSourceContainer.Attributes = targetAttributes;
+
existingSourceContainer.CreationTime.Set(
existingDestinationContainer.CreationTime.Get(
DateTimeKind.Utc),
@@ -502,7 +515,7 @@ public bool TryAddContainer(
return false;
}
-#endregion
+ #endregion
///
public override string ToString()
diff --git a/Tests/Testably.Abstractions.Tests/FileSystem/FileInfo/ReplaceTests.cs b/Tests/Testably.Abstractions.Tests/FileSystem/FileInfo/ReplaceTests.cs
index 236c9a6c4..f65010d76 100644
--- a/Tests/Testably.Abstractions.Tests/FileSystem/FileInfo/ReplaceTests.cs
+++ b/Tests/Testably.Abstractions.Tests/FileSystem/FileInfo/ReplaceTests.cs
@@ -156,8 +156,8 @@ public void
}
[SkippableTheory]
- [InlineAutoData(FileAttributes.Hidden, FileAttributes.Hidden)]
- [InlineAutoData(FileAttributes.System, FileAttributes.System)]
+ [InlineAutoData(FileAttributes.Hidden, FileAttributes.System)]
+ [InlineAutoData(FileAttributes.System, FileAttributes.Hidden)]
public void Replace_ShouldAddArchiveAttribute_OnWindows(
FileAttributes sourceFileAttributes,
FileAttributes destinationFileAttributes,
@@ -187,14 +187,48 @@ public void Replace_ShouldAddArchiveAttribute_OnWindows(
IFileInfo sut = FileSystem.FileInfo.New(sourceName);
- sut.Replace(destinationName, backupName, true);
+ sut.Replace(destinationName, backupName);
- FileSystem.File.GetAttributes(destinationName)
- .Should().Be(expectedSourceAttributes);
+ if (Test.RunsOnMac)
+ {
+ FileSystem.File.GetAttributes(destinationName)
+ .Should().Be(expectedSourceAttributes);
+ }
+ else
+ {
+ FileSystem.File.GetAttributes(destinationName)
+ .Should().Be(expectedDestinationAttributes);
+ }
FileSystem.File.GetAttributes(backupName)
.Should().Be(expectedDestinationAttributes);
}
+ [SkippableTheory]
+ [AutoData]
+ public void Replace_WhenFileIsReadOnly_ShouldThrowUnauthorizedAccessException_OnWindows(
+ string sourceName,
+ string destinationName,
+ string backupName,
+ string sourceContents,
+ string destinationContents)
+ {
+ Skip.IfNot(Test.RunsOnWindows);
+
+ FileSystem.File.WriteAllText(sourceName, sourceContents);
+
+ FileSystem.File.WriteAllText(destinationName, destinationContents);
+ FileSystem.File.SetAttributes(destinationName, FileAttributes.ReadOnly);
+
+ IFileInfo sut = FileSystem.FileInfo.New(sourceName);
+
+ Exception? exception = Record.Exception(() =>
+ {
+ sut.Replace(destinationName, backupName);
+ });
+
+ exception.Should().BeException(hResult: -2147024891);
+ }
+
[SkippableTheory]
[AutoData]
public void Replace_ShouldKeepMetadata(