@@ -13,121 +13,22 @@ namespace Microsoft.Macios.Generator.Tests;
1313/// Provides a set of custom assertion methods that can be used with xUnit, including support for multiple assertion scopes.
1414/// </summary>
1515public class AssertEx {
16- [ ThreadStatic ]
17- static List < Exception > ? _exceptions ;
18-
19- /// <summary>
20- /// Enters a scope where multiple assertions can be made without failing fast.
21- /// All assertion failures are collected and reported at the end of the scope.
22- /// </summary>
23- /// <returns>An <see cref="IDisposable"/> that ends the multiple assertion scope when disposed.</returns>
24- public static IDisposable EnterMultipleScope ( )
25- {
26- // We could probably support nesting, but for now let's keep it simple.
27- if ( _exceptions is not null )
28- throw new InvalidOperationException ( "A multiple assertion scope is already active." ) ;
29-
30- _exceptions = new ( ) ;
31- return new MultipleAssertionScope ( ) ;
32- }
33-
34- class MultipleAssertionScope : IDisposable {
35- public void Dispose ( )
36- {
37- var exceptions = _exceptions ;
38- _exceptions = null ;
39-
40- if ( exceptions is not null && exceptions . Count > 0 ) {
41- if ( exceptions . Count == 1 ) {
42- // We're not using ExceptionDispatchInfo.Capture(exceptions[0]).Throw()
43- // because we want to preserve the original stack trace, and we're not
44- // crossing any thread boundaries.
45- throw exceptions [ 0 ] ;
46- }
47-
48- throw new AggregateException ( exceptions ) ;
49- }
50- }
51- }
52-
53- /// <summary>
54- /// Executes a series of assertions and collects all failures, throwing an <see cref="AggregateException"/> if one or more assertions fail.
55- /// </summary>
56- /// <param name="asserts">The action containing the assertions to execute.</param>
57- public static void Multiple ( Action asserts )
58- {
59- ArgumentNullException . ThrowIfNull ( asserts ) ;
60-
61- var exceptions = new List < Exception > ( ) ;
62- try {
63- asserts ( ) ;
64- } catch ( Exception ex ) {
65- exceptions . Add ( ex ) ;
66- }
67-
68- if ( exceptions . Count > 0 ) {
69- if ( exceptions . Count == 1 )
70- throw exceptions [ 0 ] ;
71- throw new AggregateException ( exceptions ) ;
72- }
73- }
74-
75- /// <summary>
76- /// Verifies that two objects are equal. If inside a multiple assertion scope, it collects failures instead of throwing immediately.
77- /// </summary>
78- /// <typeparam name="T">The type of the objects to be compared.</typeparam>
79- /// <param name="expected">The expected value.</param>
80- /// <param name="actual">The value to be compared against.</param>
81- /// <param name="comparer">Optional comparer to use for the equality.</param>
82- public static void Equal < T > ( T expected , T actual , IEqualityComparer < T > ? comparer = null )
83- {
84- if ( _exceptions is null ) {
85- Assert . Equal ( expected , actual , comparer ?? EqualityComparer < T > . Default ) ;
86- return ;
87- }
88-
89- try {
90- Assert . Equal ( expected , actual , comparer ?? EqualityComparer < T > . Default ) ;
91- } catch ( EqualException ex ) {
92- _exceptions . Add ( ex ) ;
93- }
94- }
9516
96- /// <summary>
97- /// Verifies that a condition is true. If inside a multiple assertion scope, it collects failures instead of throwing immediately.
98- /// </summary>
99- /// <param name="condition">The condition to be evaluated.</param>
100- public static void True ( bool condition )
101- {
102- if ( _exceptions is null ) {
103- Assert . True ( condition ) ;
104- return ;
105- }
106-
107- try {
108- Assert . True ( condition ) ;
109- } catch ( TrueException ex ) {
110- _exceptions . Add ( ex ) ;
111- }
112- }
113-
11417 /// <summary>
11518 /// Verifies that two <see cref="PlatformAvailability"/> instances are equal by comparing their properties within a multiple assertion scope.
11619 /// </summary>
11720 /// <param name="expected">The expected platform availability.</param>
11821 /// <param name="actual">The actual platform availability.</param>
119- internal static void Equal ( PlatformAvailability expected , PlatformAvailability actual )
22+ internal static void Equal ( PlatformAvailability ? expected , PlatformAvailability ? actual )
12023 {
12124 var obsoleteComparer = new DictionaryComparer < Version , ( string ? , string ? ) > ( ) ;
12225 var unsupportedComparer = new DictionaryComparer < Version , string ? > ( ) ;
123-
124- // use a MultipleAssertionScope to test all the diff fields of the struct
125- using ( EnterMultipleScope ( ) ) {
126- Equal ( expected . Platform , actual . Platform ) ;
127- Equal ( expected . SupportedVersion , actual . SupportedVersion ) ;
128- True ( unsupportedComparer . Equals ( expected . UnsupportedVersions , actual . UnsupportedVersions ) ) ;
129- True ( obsoleteComparer . Equals ( expected . ObsoletedVersions , actual . ObsoletedVersions ) ) ;
130- }
26+ Assert . Multiple (
27+ ( ) => Assert . Equal ( expected ? . Platform , actual ? . Platform ) ,
28+ ( ) => Assert . Equal ( expected ? . SupportedVersion , actual ? . SupportedVersion ) ,
29+ ( ) => Assert . True ( unsupportedComparer . Equals ( expected ? . UnsupportedVersions , actual ? . UnsupportedVersions ) ) ,
30+ ( ) => Assert . True ( obsoleteComparer . Equals ( expected ? . ObsoletedVersions , actual ? . ObsoletedVersions ) )
31+ ) ;
13132 }
13233
13334 /// <summary>
@@ -137,11 +38,12 @@ internal static void Equal (PlatformAvailability expected, PlatformAvailability
13738 /// <param name="actual">The actual symbol availability.</param>
13839 internal static void Equal ( SymbolAvailability expected , SymbolAvailability actual )
13940 {
140- using ( EnterMultipleScope ( ) ) {
141- // compare each of the platforms individually
142- foreach ( var platform in SymbolAvailability . SupportedPlatforms ) {
143- Equal ( expected [ platform ] , actual [ platform ] ) ;
144- }
41+ var platformActions = new List < Action > ( ) ;
42+ // compare each of the platforms individually
43+ foreach ( var platform in SymbolAvailability . SupportedPlatforms ) {
44+ platformActions . Add ( ( ) => Equal ( expected [ platform ] , actual [ platform ] ) ) ;
14545 }
46+
47+ Assert . Multiple ( platformActions . ToArray ( ) ) ;
14648 }
14749}
0 commit comments