* ContainerTest.cs: Added tests for Add, Dispose, ValidateName and
[mono.git] / mcs / class / System / Test / System.ComponentModel / ContainerTest.cs
1 //
2 // System.ComponentModel.Container test cases
3 //
4 // Authors:
5 //      Gonzalo Paniagua Javier (gonzalo@ximian.com)
6 //  Ivan N. Zlatev (contact i-nZ.net)
7
8 // Copyright (c) 2006 Novell, Inc. (http://www.novell.com)
9 // Copyright (c) 2006 Ivan N. Zlatev
10 //
11
12 using NUnit.Framework;
13 using System;
14 using System.ComponentModel;
15 using System.ComponentModel.Design;
16
17 namespace MonoTests.System.ComponentModel
18 {
19         class TestService {
20         }
21         
22         class TestContainer : Container {
23                 ServiceContainer _services = new ServiceContainer ();
24                 bool allowDuplicateNames;
25                 
26                 public TestContainer()
27                 {
28                         _services.AddService (typeof (TestService), new TestService ());
29                 }
30
31                 public bool AllowDuplicateNames {
32                         get { return allowDuplicateNames; }
33                         set { allowDuplicateNames = value; }
34                 }
35
36                 protected override object GetService (Type serviceType)
37                 {
38                         return _services.GetService (serviceType);
39                 }
40
41 #if NET_2_0
42                 public void Remove_WithoutUnsiting (IComponent component)
43                 {
44                         base.RemoveWithoutUnsiting (component);
45                 }
46
47                 public void InvokeValidateName (IComponent component, string name)
48                 {
49                         ValidateName (component, name);
50                 }
51
52                 protected override void ValidateName (IComponent component, string name)
53                 {
54                         if (AllowDuplicateNames)
55                                 return;
56                         base.ValidateName (component, name);
57                 }
58 #endif
59
60                 public bool Contains (IComponent component)
61                 {
62                         bool found = false;
63                         
64                         foreach (IComponent c in Components) {
65                                 if (component.Equals (c)) {
66                                         found = true;
67                                         break;
68                                 }
69                         }
70                         return found;
71                 }
72
73                 public new void Dispose (bool disposing)
74                 {
75                         base.Dispose (disposing);
76                 }
77         }
78         
79         class TestComponent : Component {
80                 public override ISite Site {
81                         get {
82                                 return base.Site;
83                         }
84                         set {
85                                 base.Site = value;
86                                 if (value != null) {
87                                         Assert.IsNotNull (value.GetService (typeof (ISite)), "ISite");
88                                         Assert.IsNotNull (value.GetService (typeof (TestService)), "TestService");
89                                 }
90                         }
91                 }
92
93                 public bool IsDisposed {
94                         get { return disposed; }
95                 }
96
97                 public bool ThrowOnDispose {
98                         get { return throwOnDispose; }
99                         set { throwOnDispose = value; }
100                 }
101
102                 protected override void Dispose (bool disposing)
103                 {
104                         if (ThrowOnDispose)
105                                 throw new InvalidOperationException ();
106
107                         base.Dispose (disposing);
108                         disposed = true;
109                 }
110
111                 private bool disposed;
112                 private bool throwOnDispose;
113         }
114
115         [TestFixture]
116         public class ContainerTest
117         {
118                 private TestContainer _container;
119
120                 [SetUp]
121                 public void Init ()
122                 {
123                         _container = new TestContainer ();
124                 }
125
126                 [Test] // Add (IComponent)
127                 public void Add1 ()
128                 {
129                         TestContainer containerA = new TestContainer ();
130                         TestContainer containerB = new TestContainer ();
131
132                         ISite siteA;
133                         ISite siteB;
134
135                         TestComponent compA = new TestComponent ();
136                         Assert.IsNull (compA.Site);
137                         TestComponent compB = new TestComponent ();
138                         Assert.IsNull (compB.Site);
139                         Assert.AreEqual (0, containerA.Components.Count);
140                         Assert.AreEqual (0, containerB.Components.Count);
141
142                         containerA.Add (compA);
143                         siteA = compA.Site;
144                         Assert.IsNotNull (siteA);
145                         Assert.AreSame (compA, siteA.Component);
146                         Assert.AreSame (containerA, siteA.Container);
147                         Assert.IsFalse (siteA.DesignMode);
148                         Assert.IsNull (siteA.Name);
149                         containerA.Add (compB);
150                         siteB = compB.Site;
151                         Assert.IsNotNull (siteB);
152                         Assert.AreSame (compB, siteB.Component);
153                         Assert.AreSame (containerA, siteB.Container);
154                         Assert.IsFalse (siteB.DesignMode);
155                         Assert.IsNull (siteB.Name);
156
157                         Assert.IsFalse (object.ReferenceEquals (siteA, siteB));
158                         Assert.AreEqual (2, containerA.Components.Count);
159                         Assert.AreEqual (0, containerB.Components.Count);
160                         Assert.AreSame (compA, containerA.Components [0]);
161                         Assert.AreSame (compB, containerA.Components [1]);
162
163                         // check effect of adding component that is already member of
164                         // another container
165                         containerB.Add (compA);
166                         Assert.IsFalse (object.ReferenceEquals (siteA, compA.Site));
167                         siteA = compA.Site;
168                         Assert.IsNotNull (siteA);
169                         Assert.AreSame (compA, siteA.Component);
170                         Assert.AreSame (containerB, siteA.Container);
171                         Assert.IsFalse (siteA.DesignMode);
172                         Assert.IsNull (siteA.Name);
173
174                         Assert.AreEqual (1, containerA.Components.Count);
175                         Assert.AreEqual (1, containerB.Components.Count);
176                         Assert.AreSame (compB, containerA.Components [0]);
177                         Assert.AreSame (compA, containerB.Components [0]);
178
179                         // check effect of add component twice to same container
180                         containerB.Add (compA);
181                         Assert.AreSame (siteA, compA.Site);
182
183                         Assert.AreEqual (1, containerA.Components.Count);
184                         Assert.AreEqual (1, containerB.Components.Count);
185                         Assert.AreSame (compB, containerA.Components [0]);
186                         Assert.AreSame (compA, containerB.Components [0]);
187                 }
188
189                 [Test]
190                 public void Add1_Component_Null ()
191                 {
192                         _container.Add ((IComponent) null);
193                         Assert.AreEqual (0, _container.Components.Count);
194                 }
195
196                 [Test] // Add (IComponent, String)
197                 public void Add2 ()
198                 {
199                         TestContainer containerA = new TestContainer ();
200                         TestContainer containerB = new TestContainer ();
201
202                         ISite siteA;
203                         ISite siteB;
204
205                         TestComponent compA = new TestComponent ();
206                         Assert.IsNull (compA.Site);
207                         TestComponent compB = new TestComponent ();
208                         Assert.IsNull (compB.Site);
209                         Assert.AreEqual (0, containerA.Components.Count);
210                         Assert.AreEqual (0, containerB.Components.Count);
211
212                         containerA.Add (compA, "A");
213                         siteA = compA.Site;
214                         Assert.IsNotNull (siteA);
215                         Assert.AreSame (compA, siteA.Component);
216                         Assert.AreSame (containerA, siteA.Container);
217                         Assert.IsFalse (siteA.DesignMode);
218                         Assert.AreEqual ("A", siteA.Name);
219                         containerA.Add (compB, "B");
220                         siteB = compB.Site;
221                         Assert.IsNotNull (siteB);
222                         Assert.AreSame (compB, siteB.Component);
223                         Assert.AreSame (containerA, siteB.Container);
224                         Assert.IsFalse (siteB.DesignMode);
225                         Assert.AreEqual ("B", siteB.Name);
226
227                         Assert.IsFalse (object.ReferenceEquals (siteA, siteB));
228                         Assert.AreEqual (2, containerA.Components.Count);
229                         Assert.AreEqual (0, containerB.Components.Count);
230                         Assert.AreSame (compA, containerA.Components [0]);
231                         Assert.AreSame (compB, containerA.Components [1]);
232
233                         // check effect of adding component that is already member of
234                         // another container
235                         containerB.Add (compA, "A2");
236                         Assert.IsFalse (object.ReferenceEquals (siteA, compA.Site));
237                         siteA = compA.Site;
238                         Assert.IsNotNull (siteA);
239                         Assert.AreSame (compA, siteA.Component);
240                         Assert.AreSame (containerB, siteA.Container);
241                         Assert.IsFalse (siteA.DesignMode);
242                         Assert.AreEqual ("A2", siteA.Name);
243
244                         Assert.AreEqual (1, containerA.Components.Count);
245                         Assert.AreEqual (1, containerB.Components.Count);
246                         Assert.AreSame (compB, containerA.Components [0]);
247                         Assert.AreSame (compA, containerB.Components [0]);
248
249                         // check effect of add component twice to same container
250                         containerB.Add (compA, "A2");
251                         Assert.AreSame (siteA, compA.Site);
252                         Assert.AreEqual ("A2", siteA.Name);
253
254                         Assert.AreEqual (1, containerA.Components.Count);
255                         Assert.AreEqual (1, containerB.Components.Count);
256                         Assert.AreSame (compB, containerA.Components [0]);
257                         Assert.AreSame (compA, containerB.Components [0]);
258
259                         // add again with different name
260                         containerB.Add (compA, "A3");
261                         Assert.AreSame (siteA, compA.Site);
262                         Assert.AreEqual ("A2", siteA.Name);
263
264                         Assert.AreEqual (1, containerA.Components.Count);
265                         Assert.AreEqual (1, containerB.Components.Count);
266                         Assert.AreSame (compB, containerA.Components [0]);
267                         Assert.AreSame (compA, containerB.Components [0]);
268
269                         // check effect of add component twice to same container
270                         containerB.Add (compA, "A2");
271                         Assert.AreSame (siteA, compA.Site);
272                         Assert.AreEqual ("A2", siteA.Name);
273                 }
274
275                 [Test]
276                 public void Add2_Component_Null ()
277                 {
278                         _container.Add ((IComponent) null, "A");
279                         Assert.AreEqual (0, _container.Components.Count);
280                         _container.Add (new TestComponent (), "A");
281                         Assert.AreEqual (1, _container.Components.Count);
282                         _container.Add ((IComponent) null, "A");
283                         Assert.AreEqual (1, _container.Components.Count);
284                 }
285
286                 [Test]
287                 public void Add2_Name_Duplicate ()
288                 {
289                         TestContainer container = new TestContainer ();
290                         TestComponent c1 = new TestComponent ();
291                         container.Add (c1, "dup");
292
293                         // new component, same case
294                         TestComponent c2 = new TestComponent ();
295                         try {
296                                 container.Add (c2, "dup");
297                                 Assert.Fail ("#A1");
298                         } catch (ArgumentException ex) {
299                                 // Duplicate component name 'dup'.  Component names must be
300                                 // unique and case-insensitive
301                                 Assert.AreEqual (typeof (ArgumentException), ex.GetType (), "#A2");
302                                 Assert.IsNull (ex.InnerException, "#A3");
303                                 Assert.IsNotNull (ex.Message, "#A4");
304                                 Assert.IsTrue (ex.Message.IndexOf ("'dup'") != -1, "#A5");
305                                 Assert.IsNull (ex.ParamName, "#A6");
306                                 Assert.AreEqual (1, container.Components.Count, "#A7");
307                         }
308
309                         // new component, different case
310                         TestComponent c3 = new TestComponent ();
311                         try {
312                                 container.Add (c3, "duP");
313                                 Assert.Fail ("#B1");
314                         } catch (ArgumentException ex) {
315                                 // Duplicate component name 'duP'.  Component names must be
316                                 // unique and case-insensitive
317                                 Assert.AreEqual (typeof (ArgumentException), ex.GetType (), "#B2");
318                                 Assert.IsNull (ex.InnerException, "#B3");
319                                 Assert.IsNotNull (ex.Message, "#B4");
320                                 Assert.IsTrue (ex.Message.IndexOf ("'duP'") != -1, "#B5");
321                                 Assert.IsNull (ex.ParamName, "#B6");
322                                 Assert.AreEqual (1, container.Components.Count, "#B7");
323                         }
324
325                         // existing component, same case
326                         TestComponent c4 = new TestComponent ();
327                         container.Add (c4, "C4");
328                         Assert.AreEqual (2, container.Components.Count, "#C1");
329                         container.Add (c4, "dup");
330                         Assert.AreEqual (2, container.Components.Count, "#C2");
331                         Assert.AreEqual ("C4", c4.Site.Name, "#C3");
332
333                         // component of other container, same case
334                         TestContainer container2 = new TestContainer ();
335                         TestComponent c5 = new TestComponent ();
336                         container2.Add (c5, "C5");
337                         try {
338                                 container.Add (c5, "dup");
339                                 Assert.Fail ("#D1");
340                         } catch (ArgumentException ex) {
341                                 // Duplicate component name 'dup'.  Component names must be
342                                 // unique and case-insensitive
343                                 Assert.AreEqual (typeof (ArgumentException), ex.GetType (), "#D2");
344                                 Assert.IsNull (ex.InnerException, "#D3");
345                                 Assert.IsNotNull (ex.Message, "#D4");
346                                 Assert.IsTrue (ex.Message.IndexOf ("'dup'") != -1, "#D5");
347                                 Assert.IsNull (ex.ParamName, "#D6");
348                                 Assert.AreEqual (2, container.Components.Count, "#D7");
349                         }
350                         Assert.AreEqual (1, container2.Components.Count, "#D8");
351                         Assert.AreSame (c5, container2.Components [0], "#D9");
352
353 #if NET_2_0
354                         container.AllowDuplicateNames = true;
355                         TestComponent c6 = new TestComponent ();
356                         container.Add (c6, "dup");
357                         Assert.AreEqual (3, container.Components.Count, "#E1");
358                         Assert.IsNotNull (c1.Site, "#E2");
359                         Assert.AreEqual ("dup", c1.Site.Name, "#E3");
360                         Assert.IsNotNull (c6.Site, "#E4");
361                         Assert.AreEqual ("dup", c6.Site.Name, "#E5");
362                         Assert.IsFalse (object.ReferenceEquals (c1.Site, c6.Site), "#E6");
363 #endif
364                 }
365
366                 [Test]
367                 public void AddRemove ()
368                 {
369                         TestComponent component = new TestComponent ();
370                         
371                         _container.Add (component);
372                         Assert.IsNotNull (component.Site, "#1");
373                         Assert.IsTrue (_container.Contains (component), "#2");
374                         
375                         _container.Remove (component);
376                         Assert.IsNull (component.Site, "#3");
377                         Assert.IsFalse (_container.Contains (component), "#4");
378
379 #if NET_2_0
380                         _container.Add (component);
381                         _container.Remove_WithoutUnsiting (component);
382                         Assert.IsNotNull (component.Site, "#5");
383                         Assert.IsFalse (_container.Contains (component), "#6");
384 #endif
385                 }
386
387                 [Test] // Dispose ()
388                 public void Dispose1 ()
389                 {
390                         TestComponent compA;
391                         TestComponent compB;
392
393                         compA = new TestComponent ();
394                         _container.Add (compA);
395                         compB = new TestComponent ();
396                         _container.Add (compB);
397
398                         _container.Dispose ();
399
400                         Assert.AreEqual (0, _container.Components.Count, "#A1");
401                         Assert.IsTrue (compA.IsDisposed, "#A2");
402                         Assert.IsNull (compA.Site, "#A3");
403                         Assert.IsTrue (compB.IsDisposed, "#A4");
404                         Assert.IsNull (compB.Site, "#A5");
405
406                         _container = new TestContainer ();
407                         compA = new TestComponent ();
408                         compA.ThrowOnDispose = true;
409                         _container.Add (compA);
410                         compB = new TestComponent ();
411                         _container.Add (compB);
412
413                         // assert that component is not removed from components until after
414                         // Dispose of component has succeeded
415                         try {
416                                 _container.Dispose ();
417                                 Assert.Fail ("#B1");
418                         } catch (InvalidOperationException) {
419                                 Assert.AreEqual (0, _container.Components.Count, "#B2");
420                                 Assert.IsFalse (compA.IsDisposed, "#B4");
421                                 Assert.IsNull (compA.Site, "#B5");
422                                 Assert.IsTrue (compB.IsDisposed, "#B6");
423                                 Assert.IsNull (compB.Site, "#B7");
424                         } finally {
425                                 compA.ThrowOnDispose = false;
426                         }
427
428                         _container = new TestContainer ();
429                         compA = new TestComponent ();
430                         _container.Add (compA);
431                         compB = new TestComponent ();
432                         compB.ThrowOnDispose = true;
433                         _container.Add (compB);
434
435                         try {
436                                 _container.Dispose ();
437                                 Assert.Fail ("#C1");
438                         } catch (InvalidOperationException) {
439                                 Assert.AreEqual (1, _container.Components.Count, "#C2");
440                                 Assert.AreSame (compA, _container.Components [0], "#C3");
441                                 Assert.IsFalse (compA.IsDisposed, "#C4");
442                                 Assert.IsNotNull (compA.Site, "#C5");
443                                 Assert.IsFalse (compB.IsDisposed, "#C6");
444                                 Assert.IsNull (compB.Site, "#C7");
445                         } finally {
446                                 compB.ThrowOnDispose = false;
447                         }
448                 }
449
450                 [Test] // Dispose (Boolean)
451                 public void Dispose2 ()
452                 {
453                         TestComponent compA;
454                         TestComponent compB;
455
456                         compA = new TestComponent ();
457                         _container.Add (compA);
458                         compB = new TestComponent ();
459                         _container.Add (compB);
460
461                         _container.Dispose (false);
462
463                         Assert.AreEqual (2, _container.Components.Count, "#A1");
464                         Assert.IsFalse (compA.IsDisposed, "#A2");
465                         Assert.IsNotNull (compA.Site, "#A3");
466                         Assert.IsFalse (compB.IsDisposed, "#A4");
467                         Assert.IsNotNull (compB.Site, "#A5");
468
469                         _container.Dispose (true);
470
471                         Assert.AreEqual (0, _container.Components.Count, "#B1");
472                         Assert.IsTrue (compA.IsDisposed, "#B2");
473                         Assert.IsNull (compA.Site, "#B3");
474                         Assert.IsTrue (compB.IsDisposed, "#B4");
475                         Assert.IsNull (compB.Site, "#B5");
476
477                         compA = new TestComponent ();
478                         _container.Add (compA);
479                         compB = new TestComponent ();
480                         _container.Add (compB);
481
482                         Assert.AreEqual (2, _container.Components.Count, "#C1");
483                         Assert.IsFalse (compA.IsDisposed, "#C2");
484                         Assert.IsNotNull (compA.Site, "#C3");
485                         Assert.IsFalse (compB.IsDisposed, "#C4");
486                         Assert.IsNotNull (compB.Site, "#C5");
487
488                         _container.Dispose (true);
489
490                         Assert.AreEqual (0, _container.Components.Count, "#D1");
491                         Assert.IsTrue (compA.IsDisposed, "#D2");
492                         Assert.IsNull (compA.Site, "#D3");
493                         Assert.IsTrue (compB.IsDisposed, "#D4");
494                         Assert.IsNull (compB.Site, "#D5");
495                 }
496
497                 [Test]
498                 public void GetService ()
499                 {
500                         object service;
501
502                         GetServiceContainer container = new GetServiceContainer ();
503                         container.Add (new MyComponent ());
504                         service = container.GetService (typeof (MyComponent));
505                         Assert.IsNull (service, "#1");
506                         service = container.GetService (typeof (Component));
507                         Assert.IsNull (service, "#2");
508                         service = container.GetService (typeof (IContainer));
509                         Assert.AreSame (container, service, "#3");
510                         service = container.GetService ((Type) null);
511                         Assert.IsNull (service, "#4");
512                 }
513
514 #if NET_2_0
515                 [Test]
516                 public void ValidateName_Component_Null ()
517                 {
518                         try {
519                                 _container.InvokeValidateName ((IComponent) null, "A");
520                                 Assert.Fail ("#1");
521                         } catch (ArgumentNullException ex) {
522                                 Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
523                                 Assert.IsNull (ex.InnerException, "#3");
524                                 Assert.IsNotNull (ex.Message, "#4");
525                                 Assert.AreEqual ("component", ex.ParamName, "#5");
526                         }
527                 }
528
529                 [Test]
530                 public void ValidateName_Name_Null ()
531                 {
532                         TestComponent compA = new TestComponent ();
533                         _container.Add (compA, (string) null);
534                         TestComponent compB = new TestComponent ();
535                         _container.InvokeValidateName (compB, (string) null);
536                 }
537
538                 [Test]
539                 public void ValidateName_Name_Duplicate ()
540                 {
541                         TestComponent compA = new TestComponent ();
542                         _container.Add (compA, "dup");
543
544                         // same component, same case
545                         _container.InvokeValidateName (compA, "dup");
546
547                         // existing component, same case
548                         TestComponent compB = new TestComponent ();
549                         _container.Add (compB, "B");
550                         try {
551                                 _container.InvokeValidateName (compB, "dup");
552                                 Assert.Fail ("#A1");
553                         } catch (ArgumentException ex) {
554                                 // Duplicate component name 'duP'.  Component names must be
555                                 // unique and case-insensitive
556                                 Assert.AreEqual (typeof (ArgumentException), ex.GetType (), "#A2");
557                                 Assert.IsNull (ex.InnerException, "#A3");
558                                 Assert.IsNotNull (ex.Message, "#A4");
559                                 Assert.IsTrue (ex.Message.IndexOf ("'dup'") != -1, "#A5");
560                                 Assert.IsNull (ex.ParamName, "#A6");
561                                 Assert.AreEqual (2, _container.Components.Count, "#A7");
562                         }
563                         _container.InvokeValidateName (compB, "whatever");
564
565                         // new component, different case
566                         TestComponent compC = new TestComponent ();
567                         try {
568                                 _container.InvokeValidateName (compC, "dup");
569                                 Assert.Fail ("#B1");
570                         } catch (ArgumentException ex) {
571                                 // Duplicate component name 'duP'.  Component names must be
572                                 // unique and case-insensitive
573                                 Assert.AreEqual (typeof (ArgumentException), ex.GetType (), "#B2");
574                                 Assert.IsNull (ex.InnerException, "#B3");
575                                 Assert.IsNotNull (ex.Message, "#B4");
576                                 Assert.IsTrue (ex.Message.IndexOf ("'dup'") != -1, "#B5");
577                                 Assert.IsNull (ex.ParamName, "#B6");
578                                 Assert.AreEqual (2, _container.Components.Count, "#B7");
579                         }
580                         _container.InvokeValidateName (compC, "whatever");
581
582                         // component of other container, different case
583                         TestContainer container2 = new TestContainer ();
584                         TestComponent compD = new TestComponent ();
585                         container2.Add (compD, "B");
586                         try {
587                                 _container.InvokeValidateName (compD, "dup");
588                                 Assert.Fail ("#C1");
589                         } catch (ArgumentException ex) {
590                                 // Duplicate component name 'duP'.  Component names must be
591                                 // unique and case-insensitive
592                                 Assert.AreEqual (typeof (ArgumentException), ex.GetType (), "#C2");
593                                 Assert.IsNull (ex.InnerException, "#C3");
594                                 Assert.IsNotNull (ex.Message, "#C4");
595                                 Assert.IsTrue (ex.Message.IndexOf ("'dup'") != -1, "#C5");
596                                 Assert.IsNull (ex.ParamName, "#C6");
597                                 Assert.AreEqual (2, _container.Components.Count, "#C7");
598                         }
599                         _container.InvokeValidateName (compD, "whatever");
600                         Assert.AreEqual (1, container2.Components.Count, "#C8");
601                         Assert.AreSame (compD, container2.Components [0], "#C9");
602                 }
603 #endif
604
605                 class MyComponent : Component
606                 {
607                 }
608
609                 class MyContainer : IContainer
610                 {
611                         private ComponentCollection components = new ComponentCollection (
612                                 new Component [0]);
613
614                         public ComponentCollection Components {
615                                 get { return components; }
616                         }
617
618                         public void Add (IComponent component)
619                         {
620                         }
621
622                         public void Add (IComponent component, string name)
623                         {
624                         }
625
626                         public void Remove (IComponent component)
627                         {
628                         }
629
630                         public void Dispose ()
631                         {
632                         }
633                 }
634
635                 public class GetServiceContainer : Container
636                 {
637                         public new object GetService (Type service)
638                         {
639                                 return base.GetService (service);
640                         }
641                 }
642         }
643 }