update MEF to preview 9
[mcs.git] / class / System.ComponentModel.Composition / Tests / ComponentModelUnitTest / System / ComponentModel / Composition / Hosting / AggregateCatalogTest.cs
blob4e2d5cacaa387cde4b3f8804072661a85e34b634
1 // -----------------------------------------------------------------------
2 // Copyright (c) Microsoft Corporation. All rights reserved.
3 // -----------------------------------------------------------------------
4 using System;
5 using System.Collections.Generic;
6 using System.ComponentModel.Composition.Factories;
7 using System.ComponentModel.Composition.Hosting;
8 using System.ComponentModel.Composition.Primitives;
9 using System.IO;
10 using System.Linq;
11 using System.Linq.Expressions;
12 using System.Threading;
13 using System.UnitTesting;
14 using Microsoft.VisualStudio.TestTools.UnitTesting;
16 namespace System.ComponentModel.Composition.Hosting
18 [TestClass]
19 public class AggregateCatalogTest
21 [TestMethod]
22 public void Constructor1_ShouldNotThrow()
24 new AggregateCatalog();
28 [TestMethod]
29 public void Constructor1_ShouldSetCatalogsPropertyToEmpty()
31 var catalog = new AggregateCatalog();
33 EnumerableAssert.IsEmpty(catalog.Catalogs);
36 [TestMethod]
37 [Ignore]
38 [WorkItem(812029)]
39 public void Constructor1_ShouldSetPartsPropertyToEmpty()
41 var catalog = new AggregateCatalog();
43 EnumerableAssert.IsEmpty(catalog.Parts);
46 [TestMethod]
47 public void Constructor3_NullAsCatalogsArgument_ShouldSetCatalogsPropertyToEmpty()
49 var catalog = new AggregateCatalog((IEnumerable<ComposablePartCatalog>)null);
51 EnumerableAssert.IsEmpty(catalog.Catalogs);
54 [TestMethod]
55 public void Constructor3_EmptyIEnumerableAsCatalogsArgument_ShouldSetCatalogsPropertyToEmpty()
57 var catalog = new AggregateCatalog(Enumerable.Empty<ComposablePartCatalog>());
59 EnumerableAssert.IsEmpty(catalog.Catalogs);
62 [TestMethod]
63 [Ignore]
64 [WorkItem(812029)]
65 public void Constructor3_NullAsCatalogsArgument_ShouldSetPartsPropertyToEmpty()
67 var catalog = new AggregateCatalog((IEnumerable<ComposablePartCatalog>)null);
69 EnumerableAssert.IsEmpty(catalog.Parts);
72 [TestMethod]
73 [Ignore]
74 [WorkItem(812029)]
75 public void Constructor3_EmptyIEnumerableAsCatalogsArgument_ShouldSetPartsPropertyToEmpty()
77 var catalog = new AggregateCatalog(Enumerable.Empty<ComposablePartCatalog>());
79 EnumerableAssert.IsEmpty(catalog.Parts);
82 [TestMethod]
83 public void Constructor3_ArrayWithNullAsCatalogsArgument_ShouldThrowArgument()
85 var catalogs = new ComposablePartCatalog[] { null };
87 ExceptionAssert.ThrowsArgument<ArgumentException>("catalogs", () =>
89 new AggregateCatalog(catalogs);
90 });
93 [TestMethod]
94 public void Catalogs_WhenCatalogDisposed_ShouldThrowObjectDisposed()
96 var catalog = CreateAggregateCatalog();
97 catalog.Dispose();
99 ExceptionAssert.ThrowsDisposed(catalog, () =>
101 var catalogs = catalog.Catalogs;
105 [TestMethod]
106 public void Parts_WhenCatalogDisposed_ShouldThrowObjectDisposed()
108 var catalog = CreateAggregateCatalog();
109 catalog.Dispose();
111 ExceptionAssert.ThrowsDisposed(catalog, () =>
113 var parts = catalog.Parts;
117 [TestMethod]
118 public void GetExports_WhenCatalogDisposed_ShouldThrowObjectDisposed()
120 var catalog = CreateAggregateCatalog();
121 catalog.Dispose();
122 var definition = ImportDefinitionFactory.Create();
124 ExceptionAssert.ThrowsDisposed(catalog, () =>
126 catalog.GetExports(definition);
130 [TestMethod]
131 public void GetExports_NullAsConstraintArgument_ShouldThrowArgumentNull()
133 var catalog = CreateAggregateCatalog();
135 ExceptionAssert.ThrowsArgument<ArgumentNullException>("definition", () =>
137 catalog.GetExports((ImportDefinition)null);
141 [TestMethod]
142 public void Dispose_ShouldNotThrow()
144 using (var catalog = CreateAggregateCatalog())
149 [TestMethod]
150 public void Dispose_CanBeCalledMultipleTimes()
152 var catalog = CreateAggregateCatalog();
153 catalog.Dispose();
154 catalog.Dispose();
155 catalog.Dispose();
159 [TestMethod]
160 public void MutableCatalogNotifications()
162 int step = 0;
163 int changedStep = 0;
164 var catalog = new AggregateCatalog();
166 var typePartCatalog = new TypeCatalog(typeof(SharedPartStuff));
167 var typePartCatalog1 = new TypeCatalog(typeof(SharedPartStuff));
168 var typePartCatalog2 = new TypeCatalog(typeof(SharedPartStuff));
169 var typePartCatalog3 = new TypeCatalog(typeof(SharedPartStuff));
170 var typePartCatalog4 = new TypeCatalog(typeof(SharedPartStuff));
171 var typePartCatalog5 = new TypeCatalog(typeof(SharedPartStuff));
173 // Smoke test on inner collection
174 catalog.Catalogs.Add(typePartCatalog);
175 catalog.Catalogs.Remove(typePartCatalog);
176 catalog.Catalogs.Clear();
177 Assert.IsTrue(catalog.Catalogs.Count == 0, "Add/Remove/Clear -- PartsAsCollection.Count is now 0");
179 // Add notifications
180 catalog.Changed += delegate(object source, ComposablePartCatalogChangeEventArgs args)
182 // Local code
183 ++step; ++step;
184 changedStep = step;
187 //Add something then verify counters
188 catalog.Catalogs.Add(typePartCatalog);
189 Assert.IsTrue(catalog.Catalogs.Count == 1, "Add -- Catalogs.Count is now 1");
190 Assert.IsTrue(changedStep == 2, "Add -- Changed must be fired after");
192 // Reset counters
193 step = changedStep = 0;
195 // Remove something then verify counters
196 catalog.Catalogs.Remove(typePartCatalog);
197 Assert.IsTrue(catalog.Catalogs.Count == 0, "Add -- Catalogs.Count is now 0");
198 Assert.IsTrue(changedStep == 2, "Remove -- Changed must be fired after");
201 //Now Add it back
202 catalog.Catalogs.Add(typePartCatalog);
203 Assert.IsTrue(catalog.Catalogs.Count == 1, "Add -- Catalogs.Count is now 1");
205 step = changedStep = 0;
206 // Now clear the collection and verify counters
207 catalog.Catalogs.Clear();
208 Assert.IsTrue(catalog.Catalogs.Count == 0, "Add -- Catalogs.Count is now 0");
209 Assert.IsTrue(changedStep == 2, "Remove -- Changed must be fired after");
211 // Now remove a non existent item and verify counters
212 step = changedStep = 0;
213 bool removed = catalog.Catalogs.Remove(typePartCatalog);
214 Assert.IsTrue(removed == false, "Remove -- correctly returned false");
215 Assert.IsTrue(changedStep == 0, "Remove -- Changed should not fire if nothing changed");
217 // Add a bunch
218 step = changedStep = 0;
219 catalog.Catalogs.Add(typePartCatalog);
220 Assert.IsTrue(catalog.Catalogs.Count == 1, "Add -- Catalogs.Count is now 1");
221 Assert.IsTrue(changedStep == 2, "Add -- Changed must be fired after");
223 catalog.Catalogs.Add(typePartCatalog1);
224 Assert.IsTrue(catalog.Catalogs.Count == 2, "Add -- Catalogs.Count is now 1");
225 Assert.IsTrue(changedStep == 4, "Add -- Changing must be fired after");
227 catalog.Catalogs.Add(typePartCatalog2);
228 catalog.Catalogs.Add(typePartCatalog3);
229 catalog.Catalogs.Add(typePartCatalog4);
230 catalog.Catalogs.Add(typePartCatalog5);
231 Assert.IsTrue(catalog.Catalogs.Count == 6, "Add -- Catalogs.Count is now 1");
232 Assert.IsTrue(changedStep == 12, "Add -- Changing must be fired after");
234 removed = catalog.Catalogs.Remove(typePartCatalog3);
235 Assert.IsTrue(catalog.Catalogs.Count == 5, "Add -- Catalogs.Count is now 5");
236 Assert.IsTrue(removed == true, "Remove should have succeeded");
237 Assert.IsTrue(changedStep == 14, "Remove -- Changed must be fired after");
238 removed = catalog.Catalogs.Remove(typePartCatalog2);
239 removed = catalog.Catalogs.Remove(typePartCatalog1);
240 removed = catalog.Catalogs.Remove(typePartCatalog4);
241 removed = catalog.Catalogs.Remove(typePartCatalog);
242 removed = catalog.Catalogs.Remove(typePartCatalog5);
243 Assert.IsTrue(catalog.Catalogs.Count == 0, "Add -- Catalogs.Count is now 0");
244 Assert.IsTrue(removed == true, "Remove should have succeeded");
245 Assert.IsTrue(changedStep == 24, "Remove -- Changing must be fired after");
247 // Add and then clear a lot
248 step = changedStep = 0;
249 catalog.Catalogs.Add(typePartCatalog);
250 catalog.Catalogs.Add(typePartCatalog1);
251 catalog.Catalogs.Add(typePartCatalog2);
252 catalog.Catalogs.Add(typePartCatalog3);
253 catalog.Catalogs.Add(typePartCatalog4);
254 catalog.Catalogs.Add(typePartCatalog5);
255 Assert.IsTrue(catalog.Catalogs.Count == 6, "Add -- Catalogs.Count should be 6");
256 Assert.IsTrue(changedStep == 12, "Add -- Changing must be fired after");
258 catalog.Catalogs.Clear();
259 Assert.IsTrue(catalog.Catalogs.Count == 0, "Add -- Catalogs.Count should be 0");
261 step = changedStep = 0;
262 int step2 = 100;
263 int changedStep2 = 0;
265 catalog.Changed += delegate(object source, ComposablePartCatalogChangeEventArgs args)
267 // Local code
268 --step2; --step2;
269 changedStep2 = step2;
272 catalog.Catalogs.Add(typePartCatalog);
273 Assert.IsTrue(catalog.Catalogs.Count == 1, "Add -- Catalogs.Count is now 1");
274 Assert.IsTrue(changedStep == 2, "Add handler 1 -- Changed must be fired after");
275 Assert.IsTrue(changedStep2 == 98, "Add handler 2 -- Changed must be fired after");
277 catalog.Catalogs.Add(typePartCatalog1);
278 Assert.IsTrue(catalog.Catalogs.Count == 2, "Add -- Catalogs.Count is now 1");
279 Assert.IsTrue(changedStep == 4, "Add handler 1 -- Changed must be fired after");
280 Assert.IsTrue(changedStep2 == 96, "Add handler 2 -- Changed must be firedafter");
282 catalog.Catalogs.Remove(typePartCatalog);
283 Assert.IsTrue(catalog.Catalogs.Count == 1, "Add -- PartsAsCollection.Count is now 1");
284 Assert.IsTrue(changedStep == 6, "Add handler 1 -- Changed must be fired and fired after");
285 Assert.IsTrue(changedStep2 == 94, "Add handler 2 -- Changed must be fired and fired after");
287 catalog.Catalogs.Clear();
288 Assert.IsTrue(catalog.Catalogs.Count == 0, "Add -- PartsAsCollection.Count is now 0");
289 Assert.IsTrue(changedStep == 8, "Add handler 1 -- Changed must be fired after");
290 Assert.IsTrue(changedStep2 == 92, "Add handler 2 -- Changed must be fired after");
294 [TestMethod]
295 public void DisposeAggregatingCatalog()
297 int changedNotification = 0;
299 var typePartCatalog1 = new TypeCatalog(typeof(SharedPartStuff));
300 var typePartCatalog2 = new TypeCatalog(typeof(SharedPartStuff));
301 var typePartCatalog3 = new TypeCatalog(typeof(SharedPartStuff));
303 var assemblyPartCatalog1 = new AssemblyCatalog(typeof(SharedPartStuff).Assembly);
304 var assemblyPartCatalog2 = new AssemblyCatalog(typeof(SharedPartStuff).Assembly);
305 var assemblyPartCatalog3 = new AssemblyCatalog(typeof(SharedPartStuff).Assembly);
307 #if !SILVERLIGHT
308 var dirPartCatalog1 = new DirectoryCatalog(FileIO.GetRootTemporaryDirectory());
309 var dirPartCatalog2 = new DirectoryCatalog(FileIO.GetRootTemporaryDirectory());
310 var dirPartCatalog3 = new DirectoryCatalog(FileIO.GetRootTemporaryDirectory());
311 #endif
312 using (var catalog = new AggregateCatalog())
314 catalog.Catalogs.Add(typePartCatalog1);
315 catalog.Catalogs.Add(typePartCatalog2);
316 catalog.Catalogs.Add(typePartCatalog3);
318 catalog.Catalogs.Add(assemblyPartCatalog1);
319 catalog.Catalogs.Add(assemblyPartCatalog2);
320 catalog.Catalogs.Add(assemblyPartCatalog3);
322 #if !SILVERLIGHT
323 catalog.Catalogs.Add(dirPartCatalog1);
324 catalog.Catalogs.Add(dirPartCatalog2);
325 catalog.Catalogs.Add(dirPartCatalog3);
326 #endif
328 // Add notifications
329 catalog.Changed += delegate(object source, ComposablePartCatalogChangeEventArgs args)
331 // Local code
332 ++changedNotification;
337 Assert.IsTrue(changedNotification == 0, "No changed notifications");
339 //Ensure that the other catalogs are
340 ExceptionAssert.ThrowsDisposed(typePartCatalog1, () =>
342 var iEnum = typePartCatalog1.Parts.GetEnumerator();
345 ExceptionAssert.ThrowsDisposed(typePartCatalog2, () =>
347 var iEnum = typePartCatalog2.Parts.GetEnumerator();
350 ExceptionAssert.ThrowsDisposed(typePartCatalog3, () =>
352 var iEnum = typePartCatalog3.Parts.GetEnumerator();
355 //Ensure that the other catalogs are
356 ExceptionAssert.ThrowsDisposed(assemblyPartCatalog1, () =>
358 var iEnum = assemblyPartCatalog1.Parts.GetEnumerator();
361 ExceptionAssert.ThrowsDisposed(assemblyPartCatalog2, () =>
363 var iEnum = assemblyPartCatalog2.Parts.GetEnumerator();
366 ExceptionAssert.ThrowsDisposed(assemblyPartCatalog3, () =>
368 var iEnum = assemblyPartCatalog3.Parts.GetEnumerator();
371 #if !SILVERLIGHT
372 //Ensure that the other catalogs are
373 ExceptionAssert.ThrowsDisposed(dirPartCatalog1, () =>
375 var iEnum = dirPartCatalog1.Parts.GetEnumerator();
378 ExceptionAssert.ThrowsDisposed(dirPartCatalog2, () =>
380 var iEnum = dirPartCatalog2.Parts.GetEnumerator();
383 ExceptionAssert.ThrowsDisposed(dirPartCatalog3, () =>
385 var iEnum = dirPartCatalog3.Parts.GetEnumerator();
387 #endif
390 [TestMethod]
391 [Ignore]
392 [WorkItem(514749)]
393 public void MutableMultithreadedEnumerations()
395 var catalog = new AggregateCatalog();
397 ThreadStart func = delegate()
399 var typePart = new TypeCatalog(typeof(SharedPartStuff));
400 var typePart1 = new TypeCatalog(typeof(SharedPartStuff));
401 var typePart2 = new TypeCatalog(typeof(SharedPartStuff));
402 var typePart3 = new TypeCatalog(typeof(SharedPartStuff));
403 var typePart4 = new TypeCatalog(typeof(SharedPartStuff));
404 var typePart5 = new TypeCatalog(typeof(SharedPartStuff));
406 for (int i = 0; i < 100; i++)
408 catalog.Catalogs.Add(typePart);
409 catalog.Catalogs.Add(typePart1);
410 catalog.Catalogs.Add(typePart2);
411 catalog.Catalogs.Add(typePart3);
412 catalog.Catalogs.Add(typePart4);
413 catalog.Catalogs.Add(typePart5);
415 Assert.IsTrue(catalog.Catalogs.Count >= 6, "Catalogs Collection must be at least 6 big");
417 for (int k = 0; k < 5; k++)
419 int j;
420 // Ensure that iterating the returned queryable is okay even though there are many threads mutationg it
421 // We are really just looking to ensure that ollection changed exceptions are not thrown
422 j = 0;
423 var iq = catalog.Parts.GetEnumerator();
424 while (iq.MoveNext())
426 ++j;
429 Assert.IsTrue(j >= 6, "Catalogs Collection must be at least 6 big");
431 // Ensure that iterating the returned enumerator is okay even though there are many threads mutationg it
432 // We are really just looking to ensure that collection changed exceptions are not thrown
433 j = 0;
434 var ie = catalog.Catalogs.GetEnumerator();
435 while (ie.MoveNext())
437 ++j;
439 Assert.IsTrue(j >= 6, "Catalogs Collection must be at least 6 big");
443 catalog.Catalogs.Remove(typePart);
444 catalog.Catalogs.Remove(typePart1);
445 catalog.Catalogs.Remove(typePart2);
446 catalog.Catalogs.Remove(typePart3);
447 catalog.Catalogs.Remove(typePart4);
448 catalog.Catalogs.Remove(typePart5);
452 Thread[] threads = new Thread[100];
453 for (int i = 0; i < threads.Length; i++)
455 threads[i] = new Thread(func);
458 for (int i = 0; i < threads.Length; i++)
460 threads[i].Start();
462 for (int i = 0; i < threads.Length; i++)
464 threads[i].Join();
467 Assert.IsTrue(catalog.Catalogs.Count == 0, "Collection must be empty");
471 public void CreateMainAndOtherChildren(
472 out AggregateCatalog[] mainChildren,
473 out AggregateCatalog[] otherChildren,
474 out TypeCatalog[] componentCatalogs)
476 componentCatalogs = new TypeCatalog[]
478 new TypeCatalog(typeof(SharedPartStuff)),
479 new TypeCatalog(typeof(SharedPartStuff)),
480 new TypeCatalog(typeof(SharedPartStuff))
483 // Create our child catalogs
484 mainChildren = new AggregateCatalog[5];
485 for (int i = 0; i < mainChildren.Length; i++)
487 mainChildren[i] = new AggregateCatalog(componentCatalogs);
490 otherChildren = new AggregateCatalog[5];
491 for (int i = 0; i < otherChildren.Length; i++)
493 otherChildren[i] = new AggregateCatalog(componentCatalogs);
497 [TestMethod]
498 [Ignore]
499 [WorkItem(812029)]
500 public void AggregatingCatalogAddAndRemoveChildren()
502 int changedCount = 0;
503 int typesChanged = 0;
504 EventHandler<ComposablePartCatalogChangeEventArgs> onChanged = delegate(object sender, ComposablePartCatalogChangeEventArgs e)
506 ++changedCount;
507 typesChanged += e.AddedDefinitions.Concat(e.RemovedDefinitions).Count();
510 // Create our child catalogs
511 AggregateCatalog[] mainChildren;
512 AggregateCatalog[] otherChildren;
513 TypeCatalog[] componentCatalogs;
515 CreateMainAndOtherChildren(out mainChildren, out otherChildren, out componentCatalogs);
517 var parent = new AggregateCatalog(mainChildren);
518 parent.Changed += onChanged;
520 for (int i = 0; i < otherChildren.Length; i++)
522 parent.Catalogs.Add(otherChildren[i]);
525 Assert.AreEqual(otherChildren.Length, changedCount);
526 Assert.AreEqual(otherChildren.Length * 3, typesChanged);
528 changedCount = 0;
529 typesChanged = 0;
531 parent.Catalogs.Remove(otherChildren[0]);
532 parent.Catalogs.Remove(otherChildren[1]);
534 Assert.AreEqual(2, changedCount);
535 Assert.AreEqual(2 * 3, typesChanged);
537 changedCount = 0;
538 typesChanged = 0;
540 parent.Catalogs.Add(otherChildren[0]);
541 parent.Catalogs.Add(otherChildren[1]);
543 Assert.AreEqual(2, changedCount);
544 Assert.AreEqual(2 * 3, typesChanged);
546 changedCount = 0;
547 typesChanged = 0;
549 parent.Catalogs.Clear();
550 Assert.AreEqual(1, changedCount);
551 Assert.AreEqual((mainChildren.Length + otherChildren.Length) * 3, typesChanged);
553 changedCount = 0;
554 typesChanged = 0;
556 // These have already been removed and so I should be able remove components from them without recieving notifications
557 otherChildren[0].Catalogs.Remove(componentCatalogs[0]);
558 otherChildren[1].Catalogs.Remove(componentCatalogs[1]);
559 Assert.AreEqual(0, changedCount);
560 Assert.AreEqual(0, typesChanged);
562 // These have already been Cleared and so I should be able remove components from them without recieving notifications
563 otherChildren[3].Catalogs.Remove(componentCatalogs[0]);
564 otherChildren[4].Catalogs.Remove(componentCatalogs[1]);
565 Assert.AreEqual(0, changedCount);
568 [TestMethod]
569 [Ignore]
570 [WorkItem(812029)]
571 public void AggregatingCatalogAddAndRemoveNestedChildren()
573 int changedCount = 0;
574 int typesChanged = 0;
576 EventHandler<ComposablePartCatalogChangeEventArgs> onChanged = delegate(object sender, ComposablePartCatalogChangeEventArgs e)
578 ++changedCount;
579 typesChanged += e.AddedDefinitions.Concat(e.RemovedDefinitions).Count();
582 // Create our child catalogs
583 AggregateCatalog[] mainChildren;
584 AggregateCatalog[] otherChildren;
585 TypeCatalog[] componentCatalogs;
586 CreateMainAndOtherChildren(out mainChildren, out otherChildren, out componentCatalogs);
589 var parent = new AggregateCatalog(mainChildren);
590 parent.Changed += onChanged;
592 for (int i = 0; i < otherChildren.Length; i++)
594 parent.Catalogs.Add(otherChildren[i]);
597 Assert.AreEqual(otherChildren.Length, changedCount);
598 Assert.AreEqual(otherChildren.Length * 3, typesChanged);
600 changedCount = 0;
601 typesChanged = 0;
603 otherChildren[0].Catalogs.Remove(componentCatalogs[0]);
604 otherChildren[1].Catalogs.Remove(componentCatalogs[1]);
606 Assert.AreEqual(2, changedCount);
607 Assert.AreEqual(2, typesChanged);
609 changedCount = 0;
610 typesChanged = 0;
612 otherChildren[0].Catalogs.Add(componentCatalogs[0]);
613 otherChildren[1].Catalogs.Add(componentCatalogs[1]);
615 Assert.AreEqual(2, changedCount);
616 Assert.AreEqual(2, typesChanged);
618 changedCount = 0;
619 typesChanged = 0;
620 otherChildren[1].Catalogs.Clear();
621 Assert.AreEqual(1, changedCount);
622 Assert.AreEqual(componentCatalogs.Length, typesChanged);
625 [TestMethod]
626 [Ignore]
627 [WorkItem(812029)]
628 public void AggregatingDisposedAndNotifications()
630 int changedCount = 0;
631 int typesChanged = 0;
633 EventHandler<ComposablePartCatalogChangeEventArgs> onChanged = delegate(object sender, ComposablePartCatalogChangeEventArgs e)
635 ++changedCount;
636 typesChanged += e.AddedDefinitions.Concat(e.RemovedDefinitions).Count();
639 // Create our child catalogs
640 AggregateCatalog[] mainChildren;
641 AggregateCatalog[] otherChildren;
642 TypeCatalog[] componentCatalogs;
643 CreateMainAndOtherChildren(out mainChildren, out otherChildren, out componentCatalogs);
646 var parent = new AggregateCatalog(mainChildren);
647 parent.Changed += onChanged;
649 for (int i = 0; i < otherChildren.Length; i++)
651 parent.Catalogs.Add(otherChildren[i]);
654 Assert.AreEqual(otherChildren.Length, changedCount);
655 Assert.AreEqual(otherChildren.Length * 3, typesChanged);
657 changedCount = 0;
658 typesChanged = 0;
660 parent.Dispose();
662 Assert.AreEqual(0, changedCount);
663 Assert.AreEqual(0, typesChanged);
665 //Ensure that the children are also disposed
666 ExceptionAssert.ThrowsDisposed(otherChildren[0], () =>
668 otherChildren[0].Catalogs.Remove(componentCatalogs[0]);
671 //Ensure that the children are also disposed
672 ExceptionAssert.ThrowsDisposed(otherChildren[4], () =>
674 otherChildren[4].Catalogs.Remove(componentCatalogs[0]);
677 Assert.AreEqual(0, changedCount);
678 Assert.AreEqual(0, typesChanged);
681 [TestMethod]
682 public void AggregatingCatalogParmsConstructorAggregateAggregateCatalogs()
684 var aggCatalog1 = new AggregateCatalog();
685 var aggCatalog2 = new AggregateCatalog();
686 var aggCatalog3 = new AggregateCatalog();
688 // Construct with one catalog parameter
689 var catalog = new AggregateCatalog(aggCatalog1);
690 Assert.IsTrue(catalog.Catalogs.Count == 1);
692 // Construct with two catalog parameters
693 catalog = new AggregateCatalog(aggCatalog1, aggCatalog2);
694 Assert.IsTrue(catalog.Catalogs.Count == 2);
696 // Construct with three catalog parameters
697 catalog = new AggregateCatalog(aggCatalog1, aggCatalog2, aggCatalog3);
698 Assert.IsTrue(catalog.Catalogs.Count == 3);
702 [TestMethod]
703 public void AggregatingCatalogParmsConstructorAggregateAssemblyCatalogs()
705 var assemblyCatalog1 = new AssemblyCatalog(typeof(SharedPartStuff).Assembly);
706 var assemblyCatalog2 = new AssemblyCatalog(typeof(SharedPartStuff).Assembly);
707 var assemblyCatalog3 = new AssemblyCatalog(typeof(SharedPartStuff).Assembly);
709 // Construct with one catalog parameter
710 var catalog = new AggregateCatalog(assemblyCatalog1);
711 Assert.IsTrue(catalog.Catalogs.Count == 1);
713 // Construct with two catalog parameters
714 catalog = new AggregateCatalog(assemblyCatalog1, assemblyCatalog2);
715 Assert.IsTrue(catalog.Catalogs.Count == 2);
717 // Construct with three catalog parameters
718 catalog = new AggregateCatalog(assemblyCatalog1, assemblyCatalog2, assemblyCatalog3);
719 Assert.IsTrue(catalog.Catalogs.Count == 3);
722 [TestMethod]
723 public void AggregatingCatalogParmsConstructorMixedCatalogs()
725 var typePartCatalog1 = new TypeCatalog(typeof(SharedPartStuff));
726 var assemblyCatalog2 = new AssemblyCatalog(typeof(SharedPartStuff).Assembly);
727 var typePartCatalog3 = new TypeCatalog(typeof(SharedPartStuff));
729 // Construct with three catalog parameters
730 var catalog = new AggregateCatalog(typePartCatalog1, assemblyCatalog2, typePartCatalog3);
731 Assert.IsTrue(catalog.Catalogs.Count == 3);
734 [TestMethod]
735 public void AggregatingCatalogRaisesChangesForCatalogsPassedToConstructor()
737 var subCatalog = CreateAggregateCatalog();
738 var testCatalog = new AggregateCatalog(subCatalog);
740 bool changedCalled = false;
741 testCatalog.Changed += delegate
743 changedCalled = true;
746 subCatalog.Catalogs.Add(new TypeCatalog(typeof(SharedPartStuff)));
748 Assert.IsTrue(changedCalled);
751 private AggregateCatalog CreateAggregateCatalog()
753 return new AggregateCatalog();
756 [TestMethod]
757 [Ignore]
758 [WorkItem(812029)]
759 public void CatalogEvents_AggregateAddRemove()
761 var catalog = new AggregateCatalog();
762 AggregateTests(catalog, catalog);
765 [TestMethod]
766 [Ignore]
767 [WorkItem(812029)]
768 public void CatalogEvents_DeepAggregateAddRemove()
770 var deepCatalog = new AggregateCatalog();
771 var midCatalog = new AggregateCatalog(new ComposablePartCatalog[] { deepCatalog });
772 var topCatalog = new AggregateCatalog(new ComposablePartCatalog[] { midCatalog });
773 AggregateTests(topCatalog, deepCatalog);
776 private void AggregateTests(AggregateCatalog watchedCatalog, AggregateCatalog modifiedCatalog)
778 var fooCatalog = new TypeCatalog(new Type[] { typeof(FooExporter) });
779 var barCatalog = new TypeCatalog(new Type[] { typeof(BarExporter) });
780 var bothCatalog = new TypeCatalog(new Type[] { typeof(FooExporter), typeof(BarExporter) });
782 var catalogListener = new CatalogListener(watchedCatalog, modifiedCatalog);
784 catalogListener.VerifyAdd(fooCatalog, typeof(FooExporter));
785 catalogListener.VerifyAdd(barCatalog, typeof(BarExporter));
786 catalogListener.VerifyRemove(fooCatalog, typeof(FooExporter));
787 catalogListener.VerifyRemove(barCatalog, typeof(BarExporter));
789 catalogListener.VerifyAdd(bothCatalog, typeof(FooExporter), typeof(BarExporter));
790 catalogListener.VerifyClear(typeof(FooExporter), typeof(BarExporter));
792 catalogListener.VerifyAdd(bothCatalog, typeof(FooExporter), typeof(BarExporter));
793 catalogListener.VerifyRemove(bothCatalog, typeof(FooExporter), typeof(BarExporter));
797 public interface IFoo { }
798 public interface IBar { }
800 [Export(typeof(IFoo))]
801 public class FooExporter : IFoo
805 [Export(typeof(IBar))]
806 public class BarExporter : IBar
810 public class CatalogListener
812 private AggregateCatalog _watchedCatalog;
813 private AggregateCatalog _modifiedCatalog;
814 private string[] _expectedAdds;
815 private string[] _expectedRemoves;
816 private int _changedEventCount;
817 private int _changingEventCount;
819 public CatalogListener(AggregateCatalog watchCatalog, AggregateCatalog modifiedCatalog)
821 watchCatalog.Changing += OnChanging;
822 watchCatalog.Changed += OnChanged;
823 this._watchedCatalog = watchCatalog;
824 this._modifiedCatalog = modifiedCatalog;
827 public void VerifyAdd(ComposablePartCatalog catalogToAdd, params Type[] expectedTypesAdded)
829 this._expectedAdds = GetDisplayNames(expectedTypesAdded);
831 this._modifiedCatalog.Catalogs.Add(catalogToAdd);
833 Assert.IsTrue(this._changingEventCount == 1, "Changing event should have been called");
834 Assert.IsTrue(this._changedEventCount == 1, "Changed event should have been called");
836 ResetState();
839 public void VerifyRemove(ComposablePartCatalog catalogToRemove, params Type[] expectedTypesRemoved)
841 this._expectedAdds = null;
842 this._expectedRemoves = GetDisplayNames(expectedTypesRemoved);
844 this._modifiedCatalog.Catalogs.Remove(catalogToRemove);
846 Assert.IsTrue(this._changingEventCount == 1, "Changing event should have been called");
847 Assert.IsTrue(this._changedEventCount == 1, "Changed event should have been called");
849 ResetState();
852 public void VerifyClear(params Type[] expectedTypesRemoved)
854 this._expectedAdds = null;
855 this._expectedRemoves = GetDisplayNames(expectedTypesRemoved);
857 this._modifiedCatalog.Catalogs.Clear();
859 Assert.IsTrue(this._changingEventCount == 1, "Changing event should have been called");
860 Assert.IsTrue(this._changedEventCount == 1, "Changed event should have been called");
862 ResetState();
865 public void OnChanging(object sender, ComposablePartCatalogChangeEventArgs args)
867 Assert.IsTrue(this._expectedAdds != null || this._expectedRemoves != null);
869 if (this._expectedAdds == null)
871 EnumerableAssert.IsEmpty(args.AddedDefinitions);
873 else
875 EnumerableAssert.AreSequenceEqual(this._expectedAdds, GetDisplayNames(args.AddedDefinitions));
878 if (this._expectedRemoves == null)
880 EnumerableAssert.IsEmpty(args.RemovedDefinitions);
882 else
884 EnumerableAssert.AreSequenceEqual(this._expectedRemoves, GetDisplayNames(args.RemovedDefinitions));
887 Assert.IsFalse(ContainsChanges(), "The catalog should NOT contain the changes yet");
889 this._changingEventCount++;
892 public void OnChanged(object sender, ComposablePartCatalogChangeEventArgs args)
894 Assert.IsTrue(this._expectedAdds != null || this._expectedRemoves != null);
896 if (this._expectedAdds == null)
898 EnumerableAssert.IsEmpty(args.AddedDefinitions);
900 else
902 EnumerableAssert.AreSequenceEqual(this._expectedAdds, GetDisplayNames(args.AddedDefinitions));
905 if (this._expectedRemoves == null)
907 EnumerableAssert.IsEmpty(args.RemovedDefinitions);
909 else
911 EnumerableAssert.AreSequenceEqual(this._expectedRemoves, GetDisplayNames(args.RemovedDefinitions));
914 Assert.IsNull(args.AtomicComposition);
915 Assert.IsTrue(ContainsChanges(), "The catalog should contain the changes");
917 this._changedEventCount++;
920 private bool ContainsChanges()
922 var allParts = GetDisplayNames(this._watchedCatalog.Parts);
924 if (this._expectedAdds != null)
926 foreach (var add in this._expectedAdds)
928 if (!allParts.Contains(add))
930 return false;
935 if (this._expectedRemoves != null)
937 foreach (var remove in this._expectedRemoves)
939 if (allParts.Contains(remove))
941 return false;
946 return true;
949 private void ResetState()
951 this._expectedAdds = null;
952 this._expectedRemoves = null;
953 this._changedEventCount = 0;
954 this._changingEventCount = 0;
957 private static string[] GetDisplayNames(IEnumerable<ComposablePartDefinition> definitions)
959 return definitions.OfType<ICompositionElement>().Select(p => p.DisplayName).ToArray();
962 private static string[] GetDisplayNames(IEnumerable<Type> types)
964 return GetDisplayNames(types.Select(t => AttributedModelServices.CreatePartDefinition(t, null)));
968 [Export]
969 [PartCreationPolicy(CreationPolicy.Shared)]
970 public class SharedPartStuff
972 Guid id = Guid.NewGuid();
974 public override string ToString()
976 return id.ToString();