Debug.cs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389
  1. /*************************************************************************************
  2. Extended WPF Toolkit
  3. Copyright (C) 2007-2013 Xceed Software Inc.
  4. This program is provided to you under the terms of the Microsoft Public
  5. License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
  6. For more features, controls, and fast professional support,
  7. pick up the Plus Edition at http://xceed.com/wpf_toolkit
  8. Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
  9. ***********************************************************************************/
  10. /**************************************************************************\
  11. Copyright Microsoft Corporation. All Rights Reserved.
  12. \**************************************************************************/
  13. // Conditional to use more aggressive fail-fast behaviors when debugging.
  14. #define DEV_DEBUG
  15. // This file contains general utilities to aid in development.
  16. // It is distinct from unit test Assert classes.
  17. // Classes here generally shouldn't be exposed publicly since
  18. // they're not particular to any library functionality.
  19. // Because the classes here are internal, it's likely this file
  20. // might be included in multiple assemblies.
  21. namespace Standard
  22. {
  23. using System;
  24. using System.Diagnostics;
  25. using System.Threading;
  26. /// <summary>A static class for verifying assumptions.</summary>
  27. internal static class Assert
  28. {
  29. private static void _Break()
  30. {
  31. #if DEV_DEBUG
  32. Debugger.Break();
  33. #else
  34. Debug.Assert(false);
  35. #endif
  36. }
  37. /// <summary>A function signature for Assert.Evaluate.</summary>
  38. public delegate void EvaluateFunction();
  39. /// <summary>A function signature for Assert.Implies.</summary>
  40. /// <returns>Returns the truth of a predicate.</returns>
  41. public delegate bool ImplicationFunction();
  42. /// <summary>
  43. /// Executes the specified argument.
  44. /// </summary>
  45. /// <param name="argument">The function to execute.</param>
  46. [Conditional("DEBUG")]
  47. public static void Evaluate(EvaluateFunction argument)
  48. {
  49. IsNotNull(argument);
  50. argument();
  51. }
  52. /// <summary>Obsolete: Use Standard.Assert.AreEqual instead of Assert.Equals</summary>
  53. /// <typeparam name="T">The generic type to compare for equality.</typeparam>
  54. /// <param name="expected">The first generic type data to compare. This is is the expected value.</param>
  55. /// <param name="actual">The second generic type data to compare. This is the actual value.</param>
  56. [
  57. Obsolete("Use Assert.AreEqual instead of Assert.Equals", false),
  58. Conditional("DEBUG")
  59. ]
  60. public static void Equals<T>(T expected, T actual)
  61. {
  62. AreEqual(expected, actual);
  63. }
  64. /// <summary>
  65. /// Verifies that two generic type data are equal. The assertion fails if they are not.
  66. /// </summary>
  67. /// <typeparam name="T">The generic type to compare for equality.</typeparam>
  68. /// <param name="expected">The first generic type data to compare. This is is the expected value.</param>
  69. /// <param name="actual">The second generic type data to compare. This is the actual value.</param>
  70. /// <remarks>This breaks into the debugger in the case of a failed assertion.</remarks>
  71. [Conditional("DEBUG")]
  72. public static void AreEqual<T>(T expected, T actual)
  73. {
  74. if (null == expected)
  75. {
  76. // Two nulls are considered equal, regardless of type semantics.
  77. if (null != actual && !actual.Equals(expected))
  78. {
  79. _Break();
  80. }
  81. }
  82. else if (!expected.Equals(actual))
  83. {
  84. _Break();
  85. }
  86. }
  87. /// <summary>
  88. /// Verifies that two generic type data are not equal. The assertion fails if they are.
  89. /// </summary>
  90. /// <typeparam name="T">The generic type to compare for inequality.</typeparam>
  91. /// <param name="notExpected">The first generic type data to compare. This is is the value that's not expected.</param>
  92. /// <param name="actual">The second generic type data to compare. This is the actual value.</param>
  93. /// <remarks>This breaks into the debugger in the case of a failed assertion.</remarks>
  94. [Conditional("DEBUG")]
  95. public static void AreNotEqual<T>(T notExpected, T actual)
  96. {
  97. if (null == notExpected)
  98. {
  99. // Two nulls are considered equal, regardless of type semantics.
  100. if (null == actual || actual.Equals(notExpected))
  101. {
  102. _Break();
  103. }
  104. }
  105. else if (notExpected.Equals(actual))
  106. {
  107. _Break();
  108. }
  109. }
  110. /// <summary>
  111. /// Verifies that if the specified condition is true, then so is the result.
  112. /// The assertion fails if the condition is true but the result is false.
  113. /// </summary>
  114. /// <param name="condition">if set to <c>true</c> [condition].</param>
  115. /// <param name="result">
  116. /// A second Boolean statement. If the first was true then so must this be.
  117. /// If the first statement was false then the value of this is ignored.
  118. /// </param>
  119. /// <remarks>This breaks into the debugger in the case of a failed assertion.</remarks>
  120. [Conditional("DEBUG")]
  121. public static void Implies(bool condition, bool result)
  122. {
  123. if (condition && !result)
  124. {
  125. _Break();
  126. }
  127. }
  128. /// <summary>
  129. /// Lazy evaluation overload. Verifies that if a condition is true, then so is a secondary value.
  130. /// </summary>
  131. /// <param name="condition">The conditional value.</param>
  132. /// <param name="result">A function to be evaluated for truth if the condition argument is true.</param>
  133. /// <remarks>
  134. /// This overload only evaluates the result if the first condition is true.
  135. /// </remarks>
  136. [Conditional("DEBUG")]
  137. public static void Implies(bool condition, ImplicationFunction result)
  138. {
  139. if (condition && !result())
  140. {
  141. _Break();
  142. }
  143. }
  144. /// <summary>
  145. /// Verifies that a string has content. I.e. it is not null and it is not empty.
  146. /// </summary>
  147. /// <param name="value">The string to verify.</param>
  148. [Conditional("DEBUG")]
  149. public static void IsNeitherNullNorEmpty(string value)
  150. {
  151. IsFalse(string.IsNullOrEmpty(value));
  152. }
  153. /// <summary>
  154. /// Verifies that a string has content. I.e. it is not null and it is not purely whitespace.
  155. /// </summary>
  156. /// <param name="value">The string to verify.</param>
  157. [Conditional("DEBUG")]
  158. public static void IsNeitherNullNorWhitespace(string value)
  159. {
  160. if (string.IsNullOrEmpty(value))
  161. {
  162. _Break();
  163. }
  164. if (value.Trim().Length == 0)
  165. {
  166. _Break();
  167. }
  168. }
  169. /// <summary>
  170. /// Verifies the specified value is not null. The assertion fails if it is.
  171. /// </summary>
  172. /// <typeparam name="T">The generic reference type.</typeparam>
  173. /// <param name="value">The value to check for nullness.</param>
  174. /// <remarks>This breaks into the debugger in the case of a failed assertion.</remarks>
  175. [Conditional("DEBUG")]
  176. public static void IsNotNull<T>(T value) where T : class
  177. {
  178. if (null == value)
  179. {
  180. _Break();
  181. }
  182. }
  183. [Conditional("DEBUG")]
  184. public static void IsDefault<T>(T value) where T : struct
  185. {
  186. if (!value.Equals(default(T)))
  187. {
  188. Assert.Fail();
  189. }
  190. }
  191. [Conditional("DEBUG")]
  192. public static void IsNotDefault<T>(T value) where T : struct
  193. {
  194. if (value.Equals(default(T)))
  195. {
  196. Assert.Fail();
  197. }
  198. }
  199. /// <summary>
  200. /// Verifies that the specified condition is false. The assertion fails if it is true.
  201. /// </summary>
  202. /// <param name="condition">The expression that should be <c>false</c>.</param>
  203. /// <remarks>This breaks into the debugger in the case of a failed assertion.</remarks>
  204. [Conditional("DEBUG")]
  205. public static void IsFalse(bool condition)
  206. {
  207. if (condition)
  208. {
  209. _Break();
  210. }
  211. }
  212. /// <summary>
  213. /// Verifies that the specified condition is false. The assertion fails if it is true.
  214. /// </summary>
  215. /// <param name="condition">The expression that should be <c>false</c>.</param>
  216. /// <param name="message">The message to display if the condition is <c>true</c>.</param>
  217. /// <remarks>This breaks into the debugger in the case of a failed assertion.</remarks>
  218. [Conditional("DEBUG")]
  219. public static void IsFalse(bool condition, string message)
  220. {
  221. if (condition)
  222. {
  223. _Break();
  224. }
  225. }
  226. /// <summary>
  227. /// Verifies that the specified condition is true. The assertion fails if it is not.
  228. /// </summary>
  229. /// <param name="condition">A condition that is expected to be <c>true</c>.</param>
  230. /// <remarks>This breaks into the debugger in the case of a failed assertion.</remarks>
  231. [Conditional("DEBUG")]
  232. public static void IsTrue(bool condition)
  233. {
  234. if (!condition)
  235. {
  236. _Break();
  237. }
  238. }
  239. /// <summary>
  240. /// Verifies that the specified condition is true. The assertion fails if it is not.
  241. /// </summary>
  242. /// <param name="condition">A condition that is expected to be <c>true</c>.</param>
  243. /// <param name="message">The message to write in case the condition is <c>false</c>.</param>
  244. /// <remarks>This breaks into the debugger in the case of a failed assertion.</remarks>
  245. [Conditional("DEBUG")]
  246. public static void IsTrue(bool condition, string message)
  247. {
  248. if (!condition)
  249. {
  250. _Break();
  251. }
  252. }
  253. /// <summary>
  254. /// This line should never be executed. The assertion always fails.
  255. /// </summary>
  256. /// <remarks>This breaks into the debugger in the case of a failed assertion.</remarks>
  257. [Conditional("DEBUG")]
  258. public static void Fail()
  259. {
  260. _Break();
  261. }
  262. /// <summary>
  263. /// This line should never be executed. The assertion always fails.
  264. /// </summary>
  265. /// <param name="message">The message to display if this function is executed.</param>
  266. /// <remarks>This breaks into the debugger in the case of a failed assertion.</remarks>
  267. [Conditional("DEBUG")]
  268. public static void Fail(string message)
  269. {
  270. _Break();
  271. }
  272. /// <summary>
  273. /// Verifies that the specified object is null. The assertion fails if it is not.
  274. /// </summary>
  275. /// <param name="item">The item to verify is null.</param>
  276. [Conditional("DEBUG")]
  277. public static void IsNull<T>(T item) where T : class
  278. {
  279. if (null != item)
  280. {
  281. _Break();
  282. }
  283. }
  284. /// <summary>
  285. /// Verifies that the specified value is within the expected range. The assertion fails if it isn't.
  286. /// </summary>
  287. /// <param name="lowerBoundInclusive">The lower bound inclusive value.</param>
  288. /// <param name="value">The value to verify.</param>
  289. /// <param name="upperBoundInclusive">The upper bound inclusive value.</param>
  290. [Conditional("DEBUG")]
  291. public static void BoundedDoubleInc(double lowerBoundInclusive, double value, double upperBoundInclusive)
  292. {
  293. if (value < lowerBoundInclusive || value > upperBoundInclusive)
  294. {
  295. _Break();
  296. }
  297. }
  298. /// <summary>
  299. /// Verifies that the specified value is within the expected range. The assertion fails if it isn't.
  300. /// </summary>
  301. /// <param name="lowerBoundInclusive">The lower bound inclusive value.</param>
  302. /// <param name="value">The value to verify.</param>
  303. /// <param name="upperBoundExclusive">The upper bound exclusive value.</param>
  304. [Conditional("DEBUG")]
  305. public static void BoundedInteger(int lowerBoundInclusive, int value, int upperBoundExclusive)
  306. {
  307. if (value < lowerBoundInclusive || value >= upperBoundExclusive)
  308. {
  309. _Break();
  310. }
  311. }
  312. /// <summary>
  313. /// Verify the current thread's apartment state is what's expected. The assertion fails if it isn't
  314. /// </summary>
  315. /// <param name="expectedState">
  316. /// The expected apartment state for the current thread.
  317. /// </param>
  318. /// <remarks>This breaks into the debugger in the case of a failed assertion.</remarks>
  319. [Conditional("DEBUG")]
  320. public static void IsApartmentState(ApartmentState expectedState)
  321. {
  322. if (Thread.CurrentThread.GetApartmentState() != expectedState)
  323. {
  324. _Break();
  325. }
  326. }
  327. [Conditional("DEBUG")]
  328. public static void NullableIsNotNull<T>(T? value) where T : struct
  329. {
  330. if (null == value)
  331. {
  332. _Break();
  333. }
  334. }
  335. [Conditional("DEBUG")]
  336. public static void NullableIsNull<T>(T? value) where T : struct
  337. {
  338. if (null != value)
  339. {
  340. _Break();
  341. }
  342. }
  343. [Conditional("DEBUG")]
  344. public static void IsNotOnMainThread()
  345. {
  346. if (System.Windows.Application.Current.Dispatcher.CheckAccess())
  347. {
  348. _Break();
  349. }
  350. }
  351. }
  352. }