@joebigelow / wix / commits / ec61ceb6

Improve WixAssert.StringEqual to print where the first difference is.

Sean Hall committed Jun 15, 2022 at 17:07 UTC ec61ceb6b2bc0b6cf12259e08c1f8db2a9335773
1 file changed +66 -26
src/internal/WixBuildTools.TestSupport/XunitExtensions/WixAssert.cs
+66 -26
@@ -5,9 +5,11 @@ namespace WixBuildTools.TestSupport
5 using System;
6 using System.Collections.Generic;
7 using System.Linq;
8 + using System.Text;
9 using System.Xml.Linq;
10 using WixBuildTools.TestSupport.XunitExtensions;
11 using Xunit;
12 + using Xunit.Sdk;
13
14 public class WixAssert : Assert
15 {
@@ -23,7 +25,7 @@ namespace WixBuildTools.TestSupport
25 var additionalExpectedLines = expectedLines.Length > lineNumber ? String.Join(Environment.NewLine, expectedLines.Skip(lineNumber).Select((s, i) => $"{lineNumber + i}: {s}")) : $"Missing {actualLines.Length - lineNumber} lines";
26 var additionalActualLines = actualLines.Length > lineNumber ? String.Join(Environment.NewLine, actualLines.Skip(lineNumber).Select((s, i) => $"{lineNumber + i}: {s}")) : $"Missing {expectedLines.Length - lineNumber} lines";
27
26 - WixAssert.StringEqual(additionalExpectedLines, additionalActualLines);
28 + Assert.Equal<object>(additionalExpectedLines, additionalActualLines, StringObjectEqualityComparer.InvariantCulture);
29 }
30
31 public static void CompareXml(XContainer xExpected, XContainer xActual)
@@ -78,8 +80,7 @@ namespace WixBuildTools.TestSupport
80
81 public static void StringEqual(string expected, string actual, bool ignoreCase = false)
82 {
81 - var comparer = ignoreCase ? StringObjectEqualityComparer.InvariantCultureIgnoreCase : StringObjectEqualityComparer.InvariantCulture;
82 - Assert.Equal<object>(expected, actual, comparer);
83 + WixStringEqualException.ThrowIfNotEqual(expected, actual, ignoreCase);
84 }
85
86 public static void NotStringEqual(string expected, string actual, bool ignoreCase = false)
@@ -88,29 +89,6 @@ namespace WixBuildTools.TestSupport
89 Assert.NotEqual<object>(expected, actual, comparer);
90 }
91
91 - private class StringObjectEqualityComparer : IEqualityComparer<object>
92 - {
93 - public static readonly StringObjectEqualityComparer InvariantCultureIgnoreCase = new StringObjectEqualityComparer(true);
94 - public static readonly StringObjectEqualityComparer InvariantCulture = new StringObjectEqualityComparer(false);
95 -
96 - private readonly StringComparer stringComparer;
97 -
98 - public StringObjectEqualityComparer(bool ignoreCase)
99 - {
100 - this.stringComparer = ignoreCase ? StringComparer.InvariantCultureIgnoreCase : StringComparer.InvariantCulture;
101 - }
102 -
103 - public new bool Equals(object x, object y)
104 - {
105 - return this.stringComparer.Equals((string)x,(string)y);
106 - }
107 -
108 - public int GetHashCode(object obj)
109 - {
110 - return this.stringComparer.GetHashCode((string)obj);
111 - }
112 - }
113 -
92 // There appears to have been a bug in VC++, which might or might not have been partially
93 // or completely corrected. It was unable to disambiguate a call to:
94 // Xunit::Assert::Throws(System::Type^, System::Action^)
@@ -158,4 +136,66 @@ namespace WixBuildTools.TestSupport
136 return Xunit.Assert.Throws(exceptionType, testCode);
137 }
138 }
139 +
140 + internal class StringObjectEqualityComparer : IEqualityComparer<object>
141 + {
142 + public static readonly StringObjectEqualityComparer InvariantCultureIgnoreCase = new StringObjectEqualityComparer(true);
143 + public static readonly StringObjectEqualityComparer InvariantCulture = new StringObjectEqualityComparer(false);
144 +
145 + private readonly StringComparer stringComparer;
146 +
147 + public StringObjectEqualityComparer(bool ignoreCase)
148 + {
149 + this.stringComparer = ignoreCase ? StringComparer.InvariantCultureIgnoreCase : StringComparer.InvariantCulture;
150 + }
151 +
152 + public new bool Equals(object x, object y)
153 + {
154 + return this.stringComparer.Equals((string)x, (string)y);
155 + }
156 +
157 + public int GetHashCode(object obj)
158 + {
159 + return this.stringComparer.GetHashCode((string)obj);
160 + }
161 + }
162 +
163 + public class WixStringEqualException : XunitException
164 + {
165 + public WixStringEqualException(string userMessage) : base(userMessage) { }
166 +
167 + public static void ThrowIfNotEqual(string expected, string actual, bool ignoreCase)
168 + {
169 + var comparer = ignoreCase ? StringObjectEqualityComparer.InvariantCultureIgnoreCase : StringObjectEqualityComparer.InvariantCulture;
170 + if (comparer.Equals(expected, actual))
171 + {
172 + return;
173 + }
174 +
175 + var sbMessage = new StringBuilder();
176 +
177 + try
178 + {
179 + Assert.Equal(expected, actual, ignoreCase);
180 + }
181 + catch (XunitException xe)
182 + {
183 + // If either string is not completely in the message, then make sure it gets in there.
184 + if (!xe.Message.Contains(expected) || !xe.Message.Contains(actual))
185 + {
186 + sbMessage.AppendLine(xe.Message);
187 + sbMessage.AppendLine();
188 + sbMessage.AppendFormat("Expected: {0}", expected);
189 + sbMessage.AppendLine();
190 + sbMessage.AppendFormat("Actual: {0}", actual);
191 + }
192 + else
193 + {
194 + throw;
195 + }
196 + }
197 +
198 + throw new WixStringEqualException(sbMessage.ToString());
199 + }
200 + }
201 }