PageRenderTime 39ms CodeModel.GetById 9ms app.highlight 22ms RepoModel.GetById 2ms app.codeStats 0ms

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

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