1 // -----------------------------------------------------------------------
\r
2 // Copyright (c) Microsoft Corporation. All rights reserved.
\r
3 // -----------------------------------------------------------------------
\r
5 using System.Collections.Generic;
\r
6 using System.ComponentModel.Composition.UnitTesting;
\r
7 using System.ComponentModel.Composition.Factories;
\r
8 using System.Globalization;
\r
11 using System.Reflection;
\r
12 using System.Security;
\r
13 using System.Security.Permissions;
\r
15 using System.ComponentModel.Composition.Primitives;
\r
16 using System.UnitTesting;
\r
17 using Microsoft.Internal;
\r
18 using Microsoft.VisualStudio.TestTools.UnitTesting;
\r
21 using System.Runtime.Serialization;
\r
22 using System.Security.Policy;
\r
25 namespace System.ComponentModel.Composition
\r
27 [TestClass][Serializable]
\r
28 public class CompositionExceptionTests
\r
31 public delegate void Work(int index);
\r
33 public class Worker : MarshalByRefObject
\r
35 public static ExpectationCollection<IEnumerable<CompositionError>, string> expectations = new ExpectationCollection<IEnumerable<CompositionError>, string>();
\r
38 expectations.Add(ErrorFactory.CreateFromDsl("Error"), "1<Separator> Error");
\r
39 expectations.Add(ErrorFactory.CreateFromDsl("Error|Error"), "1<Separator> Error|2<Separator> Error");
\r
40 expectations.Add(ErrorFactory.CreateFromDsl("Error|Error|Error"), "1<Separator> Error|2<Separator> Error|3<Separator> Error");
\r
41 expectations.Add(ErrorFactory.CreateFromDsl("Error(Error)"), "1<Separator> Error|<Prefix>Error");
\r
42 expectations.Add(ErrorFactory.CreateFromDsl("Error(Error|Error)"), "1<Separator> Error|<Prefix>Error|2<Separator> Error|<Prefix>Error");
\r
43 expectations.Add(ErrorFactory.CreateFromDsl("Error(Error|Error|Error)"), "1<Separator> Error|<Prefix>Error|2<Separator> Error|<Prefix>Error|3<Separator> Error|<Prefix>Error");
\r
44 expectations.Add(ErrorFactory.CreateFromDsl("Error(Error(Exception))"), "1<Separator> Exception|<Prefix>Error|<Prefix>Error");
\r
45 expectations.Add(ErrorFactory.CreateFromDsl("Error(Error|Exception)"), "1<Separator> Error|<Prefix>Error|2<Separator> Exception|<Prefix>Error");
\r
46 expectations.Add(ErrorFactory.CreateFromDsl("Error(Exception)"), "1<Separator> Exception|<Prefix>Error");
\r
47 expectations.Add(ErrorFactory.CreateFromDsl("Error(Exception(Exception))"), "1<Separator> Exception|<Prefix>Exception|<Prefix>Error");
\r
48 expectations.Add(ErrorFactory.CreateFromDsl("Error(Error(Exception)|Error)"), "1<Separator> Exception|<Prefix>Error|<Prefix>Error|2<Separator> Error|<Prefix>Error");
\r
53 internal void DoWork(int index)
\r
63 public void Constructor1_ShouldSetMessagePropertyToDefault()
\r
65 var exception = new CompositionException();
\r
67 ExceptionAssert.HasDefaultMessage(exception);
\r
71 public void Constructor2_NullAsMessageArgument_ShouldSetMessagePropertyToDefault()
\r
73 var exception = new CompositionException((string)null);
\r
75 ExceptionAssert.HasDefaultMessage(exception);
\r
79 public void Constructor3_EmptyEnumerableAsErrorsArgument_ShouldSetMessagePropertyToDefault()
\r
81 var exception = new CompositionException(Enumerable.Empty<CompositionError>());
\r
83 ExceptionAssert.HasDefaultMessage(exception);
\r
87 public void Constructor4_NullAsMessageArgument_ShouldSetMessagePropertyToDefault()
\r
89 var exception = new CompositionException((string)null, new Exception());
\r
91 ExceptionAssert.HasDefaultMessage(exception);
\r
95 public void Constructor5_NullAsMessageArgument_ShouldSetMessagePropertyToDefault()
\r
97 var exception = new CompositionException((string)null, new Exception(), Enumerable.Empty<CompositionError>());
\r
99 ExceptionAssert.HasDefaultMessage(exception);
\r
103 public void Constructor2_ValueAsMessageArgument_ShouldSetMessageProperty()
\r
105 var expectations = Expectations.GetExceptionMessages();
\r
107 foreach (var e in expectations)
\r
109 var exception = new CompositionException(e);
\r
111 Assert.AreEqual(e, exception.Message);
\r
116 public void Constructor4_ValueAsMessageArgument_ShouldSetMessageProperty()
\r
118 var expectations = Expectations.GetExceptionMessages();
\r
120 foreach (var e in expectations)
\r
122 var exception = new CompositionException(e, new Exception());
\r
124 Assert.AreEqual(e, exception.Message);
\r
129 public void Constructor5_ValueAsMessageArgument_ShouldSetMessageProperty()
\r
131 var expectations = Expectations.GetExceptionMessages();
\r
133 foreach (var e in expectations)
\r
135 var exception = new CompositionException(e, new Exception(), Enumerable.Empty<CompositionError>());
\r
137 Assert.AreEqual(e, exception.Message);
\r
142 public void Constructor1_ShouldSetInnerExceptionPropertyToNull()
\r
144 var exception = new CompositionException();
\r
146 Assert.IsNull(exception.InnerException);
\r
150 public void Constructor2_ShouldSetInnerExceptionPropertyToNull()
\r
152 var exception = new CompositionException("Message");
\r
154 Assert.IsNull(exception.InnerException);
\r
158 public void Constructor3_ShouldSetInnerExceptionPropertyToNull()
\r
160 var exception = new CompositionException(Enumerable.Empty<CompositionError>());
\r
162 Assert.IsNull(exception.InnerException);
\r
166 public void Constructor4_NullAsInnerExceptionArgument_ShouldSetInnerExceptionPropertyToNull()
\r
168 var exception = new CompositionException("Message", (Exception)null);
\r
170 Assert.IsNull(exception.InnerException);
\r
174 public void Constructor5_NullAsInnerExceptionArgument_ShouldSetInnerExceptionPropertyToNull()
\r
176 var exception = new CompositionException("Message", (Exception)null, Enumerable.Empty<CompositionError>());
\r
178 Assert.IsNull(exception.InnerException);
\r
182 public void Constructor4_ValueAsInnerExceptionArgument_ShouldSetInnerExceptionProperty()
\r
184 var expectations = Expectations.GetInnerExceptions();
\r
186 foreach (var e in expectations)
\r
188 var exception = new CompositionException("Message", e);
\r
190 Assert.AreSame(e, exception.InnerException);
\r
195 public void Constructor5_ValueAsInnerExceptionArgument_ShouldSetInnerExceptionProperty()
\r
197 var expectations = Expectations.GetInnerExceptions();
\r
199 foreach (var e in expectations)
\r
201 var exception = new CompositionException("Message", e, Enumerable.Empty<CompositionError>());
\r
203 Assert.AreSame(e, exception.InnerException);
\r
208 public void Constructor2_ArrayWithNullAsErrorsArgument_ShouldThrowArgument()
\r
210 var errors = new CompositionError[] { null };
\r
212 ExceptionAssert.ThrowsArgument<ArgumentException>("errors", () =>
\r
214 new CompositionException(errors);
\r
219 public void Constructor5_ArrayWithNullAsErrorsArgument_ShouldThrowArgument()
\r
221 var errors = new CompositionError[] { null };
\r
223 ExceptionAssert.ThrowsArgument<ArgumentException>("errors", () =>
\r
225 new CompositionException("Message", new Exception(), errors);
\r
230 public void Constructor1_ShouldSetErrorsPropertyToEmpty()
\r
232 var exception = new CompositionException();
\r
234 EnumerableAssert.IsEmpty(exception.Errors);
\r
238 public void Constructor2_NullAsErrorsArgument_ShouldSetErrorsPropertyToEmptyEnumerable()
\r
240 var exception = new CompositionException((IEnumerable<CompositionError>)null);
\r
242 EnumerableAssert.IsEmpty(exception.Errors);
\r
246 public void Constructor2_EmptyEnumerableAsErrorsArgument_ShouldSetErrorsPropertyToEmptyEnumerable()
\r
248 var exception = new CompositionException(Enumerable.Empty<CompositionError>());
\r
250 EnumerableAssert.IsEmpty(exception.Errors);
\r
254 public void Constructor2_ValueAsErrorsArgument_ShouldSetErrorsProperty()
\r
256 var expectations = Expectations.GetCompositionErrors();
\r
258 foreach (var e in expectations)
\r
260 var exception = new CompositionException(e);
\r
262 EnumerableAssert.AreSequenceSame(e, exception.Errors);
\r
267 public void Constructor2_ArrayAsAsErrorsArgument_ShouldNotAllowModificationAfterConstruction()
\r
269 var error = CreateCompositionError();
\r
270 var errors = new CompositionError[] { error };
\r
272 var exception = new CompositionException(errors);
\r
276 EnumerableAssert.AreEqual(exception.Errors, error);
\r
280 public void Constructor3_ShouldSetErrorsPropertyToEmpty()
\r
282 var exception = new CompositionException();
\r
284 EnumerableAssert.IsEmpty(exception.Errors);
\r
288 public void Constructor4_ShouldSetErrorsPropertyToEmptyEnumerable()
\r
290 var exception = new CompositionException("Message", new Exception());
\r
292 EnumerableAssert.IsEmpty(exception.Errors);
\r
296 public void Constructor5_NullAsErrorsArgument_ShouldSetErrorsPropertyToEmptyEnumerable()
\r
298 var exception = new CompositionException("Message", new Exception(), (IEnumerable<CompositionError>)null);
\r
300 EnumerableAssert.IsEmpty(exception.Errors);
\r
304 public void Constructor5_EmptyEnumerableAsErrorsArgument_ShouldSetErrorsPropertyToEmptyEnumerable()
\r
306 var exception = new CompositionException("Message", new Exception(), Enumerable.Empty<CompositionError>());
\r
308 EnumerableAssert.IsEmpty(exception.Errors);
\r
312 public void Constructor5_ValueAsErrorsArgument_ShouldSetErrorsProperty()
\r
314 var expectations = Expectations.GetCompositionErrors();
\r
316 foreach (var e in expectations)
\r
318 var exception = new CompositionException("Message", new Exception(), e);
\r
320 EnumerableAssert.AreSequenceSame(e, exception.Errors);
\r
325 public void Constructor5_ArrayAsAsErrorsArgument_ShouldNotAllowModificationAfterConstruction()
\r
327 var error = CreateCompositionError();
\r
328 var errors = new CompositionError[] { error };
\r
330 var exception = new CompositionException("Message", new Exception(), errors);
\r
334 EnumerableAssert.AreEqual(exception.Errors, error);
\r
338 public void Message_ShouldIncludeElementGraph()
\r
340 var expectations = new ExpectationCollection<CompositionError, string>();
\r
341 CompositionError error = null;
\r
343 error = CreateCompositionErrorWithElementChain(1);
\r
344 expectations.Add(error, GetElementGraphString(error));
\r
346 error = CreateCompositionErrorWithElementChain(2);
\r
347 expectations.Add(error, GetElementGraphString(error));
\r
349 error = CreateCompositionErrorWithElementChain(3);
\r
350 expectations.Add(error, GetElementGraphString(error));
\r
352 error = CreateCompositionErrorWithElementChain(10);
\r
353 expectations.Add(error, GetElementGraphString(error));
\r
356 foreach (var e in expectations)
\r
358 var exception = CreateCompositionException(new CompositionError[] { e.Input });
\r
360 string result = exception.ToString();
\r
361 string expected = FixMessage(e.Output);
\r
362 StringAssert.Contains(result, expected);
\r
366 #if !SILVERLIGHT && CLR40
\r
368 public void Message_ShouldIncludeElementGraphAccrossAppDomain()
\r
370 PermissionSet ps = new PermissionSet(PermissionState.None);
\r
371 ps.AddPermission(new SecurityPermission(SecurityPermissionFlag.Execution));
\r
372 ps.AddPermission(new ReflectionPermission(ReflectionPermissionFlag.MemberAccess));
\r
374 //Create a new sandboxed domain
\r
375 AppDomainSetup setup = AppDomain.CurrentDomain.SetupInformation;
\r
376 AppDomain newDomain = AppDomain.CreateDomain("test domain", null, setup, ps);
\r
378 Worker remoteWorker = (Worker)newDomain.CreateInstanceAndUnwrap(
\r
379 Assembly.GetExecutingAssembly().FullName,
\r
380 typeof(Worker).FullName);
\r
382 var expectationIndex = new int[] { 1, 2, 3, 10};
\r
384 var expectations = new ExpectationCollection<CompositionError, string>();
\r
385 CompositionError error = null;
\r
387 error = CreateCompositionErrorWithElementChain(1);
\r
388 expectations.Add(error, GetElementGraphString(error));
\r
390 error = CreateCompositionErrorWithElementChain(2);
\r
391 expectations.Add(error, GetElementGraphString(error));
\r
393 error = CreateCompositionErrorWithElementChain(3);
\r
394 expectations.Add(error, GetElementGraphString(error));
\r
396 error = CreateCompositionErrorWithElementChain(10);
\r
397 expectations.Add(error, GetElementGraphString(error));
\r
400 foreach (var e in expectations)
\r
404 remoteWorker.Action = (int x) =>
\r
406 var lclExpectations = new ExpectationCollection<CompositionError, string>();
\r
408 var lclError = CreateCompositionErrorWithElementChain(x);
\r
409 lclExpectations.Add(lclError, GetElementGraphString(lclError));
\r
411 var ce = CreateCompositionException(new CompositionError[] { lclExpectations[0].Input });
\r
414 remoteWorker.DoWork(expectationIndex[index]);
\r
416 catch (CompositionException compositionException)
\r
418 string result = compositionException.ToString();
\r
419 string expected = FixMessage(e.Output);
\r
420 StringAssert.Contains(result, expected);
\r
422 catch (Exception exception)
\r
424 Assert.Fail(exception.ToString());
\r
431 public void Message_ShouldIncludeErrors()
\r
433 var expectations = new ExpectationCollection<IEnumerable<CompositionError>, string>();
\r
434 expectations.Add(ErrorFactory.CreateFromDsl("Error"), "1<Separator> Error");
\r
435 expectations.Add(ErrorFactory.CreateFromDsl("Error|Error"), "1<Separator> Error|2<Separator> Error");
\r
436 expectations.Add(ErrorFactory.CreateFromDsl("Error|Error|Error"), "1<Separator> Error|2<Separator> Error|3<Separator> Error");
\r
437 expectations.Add(ErrorFactory.CreateFromDsl("Error(Error)"), "1<Separator> Error|<Prefix>Error");
\r
438 expectations.Add(ErrorFactory.CreateFromDsl("Error(Error|Error)"), "1<Separator> Error|<Prefix>Error|2<Separator> Error|<Prefix>Error");
\r
439 expectations.Add(ErrorFactory.CreateFromDsl("Error(Error|Error|Error)"), "1<Separator> Error|<Prefix>Error|2<Separator> Error|<Prefix>Error|3<Separator> Error|<Prefix>Error");
\r
440 expectations.Add(ErrorFactory.CreateFromDsl("Error(Error(Exception))"), "1<Separator> Exception|<Prefix>Error|<Prefix>Error");
\r
441 expectations.Add(ErrorFactory.CreateFromDsl("Error(Error|Exception)"), "1<Separator> Error|<Prefix>Error|2<Separator> Exception|<Prefix>Error");
\r
442 expectations.Add(ErrorFactory.CreateFromDsl("Error(Exception)"), "1<Separator> Exception|<Prefix>Error");
\r
443 expectations.Add(ErrorFactory.CreateFromDsl("Error(Exception(Exception))"), "1<Separator> Exception|<Prefix>Exception|<Prefix>Error");
\r
444 expectations.Add(ErrorFactory.CreateFromDsl("Error(Error(Exception)|Error)"), "1<Separator> Exception|<Prefix>Error|<Prefix>Error|2<Separator> Error|<Prefix>Error");
\r
446 foreach (var e in expectations)
\r
448 var exception = CreateCompositionException(e.Input);
\r
450 AssertMessage(exception, e.Output.Split('|'));
\r
454 #if !SILVERLIGHT && CLR40
\r
456 public void Message_ShouldIncludeErrorsAccrossAppDomain()
\r
458 PermissionSet ps = new PermissionSet(PermissionState.None);
\r
459 ps.AddPermission(new SecurityPermission(SecurityPermissionFlag.Execution));
\r
460 ps.AddPermission(new ReflectionPermission(ReflectionPermissionFlag.MemberAccess));
\r
462 //Create a new sandboxed domain
\r
463 AppDomainSetup setup = AppDomain.CurrentDomain.SetupInformation;
\r
464 AppDomain newDomain = AppDomain.CreateDomain("test domain", null, setup, ps);
\r
466 Worker remoteWorker = (Worker)newDomain.CreateInstanceAndUnwrap(
\r
467 Assembly.GetExecutingAssembly().FullName,
\r
468 typeof(Worker).FullName);
\r
471 foreach (var expectation in Worker.expectations)
\r
475 remoteWorker.Action = (int x) =>
\r
477 Exception e = CreateCompositionException(Worker.expectations[x].Input);
\r
481 remoteWorker.DoWork(index);
\r
483 catch(CompositionException e)
\r
485 AssertMessage(e, expectation.Output.Split('|'));
\r
489 Assert.Fail(e.ToString());
\r
496 public void Messsage_ShouldIncludeCountOfRootCauses()
\r
498 var expectations = new ExpectationCollection<IEnumerable<CompositionError>, int>();
\r
499 expectations.Add(ErrorFactory.CreateFromDsl("Error"), 1);
\r
500 expectations.Add(ErrorFactory.CreateFromDsl("Error|Error"), 2);
\r
501 expectations.Add(ErrorFactory.CreateFromDsl("Error|Error|Error"), 3);
\r
502 expectations.Add(ErrorFactory.CreateFromDsl("Error(Error)"), 1);
\r
503 expectations.Add(ErrorFactory.CreateFromDsl("Error(Error)|Error(Error)"), 2);
\r
504 expectations.Add(ErrorFactory.CreateFromDsl("Error(Error|Error)"), 2);
\r
505 expectations.Add(ErrorFactory.CreateFromDsl("Error(Error|Error|Exception)"), 3);
\r
507 foreach (var e in expectations)
\r
509 var exception = CreateCompositionException(e.Input);
\r
511 AssertMessage(exception, e.Output, CultureInfo.CurrentCulture);
\r
516 public void Message_ShouldFormatCountOfRootCausesUsingTheCurrentCulture()
\r
518 var cultures = Expectations.GetCulturesForFormatting();
\r
520 foreach (var culture in cultures)
\r
522 using (new CurrentCultureContext(culture))
\r
524 var errors = CreateCompositionErrors(1000);
\r
525 var exception = CreateCompositionException(errors);
\r
526 AssertMessage(exception, 1000, culture);
\r
528 errors = CreateCompositionErrors(1);
\r
529 exception = CreateCompositionException(errors);
\r
530 AssertMessage(exception, 1, culture);
\r
535 #if !SILVERLIGHT && CLR40
\r
538 public void Message_CanBeSerialized()
\r
540 var expectations = Expectations.GetExceptionMessages();
\r
542 foreach (var e in expectations)
\r
544 var exception = CreateCompositionException(e);
\r
546 var result = SerializationTestServices.RoundTrip(exception);
\r
548 Assert.AreEqual(exception.Message, result.Message);
\r
553 public void Errors_CanBeSerialized()
\r
555 var expectations = Expectations.GetCompositionErrors();
\r
557 foreach (var e in expectations)
\r
559 var exception = CreateCompositionException(e);
\r
561 var result = SerializationTestServices.RoundTrip(exception);
\r
563 EnumerableAssert.AreSequenceEqual(exception.Errors, result.Errors, (index, expected, actual) =>
\r
565 CompositionAssert.AreEqual(expected, actual);
\r
571 private string GetElementGraphString(CompositionError error)
\r
573 StringBuilder writer = new StringBuilder();
\r
574 ICompositionElement element = error.Element;
\r
575 writer.AppendFormat(CultureInfo.CurrentCulture, Strings.CompositionException_ElementPrefix, element.DisplayName);
\r
577 while ((element = element.Origin) != null)
\r
579 writer.AppendFormat(CultureInfo.CurrentCulture, Strings.CompositionException_OriginFormat, Strings.CompositionException_OriginSeparator, element.DisplayName);
\r
582 return writer.ToString();
\r
585 private void AssertMessage(CompositionException exception, int rootCauseCount, CultureInfo culture)
\r
587 using (StringReader reader = new StringReader(exception.Message))
\r
589 string line = reader.ReadLine();
\r
591 if (rootCauseCount == 1)
\r
593 Assert.IsTrue(line.Contains(Strings.CompositionException_SingleErrorWithSinglePath));
\r
598 line.Contains(string.Format(CultureInfo.CurrentCulture, Strings.CompositionException_SingleErrorWithMultiplePaths, rootCauseCount)) ||
\r
599 line.Contains(string.Format(CultureInfo.CurrentCulture, Strings.CompositionException_MultipleErrorsWithMultiplePaths, rootCauseCount))
\r
605 private void AssertMessage(CompositionException exception, string[] expected)
\r
607 using (StringReader reader = new StringReader(exception.Message))
\r
612 foreach (string expect in expected)
\r
616 Assert.AreEqual(FixMessage(expect), reader.ReadLine());
\r
621 private string FixMessage(string expect)
\r
623 string fixedPrefix = expect.Replace("<Prefix>", Strings.CompositionException_ErrorPrefix + " ");
\r
624 string fixedSeparator = fixedPrefix.Replace("<Separator>", Strings.CompositionException_PathsCountSeparator);
\r
625 return fixedSeparator.Replace("<OriginSeparator>", Strings.CompositionException_OriginSeparator);
\r
628 private static CompositionError CreateCompositionError()
\r
630 return CreateCompositionError("Description");
\r
633 private static CompositionError CreateCompositionError(string message)
\r
635 return new CompositionError(message);
\r
638 private static CompositionError CreateCompositionErrorWithElementChain(int count)
\r
640 return new CompositionError("Description", ElementFactory.CreateChain(count));
\r
643 private static CompositionError[] CreateCompositionErrors(int count)
\r
645 CompositionError[] errors = new CompositionError[count];
\r
647 for (int i = 0; i < count; i++)
\r
649 errors[i] = CreateCompositionError("Description" + (i + 1));
\r
655 private static CompositionException CreateCompositionException()
\r
657 return CreateCompositionException((string)null, (Exception)null, (IEnumerable<CompositionError>)null);
\r
660 private static CompositionException CreateCompositionException(string message)
\r
662 return CreateCompositionException(message, (Exception)null, (IEnumerable<CompositionError>)null);
\r
665 private static CompositionException CreateCompositionException(IEnumerable<CompositionError> errors)
\r
667 return CreateCompositionException((string)null, (Exception)null, errors);
\r
670 private static CompositionException CreateCompositionException(Exception innerException)
\r
672 return CreateCompositionException((string)null, innerException, (IEnumerable<CompositionError>)null);
\r
675 private static CompositionException CreateCompositionException(string message, Exception innerException, IEnumerable<CompositionError> errors)
\r
677 return new CompositionException(message, innerException, errors);
\r