PageRenderTime 41ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/src/NUnit/framework/Constraints/Tolerance.cs

#
C# | 225 lines | 117 code | 21 blank | 87 comment | 5 complexity | f0c5425961d59d91afe59bd6492a3f68 MD5 | raw file
Possible License(s): GPL-2.0
  1. // ****************************************************************
  2. // Copyright 2008, Charlie Poole
  3. // This is free software licensed under the NUnit license. You may
  4. // obtain a copy of the license at http://nunit.org/
  5. // ****************************************************************
  6. using System;
  7. namespace NUnit.Framework.Constraints
  8. {
  9. /// <summary>
  10. /// Modes in which the tolerance value for a comparison can
  11. /// be interpreted.
  12. /// </summary>
  13. public enum ToleranceMode
  14. {
  15. /// <summary>
  16. /// The tolerance was created with a value, without specifying
  17. /// how the value would be used. This is used to prevent setting
  18. /// the mode more than once and is generally changed to Linear
  19. /// upon execution of the test.
  20. /// </summary>
  21. None,
  22. /// <summary>
  23. /// The tolerance is used as a numeric range within which
  24. /// two compared values are considered to be equal.
  25. /// </summary>
  26. Linear,
  27. /// <summary>
  28. /// Interprets the tolerance as the percentage by which
  29. /// the two compared values my deviate from each other.
  30. /// </summary>
  31. Percent,
  32. /// <summary>
  33. /// Compares two values based in their distance in
  34. /// representable numbers.
  35. /// </summary>
  36. Ulps
  37. }
  38. /// <summary>
  39. /// The Tolerance class generalizes the notion of a tolerance
  40. /// within which an equality test succeeds. Normally, it is
  41. /// used with numeric types, but it can be used with any
  42. /// type that supports taking a difference between two
  43. /// objects and comparing that difference to a value.
  44. /// </summary>
  45. public class Tolerance
  46. {
  47. private ToleranceMode mode;
  48. private object amount;
  49. private static readonly string ModeMustFollowTolerance =
  50. "Tolerance amount must be specified before setting mode";
  51. private static readonly string MultipleToleranceModes =
  52. "Tried to use multiple tolerance modes at the same time";
  53. private static readonly string NumericToleranceRequired =
  54. "A numeric tolerance is required";
  55. /// <summary>
  56. /// Returns an empty Tolerance object, equivalent to
  57. /// specifying an exact match.
  58. /// </summary>
  59. public static Tolerance Empty
  60. {
  61. get { return new Tolerance(0, ToleranceMode.None); }
  62. }
  63. /// <summary>
  64. /// Constructs a linear tolerance of a specdified amount
  65. /// </summary>
  66. public Tolerance(object amount) : this(amount, ToleranceMode.Linear) { }
  67. /// <summary>
  68. /// Constructs a tolerance given an amount and ToleranceMode
  69. /// </summary>
  70. private Tolerance(object amount, ToleranceMode mode)
  71. {
  72. this.amount = amount;
  73. this.mode = mode;
  74. }
  75. /// <summary>
  76. /// Gets the ToleranceMode for the current Tolerance
  77. /// </summary>
  78. public ToleranceMode Mode
  79. {
  80. get { return this.mode; }
  81. }
  82. /// <summary>
  83. /// Tests that the current Tolerance is linear with a
  84. /// numeric value, throwing an exception if it is not.
  85. /// </summary>
  86. private void CheckLinearAndNumeric()
  87. {
  88. if (mode != ToleranceMode.Linear)
  89. throw new InvalidOperationException(mode == ToleranceMode.None
  90. ? ModeMustFollowTolerance
  91. : MultipleToleranceModes);
  92. if (!Numerics.IsNumericType(amount))
  93. throw new InvalidOperationException(NumericToleranceRequired);
  94. }
  95. /// <summary>
  96. /// Gets the value of the current Tolerance instance.
  97. /// </summary>
  98. public object Value
  99. {
  100. get { return this.amount; }
  101. }
  102. /// <summary>
  103. /// Returns a new tolerance, using the current amount as a percentage.
  104. /// </summary>
  105. public Tolerance Percent
  106. {
  107. get
  108. {
  109. CheckLinearAndNumeric();
  110. return new Tolerance(this.amount, ToleranceMode.Percent);
  111. }
  112. }
  113. /// <summary>
  114. /// Returns a new tolerance, using the current amount in Ulps.
  115. /// </summary>
  116. public Tolerance Ulps
  117. {
  118. get
  119. {
  120. CheckLinearAndNumeric();
  121. return new Tolerance(this.amount, ToleranceMode.Ulps);
  122. }
  123. }
  124. /// <summary>
  125. /// Returns a new tolerance with a TimeSpan as the amount, using
  126. /// the current amount as a number of days.
  127. /// </summary>
  128. public Tolerance Days
  129. {
  130. get
  131. {
  132. CheckLinearAndNumeric();
  133. return new Tolerance(TimeSpan.FromDays(Convert.ToDouble(amount)));
  134. }
  135. }
  136. /// <summary>
  137. /// Returns a new tolerance with a TimeSpan as the amount, using
  138. /// the current amount as a number of hours.
  139. /// </summary>
  140. public Tolerance Hours
  141. {
  142. get
  143. {
  144. CheckLinearAndNumeric();
  145. return new Tolerance(TimeSpan.FromHours(Convert.ToDouble(amount)));
  146. }
  147. }
  148. /// <summary>
  149. /// Returns a new tolerance with a TimeSpan as the amount, using
  150. /// the current amount as a number of minutes.
  151. /// </summary>
  152. public Tolerance Minutes
  153. {
  154. get
  155. {
  156. CheckLinearAndNumeric();
  157. return new Tolerance(TimeSpan.FromMinutes(Convert.ToDouble(amount)));
  158. }
  159. }
  160. /// <summary>
  161. /// Returns a new tolerance with a TimeSpan as the amount, using
  162. /// the current amount as a number of seconds.
  163. /// </summary>
  164. public Tolerance Seconds
  165. {
  166. get
  167. {
  168. CheckLinearAndNumeric();
  169. return new Tolerance(TimeSpan.FromSeconds(Convert.ToDouble(amount)));
  170. }
  171. }
  172. /// <summary>
  173. /// Returns a new tolerance with a TimeSpan as the amount, using
  174. /// the current amount as a number of milliseconds.
  175. /// </summary>
  176. public Tolerance Milliseconds
  177. {
  178. get
  179. {
  180. CheckLinearAndNumeric();
  181. return new Tolerance(TimeSpan.FromMilliseconds(Convert.ToDouble(amount)));
  182. }
  183. }
  184. /// <summary>
  185. /// Returns a new tolerance with a TimeSpan as the amount, using
  186. /// the current amount as a number of clock ticks.
  187. /// </summary>
  188. public Tolerance Ticks
  189. {
  190. get
  191. {
  192. CheckLinearAndNumeric();
  193. return new Tolerance(TimeSpan.FromTicks(Convert.ToInt64(amount)));
  194. }
  195. }
  196. /// <summary>
  197. /// Returns true if the current tolerance is empty.
  198. /// </summary>
  199. public bool IsEmpty
  200. {
  201. get { return mode == ToleranceMode.None; }
  202. }
  203. }
  204. }