Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
163 changes: 163 additions & 0 deletions TestHelpers.Tests/MockFileDataLazyLoadContentTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
using System.Linq;
using NUnit.Framework;

namespace System.IO.Abstractions.TestingHelpers.Tests
{
[TestFixture]
public class MockFileDataLazyLoadContentTests
{
[Test]
public void MockFileData_AcceptsFuncAndReturnsContents()
{
var contents = Enumerable.Range(0, 100).Select(_ => (byte)_).ToArray();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesn't really matter, but what is the value of this ceremony when all you need is some byte array? Just do something like var contents = new byte[] { 1, 2, 3 }.

var x = new MockFileData(() => contents);
Assert.AreEqual(x.Contents, contents);
}

[Test]
public void MockFileData_LazyLoadFuncIsCalledOnDemand()
{
var contents = Enumerable.Range(19, 42).Select(_ => (byte)_).ToArray();
var lazyLoadFuncHasBeenCalled = false;
var x = new MockFileData(() =>
{
lazyLoadFuncHasBeenCalled = true;
return contents;
});
Assert.IsFalse(lazyLoadFuncHasBeenCalled);
Assert.AreEqual(x.Contents, contents);
Assert.IsTrue(lazyLoadFuncHasBeenCalled);
}

[Test]
public void MockFileData_FuncConstructorThrowsOnNullArgument()
{
Assert.Throws<ArgumentNullException>(() => new MockFileData((Func<byte[]>)null));
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd suggest an additional test case that verifies that the callback is not called multiple times.

}

[TestFixture]
public class MockFileDataLazyLoadAndDirectoryBrowsing
{
private class ContentCalledException : Exception
{
public ContentCalledException() : base("Content was called")
{
}
}

private IFileSystem fileSystem;

[SetUp]
public void SetUp()
{
var mockFileData = new MockFileData(() =>
{
throw new ContentCalledException();
});
fileSystem = new MockFileSystem();
((MockFileSystem)fileSystem).AddFile(@"b:\thefile.useless", mockFileData);
}

[Test]
public void TestThatFileExist()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the main purpose of this test of to verify that the callback does not get invoked when checking whether the file exists. This assertion should be visible in the test body.

{
Assert.IsTrue(fileSystem.File.Exists(@"b:\thefile.useless"));
}

[Test]
public void TestThatDirectoryGetFilesDoesNotLoadContent()
{
Assert.AreEqual(1, fileSystem.Directory.GetFiles(@"B:\").Length);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above, I'd like to see the assertion here

}

[Test]
public void TestThatDirectoryInfoGetFilesDoesNotLoadContent()
{
Assert.AreEqual(1, fileSystem.DirectoryInfo.FromDirectoryName(@"B:\").GetFiles().Length);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above, I'd like to see the assertion here

}

[Test]
public void TestThatContentIsBeingUsedOnDemandWhenTheFileSizeIsRetrievedThruFileInfoObject()
{
var file = fileSystem.DirectoryInfo.FromDirectoryName(@"B:\").GetFiles().Single();
long fileLength = -1;
Assert.Throws(typeof(ContentCalledException), () => fileLength = file.Length);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO asserting on fileLength does not provide any additional value.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why use an exception here instead of doing what you do in MockFileDataLazyLoadContentTests. MockFileData_LazyLoadFuncIsCalledOnDemand?

Assert.AreEqual(-1, fileLength);
}

}

[TestFixture]
public class MockFileDataInsertFileInfoObjectTests

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See comment below, let's move this to a separate PR

{
private IFileSystem destinationFileSystem;
private FileInfoBase destinationFileInfo;

private const string sourceFileName = @"a:\c.bin";
private const string destinationFileName = @"b:\c\d.bin";
private readonly byte[] fileContent = Enumerable.Range(3, 14).Select(_ => (byte)_).ToArray();
private const FileAttributes attributes = FileAttributes.Hidden;
private readonly DateTime dateCreated = DateTime.Now.AddHours(-3);
private readonly DateTime dateLastWritten = DateTime.Now.AddHours(-2);
private readonly DateTime dateLastAccessed = DateTime.Now.AddHours(-1);

[TestFixtureSetUp]
public void MockFileData_AcceptsFuncAndReturnsContents()
{
// create a file in a source file system
var sourceFileSystem = new MockFileSystem();
sourceFileSystem.File.WriteAllBytes(sourceFileName, fileContent);
sourceFileSystem.File.SetAttributes(sourceFileName, attributes);
sourceFileSystem.File.SetCreationTime(sourceFileName, dateCreated);
sourceFileSystem.File.SetLastWriteTime(sourceFileName, dateLastWritten);
sourceFileSystem.File.SetLastAccessTime(sourceFileName, dateLastAccessed);
var sourceFile = sourceFileSystem.DirectoryInfo.FromDirectoryName(Path.GetDirectoryName(sourceFileName)).GetFiles().Single();

// create a new destination file system and copy the source file there
var dfs = new MockFileSystem();
dfs.AddFile(destinationFileName, new MockFileData(sourceFileSystem, sourceFile));
destinationFileInfo = dfs.DirectoryInfo.FromDirectoryName(Path.GetDirectoryName(destinationFileName)).GetFiles().Single();
destinationFileSystem = dfs;
}

[Test]
public void TestThatFileHasRightName()
{
Assert.AreEqual(destinationFileName, destinationFileInfo.FullName);
}

[Test]
public void TestThatFileHasRightContent()
{
Assert.AreEqual(fileContent, destinationFileSystem.File.ReadAllBytes(destinationFileInfo.FullName));
}

[Test]
public void TestThatFileHasRightAttributes()
{
Assert.AreEqual(attributes, destinationFileInfo.Attributes);
}

[Test]
public void TestThatFileHasRightCreationTime()
{
Assert.AreEqual(dateCreated, destinationFileInfo.CreationTime);
}

[Test]
public void TestThatFileHasRightWriteTime()
{
Assert.AreEqual(dateLastWritten, destinationFileInfo.LastWriteTime);
}

[Test]
public void TestThatFileHasRightAccessTime()
{
Assert.AreEqual(dateLastAccessed, destinationFileInfo.LastAccessTime);
}

}

}
1 change: 1 addition & 0 deletions TestHelpers.Tests/TestHelpers.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@
<Compile Include="MockPathTests.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="MockUnixSupportTests.cs" />
<Compile Include="MockFileDataLazyLoadContentTests.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\System.IO.Abstractions\System.IO.Abstractions.csproj">
Expand Down
41 changes: 39 additions & 2 deletions TestingHelpers/MockFileData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ public class MockFileData
/// The actual contents of the file.
/// </summary>
private byte[] contents;
private readonly Func<byte[]> lazyLoadContent;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: What about calling this createContents?


/// <summary>
/// The date and time the <see cref="MockFileData"/> was created.
Expand Down Expand Up @@ -97,11 +98,47 @@ public MockFileData(byte[] contents)
}

/// <summary>
/// Gets or sets the byte contents of the <see cref="MockFileData"/>.
/// Allows insertion of a file where the content is lazy loaded through a Func.
/// </summary>
/// <param name="lazyLoadContent">Func to return the file's content the first time it is requested.</param>
public MockFileData(Func<byte[]> lazyLoadContent)
{
if (lazyLoadContent == null)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about this.lazyLoadContext = lazyLoadContent ?? throw new ArgumentNullException(nameof(lazyLoadContent))?

{
throw new ArgumentNullException("lazyLoadContent");
}
this.lazyLoadContent = lazyLoadContent;
}

/// <summary>
/// Allows insertion of a FileSystemInfoBase object into a new file system. Attributes and time stamps
/// are copied, and the content will be lazy loaded the first time it is touched.
/// </summary>
/// <param name="fileSystem">The source file system where the file info originates</param>
/// <param name="fileInfo">The source file to be copied</param>
public MockFileData(IFileSystem fileSystem, FileSystemInfoBase fileInfo)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we discuss this separately? I like the lazy loading feature but I'm not sure this new constructor has to be here (instead of in user code).

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, it's closing in on three years since I wrote this, and I realize I have forgotten all about it. :-( 1) What do you propose we should do instead? 2) would it be easier to entirely drop this PR and that I create a new one from the current master, with your suggested changes?

{
if (fileSystem == null)
{
throw new ArgumentNullException("fileSystem");
}
if (fileInfo == null)
{
throw new ArgumentNullException("fileInfo");
}
creationTime = fileInfo.CreationTime;
lastAccessTime = fileInfo.LastAccessTime;
lastWriteTime = fileInfo.LastWriteTime;
attributes = fileInfo.Attributes;
lazyLoadContent = () => fileSystem.File.ReadAllBytes(fileInfo.FullName);
}

/// <summary>
/// Gets or sets the byte contents of the <see cref="MockFileData"/>.
/// </summary>
public byte[] Contents
{
get { return contents; }
get { return contents ?? (contents = lazyLoadContent()); }
set { contents = value; }
}

Expand Down