internal static PropertyInfo ResolveProperty(Type type, string name, bool ignoreCase, object[] indexArgs, bool hasInstance, object setterValue = null, bool getter = true) { var candidates = type.GetAllProperties().Where(prop => MockingUtil.StringEqual(prop.Name, name, ignoreCase)).ToArray(); if (candidates.Length == 1) { return(candidates[0]); } if (!getter) { Array.Resize(ref indexArgs, indexArgs.Length + 1); indexArgs[indexArgs.Length - 1] = setterValue; } var propMethods = candidates .Select(prop => getter ? prop.GetGetMethod(true) : prop.GetSetMethod(true)) .Where(m => m != null && CanCall(m, hasInstance)) .ToArray(); indexArgs = indexArgs ?? MockingUtil.NoObjects; object state; var foundGetter = MockingUtil.BindToMethod(MockingUtil.AllMembers, propMethods, ref indexArgs, null, null, null, out state); return(candidates.First(prop => (getter ? prop.GetGetMethod(true) : prop.GetSetMethod(true)) == foundGetter)); }
public static ProfilerInterceptor.RefReturn <TReturn> CreateDynamicMethodInvoker <TReturn>(object target, MethodInfo method, object[] args) { if (args.Length != method.GetParameters().Length) { throw new MockException( String.Format("Number of the supplied arguments does not match to the expected one in the method signature:" + " supplied '{0}', expected '{1}'", args.Length, method.GetParameters().Length)); } ProfilerInterceptor.RefReturn <TReturn> @delegate = MockingUtil.CreateDynamicMethod <ProfilerInterceptor.RefReturn <TReturn> >( il => { // store arguments as local variables il.UnpackArgArray(OpCodes.Ldarg_1, method); // push object reference to the stack in case if instance method if (target != null) { il.Emit(OpCodes.Ldarg_0); } // push stored arguments back to the stack il.PushArgArray(method); il.Emit((target != null) ? OpCodes.Callvirt : OpCodes.Call, method as MethodInfo); il.Emit(OpCodes.Ret); }); return(@delegate); }
private static object InterceptNewobj(RuntimeTypeHandle typeHandle, RuntimeMethodHandle methodHandle, object[] data) { if (!IsInterceptionEnabled || isFinalizerThread) { return(null); } try { ReentrancyCounter++; var method = MethodBase.GetMethodFromHandle(methodHandle, typeHandle); var invocation = new Invocation(MockingUtil.TryGetUninitializedObject(method.DeclaringType), method, data ?? new object[0]); if (DispatchInvocation(invocation)) { if (invocation.CallOriginal) { SkipMethodInterceptionOnce(method); return(null); } if (invocation.IsReturnValueSet && invocation.ReturnValue != null) { return(invocation.ReturnValue); } return(invocation.Instance); } return(null); } finally { ReentrancyCounter--; } }
public static MethodInfo GetMethodWithLocalFunction(Type type, string methodName, Type[] methodParamTypes, Type[] methodGenericTypes) { #if !PORTABLE if (type.IsProxy()) { type = type.BaseType; } MethodInfo method = type.GetMethod(methodName, MockingUtil.AllMembers, null, methodParamTypes, null); if (method == null) { throw new MissingMemberException(MockingUtil.BuildMissingMethodMessage(type, null, methodName)); } if (method.ContainsGenericParameters && (!GenericTypesMatch(methodGenericTypes, method))) { throw new MissingMemberException(MockingUtil.BuildGenericMethodNonMatchingTypesMessage(type, method, methodGenericTypes)); } if (method.ContainsGenericParameters) { method = method.MakeGenericMethod(methodGenericTypes); } return(method); #else return(null); #endif }
public static object GetDefaultValue(this Type t) { Debug.Assert(t != typeof(void)); return (t.IsPointer ? IntPtr.Zero : t.IsValueType && t != typeof(void) ? MockingUtil.CreateInstance(t) : null); }
internal string InputToString() { var sb = new StringBuilder(); sb.AppendFormat("{0}.{1}(", Instance != null ? MockingUtil.GetUnproxiedType(Instance) : method.DeclaringType, method.Name); sb.Append(", ".Join(Args)); sb.Append(")"); return(sb.ToString()); }
private static Expression CreateFieldAssignmentExpression(FieldInfo assignee, ParameterExpression valueParam) { var fieldType = assignee.FieldType; var action = MockingUtil.CreateDynamicMethodWithVisibilityChecks(typeof(void), new[] { fieldType }, il => { il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Stsfld, assignee); il.Emit(OpCodes.Ret); }); return(Expression.Call(null, action, valueParam)); }
public ref TRefReturn GetProperty <TRefReturn>(string name) { return(ref ProfilerInterceptor.GuardInternal((target, arguments) => { var prop = MockingUtil.ResolveProperty(this.type, name, false, null, this.instance != null); var method = prop.GetGetMethod(true); ProfilerInterceptor.RefReturn <TRefReturn> @delegate = MockingUtil.CreateDynamicMethodInvoker <TRefReturn>(target, method, arguments); return ref ProfilerInterceptor.GuardExternal(@delegate, target, arguments); }, this.instance, MockingUtil.NoObjects)); }
public static MethodInfo GetMethodWithLocalFunction(Type type, string methodName, Type[] methodParamTypes) { #if !PORTABLE if (type.IsProxy()) { type = type.BaseType; } MethodInfo method = type.GetMethod(methodName, MockingUtil.AllMembers, null, methodParamTypes, null); if (method == null) { throw new MissingMemberException(MockingUtil.BuildMissingMethodMessage(type, null, methodName)); } return(method); #else return(null); #endif }
public ref TRefReturn CallMethod <TRefReturn>(string name, params object[] args) { return(ref ProfilerInterceptor.GuardInternal((target, arguments) => { arguments = arguments ?? MockingUtil.NoObjects; var candidates = type.GetAllMethods() .Where(m => m.Name == name && MockingUtil.CanCall(m, this.instance != null)) .Select(m => MockingUtil.TrySpecializeGenericMethod(m, arguments.Select(a => a != null ? a.GetType() : null).ToArray()) ?? m) .ToArray(); object state; var method = MockingUtil.BindToMethod(MockingUtil.AllMembers, candidates, ref arguments, null, null, null, out state); ProfilerInterceptor.RefReturn <TRefReturn> @delegate = MockingUtil.CreateDynamicMethodInvoker <TRefReturn>(target, method as MethodInfo, arguments); return ref ProfilerInterceptor.GuardExternal(@delegate, target, arguments); }, this.instance, args ?? MockingUtil.NoObjects)); }
public static MethodInfo GetRealMethodInfoFromGeneric(MethodInfo method, object[] args) { try { var generics = new Dictionary <Type, Type>(); var parameters = method.GetParameters(); var parsedArgs = MockingUtil.GetTypesFromArguments(args); for (int i = 0; i < args.Length; i++) { MockingUtil.GetGenericsTypesFromActualType(parameters[i].ParameterType, parsedArgs[i], generics); } var genericArgs = method.GetGenericArguments().Select(x => generics[x]).ToArray(); return(method.MakeGenericMethod(genericArgs)); } catch { return(null); } }
public static void RaiseEventThruReflection(object instance, EventInfo evt, object[] args) { MethodInfo raise; if ((raise = evt.GetRaiseMethod(true)) != null) { if (!raise.IsStatic && instance == null) { throw new MockException("Unable to deduce the instance on which to raise the event"); } //TODO: don't call reflection methods in GuardExternal when the profiler is working ProfilerInterceptor.GuardExternal(() => SecuredReflectionMethods.Invoke(raise, instance, args)); } else { BindingFlags all = BindingFlags.Static | BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public; var field = evt.DeclaringType.GetField(evt.Name, all) // C# event ?? evt.DeclaringType.GetField(evt.Name + "Event", all); //VB event if (field != null && field.FieldType == evt.EventHandlerType) { if (!field.IsStatic && instance == null) { throw new MockException("Unable to deduce the instance on which to raise the event"); } var handler = (Delegate)SecuredReflectionMethods.GetField(field, instance); if (ProfilerInterceptor.IsProfilerAttached) { var invoker = MockingUtil.MakeFuncCaller(handler); ProfilerInterceptor.GuardExternal(() => invoker(args, handler)); } else { var invokeMethod = field.FieldType.GetMethod("Invoke", BindingFlags.Instance | BindingFlags.Public); ProfilerInterceptor.GuardExternal(() => SecuredReflectionMethods.Invoke(invokeMethod, handler, args)); } } } }
private static object InterceptNewobj(RuntimeTypeHandle typeHandle, RuntimeMethodHandle methodHandle, object[] data) { if (!IsInterceptionEnabled || isFinalizerThread) { return(null); } try { ReentrancyCounter++; var method = MethodBase.GetMethodFromHandle(methodHandle, typeHandle); #if DEBUG ProfilerLogger.Info("*** +++ [MANAGED] Intercepting constructor call for {0}.{1}", method.DeclaringType.Name, method.Name); #endif var invocation = new Invocation(MockingUtil.TryGetUninitializedObject(method.DeclaringType), method, data ?? new object[0]); if (DispatchInvocation(invocation)) { if (invocation.CallOriginal) { SkipMethodInterceptionOnce(method); return(null); } if (invocation.IsReturnValueSet && invocation.ReturnValue != null) { return(invocation.ReturnValue); } return(invocation.Instance); } return(null); } finally { ReentrancyCounter--; } }
internal static MethodInfo GetMethodByName(Type type, Type returnType, string memberName, ref object[] args) { if (type.IsProxy()) { type = type.BaseType; } var candidateMethods = type.GetAllMethods() .Where(m => m.Name == memberName) .Concat(type.GetAllProperties() .Where(p => p.Name == memberName) .SelectMany(p => new[] { p.GetGetMethod(true), p.GetSetMethod(true) }) .Where(m => m != null)) .Select(m => { if (m.IsGenericMethodDefinition && returnType != typeof(void) && m.GetGenericArguments().Length == 1 && m.ReturnType.ContainsGenericParameters) { var generics = new Dictionary <Type, Type>(); if (MockingUtil.GetGenericsTypesFromActualType(m.ReturnType, returnType, generics)) { return(m.MakeGenericMethod(generics.Values.Single())); } } return(m); }) .ToArray(); MethodInfo mockedMethod = null; if (candidateMethods.Length == 1) { var singleCandidate = candidateMethods[0]; var returnTypeMatches = ReturnTypeMatches(returnType, singleCandidate); var argsIgnored = args == null || args.Length == 0; if (returnTypeMatches && argsIgnored) { mockedMethod = singleCandidate; args = mockedMethod.GetParameters() .Select(p => { var byref = p.ParameterType.IsByRef; var paramType = byref ? p.ParameterType.GetElementType() : p.ParameterType; if (paramType.IsPointer) { paramType = typeof(IntPtr); } var isAny = (Expression)typeof(ArgExpr).GetMethod("IsAny").MakeGenericMethod(paramType).Invoke(null, null); if (byref) { isAny = ArgExpr.Ref(isAny); } return(isAny); }) .ToArray(); } } if (mockedMethod == null) { mockedMethod = FindMethodBySignature(candidateMethods, returnType, args); if (mockedMethod == null && returnType == typeof(void)) { mockedMethod = FindMethodBySignature(candidateMethods, null, args); } } if (mockedMethod == null) { var mockedProperty = type.GetProperties(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static) .FirstOrDefault(property => property.Name == memberName); if (mockedProperty != null) { var getter = mockedProperty.GetGetMethod(true); if (getter != null && getter.ArgumentsMatchSignature(args)) { mockedMethod = getter; } if (mockedMethod == null) { var setter = mockedProperty.GetSetMethod(true); if (setter != null && setter.ArgumentsMatchSignature(args)) { mockedMethod = setter; } } if (mockedMethod == null) { throw new MissingMemberException(BuildMissingMethodMessage(type, mockedProperty, memberName)); } } } if (mockedMethod == null) { throw new MissingMemberException(BuildMissingMethodMessage(type, null, memberName)); } if (mockedMethod.ContainsGenericParameters) { mockedMethod = MockingUtil.GetRealMethodInfoFromGeneric(mockedMethod, args); } if (mockedMethod.DeclaringType != mockedMethod.ReflectedType) { mockedMethod = GetMethodByName(mockedMethod.DeclaringType, returnType, memberName, ref args); } return(mockedMethod); }
public static object CreateObject(this Type type, object[] args) { args = args ?? NoObjects; var constructorInfos = type.GetConstructors(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (constructorInfos.Length == 0 || (type.IsValueType && args.Length == 0)) { if (args.Length > 0) { throw new MockException("Type has no non-default constructors."); } return(type.GetDefaultValue()); } object state; var ctor = (ConstructorInfo)MockingUtil.BindToMethod(MockingUtil.Default, constructorInfos, ref args, null, null, null, out state); var ctorParameters = ctor.GetParameters(); for (int i = 0; i < ctorParameters.Length; ++i) { var paramType = ctorParameters[i].ParameterType; if (paramType.IsValueType && args[i] == null) { args[i] = paramType.GetDefaultValue(); } else if (args[i] != null && !paramType.IsAssignableFrom(args[i].GetType())) { args[i] = Convert.ChangeType(args[i], paramType, System.Globalization.CultureInfo.CurrentCulture); } } #if !PORTABLE var newCall = MockingUtil.CreateDynamicMethod <Func <object[], object> >(il => { il.UnpackArgArray(OpCodes.Ldarg_0, ctor); il.PushArgArray(ctor); il.Emit(OpCodes.Newobj, ctor); if (type.IsValueType) { il.Emit(OpCodes.Box, type); } il.Emit(OpCodes.Ret); }); return(ProfilerInterceptor.GuardExternal(() => { try { return newCall(args); } catch (MemberAccessException ex) { GC.KeepAlive(ex); return MockingUtil.CreateInstance(type, args); } })); #else return(MockingUtil.CreateInstance(type, args)); #endif }
internal static CallPattern FromExpression(MocksRepository repository, Expression expr) { var callPattern = new CallPattern(); expr = ((LambdaExpression)expr).Body; // the expression may end with a boxing conversion, remove that while (expr.NodeType == ExpressionType.Convert) { expr = ((UnaryExpression)expr).Operand; } Expression target; MethodBase method = null; Expression[] args; // We're parsing either a property/field expression or a method call. // parse the top of the expression tree and extract the expressions // that will turn into the constituents of the call pattern. if (expr is MemberExpression) { var memberExpr = (MemberExpression)expr; if (!(memberExpr.Member is PropertyInfo)) { throw new MockException("Fields cannot be mocked, only properties."); } var property = (PropertyInfo)memberExpr.Member; target = memberExpr.Expression; method = property.GetGetMethod(true); args = null; } else if (expr is MethodCallExpression) { var methodCall = (MethodCallExpression)expr; method = methodCall.Method; target = methodCall.Object; args = methodCall.Arguments.ToArray(); if (target != null && !target.Type.IsInterface && !target.Type.IsProxy() && target.Type != method.DeclaringType) { method = MockingUtil.GetConcreteImplementer((MethodInfo)method, target.Type); } } else if (expr is NewExpression) { #if !PORTABLE if (ProfilerInterceptor.IsReJitEnabled) { throw new MockException("Mocking the new operator is not avaiable with OnDemand option enabled. Please use .IgnoreInstance()"); } #endif var newExpr = (NewExpression)expr; method = newExpr.Constructor; if (method == null && newExpr.Type.IsValueType) { throw new MockException("Empty constructor of value type is not associated with runnable code and cannot be intercepted."); } target = null; args = newExpr.Arguments.ToArray(); } else if (expr is InvocationExpression) { var invocation = (InvocationExpression)expr; target = invocation.Expression; args = invocation.Arguments.ToArray(); } else if (expr.NodeType == ExpressionType.Assign) { var binary = (BinaryExpression)expr; if (binary.Left is MemberExpression) { MemberExpression memberExpr = (MemberExpression)binary.Left; if (!(memberExpr.Member is PropertyInfo)) { throw new MockException("Fields cannot be mocked, only properties."); } var property = (PropertyInfo)memberExpr.Member; target = memberExpr.Expression; method = property.GetSetMethod(true); args = new[] { binary.Right }; } else if (binary.Left is IndexExpression) { IndexExpression indexExpr = (IndexExpression)binary.Left; target = indexExpr.Object; method = indexExpr.Indexer.GetSetMethod(true); args = indexExpr.Arguments.Concat(new[] { binary.Right }).ToArray(); } else { throw new MockException("Left-hand of assignment is not a member or indexer."); } } else if (expr is IndexExpression) { var index = (IndexExpression)expr; target = index.Object; var property = index.Indexer; method = property.GetGetMethod(true); args = index.Arguments.ToArray(); } else { throw new MockException("The expression does not represent a method call, property access, new expression or a delegate invocation."); } // Create the matcher for the instance part of the call pattern. // If the base of the target expression is a new expression (new T()), // or null (e.g. (null as T) or ((T) null)), then use AnyMatcher for the instance part, // otherwise evaluate the instance expression and use a value matcher with the evaluated result. var rootTarget = expr; Expression prevToRoot = null; while (true) { var memberExpr = rootTarget as MemberExpression; if (memberExpr != null && memberExpr.Expression != null && memberExpr.Member is PropertyInfo) { prevToRoot = rootTarget; rootTarget = memberExpr.Expression; continue; } var callExpr = rootTarget as MethodCallExpression; if (callExpr != null && callExpr.Object != null) { prevToRoot = rootTarget; rootTarget = callExpr.Object; continue; } if (rootTarget != null && (rootTarget.NodeType == ExpressionType.Convert || rootTarget.NodeType == ExpressionType.TypeAs)) { rootTarget = ((UnaryExpression)rootTarget).Operand; continue; } if (rootTarget is InvocationExpression) { prevToRoot = rootTarget; rootTarget = ((InvocationExpression)rootTarget).Expression; continue; } if (rootTarget is BinaryExpression) { prevToRoot = rootTarget; rootTarget = ((BinaryExpression)rootTarget).Left; continue; } if (rootTarget is IndexExpression) { prevToRoot = rootTarget; rootTarget = ((IndexExpression)rootTarget).Object; continue; } break; } object targetMockObject = null; Type targetMockType = null; bool isStatic = false; var rootMatcher = MocksRepository.TryCreateMatcherFromArgMember(rootTarget); if (rootMatcher != null) { callPattern.InstanceMatcher = rootMatcher; } else if (rootTarget is MemberExpression) { var memberExpr = (MemberExpression)rootTarget; targetMockObject = memberExpr.Member is FieldInfo?memberExpr.EvaluateExpression() : memberExpr.Expression != null?memberExpr.Expression.EvaluateExpression() : null; targetMockType = memberExpr.Member is FieldInfo ? memberExpr.Type : memberExpr.Member.DeclaringType; var asPropertyInfo = memberExpr.Member as PropertyInfo; isStatic = asPropertyInfo != null ? (asPropertyInfo.GetGetMethod(true) ?? asPropertyInfo.GetSetMethod(true)).IsStatic : false; } else if (rootTarget is MethodCallExpression) { var methodCallExpr = (MethodCallExpression)rootTarget; targetMockObject = methodCallExpr.Object != null?methodCallExpr.Object.EvaluateExpression() : null; targetMockType = methodCallExpr.Method.DeclaringType; isStatic = methodCallExpr.Method.IsStatic; } else if (rootTarget is NewExpression) { callPattern.InstanceMatcher = new AnyMatcher(); } else if (rootTarget is ConstantExpression) { var constant = (ConstantExpression)rootTarget; if (constant.Value == null) { callPattern.InstanceMatcher = new AnyMatcher(); } else { if (constant.Type.IsCompilerGenerated() && prevToRoot != null && prevToRoot.Type != typeof(void)) { targetMockObject = prevToRoot.EvaluateExpression(); targetMockType = prevToRoot.Type; } else { targetMockObject = constant.Value; targetMockType = constant.Type; } } } if (targetMockObject != null) { targetMockType = targetMockObject.GetType(); } if (callPattern.InstanceMatcher != null && prevToRoot != expr && prevToRoot != null) { throw new MockException("Using a matcher for the root member together with recursive mocking is not supported. Arrange the property or method of the root member in a separate statement."); } if (callPattern.InstanceMatcher == null) { // TODO: implicit creation of mock mixins shouldn't explicitly refer to behaviors, but // should get them from some configuration made outside the Core. Debug.Assert(targetMockObject != null || targetMockType != null); MockingUtil.UnwrapDelegateTarget(ref targetMockObject); var mixin = MocksRepository.GetMockMixin(targetMockObject, targetMockType); if (mixin == null) { if (isStatic) { MockCreationSettings settings = MockCreationSettings.GetSettings(Behavior.CallOriginal); repository.InterceptStatics(targetMockType, settings, false); } else if (targetMockObject != null) { MockCreationSettings settings = MockCreationSettings.GetSettings(Behavior.CallOriginal); repository.CreateExternalMockMixin(targetMockType, targetMockObject, settings); } } var targetValue = target != null?target.EvaluateExpression() : null; var delgMethod = MockingUtil.UnwrapDelegateTarget(ref targetValue); if (delgMethod != null) { method = delgMethod.GetInheritanceChain().First(m => !m.DeclaringType.IsProxy()); } callPattern.InstanceMatcher = new ReferenceMatcher(targetValue); } // now we have the method part of the call pattern Debug.Assert(method != null); callPattern.SetMethod(method, checkCompatibility: true); //Finally, construct the arguments part of the call pattern. using (repository.StartArrangeArgMatching()) { bool hasParams = false; bool hasSingleValueInParams = false; if (args != null && args.Length > 0) { var lastParameter = method.GetParameters().Last(); if (Attribute.IsDefined(lastParameter, typeof(ParamArrayAttribute)) && args.Last() is NewArrayExpression) { hasParams = true; var paramsArg = (NewArrayExpression)args.Last(); args = args.Take(args.Length - 1).Concat(paramsArg.Expressions).ToArray(); if (paramsArg.Expressions.Count == 1) { hasSingleValueInParams = true; } } foreach (var argument in args) { callPattern.ArgumentMatchers.Add(MocksRepository.CreateMatcherForArgument(argument)); } if (hasParams) { int paramsCount = method.GetParameters().Count(); if (hasSingleValueInParams) { IMatcher matcher = callPattern.ArgumentMatchers[paramsCount - 1]; ITypedMatcher typeMatcher = matcher as ITypedMatcher; if (typeMatcher != null && typeMatcher.Type != method.GetParameters().Last().ParameterType) { callPattern.ArgumentMatchers[paramsCount - 1] = new ParamsMatcher(new IMatcher[] { matcher }); } } else { IEnumerable <IMatcher> paramMatchers = callPattern.ArgumentMatchers.Skip(paramsCount - 1).Take(callPattern.ArgumentMatchers.Count - paramsCount + 1); callPattern.ArgumentMatchers = callPattern.ArgumentMatchers.Take(paramsCount - 1).ToList(); callPattern.ArgumentMatchers.Add(new ParamsMatcher(paramMatchers.ToArray())); } } } } MethodBase methodFromCallPattern = repository.GetMethodFromCallPattern(callPattern); callPattern.AdjustForExtensionMethod(); callPattern.SetMethod(methodFromCallPattern, checkCompatibility: false); return(callPattern); }