1 // -----------------------------------------------------------------------
\r
2 // Copyright (c) Microsoft Corporation. All rights reserved.
\r
3 // -----------------------------------------------------------------------
\r
5 using System.ComponentModel.Composition;
\r
7 using System.UnitTesting;
\r
8 using Microsoft.VisualStudio.TestTools.UnitTesting;
\r
9 using System.Reflection;
\r
10 using System.ComponentModel.Composition.Hosting;
\r
11 using System.Collections.Generic;
\r
12 using System.ComponentModel.Composition.Primitives;
\r
14 namespace System.ComponentModel.Composition.UnitTesting
\r
16 public static class CompositionAssert
\r
18 internal static void AreEqual(CompositionResult expected, CompositionResult actual)
\r
20 Assert.AreEqual(expected.Succeeded, actual.Succeeded);
\r
22 EnumerableAssert.AreSequenceEqual(expected.Errors, actual.Errors, (index, expectedError, actualError) =>
\r
24 AreEqual(expectedError, actualError);
\r
28 internal static void AreEqual(CompositionError expected, CompositionError actual)
\r
30 Assert.AreEqual(((ICompositionError)expected).Id, ((ICompositionError)actual).Id);
\r
31 Assert.AreEqual(expected.Description, actual.Description);
\r
32 ExtendedAssert.IsInstanceOfSameType(expected.Exception, actual.Exception);
\r
35 public static void ThrowsPart(ErrorId id, Action action)
\r
37 ThrowsPart(id, RetryMode.Retry, action);
\r
40 public static void ThrowsPart(ErrorId id, RetryMode retry, Action action)
\r
42 ThrowsPart(new CompositionErrorExpectation { Id = id }, retry, action);
\r
45 public static void ThrowsPart(ErrorId id, ICompositionElement element, Action action)
\r
47 ThrowsPart(id, element, RetryMode.Retry, action);
\r
50 public static void ThrowsPart(ErrorId id, ICompositionElement element, RetryMode retry, Action action)
\r
52 ThrowsPart(new CompositionErrorExpectation { Id = id, Element = element }, retry, action);
\r
55 public static void ThrowsPart<TInner>(ErrorId id, Action action)
\r
56 where TInner : Exception
\r
58 ThrowsPart<TInner>(id, RetryMode.Retry, action);
\r
61 public static void ThrowsPart<TInner>(ErrorId id, RetryMode retry, Action action)
\r
62 where TInner : Exception
\r
64 ThrowsPart(new CompositionErrorExpectation { Id = id, InnerExceptionType = typeof(TInner) }, retry, action);
\r
67 private static void ThrowsPart(CompositionErrorExpectation expectation, RetryMode retry, Action action)
\r
69 ExceptionAssert.Throws<ComposablePartException>(retry, action, (thrownException, retryCount) =>
\r
71 AssertCore(retryCount, "ComposablePartException", thrownException, expectation);
\r
75 public static void ThrowsRootError(ErrorId rootId, RetryMode retry, Action action)
\r
77 var exception = ExceptionAssert.Throws<CompositionException>(retry, action, (thrownException, retryCount) =>
\r
79 ErrorId actualId = GetRootErrorId(thrownException);
\r
81 Assert.AreEqual(rootId, actualId, "Retry Count {0}: Expected '{1}' to be the root ErrorId, however, '{2}' is.", retryCount, rootId, actualId);
\r
85 public static void ThrowsError<TInner>(ErrorId id, RetryMode retry, Action action)
\r
87 ThrowsError(new CompositionErrorExpectation { Id = id, InnerExceptionType = typeof(TInner) }, RetryMode.Retry, action);
\r
90 public static void ThrowsError(ErrorId id, Action action)
\r
92 ThrowsError(new CompositionErrorExpectation { Id = id}, RetryMode.Retry, action);
\r
95 public static void ThrowsError(ErrorId id, ErrorId innerId, Action action)
\r
97 ThrowsError(id, innerId, RetryMode.Retry, action);
\r
100 public static void ThrowsError(ErrorId id, ErrorId innerId, RetryMode retry, Action action)
\r
102 ThrowsError(GetExpectation(id, innerId), retry, action);
\r
105 public static void ThrowsError(ErrorId id, ErrorId innerId, ErrorId innerInnerId, Action action)
\r
107 ThrowsError(id, innerId, innerInnerId, RetryMode.Retry, action);
\r
110 public static void ThrowsError(ErrorId id, ErrorId innerId, ErrorId innerInnerId, RetryMode retry, Action action)
\r
112 ThrowsError(GetExpectation(id, innerId, innerInnerId), retry, action);
\r
115 public static void ThrowsError(ErrorId id, RetryMode retry, Action action)
\r
117 ThrowsError(new CompositionErrorExpectation { Id = id, }, retry, action);
\r
120 public static void ThrowsError(ErrorId id, ICompositionElement element, Action action)
\r
122 ThrowsError(new CompositionErrorExpectation { Id = id, Element = element}, RetryMode.Retry, action);
\r
125 public static void ThrowsError(ErrorId id, ICompositionElement element, RetryMode retry, Action action)
\r
127 ThrowsError(new CompositionErrorExpectation { Id = id, Element = element }, retry, action);
\r
130 public static void ThrowsError(ErrorId id, Exception exception, Action action)
\r
132 ThrowsError(new CompositionErrorExpectation { Id = id, InnerException = exception }, RetryMode.Retry, action);
\r
135 public static void ThrowsError(ErrorId id, Exception exception, RetryMode retry, Action action)
\r
137 ThrowsError(new CompositionErrorExpectation { Id = id, InnerException = exception }, retry, action);
\r
140 public static void ThrowsError(ErrorId id, ICompositionElement element, Exception exception, Action action)
\r
142 ThrowsError(new CompositionErrorExpectation { Id = id, Element = element, InnerException = exception }, RetryMode.Retry, action);
\r
145 public static void ThrowsError(ErrorId id, ICompositionElement element, Exception exception, RetryMode retry, Action action)
\r
147 ThrowsError(new CompositionErrorExpectation { Id = id, Element = element, InnerException = exception }, retry, action);
\r
150 private static void ThrowsError(CompositionErrorExpectation expectation, RetryMode retry, Action action)
\r
152 ThrowsErrors(new CompositionErrorExpectation[] { expectation }, retry, action);
\r
155 public static void ThrowsErrors(ErrorId id1, ErrorId id2, Action action)
\r
157 ThrowsErrors(id1, id2, RetryMode.Retry, action);
\r
160 public static void ThrowsErrors(ErrorId id1, ErrorId id2, RetryMode retry, Action action)
\r
162 ThrowsErrors(new ErrorId[] { id1, id2 }, retry, action);
\r
165 public static void ThrowsErrors(ErrorId[] ids, RetryMode retry, Action action)
\r
167 CompositionErrorExpectation[] expectations = new CompositionErrorExpectation[ids.Length];
\r
168 for (int i = 0; i < expectations.Length; i++)
\r
170 expectations[i] = new CompositionErrorExpectation { Id = ids[i] };
\r
173 ThrowsErrors(expectations, retry, action);
\r
176 private static void ThrowsErrors(CompositionErrorExpectation[] expectations, RetryMode retry, Action action)
\r
178 ExceptionAssert.Throws<CompositionException>(retry, action, (thrownException, retryCount) =>
\r
180 AssertCore(retryCount, "CompositionException", thrownException, expectations);
\r
184 public static void ThrowsChangeRejectedRootError(ErrorId rootId, RetryMode retry, Action action)
\r
186 var exception = ExceptionAssert.Throws<ChangeRejectedException>(retry, action, (thrownException, retryCount) =>
\r
188 ErrorId actualId = GetRootErrorId(thrownException);
\r
190 Assert.AreEqual(rootId, actualId, "Retry Count {0}: Expected '{1}' to be the root ErrorId, however, '{2}' is.", retryCount, rootId, actualId);
\r
194 public static void ThrowsChangeRejectedError(ErrorId id, Action action)
\r
196 ThrowsChangeRejectedError(new CompositionErrorExpectation { Id = id }, RetryMode.Retry, action);
\r
199 public static void ThrowsChangeRejectedError(ErrorId id, RetryMode retry, Action action)
\r
201 ThrowsChangeRejectedError(new CompositionErrorExpectation { Id = id, }, retry, action);
\r
204 public static void ThrowsChangeRejectedError(ErrorId id, ICompositionElement element, Action action)
\r
206 ThrowsChangeRejectedError(new CompositionErrorExpectation { Id = id, Element = element }, RetryMode.Retry, action);
\r
209 public static void ThrowsChangeRejectedError(ErrorId id, ErrorId innerId, RetryMode retry, Action action)
\r
211 ThrowsChangeRejectedError(GetExpectation(id, innerId), retry, action);
\r
214 public static void ThrowsChangeRejectedError(ErrorId id, ErrorId innerId, ErrorId innerInnerId, Action action)
\r
216 ThrowsChangeRejectedError(id, innerId, innerInnerId, RetryMode.Retry, action);
\r
219 public static void ThrowsChangeRejectedError(ErrorId id, ErrorId innerId, ErrorId innerInnerId, RetryMode retry, Action action)
\r
221 ThrowsChangeRejectedError(GetExpectation(id, innerId, innerInnerId), retry, action);
\r
224 private static void ThrowsChangeRejectedError(CompositionErrorExpectation expectation, RetryMode retry, Action action)
\r
226 ThrowsChangeRejectedErrors(new CompositionErrorExpectation[] { expectation }, retry, action);
\r
229 public static void ThrowsChangeRejectedError(ErrorId id, ICompositionElement element, Exception exception, Action action)
\r
231 ThrowsChangeRejectedError(new CompositionErrorExpectation { Id = id, Element = element, InnerException = exception }, RetryMode.Retry, action);
\r
234 public static void ThrowsChangeRejectedErrors(ErrorId id1, ErrorId id2, RetryMode retry, Action action)
\r
236 ThrowsChangeRejectedErrors(new ErrorId[] { id1, id2 }, retry, action);
\r
239 public static void ThrowsChangeRejectedErrors(ErrorId[] ids, RetryMode retry, Action action)
\r
241 CompositionErrorExpectation[] expectations = new CompositionErrorExpectation[ids.Length];
\r
242 for (int i = 0; i < expectations.Length; i++)
\r
244 expectations[i] = new CompositionErrorExpectation { Id = ids[i] };
\r
247 ThrowsChangeRejectedErrors(expectations, retry, action);
\r
250 private static void ThrowsChangeRejectedErrors(CompositionErrorExpectation[] expectations, RetryMode retry, Action action)
\r
252 ExceptionAssert.Throws<ChangeRejectedException>(retry, action, (thrownException, retryCount) =>
\r
254 AssertCore(retryCount, "CompositionException", thrownException, expectations);
\r
258 private static void AssertCore(int retryCount, string prefix, CompositionException exception, CompositionErrorExpectation[] expectations)
\r
260 Assert.AreEqual(exception.Errors.Count, expectations.Length);
\r
262 for (int i = 0; i < exception.Errors.Count; i++)
\r
264 AssertCore(retryCount, prefix + ".Errors[" + i + "]", exception.Errors[i], expectations[i]);
\r
268 private static void AssertCore(int retryCount, string prefix, ICompositionError error, CompositionErrorExpectation expectation)
\r
270 if (expectation.IdSpecified)
\r
272 AssertCore(retryCount, prefix, "Id", expectation.Id, (ErrorId)error.Id);
\r
275 if (expectation.ElementSpecified)
\r
277 AssertCore(retryCount, prefix, "Element", expectation.Element, error.Element);
\r
280 if (expectation.InnerExceptionSpecified)
\r
282 AssertCore(retryCount, prefix, "InnerException", expectation.InnerException, error.InnerException);
\r
285 if (expectation.InnerExceptionTypeSpecified)
\r
287 AssertCore(retryCount, prefix, "InnerException.GetType()", expectation.InnerExceptionType, error.InnerException == null ? null : error.InnerException.GetType());
\r
290 if (expectation.InnerExpectationsSpecified)
\r
292 ICompositionError innerError = error.InnerException as ICompositionError;
\r
293 if (innerError != null)
\r
295 Assert.AreEqual(1, expectation.InnerExpectations.Length);
\r
296 AssertCore(retryCount, prefix + ".InnerException", innerError, expectation.InnerExpectations[0]);
\r
300 AssertCore(retryCount, prefix + ".InnerException", (CompositionException)error.InnerException, expectation.InnerExpectations);
\r
305 private static void AssertCore<T>(int retryCount, string prefix, string propertyName, T expected, T actual)
\r
307 Assert.AreEqual(expected, actual, "Retry Count {0}: Expected '{1}' to be {3}.{4}, however, '{2}' is.", retryCount, expected, actual, prefix, propertyName);
\r
310 private static CompositionErrorExpectation GetExpectation(params ErrorId[] ids)
\r
312 var parent = new CompositionErrorExpectation() { Id = ids[0] };
\r
313 var expectation = parent;
\r
315 for (int i = 1; i < ids.Length; i++)
\r
317 expectation.InnerExpectations = new CompositionErrorExpectation[] { new CompositionErrorExpectation() { Id = ids[i] } };
\r
318 expectation = expectation.InnerExpectations[0];
\r
324 private static ErrorId GetRootErrorId(CompositionException exception)
\r
326 Assert.IsTrue(exception.Errors.Count == 1);
\r
328 return GetRootErrorId(exception.Errors[0]);
\r
331 private static ErrorId GetRootErrorId(ICompositionError error)
\r
333 Exception exception = error.InnerException;
\r
335 var childError = exception as ICompositionError;
\r
336 if (childError != null)
\r
338 return GetRootErrorId(childError);
\r
341 CompositionException composition = exception as CompositionException;
\r
342 if (composition != null)
\r
344 return GetRootErrorId(composition);
\r
347 return (ErrorId)error.Id;
\r
350 private class CompositionErrorExpectation
\r
352 private ErrorId _id;
\r
353 private Exception _innerException;
\r
354 private Type _innerExceptionType;
\r
355 private ICompositionElement _element;
\r
356 private CompositionErrorExpectation[] _innerExpectations;
\r
360 get { return _id; }
\r
364 IdSpecified = true;
\r
368 public Exception InnerException
\r
370 get { return _innerException; }
\r
373 _innerException = value;
\r
374 InnerExceptionSpecified = true;
\r
378 public Type InnerExceptionType
\r
380 get { return _innerExceptionType; }
\r
383 _innerExceptionType = value;
\r
384 InnerExceptionTypeSpecified = true;
\r
388 public ICompositionElement Element
\r
390 get { return _element; }
\r
394 ElementSpecified = true;
\r
398 public CompositionErrorExpectation[] InnerExpectations
\r
400 get { return _innerExpectations; }
\r
403 _innerExpectations = value;
\r
404 InnerExpectationsSpecified = true;
\r
408 public bool IdSpecified
\r
414 public bool InnerExceptionSpecified
\r
420 public bool InnerExceptionTypeSpecified
\r
426 public bool ElementSpecified
\r
432 public bool InnerExpectationsSpecified
\r