// Copyright 2004-2008 Castle Project - http://www.castleproject.org/ // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. namespace Castle.DynamicProxy.Tests { using System; using System.Collections; using System.Reflection; using Castle.DynamicProxy.Generators; using Castle.DynamicProxy.Tests.GenInterfaces; using Castle.DynamicProxy.Tests.Interceptors; using NUnit.Framework; [TestFixture] public class GenericInterfaceProxyTestCase : BasePEVerifyTestCase { private LogInvocationInterceptor logger; public override void Init() { base.Init(); logger = new LogInvocationInterceptor(); } [Test] public void ProxyWithGenericArgument() { GenInterface proxy = generator.CreateInterfaceProxyWithTarget>( new GenInterfaceImpl(), logger); Assert.IsNotNull(proxy); Assert.AreEqual(1, proxy.DoSomething(1)); Assert.AreEqual("DoSomething ", logger.LogContents); } #if !MONO [Test] public void ProxyWithGenericArgumentAndGenericMethod() { GenInterfaceWithGenMethods proxy = generator.CreateInterfaceProxyWithTarget>( new GenInterfaceWithGenMethodsImpl(), logger); Assert.IsNotNull(proxy); proxy.DoSomething(10L, 1); Assert.AreEqual("DoSomething ", logger.LogContents); } [Test] public void ProxyWithGenericArgumentAndGenericMethodAndGenericReturn() { GenInterfaceWithGenMethodsAndGenReturn proxy = generator.CreateInterfaceProxyWithTarget>( new GenInterfaceWithGenMethodsAndGenReturnImpl(), logger); Assert.IsNotNull(proxy); Assert.AreEqual(10L, proxy.DoSomething(10L, 1)); Assert.AreEqual("DoSomething ", logger.LogContents); } [Test] public void ProxyWithGenInterfaceWithGenericArrays() { IGenInterfaceWithGenArray proxy = generator.CreateInterfaceProxyWithTarget>( new GenInterfaceWithGenArray(), logger); Assert.IsNotNull(proxy); int[] items = new int[] {1, 2, 3}; proxy.CopyTo(items); items = proxy.CreateItems(); Assert.IsNotNull(items); Assert.AreEqual(3, items.Length); Assert.AreEqual("CopyTo CreateItems ", logger.LogContents); } [Test] public void ProxyWithGenInterfaceWithBase() { IGenInterfaceHierarchySpecialization proxy = generator.CreateInterfaceProxyWithTarget>( new GenInterfaceHierarchy(), logger); Assert.IsNotNull(proxy); proxy.Add(); proxy.Add(1); Assert.IsNotNull(proxy.FetchAll()); Assert.AreEqual("Add Add FetchAll ", logger.LogContents); } [Test] [ExpectedException(typeof (GeneratorException), ExpectedMessage = "DynamicProxy cannot create an interface (with target) proxy for 'InterfaceWithExplicitImpl`1' as the target 'GenExplicitImplementation`1' has an explicit implementation of one of the methods exposed by the interface. The runtime prevents use from invoking the private method on the target. Method Castle.DynamicProxy.Tests.GenInterfaces.InterfaceWithExplicitImpl.GetEnum1" )] public void ProxyWithGenExplicitImplementation() { DisableVerification(); generator.CreateInterfaceProxyWithTarget>( new GenExplicitImplementation(), logger); } [Test] public void TwoGenericsInterfaceWithoutTarget() { generator.CreateInterfaceProxyWithoutTarget(typeof (GenInterface), new Type[] {typeof (InterfaceWithExplicitImpl)}, new LogInvocationInterceptor()); } [Test] public void NonGenInterfaceWithParentGenClassImplementingGenInterface() { generator.CreateInterfaceProxyWithoutTarget(typeof (IUserRepository), new Type[] {typeof (InterfaceWithExplicitImpl)}, new LogInvocationInterceptor()); } [Test] public void WithoutTarget() { generator.CreateInterfaceProxyWithoutTarget(typeof (InterfaceWithExplicitImpl), new LogInvocationInterceptor()); } [Test] public void MethodInfoClosedInGenIfcGenMethodRefTypeNoTarget() { KeepDataInterceptor interceptor = new KeepDataInterceptor(); GenInterfaceWithGenMethods proxy = generator.CreateInterfaceProxyWithoutTarget>(interceptor); proxy.DoSomething(1, null); GenericTestUtility.CheckMethodInfoIsClosed(interceptor.Invocation.GetConcreteMethod(), typeof (void), typeof (int), typeof (ArrayList)); Assert.AreEqual(interceptor.Invocation.GetConcreteMethod(), interceptor.Invocation.GetConcreteMethodInvocationTarget()); proxy.DoSomething(new Hashtable(), new ArrayList()); GenericTestUtility.CheckMethodInfoIsClosed(interceptor.Invocation.GetConcreteMethod(), typeof (void), typeof (Hashtable), typeof (ArrayList)); Assert.AreEqual(interceptor.Invocation.GetConcreteMethod(), interceptor.Invocation.GetConcreteMethodInvocationTarget()); } [Test] public void MethodInfoClosedInGenIfcGenMethodValueTypeNoTarget() { KeepDataInterceptor interceptor = new KeepDataInterceptor(); GenInterfaceWithGenMethods proxy = generator.CreateInterfaceProxyWithoutTarget>(interceptor); proxy.DoSomething(1, 1); GenericTestUtility.CheckMethodInfoIsClosed(interceptor.Invocation.GetConcreteMethod(), typeof (void), typeof (int), typeof (int)); Assert.AreEqual(interceptor.Invocation.GetConcreteMethod(), interceptor.Invocation.GetConcreteMethodInvocationTarget()); proxy.DoSomething(new Hashtable(), 1); GenericTestUtility.CheckMethodInfoIsClosed(interceptor.Invocation.GetConcreteMethod(), typeof (void), typeof (Hashtable), typeof (int)); Assert.AreEqual(interceptor.Invocation.GetConcreteMethod(), interceptor.Invocation.GetConcreteMethodInvocationTarget()); } [Test] public void MethodInfoClosedInGenIfcNongenMethodRefTypeNoTarget() { KeepDataInterceptor interceptor = new KeepDataInterceptor(); IGenInterfaceHierarchyBase proxy = generator.CreateInterfaceProxyWithoutTarget>(interceptor); proxy.Get(); GenericTestUtility.CheckMethodInfoIsClosed(interceptor.Invocation.GetConcreteMethod(), typeof (ArrayList)); Assert.AreEqual(interceptor.Invocation.GetConcreteMethod(), interceptor.Invocation.GetConcreteMethodInvocationTarget()); proxy.Add(null); GenericTestUtility.CheckMethodInfoIsClosed(interceptor.Invocation.GetConcreteMethod(), typeof (void), typeof (ArrayList)); Assert.AreEqual(interceptor.Invocation.GetConcreteMethod(), interceptor.Invocation.GetConcreteMethodInvocationTarget()); } [Test] public void MethodInfoClosedInGenIfcNongenMethodValueTypeNoTarget() { KeepDataInterceptor interceptor = new KeepDataInterceptor(); IGenInterfaceHierarchyBase proxy = generator.CreateInterfaceProxyWithoutTarget>(interceptor); proxy.Get(); GenericTestUtility.CheckMethodInfoIsClosed(interceptor.Invocation.GetConcreteMethod(), typeof (int)); Assert.AreEqual(interceptor.Invocation.GetConcreteMethod(), interceptor.Invocation.GetConcreteMethodInvocationTarget()); proxy.Add(0); GenericTestUtility.CheckMethodInfoIsClosed(interceptor.Invocation.GetConcreteMethod(), typeof (void), typeof (int)); Assert.AreEqual(interceptor.Invocation.GetConcreteMethod(), interceptor.Invocation.GetConcreteMethodInvocationTarget()); } [Test] public void MethodInfoClosedInNongenIfcGenMethodNoTarget() { KeepDataInterceptor interceptor = new KeepDataInterceptor(); OnlyGenMethodsInterface proxy = generator.CreateInterfaceProxyWithoutTarget(interceptor); proxy.DoSomething(1); GenericTestUtility.CheckMethodInfoIsClosed(interceptor.Invocation.GetConcreteMethod(), typeof (int), typeof (int)); Assert.AreEqual(interceptor.Invocation.GetConcreteMethod(), interceptor.Invocation.GetConcreteMethodInvocationTarget()); proxy.DoSomething(new Hashtable()); GenericTestUtility.CheckMethodInfoIsClosed(interceptor.Invocation.GetConcreteMethod(), typeof (Hashtable), typeof (Hashtable)); Assert.AreEqual(interceptor.Invocation.GetConcreteMethod(), interceptor.Invocation.GetConcreteMethodInvocationTarget()); } [Test] public void MethodInfoClosedInGenIfcGenMethodRefTypeWithTarget() { KeepDataInterceptor interceptor = new KeepDataInterceptor(); GenInterfaceWithGenMethods target = new GenInterfaceWithGenMethodsImpl(); GenInterfaceWithGenMethods proxy = generator.CreateInterfaceProxyWithTarget>(target, interceptor); proxy.DoSomething(1, null); GenericTestUtility.CheckMethodInfoIsClosed(interceptor.Invocation.GetConcreteMethod(), typeof (void), typeof (int), typeof (ArrayList)); GenericTestUtility.CheckMethodInfoIsClosed(interceptor.Invocation.GetConcreteMethodInvocationTarget(), typeof (void), typeof (int), typeof (ArrayList)); Assert.AreNotEqual(interceptor.Invocation.GetConcreteMethod(), interceptor.Invocation.GetConcreteMethodInvocationTarget()); proxy.DoSomething(new Hashtable(), new ArrayList()); GenericTestUtility.CheckMethodInfoIsClosed(interceptor.Invocation.GetConcreteMethod(), typeof (void), typeof (Hashtable), typeof (ArrayList)); GenericTestUtility.CheckMethodInfoIsClosed(interceptor.Invocation.GetConcreteMethodInvocationTarget(), typeof (void), typeof (Hashtable), typeof (ArrayList)); Assert.AreNotEqual(interceptor.Invocation.GetConcreteMethod(), interceptor.Invocation.GetConcreteMethodInvocationTarget()); } [Test] public void MethodInfoClosedInGenIfcGenMethodValueTypeWithTarget() { KeepDataInterceptor interceptor = new KeepDataInterceptor(); GenInterfaceWithGenMethods target = new GenInterfaceWithGenMethodsImpl(); GenInterfaceWithGenMethods proxy = generator.CreateInterfaceProxyWithTarget>(target, interceptor); proxy.DoSomething(1, 1); GenericTestUtility.CheckMethodInfoIsClosed(interceptor.Invocation.GetConcreteMethod(), typeof (void), typeof (int), typeof (int)); GenericTestUtility.CheckMethodInfoIsClosed(interceptor.Invocation.GetConcreteMethodInvocationTarget(), typeof (void), typeof (int), typeof (int)); Assert.AreNotEqual(interceptor.Invocation.GetConcreteMethod(), interceptor.Invocation.GetConcreteMethodInvocationTarget()); proxy.DoSomething(new Hashtable(), 1); GenericTestUtility.CheckMethodInfoIsClosed(interceptor.Invocation.GetConcreteMethod(), typeof (void), typeof (Hashtable), typeof (int)); GenericTestUtility.CheckMethodInfoIsClosed(interceptor.Invocation.GetConcreteMethodInvocationTarget(), typeof (void), typeof (Hashtable), typeof (int)); Assert.AreNotEqual(interceptor.Invocation.GetConcreteMethod(), interceptor.Invocation.GetConcreteMethodInvocationTarget()); } [Test] public void MethodInfoClosedInGenIfcNongenMethodRefTypeWithTarget() { KeepDataInterceptor interceptor = new KeepDataInterceptor(); IGenInterfaceHierarchyBase target = new GenInterfaceHierarchy(); IGenInterfaceHierarchyBase proxy = generator.CreateInterfaceProxyWithTarget>(target, interceptor); proxy.Add(null); GenericTestUtility.CheckMethodInfoIsClosed(interceptor.Invocation.GetConcreteMethod(), typeof (void), typeof (ArrayList)); GenericTestUtility.CheckMethodInfoIsClosed(interceptor.Invocation.GetConcreteMethodInvocationTarget(), typeof (void), typeof (ArrayList)); Assert.AreNotEqual(interceptor.Invocation.GetConcreteMethod(), interceptor.Invocation.GetConcreteMethodInvocationTarget()); proxy.Get(); GenericTestUtility.CheckMethodInfoIsClosed(interceptor.Invocation.GetConcreteMethod(), typeof (ArrayList)); GenericTestUtility.CheckMethodInfoIsClosed(interceptor.Invocation.GetConcreteMethodInvocationTarget(), typeof (ArrayList)); Assert.AreNotEqual(interceptor.Invocation.GetConcreteMethod(), interceptor.Invocation.GetConcreteMethodInvocationTarget()); } [Test] public void MethodInfoClosedInGenIfcNongenMethodValueTypeWithTarget() { KeepDataInterceptor interceptor = new KeepDataInterceptor(); IGenInterfaceHierarchyBase target = new GenInterfaceHierarchy(); IGenInterfaceHierarchyBase proxy = generator.CreateInterfaceProxyWithTarget>(target, interceptor); proxy.Add(0); GenericTestUtility.CheckMethodInfoIsClosed(interceptor.Invocation.GetConcreteMethod(), typeof (void), typeof (int)); GenericTestUtility.CheckMethodInfoIsClosed(interceptor.Invocation.GetConcreteMethodInvocationTarget(), typeof (void), typeof (int)); Assert.AreNotEqual(interceptor.Invocation.GetConcreteMethod(), interceptor.Invocation.GetConcreteMethodInvocationTarget()); proxy.Get(); GenericTestUtility.CheckMethodInfoIsClosed(interceptor.Invocation.GetConcreteMethod(), typeof (int)); GenericTestUtility.CheckMethodInfoIsClosed(interceptor.Invocation.GetConcreteMethodInvocationTarget(), typeof (int)); Assert.AreNotEqual(interceptor.Invocation.GetConcreteMethod(), interceptor.Invocation.GetConcreteMethodInvocationTarget()); } [Test] public void MethodInfoClosedInNongenIfcGenMethodWithTarget() { KeepDataInterceptor interceptor = new KeepDataInterceptor(); OnlyGenMethodsInterface target = new OnlyGenMethodsInterfaceImpl(); OnlyGenMethodsInterface proxy = generator.CreateInterfaceProxyWithTarget(target, interceptor); proxy.DoSomething(1); GenericTestUtility.CheckMethodInfoIsClosed(interceptor.Invocation.GetConcreteMethod(), typeof (int), typeof (int)); GenericTestUtility.CheckMethodInfoIsClosed(interceptor.Invocation.GetConcreteMethodInvocationTarget(), typeof (int), typeof (int)); Assert.AreNotEqual(interceptor.Invocation.GetConcreteMethod(), interceptor.Invocation.GetConcreteMethodInvocationTarget()); proxy.DoSomething(new Hashtable()); GenericTestUtility.CheckMethodInfoIsClosed(interceptor.Invocation.GetConcreteMethod(), typeof (Hashtable), typeof (Hashtable)); GenericTestUtility.CheckMethodInfoIsClosed(interceptor.Invocation.GetConcreteMethodInvocationTarget(), typeof (Hashtable), typeof (Hashtable)); Assert.AreNotEqual(interceptor.Invocation.GetConcreteMethod(), interceptor.Invocation.GetConcreteMethodInvocationTarget()); } [Test] [ExpectedException(typeof (ArgumentException))] public void ThrowsWhenProxyingGenericTypeDefNoTarget() { KeepDataInterceptor interceptor = new KeepDataInterceptor(); object o = generator.CreateInterfaceProxyWithoutTarget(typeof (IGenInterfaceHierarchyBase<>), interceptor); } [Test(Description = "There is a strange CLR bug resulting from our loading the tokens of methods in generic types. " + "This test ensures we do not trigger it.")] [Ignore("Currently, we trigger the bug, and work around it - see MethodFinder")] public void TypeGetMethodsIsStable() { ProxyWithGenInterfaceWithBase(); Assert.AreEqual(4, typeof (IGenInterfaceHierarchyBase).GetMethods().Length); } [Test(Description = "There is a strange CLR bug resulting from our loading the tokens of methods in generic types. " + "This test ensures we correctly work around it.")] public void MethodFinderIsStable() { ProxyWithGenInterfaceWithBase(); Assert.AreEqual(4, MethodFinder.GetAllInstanceMethods(typeof (IGenInterfaceHierarchyBase), BindingFlags.Public | BindingFlags.Instance).Length); } [Test(Description = "There is a strange CLR bug resulting from our loading the tokens of methods in generic types. " + "This test ensures we do not trigger it across AppDomains. If we do, MethodFinder must provide a cross-AppDomain workaround." )] public void TypeGetMethodsIsStableInDifferentAppDomains() { ProxyWithGenInterfaceWithBase(); AppDomain newDomain = AppDomain.CreateDomain("NewDomain", AppDomain.CurrentDomain.Evidence, AppDomain.CurrentDomain.SetupInformation); try { newDomain.DoCallBack(delegate { Assert.AreEqual(4, typeof (IGenInterfaceHierarchyBase).GetMethods().Length); }); } finally { AppDomain.Unload(newDomain); } } #endif } }