Skip to content
Merged
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
19 changes: 12 additions & 7 deletions docs/comparer.md
Original file line number Diff line number Diff line change
Expand Up @@ -124,18 +124,23 @@ public static async Task<CompareResult> AreEqual(Stream stream1, Stream stream2)

while (true)
{
var count = await ReadBufferAsync(stream1, buffer1);
var count1 = await ReadBufferAsync(stream1, buffer1);
var count2 = await ReadBufferAsync(stream2, buffer2);

//no need to compare size here since only enter on files being same size
// Callers do not always guarantee the streams are the same length
// (e.g. a non-seekable received stream), so a length difference must
// be treated as not-equal instead of a short-circuit to equal.
if (count1 != count2)
{
return CompareResult.NotEqual();
}

if (count == 0)
if (count1 == 0)
{
return CompareResult.Equal;
}

await ReadBufferAsync(stream2, buffer2);

for (var i = 0; i < count; i += sizeof(long))
for (var i = 0; i < count1; i += sizeof(long))
{
if (BitConverter.ToInt64(buffer1, i) != BitConverter.ToInt64(buffer2, i))
{
Expand Down Expand Up @@ -172,7 +177,7 @@ static async Task<int> ReadBufferAsync(Stream stream, byte[] buffer)
return bytesRead;
}
```
<sup><a href='/src/Verify/Compare/StreamComparer.cs#L3-L65' title='Snippet source file'>snippet source</a> | <a href='#snippet-DefualtCompare' title='Start of snippet'>anchor</a></sup>
<sup><a href='/src/Verify/Compare/StreamComparer.cs#L3-L70' title='Snippet source file'>snippet source</a> | <a href='#snippet-DefualtCompare' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->


Expand Down
22 changes: 11 additions & 11 deletions docs/recording.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public Task Usage()
return Verify("TheValue");
}
```
<sup><a href='/src/Verify.Tests/RecordingTests.cs#L23-L33' title='Snippet source file'>snippet source</a> | <a href='#snippet-Recording' title='Start of snippet'>anchor</a></sup>
<sup><a href='/src/Verify.Tests/RecordingTests.cs#L54-L64' title='Snippet source file'>snippet source</a> | <a href='#snippet-Recording' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->

Results in:
Expand Down Expand Up @@ -61,7 +61,7 @@ public Task TryAdd()
return Verify("TheValue");
}
```
<sup><a href='/src/Verify.Tests/RecordingTests.cs#L59-L71' title='Snippet source file'>snippet source</a> | <a href='#snippet-RecordingTryAdd' title='Start of snippet'>anchor</a></sup>
<sup><a href='/src/Verify.Tests/RecordingTests.cs#L90-L102' title='Snippet source file'>snippet source</a> | <a href='#snippet-RecordingTryAdd' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->


Expand All @@ -85,7 +85,7 @@ public Task RecordingScoped()
return Verify();
}
```
<sup><a href='/src/Verify.Tests/RecordingTests.cs#L82-L97' title='Snippet source file'>snippet source</a> | <a href='#snippet-RecordingScoped' title='Start of snippet'>anchor</a></sup>
<sup><a href='/src/Verify.Tests/RecordingTests.cs#L113-L128' title='Snippet source file'>snippet source</a> | <a href='#snippet-RecordingScoped' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->

Results in:
Expand Down Expand Up @@ -117,7 +117,7 @@ public Task SameKey()
return Verify("TheValue");
}
```
<sup><a href='/src/Verify.Tests/RecordingTests.cs#L281-L292' title='Snippet source file'>snippet source</a> | <a href='#snippet-RecordingSameKey' title='Start of snippet'>anchor</a></sup>
<sup><a href='/src/Verify.Tests/RecordingTests.cs#L312-L323' title='Snippet source file'>snippet source</a> | <a href='#snippet-RecordingSameKey' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->

Results in:
Expand Down Expand Up @@ -156,7 +156,7 @@ public Task Identifier()
return Verify(Recording.Stop("identifier"));
}
```
<sup><a href='/src/Verify.Tests/RecordingTests.cs#L99-L109' title='Snippet source file'>snippet source</a> | <a href='#snippet-RecordingIdentifier' title='Start of snippet'>anchor</a></sup>
<sup><a href='/src/Verify.Tests/RecordingTests.cs#L130-L140' title='Snippet source file'>snippet source</a> | <a href='#snippet-RecordingIdentifier' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->

