1 // Copyright 2004-2008 Castle Project - http://www.castleproject.org/
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
7 // http://www.apache.org/licenses/LICENSE-2.0
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
15 namespace Castle
.MicroKernel
.Tests
18 using System
.Collections
;
19 using System
.Threading
;
20 using Castle
.MicroKernel
.SubSystems
.Naming
;
21 using Castle
.MicroKernel
.Tests
.ClassComponents
;
22 using NUnit
.Framework
;
25 public class KeySearchNamingSubSystemTestCase
28 public void EmptyDelegateReturnsFirstTypeLoaded()
30 IKernel kernel
= new DefaultKernel();
31 kernel
.AddSubSystem(SubSystemConstants
.NamingKey
, new KeySearchNamingSubSystem());
33 kernel
.AddComponent("1.common", typeof(ICommon
), typeof(CommonImpl1
));
34 kernel
.AddComponent("2.common", typeof(ICommon
), typeof(CommonImpl2
));
36 ICommon common
= kernel
[typeof(ICommon
)] as ICommon
;
38 Assert
.IsNotNull(common
);
39 Assert
.AreEqual(typeof(CommonImpl1
), common
.GetType());
43 public void ReturnsCorrectType()
45 IKernel kernel
= new DefaultKernel();
46 kernel
.AddSubSystem(SubSystemConstants
.NamingKey
,
47 new KeySearchNamingSubSystem(
48 delegate(string key
) { return key.StartsWith("castlestronghold.com"); }
));
50 kernel
.AddComponent("castleproject.org.common", typeof(ICommon
), typeof(CommonImpl1
));
51 kernel
.AddComponent("castlestronghold.com.common", typeof(ICommon
), typeof(CommonImpl2
));
53 ICommon common
= kernel
[typeof(ICommon
)] as ICommon
;
55 Assert
.IsNotNull(common
);
56 Assert
.AreEqual(typeof(CommonImpl2
), common
.GetType());
60 public void ReturnsFirstTypeWhenNotFound()
62 IKernel kernel
= new DefaultKernel();
63 kernel
.AddSubSystem(SubSystemConstants
.NamingKey
,
64 new KeySearchNamingSubSystem(delegate(string key
) { return key.StartsWith("3"); }
));
66 kernel
.AddComponent("1.common", typeof(ICommon
), typeof(CommonImpl1
));
67 kernel
.AddComponent("2.common", typeof(ICommon
), typeof(CommonImpl2
));
69 ICommon common
= kernel
[typeof(ICommon
)] as ICommon
;
71 Assert
.IsNotNull(common
);
72 Assert
.AreEqual(typeof(CommonImpl1
), common
.GetType());
76 public void ReturnsFirstMatchingType()
78 IKernel kernel
= new DefaultKernel();
79 kernel
.AddSubSystem(SubSystemConstants
.NamingKey
,
80 new KeySearchNamingSubSystem(delegate(string key
) { return key.StartsWith("1"); }
));
82 kernel
.AddComponent("1.common", typeof(ICommon
), typeof(CommonImpl1
));
83 kernel
.AddComponent("11.common", typeof(ICommon
), typeof(CommonImpl2
));
85 ICommon common
= kernel
[typeof(ICommon
)] as ICommon
;
87 Assert
.IsNotNull(common
);
88 Assert
.AreEqual(typeof(CommonImpl1
), common
.GetType());
92 public void ComponentUnregistersProperly()
94 IKernel kernel
= new DefaultKernel();
96 kernel
.AddSubSystem(SubSystemConstants
.NamingKey
,
97 new KeySearchNamingSubSystem(delegate(string key
) { return key.StartsWith("2"); }
));
99 kernel
.AddComponent("1.common", typeof(ICommon
), typeof(CommonImpl1
));
100 kernel
.AddComponent("2.common", typeof(ICommon
), typeof(CommonImpl2
));
102 ICommon common
= kernel
[typeof(ICommon
)] as ICommon
;
104 Assert
.IsNotNull(common
);
105 Assert
.AreEqual(typeof(CommonImpl2
), common
.GetType());
107 kernel
.RemoveComponent("2.common");
109 common
= kernel
[typeof(ICommon
)] as ICommon
;
111 Assert
.IsNotNull(common
);
112 Assert
.AreEqual(typeof(CommonImpl1
), common
.GetType());
114 kernel
.RemoveComponent("1.common");
115 Assert
.AreEqual(0, kernel
.GetHandlers(typeof(ICommon
)).Length
);
119 public void FirstLoadedComponentUnregistersProperly()
121 IKernel kernel
= new DefaultKernel();
122 kernel
.AddSubSystem(SubSystemConstants
.NamingKey
,
123 new KeySearchNamingSubSystem(delegate(string key
) { return key.StartsWith("1"); }
));
125 kernel
.AddComponent("1.common", typeof(ICommon
), typeof(CommonImpl1
));
126 kernel
.AddComponent("2.common", typeof(ICommon
), typeof(CommonImpl2
));
128 ICommon common
= kernel
[typeof(ICommon
)] as ICommon
;
130 Assert
.IsNotNull(common
);
131 Assert
.AreEqual(typeof(CommonImpl1
), common
.GetType());
133 kernel
.RemoveComponent("1.common");
135 common
= kernel
[typeof(ICommon
)] as ICommon
;
137 Assert
.IsNotNull(common
);
138 Assert
.AreEqual(typeof(CommonImpl2
), common
.GetType());
142 [ExpectedException(typeof(ComponentNotFoundException
))]
143 public void SingleComponentUnregistersProperly()
145 IKernel kernel
= new DefaultKernel();
146 kernel
.AddSubSystem(SubSystemConstants
.NamingKey
,
147 new KeySearchNamingSubSystem(delegate(string key
) { return key.StartsWith("1"); }
));
149 kernel
.AddComponent("1.common", typeof(ICommon
), typeof(CommonImpl1
));
151 ICommon common
= kernel
[typeof(ICommon
)] as ICommon
;
153 Assert
.IsNotNull(common
);
154 Assert
.AreEqual(typeof(CommonImpl1
), common
.GetType());
156 kernel
.RemoveComponent("1.common");
158 Assert
.IsFalse(kernel
.HasComponent("1.common"));
159 Assert
.IsFalse(kernel
.HasComponent(typeof(CommonImpl1
)));
160 common
= kernel
[typeof(ICommon
)] as ICommon
;
164 public void MultiThreadedAddResolve()
166 int threadCount
= 100;
167 ArrayList list
= ArrayList
.Synchronized(new ArrayList());
168 Random rand
= new Random();
169 ManualResetEvent waitEvent
= new ManualResetEvent(false);
171 IKernel kernel
= new DefaultKernel();
172 kernel
.AddSubSystem(SubSystemConstants
.NamingKey
, new KeySearchNamingSubSystem());
173 kernel
.AddComponent("common", typeof(ICommon
), typeof(CommonImpl1
));
175 WaitCallback resolveThread
= delegate
178 while(threadCount
> 0 && list
.Count
== 0)
182 ICommon common
= kernel
[typeof(ICommon
)] as ICommon
;
186 list
.Add(e
.ToString());
190 ThreadPool
.QueueUserWorkItem(resolveThread
);
192 WaitCallback addThread
= delegate
195 kernel
.AddComponent(rand
.Next() + ".common", typeof(ICommon
), typeof(CommonImpl1
));
196 Interlocked
.Decrement(ref threadCount
);
198 for(int i
= 0; i
< threadCount
; i
++)
200 ThreadPool
.QueueUserWorkItem(addThread
);
204 while(threadCount
> 0 && list
.Count
== 0)
211 Assert
.Fail(list
[0].ToString());
216 /// What I consider an edge case (only consistently reproducable with 1000+ threads):
217 /// + Large number of components that implement the same service
218 /// + Thread 1 Requests component by service
219 /// + Thread n is simultaneously removing component
220 /// + Predicate does not match any keys for the requested service OR
221 /// + Matching component is removed before the Predicate can match it
224 [ExpectedException(typeof(ArgumentOutOfRangeException
))]
225 [Ignore("This test needs to be reviewed")]
226 public void MultiThreaded_RemoveResolve_Throws_When_LargeRatio_Of_ComponentsToService()
228 int threadCount
= 1000;
229 ArrayList list
= ArrayList
.Synchronized(new ArrayList());
230 Random rand
= new Random();
231 ManualResetEvent waitEvent
= new ManualResetEvent(false);
233 IKernel kernel
= new DefaultKernel();
234 kernel
.AddSubSystem(SubSystemConstants
.NamingKey
, new KeySearchNamingSubSystem(delegate { return false; }
));
236 kernel
.AddComponent("common", typeof(ICommon
), typeof(CommonImpl1
));
238 WaitCallback resolveThread
= delegate
241 while(threadCount
> 0 && list
.Count
== 0)
245 ICommon common
= kernel
[typeof(ICommon
)] as ICommon
;
253 ThreadPool
.QueueUserWorkItem(resolveThread
);
255 WaitCallback removeThread
= delegate
258 kernel
.RemoveComponent(threadCount
+ ".common");
259 Interlocked
.Decrement(ref threadCount
);
261 for(int i
= 0; i
< threadCount
; i
++)
263 kernel
.AddComponent(i
+ ".common", typeof(ICommon
), typeof(CommonImpl1
));
264 ThreadPool
.QueueUserWorkItem(removeThread
);
268 while(threadCount
> 0 && list
.Count
== 0)
275 throw (Exception
) list
[0];