1 // Copyright 2004-2007 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
.DynamicProxy
.Tests
18 using System
.Reflection
;
19 using System
.Collections
;
20 using Castle
.Core
.Interceptor
;
21 using Castle
.DynamicProxy
.Generators
;
22 using Castle
.DynamicProxy
.Tests
.BugsReported
;
23 using Castle
.DynamicProxy
.Tests
.Classes
;
24 using Castle
.DynamicProxy
.Tests
.Interceptors
;
25 using Castle
.DynamicProxy
.Tests
.InterClasses
;
26 using NUnit
.Framework
;
27 using ClassWithIndexer
=Castle
.DynamicProxy
.Tests
.Classes
.ClassWithIndexer
;
28 using Castle
.DynamicProxy
.Generators
.Emitters
;
31 public class BasicClassProxyTestCase
: BasePEVerifyTestCase
34 public void ProxyForClass()
36 object proxy
= generator
.CreateClassProxy(typeof(ServiceClass
), new ResultModifierInterceptor());
38 Assert
.IsNotNull(proxy
);
39 Assert
.IsTrue(typeof(ServiceClass
).IsAssignableFrom(proxy
.GetType()));
41 ServiceClass instance
= (ServiceClass
) proxy
;
43 // return value is changed by the interceptor
44 Assert
.AreEqual(44, instance
.Sum(20, 25));
46 // return value is changed by the interceptor
47 Assert
.AreEqual(true, instance
.Valid
);
49 // The rest aren't changed
50 Assert
.AreEqual(45, instance
.Sum((byte) 20, (byte) 25)); // byte
51 Assert
.AreEqual(45, instance
.Sum(20L, 25L)); // long
52 Assert
.AreEqual(45, instance
.Sum((short) 20, (short) 25)); // short
53 Assert
.AreEqual(45, instance
.Sum(20f
, 25f
)); // float
54 Assert
.AreEqual(45, instance
.Sum(20.0, 25.0)); // double
55 Assert
.AreEqual(45, instance
.Sum((ushort) 20, (ushort) 25)); // ushort
56 Assert
.AreEqual(45, instance
.Sum((uint) 20, (uint) 25)); // uint
57 Assert
.AreEqual(45, instance
.Sum((ulong) 20, (ulong) 25)); // ulong
63 object proxy
= generator
.CreateClassProxy(
64 typeof(ServiceClass
), new StandardInterceptor());
65 proxy
= generator
.CreateClassProxy(
66 typeof(ServiceClass
), new StandardInterceptor());
67 proxy
= generator
.CreateClassProxy(
68 typeof(ServiceClass
), new StandardInterceptor());
69 proxy
= generator
.CreateClassProxy(
70 typeof(ServiceClass
), new StandardInterceptor());
75 [Test
, ExpectedException(typeof(GeneratorException
), "Type is not public, so a proxy " +
76 "cannot be generated. Type: System.AppDomainInitializerInfo")]
77 public void ProxyForNonPublicClass()
79 // have to use a type that is not from this assembly, because it is marked as internals visible to
82 object proxy
= generator
.CreateClassProxy(
83 Type
.GetType("System.AppDomainInitializerInfo, mscorlib"), new StandardInterceptor());
89 public void ProxyForClassWithIndexer()
91 LogInvocationInterceptor logger
= new LogInvocationInterceptor();
93 object proxy
= generator
.CreateClassProxy(typeof(ClassWithIndexer
), logger
);
95 Assert
.IsNotNull(proxy
);
96 Assert
.IsInstanceOfType(typeof(ClassWithIndexer
), proxy
);
98 ClassWithIndexer type
= (ClassWithIndexer
) proxy
;
101 Assert
.AreEqual(10, type
["name"]);
103 Assert
.AreEqual("set_Item get_Item ", logger
.LogContents
);
109 public void ClassWithDifferentAccessLevelOnProperties()
111 LogInvocationInterceptor logger
= new LogInvocationInterceptor();
113 object proxy
= generator
.CreateClassProxy(typeof(DiffAccessLevelOnProperties
), logger
);
115 Assert
.IsNotNull(proxy
);
116 Assert
.IsInstanceOfType(typeof(DiffAccessLevelOnProperties
), proxy
);
118 DiffAccessLevelOnProperties type
= (DiffAccessLevelOnProperties
) proxy
;
120 type
.SetProperties();
122 Assert
.AreEqual("10 11 12 13 name", type
.ToString());
128 public void ClassWithInheritance()
130 LogInvocationInterceptor logger
= new LogInvocationInterceptor();
132 object proxy
= generator
.CreateClassProxy(typeof(ExtendedServiceClass
), logger
);
134 Assert
.IsNotNull(proxy
);
136 ExtendedServiceClass extended
= (ExtendedServiceClass
) proxy
;
141 Assert
.AreEqual("Sum2 Sum ", logger
.LogContents
);
145 public void ProxyForNestedClass()
147 object proxy
= generator
.CreateClassProxy(typeof(ServiceClass
.InernalClass
), new Type
[] {typeof(IDisposable)}
);
148 Assert
.IsNotNull(proxy
);
149 Assert
.IsTrue(proxy
is ServiceClass
.InernalClass
);
153 public void ProxyForClassWithInterfaces()
155 object proxy
= generator
.CreateClassProxy(typeof(ServiceClass
), new Type
[] {typeof(IDisposable)}
,
156 new ResultModifierInterceptor());
158 Assert
.IsNotNull(proxy
);
159 Assert
.IsTrue(typeof(ServiceClass
).IsAssignableFrom(proxy
.GetType()));
160 Assert
.IsTrue(typeof(IDisposable
).IsAssignableFrom(proxy
.GetType()));
162 ServiceClass inter
= (ServiceClass
) proxy
;
164 Assert
.AreEqual(44, inter
.Sum(20, 25));
165 Assert
.AreEqual(true, inter
.Valid
);
169 IDisposable disp
= (IDisposable
) proxy
;
172 Assert
.Fail("Expected exception as Dispose has no implementation");
174 catch(NotImplementedException ex
)
176 Assert
.AreEqual("This is a DynamicProxy2 error: the interceptor attempted " +
177 "to 'Proceed' for a method without a target, for example, an interface method or an abstract method",
183 public void ProxyForCharReturnType()
185 LogInvocationInterceptor logger
= new LogInvocationInterceptor();
186 object proxy
= generator
.CreateClassProxy(typeof(ClassWithCharRetType
), logger
);
187 Assert
.IsNotNull(proxy
);
188 ClassWithCharRetType classProxy
= (ClassWithCharRetType
) proxy
;
189 Assert
.AreEqual('c', classProxy
.DoSomething());
193 public void ProxyForClassWithConstructors()
195 object proxy
= generator
.CreateClassProxy(
196 typeof(ClassWithConstructors
), new IInterceptor
[] {new StandardInterceptor()}
,
197 new object[] {"name"}
);
199 Assert
.IsNotNull(proxy
);
200 ClassWithConstructors classProxy
= (ClassWithConstructors
) proxy
;
201 Assert
.AreEqual("name", classProxy
.Name
);
203 proxy
= generator
.CreateClassProxy(
204 typeof(ClassWithConstructors
), new IInterceptor
[] {new StandardInterceptor()}
,
205 new object[] {"name", 10}
);
207 Assert
.IsNotNull(proxy
);
208 classProxy
= (ClassWithConstructors
) proxy
;
209 Assert
.AreEqual("name", classProxy
.Name
);
210 Assert
.AreEqual(10, classProxy
.X
);
214 /// See http://support.castleproject.org/browse/DYNPROXY-43
217 public void MethodParamNamesAreReplicated()
219 MyClass mc
= generator
.CreateClassProxy
<MyClass
>(new StandardInterceptor());
220 ParameterInfo
[] methodParams
= GetMyTestMethodParams(mc
.GetType());
221 Assert
.AreEqual("myParam", methodParams
[0].Name
);
225 public void ProducesInvocationsThatCantChangeTarget()
227 AssertCannotChangeTargetInterceptor invocationChecker
= new AssertCannotChangeTargetInterceptor();
228 object proxy
= generator
.CreateClassProxy(typeof(ClassWithCharRetType
), invocationChecker
);
229 Assert
.IsNotNull(proxy
);
230 ClassWithCharRetType classProxy
= (ClassWithCharRetType
) proxy
;
231 Assert
.AreEqual('c', classProxy
.DoSomething());
235 [Ignore("Multi dimensional arrays seems to not work at all")]
236 public void ProxyTypeWithMultiDimentionalArrayAsParameters()
238 LogInvocationInterceptor log
= new LogInvocationInterceptor();
240 ClassWithMultiDimentionalArray proxy
=
241 generator
.CreateClassProxy
<ClassWithMultiDimentionalArray
>(log
);
243 int[,] x
= new int[1,2];
245 proxy
.Do(new int[] {1}
);
247 proxy
.Do3(new string[] {"1", "2"}
);
249 Assert
.AreEqual("Do Do2 Do3 ", log
.LogContents
);
252 private ParameterInfo
[] GetMyTestMethodParams(Type type
)
254 MethodInfo methodInfo
= type
.GetMethod("MyTestMethod");
255 return methodInfo
.GetParameters();
259 public void ProxyForBaseTypeFromSignedAssembly ()
261 Type t
= typeof (Hashtable
);
262 Assert
.IsTrue (StrongNameUtil
.IsAssemblySigned (t
.Assembly
));
263 object proxy
= generator
.CreateClassProxy (t
, new StandardInterceptor ());
264 Assert
.IsTrue (StrongNameUtil
.IsAssemblySigned (proxy
.GetType ().Assembly
));
268 public void ProxyForBaseTypeAndInterfaceFromSignedAssembly ()
270 Type t1
= typeof (Hashtable
);
271 Type t2
= typeof (IServiceProvider
);
272 Assert
.IsTrue (StrongNameUtil
.IsAssemblySigned (t1
.Assembly
));
273 Assert
.IsTrue (StrongNameUtil
.IsAssemblySigned (t2
.Assembly
));
274 object proxy
= generator
.CreateClassProxy (t1
, new Type
[] {t2}
, new StandardInterceptor ());
275 Assert
.IsTrue (StrongNameUtil
.IsAssemblySigned (proxy
.GetType ().Assembly
));
279 [Ignore ("To get this running, the Tests project must not be signed.")]
280 public void ProxyForBaseTypeFromUnsignedAssembly ()
282 Type t
= typeof (MyClass
);
283 Assert
.IsFalse (StrongNameUtil
.IsAssemblySigned (t
.Assembly
));
284 object proxy
= generator
.CreateClassProxy (t
, new StandardInterceptor ());
285 Assert
.IsFalse (StrongNameUtil
.IsAssemblySigned (proxy
.GetType ().Assembly
));
289 [Ignore ("To get this running, the Tests project must not be signed.")]
290 public void ProxyForBaseTypeAndInterfaceFromUnsignedAssembly ()
292 Type t1
= typeof (MyClass
);
293 Type t2
= typeof (IService
);
294 Assert
.IsFalse (StrongNameUtil
.IsAssemblySigned (t1
.Assembly
));
295 Assert
.IsFalse (StrongNameUtil
.IsAssemblySigned (t2
.Assembly
));
296 object proxy
= generator
.CreateClassProxy (t1
, new Type
[] { t2 }
, new StandardInterceptor ());
297 Assert
.IsFalse (StrongNameUtil
.IsAssemblySigned (proxy
.GetType ().Assembly
));
301 [Ignore ("To get this running, the Tests project must not be signed.")]
302 public void ProxyForBaseTypeAndInterfaceFromSignedAndUnsignedAssemblies1 ()
304 Type t1
= typeof (MyClass
);
305 Type t2
= typeof (IServiceProvider
);
306 Assert
.IsFalse (StrongNameUtil
.IsAssemblySigned (t1
.Assembly
));
307 Assert
.IsTrue (StrongNameUtil
.IsAssemblySigned (t2
.Assembly
));
308 object proxy
= generator
.CreateClassProxy (t1
, new Type
[] { t2 }
, new StandardInterceptor ());
309 Assert
.IsFalse (StrongNameUtil
.IsAssemblySigned (proxy
.GetType ().Assembly
));
313 [Ignore ("To get this running, the Tests project must not be signed.")]
314 public void ProxyForBaseTypeAndInterfaceFromSignedAndUnsignedAssemblies2 ()
316 Type t1
= typeof (Hashtable
);
317 Type t2
= typeof (IService
);
318 Assert
.IsTrue (StrongNameUtil
.IsAssemblySigned (t1
.Assembly
));
319 Assert
.IsFalse (StrongNameUtil
.IsAssemblySigned (t2
.Assembly
));
320 object proxy
= generator
.CreateClassProxy (t1
, new Type
[] { t2 }
, new StandardInterceptor ());
321 Assert
.IsFalse (StrongNameUtil
.IsAssemblySigned (proxy
.GetType ().Assembly
));