Results in:
Expand Down Expand Up @@ -188,7 +188,7 @@ public Task Case()
return Verify("TheValue");
}
```
<sup><a href='/src/Verify.Tests/RecordingTests.cs#L303-L314' title='Snippet source file'>snippet source</a> | <a href='#snippet-RecordingIgnoreCase' title='Start of snippet'>anchor</a></sup>
<sup><a href='/src/Verify.Tests/RecordingTests.cs#L334-L345' title='Snippet source file'>snippet source</a> | <a href='#snippet-RecordingIgnoreCase' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->

Results in:
Expand Down Expand Up @@ -223,7 +223,7 @@ public Task Stop()
return Verify(appends.Where(_ => _.Name != "name1"));
}
```
<sup><a href='/src/Verify.Tests/RecordingTests.cs#L141-L153' title='Snippet source file'>snippet source</a> | <a href='#snippet-RecordingStop' title='Start of snippet'>anchor</a></sup>
<sup><a href='/src/Verify.Tests/RecordingTests.cs#L172-L184' title='Snippet source file'>snippet source</a> | <a href='#snippet-RecordingStop' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->

Results in:
Expand Down Expand Up @@ -255,7 +255,7 @@ public Task StopNotInResult()
return Verify("other data");
}
```
<sup><a href='/src/Verify.Tests/RecordingTests.cs#L155-L167' title='Snippet source file'>snippet source</a> | <a href='#snippet-RecordingStopNotInResult' title='Start of snippet'>anchor</a></sup>
<sup><a href='/src/Verify.Tests/RecordingTests.cs#L186-L198' title='Snippet source file'>snippet source</a> | <a href='#snippet-RecordingStopNotInResult' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->

Results in:
Expand Down Expand Up @@ -284,7 +284,7 @@ public void IsRecording()
Assert.True(Recording.IsRecording());
}
```
<sup><a href='/src/Verify.Tests/RecordingTests.cs#L111-L121' title='Snippet source file'>snippet source</a> | <a href='#snippet-IsRecording' title='Start of snippet'>anchor</a></sup>
<sup><a href='/src/Verify.Tests/RecordingTests.cs#L142-L152' title='Snippet source file'>snippet source</a> | <a href='#snippet-IsRecording' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->

This can be helpful if the cost of capturing data, to add to recording, is high.
Expand All @@ -307,7 +307,7 @@ public Task Clear()
return Verify();
}
```
<sup><a href='/src/Verify.Tests/RecordingTests.cs#L201-L213' title='Snippet source file'>snippet source</a> | <a href='#snippet-RecordingClear' title='Start of snippet'>anchor</a></sup>
<sup><a href='/src/Verify.Tests/RecordingTests.cs#L232-L244' title='Snippet source file'>snippet source</a> | <a href='#snippet-RecordingClear' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->

Results in:
Expand Down Expand Up @@ -343,7 +343,7 @@ public Task PauseResume()
return Verify();
}
```
<sup><a href='/src/Verify.Tests/RecordingTests.cs#L225-L240' title='Snippet source file'>snippet source</a> | <a href='#snippet-RecordingPauseResume' title='Start of snippet'>anchor</a></sup>
<sup><a href='/src/Verify.Tests/RecordingTests.cs#L256-L271' title='Snippet source file'>snippet source</a> | <a href='#snippet-RecordingPauseResume' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->

