VerifyTests/Verify

Using Verify without a unit test sample appears to try to overwrite the file

MattKotsenas opened this issue · 10 comments

Preamble

I'm trying to use Verify without a unit test as described in

## Verify a file without using a unit test

When I put that snippet in a new console app, changing only the source file to be args[0] to pull from the command line I get this exception:

Unhandled exception. System.IO.IOException: The process cannot access the file 'D:\Projects\YamlDotNet\YamlDotNet\bin\YamlDotNet.16.1.0-refactor-dotnet-pack-.nupkg' because it is being used by another process.
   at Microsoft.Win32.SafeHandles.SafeFileHandle.CreateFile(String fullPath, FileMode mode, FileAccess access, FileShare share, FileOptions options)
   at Microsoft.Win32.SafeHandles.SafeFileHandle.Open(String fullPath, FileMode mode, FileAccess access, FileShare share, FileOptions options, Int64 preallocationSize, Nullable`1 unixCreateMode)
   at System.IO.Strategies.OSFileStreamStrategy..ctor(String path, FileMode mode, FileAccess access, FileShare share, FileOptions options, Int64 preallocationSize, Nullable`1 unixCreateMode)
   at System.IO.Strategies.FileStreamHelpers.ChooseStrategyCore(String path, FileMode mode, FileAccess access, FileShare share, FileOptions options, Int64 preallocationSize, Nullable`1 unixCreateMode)
   at System.IO.StreamWriter.ValidateArgsAndOpenPath(String path, Boolean append, Encoding encoding, Int32 bufferSize)
   at System.IO.StreamWriter..ctor(String path, Boolean append, Encoding encoding)
   at IoHelpers.WriteText(String path, StringBuilder text) in /_/src/Verify/IoHelpers.cs:line 139
   at Comparer.Text(FilePair filePair, StringBuilder received, VerifySettings settings) in /_/src/Verify/Compare/Comparer.cs:line 8
   at VerifyEngine.GetResult(VerifySettings settings, FilePair file, Target target, Boolean previousTextFailed) in /_/src/Verify/Verifier/VerifyEngine.cs:line 28
   at VerifyEngine.<>c__DisplayClass18_0.<<HandleResults>g__Inner|0>d.MoveNext() in /_/src/Verify/Verifier/VerifyEngine.cs:line 53
--- End of stack trace from previous location ---
   at VerifyEngine.HandleResults(List`1 targetList) in /_/src/Verify/Verifier/VerifyEngine.cs:line 71
   at VerifyTests.InnerVerifier.VerifyInner(Object root, Func`1 cleanup, IEnumerable`1 targets, Boolean doExpressionConversion) in /_/src/Verify/Verifier/InnerVerifier_Inner.cs:line 30
   at VerifyTests.InnerVerifier.VerifyStream(Stream stream, String extension, Object info) in /_/src/Verify/Verifier/InnerVerifier_Stream.cs:line 93
   at Program.<>c__DisplayClass0_0.<<<Main>$>b__0>d.MoveNext() in D:\Projects\verify-nupkg-tool\Program.cs:line 18
--- End of stack trace from previous location ---
   at Program.<Main>$(String[] args) in D:\Projects\verify-nupkg-tool\Program.cs:line 13
   at Program.<Main>(String[] args)

That appears that the verifier is trying to overwrite the source file. I assume that either I'm doing something silly, or the snippet is out-of-date.

Minimal Repro

var solutionDirectory = AttributeReader.GetSolutionDirectory();
var settings = new VerifySettings();
settings.DisableRequireUniquePrefix();

var sourceFile = args[0]; // Path.Combine(solutionDirectory, "Verify.Tests", "sample.txt");

await new SettingsTask(
    settings,
    async settings =>
    {
        using var verifier = new InnerVerifier(sourceFile, settings);
        return await verifier.VerifyFile(sourceFile, null, null);
    });

And then run via dotnet run -- path/to/file.txt

Submit a PR that fixes the bug

