summaryrefslogtreecommitdiff
path: root/src/internal/WixBuildTools.TestSupport/XunitExtensions
diff options
context:
space:
mode:
authorRob Mensching <rob@firegiant.com>2022-11-08 14:58:05 -0800
committerRob Mensching <rob@firegiant.com>2022-11-08 16:20:25 -0800
commitc843b47d6233153fa961c6d0e61edf7cedf255bb (patch)
tree9eae6badd42d3badb8665b7414b4d44ca48d6ae1 /src/internal/WixBuildTools.TestSupport/XunitExtensions
parent7e498d6348c26583972ea1cdf7d51dadc8f5b792 (diff)
downloadwix-c843b47d6233153fa961c6d0e61edf7cedf255bb.tar.gz
wix-c843b47d6233153fa961c6d0e61edf7cedf255bb.tar.bz2
wix-c843b47d6233153fa961c6d0e61edf7cedf255bb.zip
Separate WixInternal content from official WixToolset namespace
Diffstat (limited to 'src/internal/WixBuildTools.TestSupport/XunitExtensions')
-rw-r--r--src/internal/WixBuildTools.TestSupport/XunitExtensions/SkipTestException.cs15
-rw-r--r--src/internal/WixBuildTools.TestSupport/XunitExtensions/SkippableFactAttribute.cs13
-rw-r--r--src/internal/WixBuildTools.TestSupport/XunitExtensions/SkippableFactDiscoverer.cs23
-rw-r--r--src/internal/WixBuildTools.TestSupport/XunitExtensions/SkippableFactMessageBus.cs40
-rw-r--r--src/internal/WixBuildTools.TestSupport/XunitExtensions/SkippableFactTestCase.cs40
-rw-r--r--src/internal/WixBuildTools.TestSupport/XunitExtensions/SkippableTheoryAttribute.cs12
-rw-r--r--src/internal/WixBuildTools.TestSupport/XunitExtensions/SkippableTheoryDiscoverer.cs41
-rw-r--r--src/internal/WixBuildTools.TestSupport/XunitExtensions/SkippableTheoryTestCase.cs41
-rw-r--r--src/internal/WixBuildTools.TestSupport/XunitExtensions/SpecificReturnCodeException.cs20
-rw-r--r--src/internal/WixBuildTools.TestSupport/XunitExtensions/SucceededException.cs19
-rw-r--r--src/internal/WixBuildTools.TestSupport/XunitExtensions/WixAssert.cs201
11 files changed, 0 insertions, 465 deletions
diff --git a/src/internal/WixBuildTools.TestSupport/XunitExtensions/SkipTestException.cs b/src/internal/WixBuildTools.TestSupport/XunitExtensions/SkipTestException.cs
deleted file mode 100644
index bd7d23f9..00000000
--- a/src/internal/WixBuildTools.TestSupport/XunitExtensions/SkipTestException.cs
+++ /dev/null
@@ -1,15 +0,0 @@
1// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
3namespace WixBuildTools.TestSupport.XunitExtensions
4{
5 using System;
6
7 public class SkipTestException : Exception
8 {
9 public SkipTestException(string reason)
10 : base(reason)
11 {
12
13 }
14 }
15}
diff --git a/src/internal/WixBuildTools.TestSupport/XunitExtensions/SkippableFactAttribute.cs b/src/internal/WixBuildTools.TestSupport/XunitExtensions/SkippableFactAttribute.cs
deleted file mode 100644
index 4974d489..00000000
--- a/src/internal/WixBuildTools.TestSupport/XunitExtensions/SkippableFactAttribute.cs
+++ /dev/null
@@ -1,13 +0,0 @@
1// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
3namespace WixBuildTools.TestSupport.XunitExtensions
4{
5 using Xunit;
6 using Xunit.Sdk;
7
8 // https://github.com/xunit/samples.xunit/blob/5dc1d35a63c3394a8678ac466b882576a70f56f6/DynamicSkipExample
9 [XunitTestCaseDiscoverer("WixBuildTools.TestSupport.XunitExtensions.SkippableFactDiscoverer", "WixBuildTools.TestSupport")]
10 public class SkippableFactAttribute : FactAttribute
11 {
12 }
13}
diff --git a/src/internal/WixBuildTools.TestSupport/XunitExtensions/SkippableFactDiscoverer.cs b/src/internal/WixBuildTools.TestSupport/XunitExtensions/SkippableFactDiscoverer.cs
deleted file mode 100644
index b692c912..00000000
--- a/src/internal/WixBuildTools.TestSupport/XunitExtensions/SkippableFactDiscoverer.cs
+++ /dev/null
@@ -1,23 +0,0 @@
1// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
3namespace WixBuildTools.TestSupport.XunitExtensions
4{
5 using System.Collections.Generic;
6 using Xunit.Abstractions;
7 using Xunit.Sdk;
8
9 public class SkippableFactDiscoverer : IXunitTestCaseDiscoverer
10 {
11 private IMessageSink DiagnosticMessageSink { get; }
12
13 public SkippableFactDiscoverer(IMessageSink diagnosticMessageSink)
14 {
15 this.DiagnosticMessageSink = diagnosticMessageSink;
16 }
17
18 public IEnumerable<IXunitTestCase> Discover(ITestFrameworkDiscoveryOptions discoveryOptions, ITestMethod testMethod, IAttributeInfo factAttribute)
19 {
20 yield return new SkippableFactTestCase(this.DiagnosticMessageSink, discoveryOptions.MethodDisplayOrDefault(), discoveryOptions.MethodDisplayOptionsOrDefault(), testMethod);
21 }
22 }
23}
diff --git a/src/internal/WixBuildTools.TestSupport/XunitExtensions/SkippableFactMessageBus.cs b/src/internal/WixBuildTools.TestSupport/XunitExtensions/SkippableFactMessageBus.cs
deleted file mode 100644
index 6d01889e..00000000
--- a/src/internal/WixBuildTools.TestSupport/XunitExtensions/SkippableFactMessageBus.cs
+++ /dev/null
@@ -1,40 +0,0 @@
1// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
3namespace WixBuildTools.TestSupport.XunitExtensions
4{
5 using System.Linq;
6 using Xunit.Abstractions;
7 using Xunit.Sdk;
8
9 public class SkippableFactMessageBus : IMessageBus
10 {
11 private IMessageBus InnerBus { get; }
12
13 public SkippableFactMessageBus(IMessageBus innerBus)
14 {
15 this.InnerBus = innerBus;
16 }
17
18 public int DynamicallySkippedTestCount { get; private set; }
19
20 public void Dispose()
21 {
22 }
23
24 public bool QueueMessage(IMessageSinkMessage message)
25 {
26 if (message is ITestFailed testFailed)
27 {
28 var exceptionType = testFailed.ExceptionTypes.FirstOrDefault();
29 if (exceptionType == typeof(SkipTestException).FullName)
30 {
31 ++this.DynamicallySkippedTestCount;
32 return this.InnerBus.QueueMessage(new TestSkipped(testFailed.Test, testFailed.Messages.FirstOrDefault()));
33 }
34 }
35
36 // Nothing we care about, send it on its way
37 return this.InnerBus.QueueMessage(message);
38 }
39 }
40}
diff --git a/src/internal/WixBuildTools.TestSupport/XunitExtensions/SkippableFactTestCase.cs b/src/internal/WixBuildTools.TestSupport/XunitExtensions/SkippableFactTestCase.cs
deleted file mode 100644
index f13fec83..00000000
--- a/src/internal/WixBuildTools.TestSupport/XunitExtensions/SkippableFactTestCase.cs
+++ /dev/null
@@ -1,40 +0,0 @@
1// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
3namespace WixBuildTools.TestSupport.XunitExtensions
4{
5 using System;
6 using System.ComponentModel;
7 using System.Threading;
8 using System.Threading.Tasks;
9 using Xunit.Abstractions;
10 using Xunit.Sdk;
11
12 public class SkippableFactTestCase : XunitTestCase
13 {
14 [EditorBrowsable(EditorBrowsableState.Never)]
15 [Obsolete("Called by the de-serializer; should only be called by deriving classes for de-serialization purposes")]
16 public SkippableFactTestCase() { }
17
18 public SkippableFactTestCase(IMessageSink diagnosticMessageSink, TestMethodDisplay defaultMethodDisplay, TestMethodDisplayOptions defaultMethodDisplayOptions, ITestMethod testMethod, object[] testMethodArguments = null)
19 : base(diagnosticMessageSink, defaultMethodDisplay, defaultMethodDisplayOptions, testMethod, testMethodArguments)
20 {
21 }
22
23 public override async Task<RunSummary> RunAsync(IMessageSink diagnosticMessageSink,
24 IMessageBus messageBus,
25 object[] constructorArguments,
26 ExceptionAggregator aggregator,
27 CancellationTokenSource cancellationTokenSource)
28 {
29 var skipMessageBus = new SkippableFactMessageBus(messageBus);
30 var result = await base.RunAsync(diagnosticMessageSink, skipMessageBus, constructorArguments, aggregator, cancellationTokenSource);
31 if (skipMessageBus.DynamicallySkippedTestCount > 0)
32 {
33 result.Failed -= skipMessageBus.DynamicallySkippedTestCount;
34 result.Skipped += skipMessageBus.DynamicallySkippedTestCount;
35 }
36
37 return result;
38 }
39 }
40}
diff --git a/src/internal/WixBuildTools.TestSupport/XunitExtensions/SkippableTheoryAttribute.cs b/src/internal/WixBuildTools.TestSupport/XunitExtensions/SkippableTheoryAttribute.cs
deleted file mode 100644
index e026bb59..00000000
--- a/src/internal/WixBuildTools.TestSupport/XunitExtensions/SkippableTheoryAttribute.cs
+++ /dev/null
@@ -1,12 +0,0 @@
1// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
3namespace WixBuildTools.TestSupport.XunitExtensions
4{
5 using Xunit;
6 using Xunit.Sdk;
7
8 [XunitTestCaseDiscoverer("WixBuildTools.TestSupport.XunitExtensions.SkippableFactDiscoverer", "WixBuildTools.TestSupport")]
9 public class SkippableTheoryAttribute : TheoryAttribute
10 {
11 }
12}
diff --git a/src/internal/WixBuildTools.TestSupport/XunitExtensions/SkippableTheoryDiscoverer.cs b/src/internal/WixBuildTools.TestSupport/XunitExtensions/SkippableTheoryDiscoverer.cs
deleted file mode 100644
index cf4e2b43..00000000
--- a/src/internal/WixBuildTools.TestSupport/XunitExtensions/SkippableTheoryDiscoverer.cs
+++ /dev/null
@@ -1,41 +0,0 @@
1// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
3namespace WixBuildTools.TestSupport.XunitExtensions
4{
5 using System.Collections.Generic;
6 using Xunit.Abstractions;
7 using Xunit.Sdk;
8
9 public class SkippableTheoryDiscoverer : IXunitTestCaseDiscoverer
10 {
11 private IMessageSink DiagnosticMessageSink { get; }
12 private TheoryDiscoverer TheoryDiscoverer { get; }
13
14 public SkippableTheoryDiscoverer(IMessageSink diagnosticMessageSink)
15 {
16 this.DiagnosticMessageSink = diagnosticMessageSink;
17
18 this.TheoryDiscoverer = new TheoryDiscoverer(diagnosticMessageSink);
19 }
20
21 public IEnumerable<IXunitTestCase> Discover(ITestFrameworkDiscoveryOptions discoveryOptions, ITestMethod testMethod, IAttributeInfo factAttribute)
22 {
23 var defaultMethodDisplay = discoveryOptions.MethodDisplayOrDefault();
24 var defaultMethodDisplayOptions = discoveryOptions.MethodDisplayOptionsOrDefault();
25
26 // Unlike fact discovery, the underlying algorithm for theories is complex, so we let the theory discoverer
27 // do its work, and do a little on-the-fly conversion into our own test cases.
28 foreach (var testCase in this.TheoryDiscoverer.Discover(discoveryOptions, testMethod, factAttribute))
29 {
30 if (testCase is XunitTheoryTestCase)
31 {
32 yield return new SkippableTheoryTestCase(this.DiagnosticMessageSink, defaultMethodDisplay, defaultMethodDisplayOptions, testCase.TestMethod);
33 }
34 else
35 {
36 yield return new SkippableFactTestCase(this.DiagnosticMessageSink, defaultMethodDisplay, defaultMethodDisplayOptions, testCase.TestMethod, testCase.TestMethodArguments);
37 }
38 }
39 }
40 }
41}
diff --git a/src/internal/WixBuildTools.TestSupport/XunitExtensions/SkippableTheoryTestCase.cs b/src/internal/WixBuildTools.TestSupport/XunitExtensions/SkippableTheoryTestCase.cs
deleted file mode 100644
index 3299fe7e..00000000
--- a/src/internal/WixBuildTools.TestSupport/XunitExtensions/SkippableTheoryTestCase.cs
+++ /dev/null
@@ -1,41 +0,0 @@
1// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
3namespace WixBuildTools.TestSupport.XunitExtensions
4{
5 using System;
6 using System.ComponentModel;
7 using System.Threading;
8 using System.Threading.Tasks;
9 using Xunit.Abstractions;
10 using Xunit.Sdk;
11
12 public class SkippableTheoryTestCase : XunitTheoryTestCase
13 {
14 [EditorBrowsable(EditorBrowsableState.Never)]
15 [Obsolete("Called by the de-serializer; should only be called by deriving classes for de-serialization purposes")]
16 public SkippableTheoryTestCase() { }
17
18 public SkippableTheoryTestCase(IMessageSink diagnosticMessageSink, TestMethodDisplay defaultMethodDisplay, TestMethodDisplayOptions defaultMethodDisplayOptions, ITestMethod testMethod)
19 : base(diagnosticMessageSink, defaultMethodDisplay, defaultMethodDisplayOptions, testMethod)
20 {
21 }
22
23 public override async Task<RunSummary> RunAsync(IMessageSink diagnosticMessageSink,
24 IMessageBus messageBus,
25 object[] constructorArguments,
26 ExceptionAggregator aggregator,
27 CancellationTokenSource cancellationTokenSource)
28 {
29 // Duplicated code from SkippableFactTestCase. I'm sure we could find a way to de-dup with some thought.
30 var skipMessageBus = new SkippableFactMessageBus(messageBus);
31 var result = await base.RunAsync(diagnosticMessageSink, skipMessageBus, constructorArguments, aggregator, cancellationTokenSource);
32 if (skipMessageBus.DynamicallySkippedTestCount > 0)
33 {
34 result.Failed -= skipMessageBus.DynamicallySkippedTestCount;
35 result.Skipped += skipMessageBus.DynamicallySkippedTestCount;
36 }
37
38 return result;
39 }
40 }
41}
diff --git a/src/internal/WixBuildTools.TestSupport/XunitExtensions/SpecificReturnCodeException.cs b/src/internal/WixBuildTools.TestSupport/XunitExtensions/SpecificReturnCodeException.cs
deleted file mode 100644
index c703e90a..00000000
--- a/src/internal/WixBuildTools.TestSupport/XunitExtensions/SpecificReturnCodeException.cs
+++ /dev/null
@@ -1,20 +0,0 @@
1// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
3namespace WixBuildTools.TestSupport
4{
5 using System;
6 using Xunit.Sdk;
7
8 public class SpecificReturnCodeException : XunitException
9 {
10 public SpecificReturnCodeException(int hrExpected, int hr, string userMessage)
11 : base(String.Format("WixAssert.SpecificReturnCode() Failure\r\n" +
12 "Expected HRESULT: 0x{0:X8}\r\n" +
13 "Actual HRESULT: 0x{1:X8}\r\n" +
14 "Message: {2}",
15 hrExpected, hr, userMessage))
16 {
17 this.HResult = hr;
18 }
19 }
20}
diff --git a/src/internal/WixBuildTools.TestSupport/XunitExtensions/SucceededException.cs b/src/internal/WixBuildTools.TestSupport/XunitExtensions/SucceededException.cs
deleted file mode 100644
index 704fba28..00000000
--- a/src/internal/WixBuildTools.TestSupport/XunitExtensions/SucceededException.cs
+++ /dev/null
@@ -1,19 +0,0 @@
1// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
3namespace WixBuildTools.TestSupport
4{
5 using System;
6 using Xunit.Sdk;
7
8 public class SucceededException : XunitException
9 {
10 public SucceededException(int hr, string userMessage)
11 : base(String.Format("WixAssert.Succeeded() Failure\r\n" +
12 "HRESULT: 0x{0:X8}\r\n" +
13 "Message: {1}",
14 hr, userMessage))
15 {
16 this.HResult = hr;
17 }
18 }
19}
diff --git a/src/internal/WixBuildTools.TestSupport/XunitExtensions/WixAssert.cs b/src/internal/WixBuildTools.TestSupport/XunitExtensions/WixAssert.cs
deleted file mode 100644
index a8513bfb..00000000
--- a/src/internal/WixBuildTools.TestSupport/XunitExtensions/WixAssert.cs
+++ /dev/null
@@ -1,201 +0,0 @@
1// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
3namespace WixBuildTools.TestSupport
4{
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 {
16 public static void CompareLineByLine(string[] expectedLines, string[] actualLines)
17 {
18 var lineNumber = 0;
19
20 for (; lineNumber < expectedLines.Length && lineNumber < actualLines.Length; ++lineNumber)
21 {
22 WixAssert.StringEqual($"{lineNumber}: {expectedLines[lineNumber]}", $"{lineNumber}: {actualLines[lineNumber]}");
23 }
24
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
28 Assert.Equal<object>(additionalExpectedLines, additionalActualLines, StringObjectEqualityComparer.InvariantCulture);
29 }
30
31 public static void CompareXml(XContainer xExpected, XContainer xActual)
32 {
33 var expecteds = xExpected.Descendants().Select(x => $"{x.Name.LocalName}:{String.Join(",", x.Attributes().OrderBy(a => a.Name.LocalName).Select(a => $"{a.Name.LocalName}={a.Value}"))}");
34 var actuals = xActual.Descendants().Select(x => $"{x.Name.LocalName}:{String.Join(",", x.Attributes().OrderBy(a => a.Name.LocalName).Select(a => $"{a.Name.LocalName}={a.Value}"))}");
35
36 CompareLineByLine(expecteds.OrderBy(s => s).ToArray(), actuals.OrderBy(s => s).ToArray());
37 }
38
39 public static void CompareXml(string expectedPath, string actualPath)
40 {
41 var expectedDoc = XDocument.Load(expectedPath, LoadOptions.PreserveWhitespace | LoadOptions.SetBaseUri | LoadOptions.SetLineInfo);
42 var actualDoc = XDocument.Load(actualPath, LoadOptions.PreserveWhitespace | LoadOptions.SetBaseUri | LoadOptions.SetLineInfo);
43
44 CompareXml(expectedDoc, actualDoc);
45 }
46
47 /// <summary>
48 /// Dynamically skips the test.
49 /// Requires that the test was marked with a fact attribute derived from <see cref="WixBuildTools.TestSupport.XunitExtensions.SkippableFactAttribute" />
50 /// or <see cref="WixBuildTools.TestSupport.XunitExtensions.SkippableTheoryAttribute" />
51 /// </summary>
52 public static void Skip(string message)
53 {
54 throw new SkipTestException(message);
55 }
56
57 public static void SpecificReturnCode(int hrExpected, int hr, string format, params object[] formatArgs)
58 {
59 if (hrExpected != hr)
60 {
61 throw new SpecificReturnCodeException(hrExpected, hr, String.Format(format, formatArgs));
62 }
63 }
64
65 public static void Succeeded(int hr, string format, params object[] formatArgs)
66 {
67 if (0 > hr)
68 {
69 throw new SucceededException(hr, String.Format(format, formatArgs));
70 }
71 }
72
73 public static void StringCollectionEmpty(IList<string> collection)
74 {
75 if (collection.Count > 0)
76 {
77 Assert.True(false, $"The collection was expected to be empty, but instead was [{Environment.NewLine}\"{String.Join($"\", {Environment.NewLine}\"", collection)}\"{Environment.NewLine}]");
78 }
79 }
80
81 public static void StringEqual(string expected, string actual, bool ignoreCase = false)
82 {
83 WixStringEqualException.ThrowIfNotEqual(expected, actual, ignoreCase);
84 }
85
86 public static void NotStringEqual(string expected, string actual, bool ignoreCase = false)
87 {
88 var comparer = ignoreCase ? StringObjectEqualityComparer.InvariantCultureIgnoreCase : StringObjectEqualityComparer.InvariantCulture;
89 Assert.NotEqual<object>(expected, actual, comparer);
90 }
91
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^)
95 // from a call to:
96 // Xunit::Assert::Throws(System::Type^, System::Func<System::Object^>^)
97 // that implicitly ignores its return value.
98 //
99 // The ambiguity may have been reported by some versions of the compiler and not by others.
100 // Some versions of the compiler may not have emitted any code in this situation, making it
101 // appear that the test has passed when, in fact, it hasn't been run.
102 //
103 // This situation is not an issue for C#.
104 //
105 // The following method is used to isolate DUtilTests in order to overcome the above problem.
106
107 /// <summary>
108 /// This shim allows C++/CLR code to call the Xunit method with the same signature
109 /// without getting an ambiguous overload error. If the specified test code
110 /// fails to generate an exception of the exact specified type, an assertion
111 /// exception is thrown. Otherwise, execution flow proceeds as normal.
112 /// </summary>
113 /// <typeparam name="T">The type name of the expected exception.</typeparam>
114 /// <param name="testCode">An Action delegate to run the test code.</param>
115 public static new void Throws<T>(System.Action testCode)
116 where T : System.Exception
117 {
118 Xunit.Assert.Throws<T>(testCode);
119 }
120
121 // This shim has been tested, but is not currently used anywhere. It was provided
122 // at the same time as the preceding shim because it involved the same overload
123 // resolution conflict.
124
125 /// <summary>
126 /// This shim allows C++/CLR code to call the Xunit method with the same signature
127 /// without getting an ambiguous overload error. If the specified test code
128 /// fails to generate an exception of the exact specified type, an assertion
129 /// exception is thrown. Otherwise, execution flow proceeds as normal.
130 /// </summary>
131 /// <param name="exceptionType">The type object associated with exceptions of the expected type.</param>
132 /// <param name="testCode">An Action delegate to run the test code.</param>
133 /// <returns>An exception of a type other than the type specified, is such an exception is thrown.</returns>
134 public static new System.Exception Throws(System.Type exceptionType, System.Action testCode)
135 {
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}