Results in:
Expand Down
29 changes: 29 additions & 0 deletions src/Verify.Tests/CallbackTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
public class CallbackTests
{
[Fact]
public async Task OnFirstVerifyAwaitsAllHandlers()
{
var settings = new VerifySettings();
var ran = new List<int>();
// The slower handler is registered first: if only the last handler is
// awaited (the bug), it will not have completed by the assert.
settings.OnFirstVerify(
async (_, _, _) =>
{
await Task.Delay(200);
ran.Add(1);
});
settings.OnFirstVerify(
async (_, _, _) =>
{
await Task.Delay(1);
ran.Add(2);
});

var filePair = new FilePair("txt", "received.txt", "verified.txt");
var result = new NewResult(filePair, null);
await settings.RunOnFirstVerify(result, false);

Assert.Equal(2, ran.Count);
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
{
Type: VerifyCheckException,
Message:
Expected .gitIgnore to contain settings for Verify.
Path: file:///{ProjectDirectory}InnerVerifyChecksTests/Invalid/.gitIgnore
Expected .gitignore to contain settings for Verify.
Path: file:///{ProjectDirectory}InnerVerifyChecksTests/Invalid/.gitignore
Recommended settings:

# Verify
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
{
Type: VerifyCheckException,
Message:
Expected .gitIgnore to contain settings for Verify.
Path: file:///{ProjectDirectory}InnerVerifyChecksTests/Invalid/.gitIgnore
Expected .gitignore to contain settings for Verify.
Path: file:///{ProjectDirectory}InnerVerifyChecksTests/Invalid/.gitignore
Recommended settings:

# Verify
Expand Down
51 changes: 51 additions & 0 deletions src/Verify.Tests/Naming/MatchingFileFinderTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
public class MatchingFileFinderTests
{
[Fact]
public void FindVerifiedWithTrailingSeparator()
{
var directory = CreateTempDirectory();
try
{
File.WriteAllText(Path.Combine(directory, "SomeTest.verified.txt"), "a");
File.WriteAllText(Path.Combine(directory, "Other.verified.txt"), "b");

var withSeparator = directory + Path.DirectorySeparatorChar;
var found = MatchingFileFinder.FindVerified("SomeTest", withSeparator)
.ToList();

Assert.Single(found);
Assert.EndsWith("SomeTest.verified.txt", found[0]);
}
finally
{
Directory.Delete(directory, true);
}
}

[Fact]
public void FindVerifiedWithoutTrailingSeparator()
{
var directory = CreateTempDirectory();
try
{
File.WriteAllText(Path.Combine(directory, "SomeTest.verified.txt"), "a");
File.WriteAllText(Path.Combine(directory, "Other.verified.txt"), "b");

var found = MatchingFileFinder.FindVerified("SomeTest", directory)
.ToList();

Assert.Single(found);
}
finally
{
Directory.Delete(directory, true);
}
}

static string CreateTempDirectory()
{
var directory = Path.Combine(Path.GetTempPath(), $"MatchingFileFinder{Guid.NewGuid():N}");
Directory.CreateDirectory(directory);
return directory;
}
}
15 changes: 15 additions & 0 deletions src/Verify.Tests/Naming/NameForParameterTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,21 @@ public Task StringEmpty() =>
public Task StringInvalidPathChar() =>
Verify(VerifierSettings.GetNameForParameter("a/a", counter: CounterBuilder.Empty()));

[Fact]
public void CollectionItemPathFriendlyFalseNotCleaned()
{
// pathFriendly must flow to collection items, so path chars are kept
// raw when the caller does not want file-name cleaning applied.
var name = VerifierSettings.GetNameForParameter(
new List<string>
{
"a/b"
},
counter: CounterBuilder.Empty(),
pathFriendly: false);
Assert.Contains("a/b", name);
}

[Fact]
public Task Int() =>
Verify(VerifierSettings.GetNameForParameter(10, counter: CounterBuilder.Empty()));
Expand Down
31 changes: 31 additions & 0 deletions src/Verify.Tests/RecordingTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,37 @@ public Task IgnoreNames()
return Verify();
}

[Fact]
public async Task StoppedInChildContextIsNotRecording()
{
Recording.Start();
Recording.Add("name", "value");
// Consuming inside a child execution context (as the verify engine does)
// must not leave the recording active in this context.
await Task.Run(() => Recording.TryStop(out _));
Assert.False(Recording.IsRecording());
}

[Fact]
public void DisposeAfterStopDoesNotThrow()
{
using (Recording.Start())
{
Recording.Add("name", "value");
Recording.Stop();
}
}

[Fact]
public void DisposeNamedAfterStopDoesNotThrow()
{
using (Recording.Start("DisposeNamedAfterStop"))
{
Recording.Add("DisposeNamedAfterStop", "name", "value");
Recording.Stop("DisposeNamedAfterStop");
}
}

[Fact]
public Task Dates()
{
Expand Down
28 changes: 28 additions & 0 deletions src/Verify.Tests/StreamComparerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,34 @@ public async Task BinaryNotEquals()
Assert.False(result.IsEqual);
}

[Fact]
public async Task PrefixIsNotEqual()
{
// received is an 8-byte-aligned prefix of verified; must not be Equal.
using var received = new MemoryStream(new byte[16]);
using var verified = new MemoryStream(new byte[32]);
var result = await StreamComparer.AreEqual(received, verified);
Assert.False(result.IsEqual);
}

[Fact]
public async Task EmptyReceivedIsNotEqual()
{
using var received = new MemoryStream();
using var verified = new MemoryStream(new byte[16]);
var result = await StreamComparer.AreEqual(received, verified);
Assert.False(result.IsEqual);
}

[Fact]
public async Task LongerReceivedIsNotEqual()
{
using var received = new MemoryStream(new byte[32]);
using var verified = new MemoryStream(new byte[16]);
var result = await StreamComparer.AreEqual(received, verified);
Assert.False(result.IsEqual);
}

[Fact]
public async Task ShouldNotLock()
{
Expand Down
30 changes: 21 additions & 9 deletions src/Verify/Callbacks/VerifierSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,20 @@ public static void OnFirstVerify(FirstVerify firstVerify)
handleOnFirstVerify += firstVerify;
}

internal static Task RunOnFirstVerify(NewResult item, bool autoVerify)
internal static async Task RunOnFirstVerify(NewResult item, bool autoVerify)
{
if (handleOnFirstVerify is null)
{
return Task.CompletedTask;
return;
}

return handleOnFirstVerify(item.File, item.ReceivedText?.ToString(), autoVerify);
var receivedText = item.ReceivedText?.ToString();
// Await every registered handler; invoking the multicast delegate
// directly would only await the last handler's Task.
foreach (var handler in handleOnFirstVerify.GetInvocationList())
{
await ((FirstVerify) handler)(item.File, receivedText, autoVerify);
}
}

static VerifyDelete? handleOnVerifyDelete;
Expand All @@ -55,24 +61,30 @@ public static void OnDelete(VerifyDelete verifyDelete)

static VerifyMismatch? handleOnVerifyMismatch;

internal static Task RunOnVerifyDelete(string file, bool autoVerify)
internal static async Task RunOnVerifyDelete(string file, bool autoVerify)
{
if (handleOnVerifyDelete is null)
{
return Task.CompletedTask;
return;
}

return handleOnVerifyDelete(file, autoVerify);
foreach (var handler in handleOnVerifyDelete.GetInvocationList())
{
await ((VerifyDelete) handler)(file, autoVerify);
}
}

internal static Task RunOnVerifyMismatch(FilePair item, string? message, bool autoVerify)
internal static async Task RunOnVerifyMismatch(FilePair item, string? message, bool autoVerify)
{
if (handleOnVerifyMismatch is null)
{
return Task.CompletedTask;
return;
}

return handleOnVerifyMismatch(item, message, autoVerify);
foreach (var handler in handleOnVerifyMismatch.GetInvocationList())
{
await ((VerifyMismatch) handler)(item, message, autoVerify);
}
}

public static void OnVerifyMismatch(VerifyMismatch verifyMismatch)
Expand Down
Loading
Loading