Skip to content

Commit

Permalink
feat: Implemented MockDirectory.CreateTempSubDirectory (#964)
Browse files Browse the repository at this point in the history
Implemented MockDirectory.CreateTempSubdirectory(). This implementation generates a random 6 character string with an optional user specified prefix and creates the directory in the temporary directory returned by `Path.GetTempPath()`.

The 6 random characters seems to be the algorithm used on my platform (Mac) by the System.IO implementation.

Notes on this PR
1. There's a potential temporary directory namespace of $62^6$ or about 56.8 billion. As we get closer to this limit, the likelihood of generating a duplicate increases as well as the likelihood of slowdowns of the random generation. At the extreme case, if all possible temporary directories are created, creating a random directory name will effectively become an infinite loop. I assume we don't need to handle conditions close to the limit.
2. `MockDirectory` now contains a `Random` instance to generate random temp directory names. `Random.Shared` can't be used as it was introduced in .NET 6 it it appears we are supporting earlier .NET versions.
3. `MockDirectory` is marked as `[Serializable]`, however the `Random` instance cannot be serialized. I have marked the `Random` instance as `[NonSerialized]` and created a new `Random` instance on deserializing. The state of the random number generator will be different when deserialized. I don't think this is an issue as there was no way to specify the seed of the `Random` instance when creating the `MockDirectory` instance, so there's no way to generate the same sequence of random directories again (besides a very slim chance).
4. I have had to add `<EnableUnsafeBinaryFormatterSerialization>` on the test project and `#pragma warning disable SYSLIB0011` on the deserialize method to allow testing that deserialization of a `MockDirectory` also instantiates a new random number generator. Deserialization is heavily deprecated and this is only on test classes, so I am assuming this is OK.
  • Loading branch information
gregington authored Apr 13, 2023
1 parent 85fc762 commit 941f487
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,17 @@ public override IFileSystemInfo CreateSymbolicLink(string path, string pathToTar
/// <inheritdoc />
public override IDirectoryInfo CreateTempSubdirectory(string prefix = null)
{
throw CommonExceptions.NotImplemented();
prefix ??= "";
string potentialTempDirectory;

// Perform directory name generation in a loop, just in case the randomly generated name already exists.
do
{
var randomDir = $"{prefix}{Path.GetRandomFileName()}";
potentialTempDirectory = Path.Combine(Path.GetTempPath(), randomDir);
} while (Exists(potentialTempDirectory));

return CreateDirectoryInternal(potentialTempDirectory);
}
#endif

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -813,6 +813,37 @@ public void MockDirectory_CreateDirectory_ShouldSucceedIfTryingToCreateUNCPathSh
Assert.IsTrue(fileSystem.Directory.Exists(@"\\server\share\"));
}

#if FEATURE_CREATE_TEMP_SUBDIRECTORY
[Test]
public void MockDirectory_CreateTempSubdirectory_ShouldCreateSubdirectoryInTempDirectory()
{
// Arrange
var fileSystem = new MockFileSystem();

// Act
var result = fileSystem.Directory.CreateTempSubdirectory();

// Assert
Assert.IsTrue(fileSystem.Directory.Exists(result.FullName));
Assert.IsTrue(result.FullName.Contains(Path.GetTempPath()));
}

[Test]
public void MockDirectory_CreateTempSubdirectoryWithPrefix_ShouldCreateDirectoryWithGivenPrefixInTempDirectory()
{
// Arrange
var fileSystem = new MockFileSystem();

// Act
var result = fileSystem.Directory.CreateTempSubdirectory("foo-");

// Assert
Assert.IsTrue(fileSystem.Directory.Exists(result.FullName));
Assert.IsTrue(Path.GetFileName(result.FullName).StartsWith("foo-"));
Assert.IsTrue(result.FullName.Contains(Path.GetTempPath()));
}
#endif

[Test]
public void MockDirectory_Delete_ShouldDeleteDirectory()
{
Expand Down

0 comments on commit 941f487

Please sign in to comment.