-
Notifications
You must be signed in to change notification settings - Fork 67
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
dotnet/roslyn-sdk#1099: Port XunitVerifier to use xUnit.net 2.5 asser…
…tion library (as source)
- Loading branch information
1 parent
4ff97d3
commit 1b8cf8a
Showing
7 changed files
with
241 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
14 changes: 14 additions & 0 deletions
14
src/xunit.analyzers.tests/AssertsExtensions/EmptyException.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
using System; | ||
|
||
namespace Xunit.Sdk; | ||
|
||
internal partial class EmptyException | ||
{ | ||
public static EmptyException ForNamedNonEmptyCollection( | ||
string collection, | ||
string collectionName) => | ||
new( | ||
$"Assert.Empty() Failure: Collection '{collectionName}' was not empty" + Environment.NewLine + | ||
"Collection: " + collection | ||
); | ||
} |
23 changes: 23 additions & 0 deletions
23
src/xunit.analyzers.tests/AssertsExtensions/EqualException.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
using System; | ||
|
||
namespace Xunit.Sdk; | ||
|
||
internal partial class EqualException | ||
{ | ||
public static EqualException ForMismatchedValuesWithMessage( | ||
object? expected, | ||
object? actual, | ||
string? message) | ||
{ | ||
var expectedText = expected as string ?? ArgumentFormatter.Format(expected); | ||
var actualText = actual as string ?? ArgumentFormatter.Format(actual); | ||
|
||
if (string.IsNullOrWhiteSpace(message)) | ||
message = | ||
"Assert.Equal() Failure: Values differ" + Environment.NewLine + | ||
"Expected: " + expectedText.Replace(Environment.NewLine, newLineAndIndent) + Environment.NewLine + | ||
"Actual: " + actualText.Replace(Environment.NewLine, newLineAndIndent); | ||
|
||
return new(message); | ||
} | ||
} |
7 changes: 7 additions & 0 deletions
7
src/xunit.analyzers.tests/AssertsExtensions/NotEmptyException.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
namespace Xunit.Sdk; | ||
|
||
internal partial class NotEmptyException | ||
{ | ||
public static NotEmptyException ForNamedNonEmptyCollection(string collectionName) => | ||
new($"Assert.NotEmpty() Failure: Collection '{collectionName}' was empty"); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,158 @@ | ||
// Licensed to the .NET Foundation under one or more agreements. | ||
// The .NET Foundation licenses this file to you under the MIT license. | ||
// See the LICENSE file in the project root for more information. | ||
|
||
using System; | ||
using System.Collections.Generic; | ||
using System.Collections.Immutable; | ||
using System.Diagnostics.CodeAnalysis; | ||
using System.Linq; | ||
using Xunit; | ||
using Xunit.Sdk; | ||
|
||
namespace Microsoft.CodeAnalysis.Testing.Verifiers | ||
{ | ||
public class XunitVerifier : IVerifier | ||
{ | ||
public XunitVerifier() : | ||
this(ImmutableStack<string>.Empty) | ||
{ } | ||
|
||
protected XunitVerifier(ImmutableStack<string> context) | ||
{ | ||
Context = context ?? throw new ArgumentNullException(nameof(context)); | ||
} | ||
|
||
protected ImmutableStack<string> Context { get; } | ||
|
||
public virtual void Empty<T>( | ||
string collectionName, | ||
IEnumerable<T> collection) | ||
{ | ||
var tracker = CollectionTracker<T>.Wrap(collection); | ||
using var enumerator = tracker.GetEnumerator(); | ||
|
||
if (enumerator.MoveNext()) | ||
throw EmptyException.ForNamedNonEmptyCollection(tracker.FormatStart(), collectionName); | ||
} | ||
|
||
public virtual void Equal<T>( | ||
T expected, | ||
T actual, | ||
string? message = null) | ||
{ | ||
if (message is null && Context.IsEmpty) | ||
Assert.Equal(expected, actual); | ||
else if (!EqualityComparer<T>.Default.Equals(expected, actual)) | ||
throw EqualException.ForMismatchedValuesWithMessage(expected, actual, CreateMessage(message)); | ||
} | ||
|
||
public virtual void True( | ||
[DoesNotReturnIf(false)] bool assert, | ||
string? message = null) | ||
{ | ||
if (message is null && Context.IsEmpty) | ||
Assert.True(assert); | ||
else | ||
Assert.True(assert, CreateMessage(message)); | ||
} | ||
|
||
public virtual void False( | ||
[DoesNotReturnIf(true)] bool assert, | ||
string? message = null) | ||
{ | ||
if (message is null && Context.IsEmpty) | ||
Assert.False(assert); | ||
else | ||
Assert.False(assert, CreateMessage(message)); | ||
} | ||
|
||
[DoesNotReturn] | ||
public virtual void Fail(string? message = null) | ||
{ | ||
if (message is null && Context.IsEmpty) | ||
Assert.True(false); | ||
else | ||
Assert.True(false, CreateMessage(message)); | ||
|
||
throw new InvalidOperationException("This code is unreachable"); | ||
} | ||
|
||
public virtual void LanguageIsSupported(string language) | ||
{ | ||
Assert.False(language != LanguageNames.CSharp && language != LanguageNames.VisualBasic, CreateMessage($"Unsupported Language: '{language}'")); | ||
} | ||
|
||
public virtual void NotEmpty<T>( | ||
string collectionName, | ||
IEnumerable<T> collection) | ||
{ | ||
using var enumerator = collection.GetEnumerator(); | ||
|
||
if (!enumerator.MoveNext()) | ||
throw NotEmptyException.ForNamedNonEmptyCollection(collectionName); | ||
} | ||
|
||
public virtual void SequenceEqual<T>( | ||
IEnumerable<T> expected, | ||
IEnumerable<T> actual, | ||
IEqualityComparer<T>? equalityComparer = null, | ||
string? message = null) | ||
{ | ||
var comparer = new SequenceEqualEnumerableEqualityComparer<T>(equalityComparer); | ||
var areEqual = comparer.Equals(expected, actual); | ||
|
||
if (!areEqual) | ||
throw EqualException.ForMismatchedValuesWithMessage(expected, actual, CreateMessage(message)); | ||
} | ||
|
||
public virtual IVerifier PushContext(string context) | ||
{ | ||
Assert.IsType<XunitVerifier>(this); | ||
|
||
return new XunitVerifier(Context.Push(context)); | ||
} | ||
|
||
protected virtual string CreateMessage(string? message) | ||
{ | ||
foreach (var frame in Context) | ||
message = "Context: " + frame + Environment.NewLine + message; | ||
|
||
return message ?? string.Empty; | ||
} | ||
|
||
sealed class SequenceEqualEnumerableEqualityComparer<T> : IEqualityComparer<IEnumerable<T>?> | ||
{ | ||
readonly IEqualityComparer<T> itemEqualityComparer; | ||
|
||
public SequenceEqualEnumerableEqualityComparer(IEqualityComparer<T>? itemEqualityComparer) | ||
{ | ||
this.itemEqualityComparer = itemEqualityComparer ?? EqualityComparer<T>.Default; | ||
} | ||
|
||
public bool Equals(IEnumerable<T>? x, IEnumerable<T>? y) | ||
{ | ||
if (ReferenceEquals(x, y)) { return true; } | ||
if (x is null || y is null) { return false; } | ||
|
||
return x.SequenceEqual(y, itemEqualityComparer); | ||
} | ||
|
||
public int GetHashCode(IEnumerable<T>? obj) | ||
{ | ||
if (obj is null) | ||
return 0; | ||
|
||
// From System.Tuple | ||
// | ||
// The suppression is required due to an invalid contract in IEqualityComparer<T> | ||
// https://github.com/dotnet/runtime/issues/30998 | ||
return obj | ||
.Select(item => itemEqualityComparer.GetHashCode(item!)) | ||
.Aggregate( | ||
0, | ||
(aggHash, nextHash) => ((aggHash << 5) + aggHash) ^ nextHash); | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters