PageRenderTime 40ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 0ms

/test/Microsoft.TestCommon/MemberHelper.cs

https://bitbucket.org/mdavid/aspnetwebstack
C# | 381 lines | 311 code | 49 blank | 21 comment | 34 complexity | 585876aa35658a8baf235cdcf18b8e85 MD5 | raw file
  1. using System.Collections.Generic;
  2. using System.ComponentModel;
  3. using System.Reflection;
  4. using Assert = Microsoft.TestCommon.AssertEx;
  5. namespace System.Web.TestUtil
  6. {
  7. public static class MemberHelper
  8. {
  9. private static ConstructorInfo GetConstructorInfo(object instance, Type[] parameterTypes)
  10. {
  11. if (instance == null)
  12. {
  13. throw new ArgumentNullException("instance");
  14. }
  15. ConstructorInfo constructorInfo = instance.GetType().GetConstructor(parameterTypes);
  16. if (constructorInfo == null)
  17. {
  18. throw new ArgumentException(String.Format(
  19. "A matching constructor on type '{0}' could not be found.",
  20. instance.GetType().FullName));
  21. }
  22. return constructorInfo;
  23. }
  24. private static EventInfo GetEventInfo(object instance, string eventName)
  25. {
  26. if (instance == null)
  27. {
  28. throw new ArgumentNullException("instance");
  29. }
  30. if (String.IsNullOrEmpty(eventName))
  31. {
  32. throw new ArgumentException("An event must be specified.", "eventName");
  33. }
  34. EventInfo eventInfo = instance.GetType().GetEvent(eventName);
  35. if (eventInfo == null)
  36. {
  37. throw new ArgumentException(String.Format(
  38. "An event named '{0}' on type '{1}' could not be found.",
  39. eventName, instance.GetType().FullName));
  40. }
  41. return eventInfo;
  42. }
  43. private static MethodInfo GetMethodInfo(object instance, string methodName, Type[] types = null, MethodAttributes attrs = MethodAttributes.Public)
  44. {
  45. if (instance == null)
  46. {
  47. throw new ArgumentNullException("instance");
  48. }
  49. if (String.IsNullOrEmpty(methodName))
  50. {
  51. throw new ArgumentException("A method must be specified.", "methodName");
  52. }
  53. MethodInfo methodInfo;
  54. if (types != null)
  55. {
  56. methodInfo = instance.GetType().GetMethod(methodName,
  57. BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic,
  58. null,
  59. types,
  60. null);
  61. }
  62. else
  63. {
  64. methodInfo = instance.GetType().GetMethod(methodName,
  65. BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
  66. }
  67. if (methodInfo == null)
  68. {
  69. throw new ArgumentException(String.Format(
  70. "A method named '{0}' on type '{1}' could not be found.",
  71. methodName, instance.GetType().FullName));
  72. }
  73. if ((methodInfo.Attributes & attrs) != attrs)
  74. {
  75. throw new ArgumentException(String.Format(
  76. "Method '{0}' on type '{1}' with attributes '{2}' does not match the attributes '{3}'.",
  77. methodName, instance.GetType().FullName, methodInfo.Attributes, attrs));
  78. }
  79. return methodInfo;
  80. }
  81. private static PropertyInfo GetPropertyInfo(object instance, string propertyName)
  82. {
  83. if (instance == null)
  84. {
  85. throw new ArgumentNullException("instance");
  86. }
  87. if (String.IsNullOrEmpty(propertyName))
  88. {
  89. throw new ArgumentException("A property must be specified.", "propertyName");
  90. }
  91. PropertyInfo propInfo = instance.GetType().GetProperty(propertyName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
  92. if (propInfo == null)
  93. {
  94. throw new ArgumentException(String.Format(
  95. "A property named '{0}' on type '{1}' could not be found.",
  96. propertyName, instance.GetType().FullName));
  97. }
  98. return propInfo;
  99. }
  100. private static void TestAttribute<TAttribute>(MemberInfo memberInfo, TAttribute attributeValue)
  101. where TAttribute : Attribute
  102. {
  103. object[] attrs = memberInfo.GetCustomAttributes(typeof(TAttribute), true);
  104. if (attributeValue == null)
  105. {
  106. Assert.True(attrs.Length == 0, "Member should not have an attribute of type " + typeof(TAttribute));
  107. }
  108. else
  109. {
  110. Assert.True(attrs != null && attrs.Length > 0,
  111. "Member does not have an attribute of type " + typeof(TAttribute));
  112. Assert.Equal(attributeValue, attrs[0]);
  113. }
  114. }
  115. public static void TestBooleanProperty(object instance, string propertyName, bool initialValue, bool testDefaultValue)
  116. {
  117. // Assert initial value
  118. TestGetPropertyValue(instance, propertyName, initialValue);
  119. if (testDefaultValue)
  120. {
  121. // Assert DefaultValue attribute matches inital value
  122. TestDefaultValue(instance, propertyName);
  123. }
  124. TestPropertyValue(instance, propertyName, true);
  125. TestPropertyValue(instance, propertyName, false);
  126. }
  127. public static void TestDefaultValue(object instance, string propertyName)
  128. {
  129. PropertyInfo propInfo = GetPropertyInfo(instance, propertyName);
  130. object initialValue = propInfo.GetValue(instance, null);
  131. TestAttribute(propInfo, new DefaultValueAttribute(initialValue));
  132. }
  133. public static void TestEvent<TEventArgs>(object instance, string eventName, TEventArgs eventArgs) where TEventArgs : EventArgs
  134. {
  135. EventInfo eventInfo = GetEventInfo(instance, eventName);
  136. // Assert category "Action"
  137. TestAttribute(eventInfo, new CategoryAttribute("Action"));
  138. // Call protected method with no event handlers, assert no error
  139. MethodInfo methodInfo = GetMethodInfo(instance, "On" + eventName, attrs: MethodAttributes.Family | MethodAttributes.Virtual);
  140. methodInfo.Invoke(instance, new object[] { eventArgs });
  141. // Attach handler, call method, assert fires once
  142. List<object> eventHandlerArgs = new List<object>();
  143. EventHandler<TEventArgs> handler = new EventHandler<TEventArgs>(delegate(object sender, TEventArgs t)
  144. {
  145. eventHandlerArgs.Add(sender);
  146. eventHandlerArgs.Add(t);
  147. });
  148. eventInfo.AddEventHandler(instance, handler);
  149. methodInfo.Invoke(instance, new object[] { eventArgs });
  150. Assert.Equal(new[] { instance, eventArgs }, eventHandlerArgs.ToArray());
  151. // Detach handler, call method, assert not fired
  152. eventHandlerArgs = new List<object>();
  153. eventInfo.RemoveEventHandler(instance, handler);
  154. methodInfo.Invoke(instance, new object[] { eventArgs });
  155. Assert.Empty(eventHandlerArgs);
  156. }
  157. public static void TestGetPropertyValue(object instance, string propertyName, object valueToCheck)
  158. {
  159. PropertyInfo propInfo = GetPropertyInfo(instance, propertyName);
  160. object value = propInfo.GetValue(instance, null);
  161. Assert.Equal(valueToCheck, value);
  162. }
  163. public static void TestEnumProperty<TEnumValue>(object instance, string propertyName, TEnumValue initialValue, bool testDefaultValue)
  164. {
  165. // Assert initial value
  166. TestGetPropertyValue(instance, propertyName, initialValue);
  167. if (testDefaultValue)
  168. {
  169. // Assert DefaultValue attribute matches inital value
  170. TestDefaultValue(instance, propertyName);
  171. }
  172. PropertyInfo propInfo = GetPropertyInfo(instance, propertyName);
  173. // Values are sorted numerically
  174. TEnumValue[] values = (TEnumValue[])Enum.GetValues(propInfo.PropertyType);
  175. // Assert get/set works for all valid enum values
  176. foreach (TEnumValue value in values)
  177. {
  178. TestPropertyValue(instance, propertyName, value);
  179. }
  180. // Assert ArgumentOutOfRangeException is thrown for value one less than smallest
  181. // enum value, and one more than largest enum value
  182. var targetException = Assert.Throws<TargetInvocationException>(() => propInfo.SetValue(instance, Convert.ToInt32(values[0]) - 1, null));
  183. Assert.IsType<ArgumentOutOfRangeException>(targetException.InnerException);
  184. targetException = Assert.Throws<TargetInvocationException>(() => propInfo.SetValue(instance, Convert.ToInt32(values[values.Length - 1]) + 1, null));
  185. Assert.IsType<ArgumentOutOfRangeException>(targetException.InnerException);
  186. }
  187. public static void TestInt32Property(object instance, string propertyName, int value1, int value2)
  188. {
  189. TestPropertyValue(instance, propertyName, value1);
  190. TestPropertyValue(instance, propertyName, value2);
  191. }
  192. public static void TestPropertyWithDefaultInstance(object instance, string propertyName, object valueToSet)
  193. {
  194. PropertyInfo propInfo = GetPropertyInfo(instance, propertyName);
  195. // Set to explicit property
  196. propInfo.SetValue(instance, valueToSet, null);
  197. object value = propInfo.GetValue(instance, null);
  198. Assert.Equal(valueToSet, value);
  199. // Set to null
  200. propInfo.SetValue(instance, null, null);
  201. value = propInfo.GetValue(instance, null);
  202. Assert.IsAssignableFrom(propInfo.PropertyType, value);
  203. }
  204. public static void TestPropertyWithDefaultInstance(object instance, string propertyName, object valueToSet, object defaultValue)
  205. {
  206. PropertyInfo propInfo = GetPropertyInfo(instance, propertyName);
  207. // Set to explicit property
  208. propInfo.SetValue(instance, valueToSet, null);
  209. object value = propInfo.GetValue(instance, null);
  210. Assert.Same(valueToSet, value);
  211. // Set to null
  212. propInfo.SetValue(instance, null, null);
  213. value = propInfo.GetValue(instance, null);
  214. Assert.Equal(defaultValue, value);
  215. }
  216. public static void TestPropertyValue(object instance, string propertyName, object value)
  217. {
  218. TestPropertyValue(instance, propertyName, value, value);
  219. }
  220. public static void TestPropertyValue(object instance, string propertyName, object valueToSet, object valueToCheck)
  221. {
  222. PropertyInfo propInfo = GetPropertyInfo(instance, propertyName);
  223. propInfo.SetValue(instance, valueToSet, null);
  224. object value = propInfo.GetValue(instance, null);
  225. Assert.Equal(valueToCheck, value);
  226. }
  227. public static void TestStringParams(object instance, Type[] constructorParameterTypes, object[] parameters)
  228. {
  229. ConstructorInfo ctor = GetConstructorInfo(instance, constructorParameterTypes);
  230. TestStringParams(ctor, instance, parameters);
  231. }
  232. public static void TestStringParams(object instance, string methodName, object[] parameters)
  233. {
  234. TestStringParams(instance, methodName, null, parameters);
  235. }
  236. public static void TestStringParams(object instance, string methodName, Type[] types, object[] parameters)
  237. {
  238. MethodInfo method = GetMethodInfo(instance, methodName, types);
  239. TestStringParams(method, instance, parameters);
  240. }
  241. private static void TestStringParams(MethodBase method, object instance, object[] parameters)
  242. {
  243. ParameterInfo[] parameterInfos = method.GetParameters();
  244. foreach (ParameterInfo parameterInfo in parameterInfos)
  245. {
  246. if (parameterInfo.ParameterType == typeof(String))
  247. {
  248. object originalParameter = parameters[parameterInfo.Position];
  249. parameters[parameterInfo.Position] = null;
  250. Assert.ThrowsArgumentNullOrEmpty(
  251. delegate()
  252. {
  253. try
  254. {
  255. method.Invoke(instance, parameters);
  256. }
  257. catch (TargetInvocationException e)
  258. {
  259. throw e.InnerException;
  260. }
  261. },
  262. parameterInfo.Name);
  263. parameters[parameterInfo.Position] = String.Empty;
  264. Assert.ThrowsArgumentNullOrEmpty(
  265. delegate()
  266. {
  267. try
  268. {
  269. method.Invoke(instance, parameters);
  270. }
  271. catch (TargetInvocationException e)
  272. {
  273. throw e.InnerException;
  274. }
  275. },
  276. parameterInfo.Name);
  277. parameters[parameterInfo.Position] = originalParameter;
  278. }
  279. }
  280. }
  281. public static void TestStringProperty(object instance, string propertyName, string initialValue,
  282. bool testDefaultValueAttribute = false, bool allowNullAndEmpty = true,
  283. string nullAndEmptyReturnValue = "")
  284. {
  285. // Assert initial value
  286. TestGetPropertyValue(instance, propertyName, initialValue);
  287. if (testDefaultValueAttribute)
  288. {
  289. // Assert DefaultValue attribute matches inital value
  290. TestDefaultValue(instance, propertyName);
  291. }
  292. if (allowNullAndEmpty)
  293. {
  294. // Assert get/set works for null
  295. TestPropertyValue(instance, propertyName, null, nullAndEmptyReturnValue);
  296. // Assert get/set works for String.Empty
  297. TestPropertyValue(instance, propertyName, String.Empty, nullAndEmptyReturnValue);
  298. }
  299. else
  300. {
  301. Assert.ThrowsArgumentNullOrEmpty(
  302. delegate()
  303. {
  304. try
  305. {
  306. TestPropertyValue(instance, propertyName, null);
  307. }
  308. catch (TargetInvocationException e)
  309. {
  310. throw e.InnerException;
  311. }
  312. },
  313. "value");
  314. Assert.ThrowsArgumentNullOrEmpty(
  315. delegate()
  316. {
  317. try
  318. {
  319. TestPropertyValue(instance, propertyName, String.Empty);
  320. }
  321. catch (TargetInvocationException e)
  322. {
  323. throw e.InnerException;
  324. }
  325. },
  326. "value");
  327. }
  328. // Assert get/set works for arbitrary value
  329. TestPropertyValue(instance, propertyName, "TestValue");
  330. }
  331. }
  332. }