Happy to do so, but wanted to verify this is a real issue and not a user issue first :)

yeah that looks like a bug. perhaps @flcdrg can help

AFAIK everything is working over in https://github.com/flcdrg/Verify.Cli. I know I did have to update my code recently due to parameter changes, but I think you've got that in your example.

I'll take a closer look later tonight/weekend to see if I can see anything obvious.

Ok.. so the sample code works fine if you're pointing it at a text file.. but I can reproduce the same exception if I point it at a .nupkg file like you appear to be doing.

I can see that known extensions get handled specially inside VerifyStream in InnerVerifier_Stream.cs. I'm guessing because 'nupkg' isn't a known extension, it goes down the alternate path (line 96).

nupkg files do work fine when called in a unit test context, so maybe there's something extra we need to do for these kinds of files when in a non-unit test context.

do text files work if u put a write lock on them?

No.. it fails with a similar exeption and stack trace:

[Exception] System.Private.CoreLib.dll!Microsoft.Win32.SafeHandles.SafeFileHandle.CreateFile(string fullPath, System.IO.FileMode mode, System.IO.FileAccess access, System.IO.FileShare share, System.IO.FileOptions options) Line 114
	at /_/src/libraries/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.Windows.cs(114)
[Exception] System.Private.CoreLib.dll!Microsoft.Win32.SafeHandles.SafeFileHandle.Open(string fullPath, System.IO.FileMode mode, System.IO.FileAccess access, System.IO.FileShare share, System.IO.FileOptions options, long preallocationSize, System.IO.UnixFileMode? unixCreateMode) Line 47
	at /_/src/libraries/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.Windows.cs(47)
[Exception] System.Private.CoreLib.dll!System.IO.Strategies.OSFileStreamStrategy.OSFileStreamStrategy(string path, System.IO.FileMode mode, System.IO.FileAccess access, System.IO.FileShare share, System.IO.FileOptions options, long preallocationSize, System.IO.UnixFileMode? unixCreateMode) Line 46
	at /_/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/OSFileStreamStrategy.cs(46)
[Exception] System.Private.CoreLib.dll!System.IO.Strategies.FileStreamHelpers.ChooseStrategyCore(string path, System.IO.FileMode mode, System.IO.FileAccess access, System.IO.FileShare share, System.IO.FileOptions options, long preallocationSize, System.IO.UnixFileMode? unixCreateMode) Line 35
	at /_/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/FileStreamHelpers.Windows.cs(35)
[Exception] System.Private.CoreLib.dll!System.IO.FileStream.FileStream(string path, System.IO.FileMode mode, System.IO.FileAccess access, System.IO.FileShare share, int bufferSize, bool useAsync) Line 141
	at /_/src/libraries/System.Private.CoreLib/src/System/IO/FileStream.cs(141)
[Exception] Verify.dll!IoHelpers.OpenRead(string path) Line 111
	at C:\dev\git\Verify\src\Verify\IoHelpers.cs(111)
[Exception] Verify.dll!VerifyTests.InnerVerifier.VerifyFile(string path, object info, string extension) Line 10
	at C:\dev\git\Verify\src\Verify\Verifier\InnerVerifier_File.cs(10)
[Exception] ConsoleApp2.dll!Program.<Main>$.AnonymousMethod__0(VerifyTests.VerifySettings settings) Line 18
	at C:\dev\sandbox\ConsoleApp2\ConsoleApp2\Program.cs(18)
[Exception] ConsoleApp2.dll!Program.<Main>$(string[] args) Line 13
	at C:\dev\sandbox\ConsoleApp2\ConsoleApp2\Program.cs(13)

Regarding the nupkg thing, in my real use case I'm also including https://github.com/MattKotsenas/Verify.Nupkg in case that matters. However as you mentioned I get the same behavior without initializing that extension, so I (perhaps incorrectly) thought it wasn't relevant.

That API works very nicely and looks like I can now delete redundant code from Verify.Cli

cool. BTW i also added support for converters to that API