System.IO.Abstractions
System.IO.Abstractions copied to clipboard
fix: Make mocked data lazy-loaded
This moves the initialization of cachedMockFileData
to the first time that it is actually used. Apparently, this is more closely to how it works in .NET 6.
Closes #899
@fgreinacher this partly implicitly reverts a change that you made here. In #899, we noticed that the behaviour of FileInfo
in .NET 6 is a bit different to the current behaviour of the MockFileSystem
. This aligns the mock's behaviour a bit better to CoreCLR, but is probably not perfect, either.
Thinking aloud, now that I have a little more time for this PR:
With this change, we would actually regress in regards to the DirectoryInfo.GetFiles, DirectoryInfo.EnumerateFiles, ...
(see here for details) methods initialization behavior, as those methods no longer return an initalized MockFileInfo.
Remember, before it was automatically initialized by the Refresh()
call in MockFileInfo ctor!
Can't we fix this regression by simply calling Refresh
in the corresponding MockDirectoryInfo methods, e.g. here
https://github.com/TestableIO/System.IO.Abstractions/blob/main/src/System.IO.Abstractions.TestingHelpers/MockDirectoryInfo.cs#L311-L368
when we are constructing the MockFileInfo object?
We don't have any tests for the "initalize FileInfo when going through these methods", that is why this change in behavior is not caught by the tests, but propably need them. Willing to go the extra mile?
With this change, we would actually regress in regards to the
DirectoryInfo.GetFiles, DirectoryInfo.EnumerateFiles, ...
(see here for details) methods initialization behavior, as those methods no longer return an initalized MockFileInfo. Remember, before it was automatically initialized by theRefresh()
call in MockFileInfo ctor!
If we're speaking .NET 5's System.IO.DirectoryInfo
, I don't think that the FileInfo
returned by GetFiles
etc. are actually initialized by the framework.
-
GetFiles
callsInternalEnumerateInfos
-
InternalEnumerateInfos
returns a newFileSystemEnumerable<FileInfo>
(viaFileSystemEnumerableFactory
) -
FileSystemEnumerable
, through a delegate and viaFileSystemEntry
returns aFileSystemInfo
from theCreate
method - Since that uses the normal
FileInfo
constructor internally, it's not initialized
Sooo … the changed behaviour caused by this PR would be a regression to the current System.IO.Abstractions
behaviour, but closer to the current .NET behaviour?
We don't have any tests for the "initalize FileInfo when going through these methods", that is why this change in behavior is not caught by the tests, but propably need them. Willing to go the extra mile?
Therefore, we possibly don't need this?
With this change, we would actually regress in regards to the
DirectoryInfo.GetFiles, DirectoryInfo.EnumerateFiles, ...
(see here for details) methods initialization behavior, as those methods no longer return an initalized MockFileInfo. Remember, before it was automatically initialized by theRefresh()
call in MockFileInfo ctor!If we're speaking .NET 5's
System.IO.DirectoryInfo
, I don't think that theFileInfo
returned byGetFiles
etc. are actually initialized by the framework.
GetFiles
callsInternalEnumerateInfos
InternalEnumerateInfos
returns a newFileSystemEnumerable<FileInfo>
(viaFileSystemEnumerableFactory
)FileSystemEnumerable
, through a delegate and viaFileSystemEntry
returns aFileSystemInfo
from theCreate
method
You need to follow the reading of this method, a few lines below, the FileSystemInfo.Init
method is called, see here
https://github.com/dotnet/runtime/blob/13f648fa15c2989455415f4941dad2abfbaa6bba/src/libraries/System.Private.CoreLib/src/System/IO/FileSystemInfo.Windows.cs#L34
To my understanding, this does initialize the cache, following the calls into FileSystemInfo.Init where it sets the _dataInitialized=0