/src/UnitTests/AOP/MethodBodyInterceptionTests.cs

http://github.com/philiplaureano/LinFu · C# · 288 lines · 224 code · 64 blank · 0 comment · 6 complexity · 0e00c8205b43eb0eb6de5d16cca4f670 MD5 · raw file

  1. using System;
  2. using System.Linq;
  3. using LinFu.AOP.Cecil.Extensions;
  4. using LinFu.AOP.Interfaces;
  5. using LinFu.IoC.Reflection;
  6. using LinFu.Reflection.Emit;
  7. using Mono.Cecil;
  8. using Xunit;
  9. using SampleLibrary.AOP;
  10. namespace LinFu.UnitTests.AOP
  11. {
  12. public class MethodBodyInterceptionTests
  13. {
  14. private void Test(Action<object> testInstance)
  15. {
  16. var libraryFileName = "SampleLibrary.dll";
  17. var typeName = "SampleClassWithNonVirtualMethod";
  18. Func<MethodReference, bool> methodFilter = m => m.Name == "DoSomething";
  19. Test(libraryFileName, typeName, methodFilter, type => Test(type, testInstance));
  20. }
  21. private void Test(string libraryFileName, string typeName, Func<MethodReference, bool> methodFilter,
  22. Action<Type> testTargetType)
  23. {
  24. var assembly = AssemblyDefinition.ReadAssembly(libraryFileName);
  25. var module = assembly.MainModule;
  26. var targetType = (from TypeDefinition t in module.Types
  27. where t.Name == typeName
  28. select t).First();
  29. Assert.NotNull(targetType);
  30. ModifyType(targetType, methodFilter);
  31. var modifiedTargetType = CreateModifiedType(assembly, typeName);
  32. testTargetType(modifiedTargetType);
  33. }
  34. private void Test(Type modifiedTargetType, Action<object> testInstance)
  35. {
  36. var instance = Activator.CreateInstance(modifiedTargetType);
  37. testInstance(instance);
  38. }
  39. private Type CreateModifiedType(AssemblyDefinition assembly, string typeName)
  40. {
  41. var modifiedAssembly = assembly.ToAssembly();
  42. return (from t in modifiedAssembly.GetTypes()
  43. where t.Name == typeName
  44. select t).First();
  45. }
  46. private void ModifyType(TypeDefinition targetType, Func<MethodReference, bool> methodFilter)
  47. {
  48. targetType.InterceptMethodBody(methodFilter);
  49. }
  50. [Fact]
  51. public void ShouldImplementIModifiableTypeOnModifiedSampleClass()
  52. {
  53. Action<object> condition = instance =>
  54. {
  55. Assert.NotNull(instance);
  56. Assert.True(instance is IModifiableType);
  57. };
  58. Test(condition);
  59. }
  60. [Fact]
  61. public void ShouldInterceptStaticMethodWithAroundInvokeProvider()
  62. {
  63. Func<MethodReference, bool> methodFilter = m => m.Name == "DoSomething";
  64. var aroundInvoke = new SampleAroundInvoke();
  65. var provider = new SampleAroundInvokeProvider(aroundInvoke);
  66. AroundMethodBodyRegistry.AddProvider(provider);
  67. Action<Type> doTest = type =>
  68. {
  69. var doSomethingMethod = type.GetMethod("DoSomething");
  70. Assert.NotNull(doSomethingMethod);
  71. doSomethingMethod.Invoke(null, new object[0]);
  72. Assert.True(aroundInvoke.BeforeInvokeWasCalled);
  73. Assert.True(aroundInvoke.AfterInvokeWasCalled);
  74. };
  75. Test("SampleLibrary.dll", "SampleStaticClassWithStaticMethod", methodFilter, doTest);
  76. }
  77. [Fact]
  78. public void ShouldInvokeAroundInvokeProviderIfInterceptionIsEnabled()
  79. {
  80. var aroundInvoke = new SampleAroundInvoke();
  81. var provider = new SampleAroundInvokeProvider(aroundInvoke);
  82. Action<object> condition = instance =>
  83. {
  84. Assert.NotNull(instance);
  85. var modifiedInstance = (IModifiableType) instance;
  86. modifiedInstance.AroundMethodBodyProvider = provider;
  87. instance.Invoke("DoSomething");
  88. Assert.True(aroundInvoke.BeforeInvokeWasCalled);
  89. Assert.True(aroundInvoke.AfterInvokeWasCalled);
  90. };
  91. Test(condition);
  92. }
  93. [Fact]
  94. public void ShouldInvokeClassAroundInvokeProviderIfInterceptionIsEnabled()
  95. {
  96. var aroundInvoke = new SampleAroundInvoke();
  97. var provider = new SampleAroundInvokeProvider(aroundInvoke);
  98. Action<object> condition = instance =>
  99. {
  100. Assert.NotNull(instance);
  101. AroundMethodBodyRegistry.AddProvider(provider);
  102. instance.Invoke("DoSomething");
  103. Assert.True(aroundInvoke.BeforeInvokeWasCalled);
  104. Assert.True(aroundInvoke.AfterInvokeWasCalled);
  105. };
  106. Test(condition);
  107. }
  108. [Fact]
  109. public void ShouldInvokeClassMethodReplacementProviderIfInterceptionIsEnabled()
  110. {
  111. Func<MethodReference, bool> methodFilter = m => m.Name == "DoSomething";
  112. var replacement = new SampleMethodReplacement();
  113. var provider = new SampleMethodReplacementProvider(replacement);
  114. MethodBodyReplacementProviderRegistry.SetProvider(provider);
  115. Action<Type> doTest = type =>
  116. {
  117. var doSomethingMethod = type.GetMethod("DoSomething");
  118. Assert.NotNull(doSomethingMethod);
  119. doSomethingMethod.Invoke(null, new object[0]);
  120. };
  121. Test("SampleLibrary.dll", "SampleStaticClassWithStaticMethod", methodFilter, doTest);
  122. Assert.True(replacement.HasBeenCalled);
  123. }
  124. [Fact]
  125. public void ShouldInvokeMethodBodyReplacementIfInterceptionIsEnabled()
  126. {
  127. var sampleInterceptor = new SampleInterceptor();
  128. var sampleProvider = new SampleMethodReplacementProvider(sampleInterceptor);
  129. Action<object> condition = instance =>
  130. {
  131. Assert.NotNull(instance);
  132. Assert.True(instance is IModifiableType);
  133. var modifiableType = (IModifiableType) instance;
  134. modifiableType.MethodBodyReplacementProvider = sampleProvider;
  135. modifiableType.IsInterceptionDisabled = false;
  136. instance.Invoke("DoSomething");
  137. };
  138. Test(condition);
  139. Assert.True(sampleInterceptor.HasBeenInvoked);
  140. }
  141. [Fact]
  142. public void ShouldNotImplementIModifiableTypeOnStaticClasses()
  143. {
  144. Func<MethodReference, bool> methodFilter = m => m.Name == "DoSomething";
  145. var aroundInvoke = new SampleAroundInvoke();
  146. var provider = new SampleAroundInvokeProvider(aroundInvoke);
  147. AroundMethodBodyRegistry.AddProvider(provider);
  148. Action<Type> doTest = type =>
  149. {
  150. var doSomethingMethod = type.GetMethod("DoSomething");
  151. Assert.NotNull(doSomethingMethod);
  152. Assert.DoesNotContain(typeof(IModifiableType), type.GetInterfaces());
  153. };
  154. Test("SampleLibrary.dll", "SampleStaticClassWithStaticMethod", methodFilter, doTest);
  155. }
  156. [Fact]
  157. public void ShouldNotInvokeAroundInvokeProviderIfInterceptionIsDisabled()
  158. {
  159. var aroundInvoke = new SampleAroundInvoke();
  160. var provider = new SampleAroundInvokeProvider(aroundInvoke);
  161. Action<object> condition = instance =>
  162. {
  163. Assert.NotNull(instance);
  164. var modifiedInstance = (IModifiableType) instance;
  165. modifiedInstance.AroundMethodBodyProvider = provider;
  166. modifiedInstance.IsInterceptionDisabled = true;
  167. instance.Invoke("DoSomething");
  168. Assert.False(aroundInvoke.BeforeInvokeWasCalled);
  169. Assert.False(aroundInvoke.AfterInvokeWasCalled);
  170. };
  171. Test(condition);
  172. }
  173. [Fact]
  174. public void ShouldNotInvokeClassAroundInvokeProviderIfInterceptionIsDisabled()
  175. {
  176. var aroundInvoke = new SampleAroundInvoke();
  177. var provider = new SampleAroundInvokeProvider(aroundInvoke);
  178. Action<object> condition = instance =>
  179. {
  180. Assert.NotNull(instance);
  181. var modified = (IModifiableType) instance;
  182. modified.IsInterceptionDisabled = true;
  183. AroundMethodBodyRegistry.AddProvider(provider);
  184. instance.Invoke("DoSomething");
  185. Assert.False(aroundInvoke.BeforeInvokeWasCalled);
  186. Assert.False(aroundInvoke.AfterInvokeWasCalled);
  187. };
  188. Test(condition);
  189. }
  190. [Fact]
  191. public void ShouldNotInvokeClassMethodReplacementProviderIfInterceptionIsDisabled()
  192. {
  193. var sampleInterceptor = new SampleInterceptor();
  194. var sampleProvider = new SampleMethodReplacementProvider(sampleInterceptor);
  195. MethodBodyReplacementProviderRegistry.SetProvider(sampleProvider);
  196. Action<object> condition = instance =>
  197. {
  198. Assert.NotNull(instance);
  199. var modified = (IModifiableType) instance;
  200. modified.IsInterceptionDisabled = true;
  201. instance.Invoke("DoSomething");
  202. Assert.False(sampleInterceptor.HasBeenInvoked);
  203. };
  204. Test(condition);
  205. }
  206. [Fact]
  207. public void ShouldNotInvokeMethodBodyReplacementIfInterceptionIsDisabled()
  208. {
  209. var sampleInterceptor = new SampleInterceptor();
  210. var sampleProvider = new SampleMethodReplacementProvider(sampleInterceptor);
  211. Action<object> condition = instance =>
  212. {
  213. Assert.NotNull(instance);
  214. Assert.True(instance is IModifiableType);
  215. var modifiableType = (IModifiableType) instance;
  216. modifiableType.MethodBodyReplacementProvider = sampleProvider;
  217. modifiableType.IsInterceptionDisabled = true;
  218. instance.Invoke("DoSomething");
  219. };
  220. Test(condition);
  221. Assert.False(sampleInterceptor.HasBeenInvoked);
  222. }
  223. }
  224. }