PageRenderTime 47ms CodeModel.GetById 22ms RepoModel.GetById 1ms app.codeStats 0ms

/src/NUnit/framework/Constraints/StringConstraints.cs

#
C# | 310 lines | 154 code | 34 blank | 122 comment | 17 complexity | 4a6ad39aea64fc868a8f7cecc2b64efc MD5 | raw file
Possible License(s): GPL-2.0
  1. // ****************************************************************
  2. // Copyright 2007, 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. #if !NETCF
  8. using System.Text.RegularExpressions;
  9. #endif
  10. namespace NUnit.Framework.Constraints
  11. {
  12. #region StringConstraint
  13. /// <summary>
  14. /// StringConstraint is the abstract base for constraints
  15. /// that operate on strings. It supports the IgnoreCase
  16. /// modifier for string operations.
  17. /// </summary>
  18. public abstract class StringConstraint : Constraint
  19. {
  20. /// <summary>
  21. /// The expected value
  22. /// </summary>
  23. protected string expected;
  24. /// <summary>
  25. /// Indicates whether tests should be case-insensitive
  26. /// </summary>
  27. protected bool caseInsensitive;
  28. /// <summary>
  29. /// Constructs a StringConstraint given an expected value
  30. /// </summary>
  31. /// <param name="expected">The expected value</param>
  32. public StringConstraint(string expected)
  33. : base(expected)
  34. {
  35. this.expected = expected;
  36. }
  37. /// <summary>
  38. /// Modify the constraint to ignore case in matching.
  39. /// </summary>
  40. public StringConstraint IgnoreCase
  41. {
  42. get { caseInsensitive = true; return this; }
  43. }
  44. }
  45. #endregion
  46. #region EmptyStringConstraint
  47. /// <summary>
  48. /// EmptyStringConstraint tests whether a string is empty.
  49. /// </summary>
  50. public class EmptyStringConstraint : Constraint
  51. {
  52. /// <summary>
  53. /// Test whether the constraint is satisfied by a given value
  54. /// </summary>
  55. /// <param name="actual">The value to be tested</param>
  56. /// <returns>True for success, false for failure</returns>
  57. public override bool Matches(object actual)
  58. {
  59. this.actual = actual;
  60. if (!(actual is string))
  61. return false;
  62. return (string)actual == string.Empty;
  63. }
  64. /// <summary>
  65. /// Write the constraint description to a MessageWriter
  66. /// </summary>
  67. /// <param name="writer">The writer on which the description is displayed</param>
  68. public override void WriteDescriptionTo(MessageWriter writer)
  69. {
  70. writer.Write("<empty>");
  71. }
  72. }
  73. #endregion
  74. #region NullOrEmptyStringConstraint
  75. /// <summary>
  76. /// NullEmptyStringConstraint tests whether a string is either null or empty.
  77. /// </summary>
  78. public class NullOrEmptyStringConstraint : Constraint
  79. {
  80. /// <summary>
  81. /// Constructs a new NullOrEmptyStringConstraint
  82. /// </summary>
  83. public NullOrEmptyStringConstraint()
  84. {
  85. this.DisplayName = "nullorempty";
  86. }
  87. /// <summary>
  88. /// Test whether the constraint is satisfied by a given value
  89. /// </summary>
  90. /// <param name="actual">The value to be tested</param>
  91. /// <returns>True for success, false for failure</returns>
  92. public override bool Matches(object actual)
  93. {
  94. this.actual = actual;
  95. if (actual == null)
  96. return true;
  97. if (!(actual is string))
  98. throw new ArgumentException("Actual value must be a string", "actual");
  99. return (string)actual == string.Empty;
  100. }
  101. /// <summary>
  102. /// Write the constraint description to a MessageWriter
  103. /// </summary>
  104. /// <param name="writer">The writer on which the description is displayed</param>
  105. public override void WriteDescriptionTo(MessageWriter writer)
  106. {
  107. writer.Write("null or empty string");
  108. }
  109. }
  110. #endregion
  111. #region Substring Constraint
  112. /// <summary>
  113. /// SubstringConstraint can test whether a string contains
  114. /// the expected substring.
  115. /// </summary>
  116. public class SubstringConstraint : StringConstraint
  117. {
  118. /// <summary>
  119. /// Initializes a new instance of the <see cref="T:SubstringConstraint"/> class.
  120. /// </summary>
  121. /// <param name="expected">The expected.</param>
  122. public SubstringConstraint(string expected) : base(expected) { }
  123. /// <summary>
  124. /// Test whether the constraint is satisfied by a given value
  125. /// </summary>
  126. /// <param name="actual">The value to be tested</param>
  127. /// <returns>True for success, false for failure</returns>
  128. public override bool Matches(object actual)
  129. {
  130. this.actual = actual;
  131. if ( !(actual is string) )
  132. return false;
  133. if (this.caseInsensitive)
  134. return ((string)actual).ToLower().IndexOf(expected.ToLower()) >= 0;
  135. else
  136. return ((string)actual).IndexOf(expected) >= 0;
  137. }
  138. /// <summary>
  139. /// Write the constraint description to a MessageWriter
  140. /// </summary>
  141. /// <param name="writer">The writer on which the description is displayed</param>
  142. public override void WriteDescriptionTo(MessageWriter writer)
  143. {
  144. writer.WritePredicate("String containing");
  145. writer.WriteExpectedValue(expected);
  146. if ( this.caseInsensitive )
  147. writer.WriteModifier( "ignoring case" );
  148. }
  149. }
  150. #endregion
  151. #region StartsWithConstraint
  152. /// <summary>
  153. /// StartsWithConstraint can test whether a string starts
  154. /// with an expected substring.
  155. /// </summary>
  156. public class StartsWithConstraint : StringConstraint
  157. {
  158. /// <summary>
  159. /// Initializes a new instance of the <see cref="T:StartsWithConstraint"/> class.
  160. /// </summary>
  161. /// <param name="expected">The expected string</param>
  162. public StartsWithConstraint(string expected) : base(expected) { }
  163. /// <summary>
  164. /// Test whether the constraint is matched by the actual value.
  165. /// This is a template method, which calls the IsMatch method
  166. /// of the derived class.
  167. /// </summary>
  168. /// <param name="actual"></param>
  169. /// <returns></returns>
  170. public override bool Matches(object actual)
  171. {
  172. this.actual = actual;
  173. if (!(actual is string))
  174. return false;
  175. if ( this.caseInsensitive )
  176. return ((string)actual).ToLower().StartsWith(expected.ToLower());
  177. else
  178. return ((string)actual).StartsWith(expected);
  179. }
  180. /// <summary>
  181. /// Write the constraint description to a MessageWriter
  182. /// </summary>
  183. /// <param name="writer">The writer on which the description is displayed</param>
  184. public override void WriteDescriptionTo(MessageWriter writer)
  185. {
  186. writer.WritePredicate("String starting with");
  187. writer.WriteExpectedValue( MsgUtils.ClipString(expected, writer.MaxLineLength - 40, 0) );
  188. if ( this.caseInsensitive )
  189. writer.WriteModifier( "ignoring case" );
  190. }
  191. }
  192. #endregion
  193. #region EndsWithConstraint
  194. /// <summary>
  195. /// EndsWithConstraint can test whether a string ends
  196. /// with an expected substring.
  197. /// </summary>
  198. public class EndsWithConstraint : StringConstraint
  199. {
  200. /// <summary>
  201. /// Initializes a new instance of the <see cref="T:EndsWithConstraint"/> class.
  202. /// </summary>
  203. /// <param name="expected">The expected string</param>
  204. public EndsWithConstraint(string expected) : base(expected) { }
  205. /// <summary>
  206. /// Test whether the constraint is matched by the actual value.
  207. /// This is a template method, which calls the IsMatch method
  208. /// of the derived class.
  209. /// </summary>
  210. /// <param name="actual"></param>
  211. /// <returns></returns>
  212. public override bool Matches(object actual)
  213. {
  214. this.actual = actual;
  215. if (!(actual is string))
  216. return false;
  217. if ( this.caseInsensitive )
  218. return ((string)actual).ToLower().EndsWith(expected.ToLower());
  219. else
  220. return ((string)actual).EndsWith(expected);
  221. }
  222. /// <summary>
  223. /// Write the constraint description to a MessageWriter
  224. /// </summary>
  225. /// <param name="writer">The writer on which the description is displayed</param>
  226. public override void WriteDescriptionTo(MessageWriter writer)
  227. {
  228. writer.WritePredicate("String ending with");
  229. writer.WriteExpectedValue(expected);
  230. if ( this.caseInsensitive )
  231. writer.WriteModifier( "ignoring case" );
  232. }
  233. }
  234. #endregion
  235. #region RegexConstraint
  236. #if !NETCF
  237. /// <summary>
  238. /// RegexConstraint can test whether a string matches
  239. /// the pattern provided.
  240. /// </summary>
  241. public class RegexConstraint : StringConstraint
  242. {
  243. /// <summary>
  244. /// Initializes a new instance of the <see cref="T:RegexConstraint"/> class.
  245. /// </summary>
  246. /// <param name="pattern">The pattern.</param>
  247. public RegexConstraint(string pattern) : base(pattern) { }
  248. /// <summary>
  249. /// Test whether the constraint is satisfied by a given value
  250. /// </summary>
  251. /// <param name="actual">The value to be tested</param>
  252. /// <returns>True for success, false for failure</returns>
  253. public override bool Matches(object actual)
  254. {
  255. this.actual = actual;
  256. return actual is string &&
  257. Regex.IsMatch(
  258. (string)actual,
  259. this.expected,
  260. this.caseInsensitive ? RegexOptions.IgnoreCase : RegexOptions.None );
  261. }
  262. /// <summary>
  263. /// Write the constraint description to a MessageWriter
  264. /// </summary>
  265. /// <param name="writer">The writer on which the description is displayed</param>
  266. public override void WriteDescriptionTo(MessageWriter writer)
  267. {
  268. writer.WritePredicate("String matching");
  269. writer.WriteExpectedValue(this.expected);
  270. if ( this.caseInsensitive )
  271. writer.WriteModifier( "ignoring case" );
  272. }
  273. }
  274. #endif
  275. #endregion
  276. }