1 // ****************************************************************
\r
2 // Copyright 2007, Charlie Poole
\r
3 // This is free software licensed under the NUnit license. You may
\r
4 // obtain a copy of the license at http://nunit.org/?p=license&r=2.4
\r
5 // ****************************************************************
\r
8 using System.Collections;
\r
10 namespace NUnit.Framework.Constraints
\r
13 /// ConstraintBuilder is used to resolve the Not and All properties,
\r
14 /// which serve as prefix operators for constraints. With the addition
\r
15 /// of an operand stack, And and Or could be supported, but we have
\r
16 /// left them out in favor of a simpler, more type-safe implementation.
\r
17 /// Use the & and | operator overloads to combine constraints.
\r
19 public class ConstraintBuilder
\r
30 Stack ops = new Stack();
\r
32 Stack opnds = new Stack();
\r
35 /// Implicitly convert ConstraintBuilder to an actual Constraint
\r
36 /// at the point where the syntax demands it.
\r
38 /// <param name="builder"></param>
\r
39 /// <returns></returns>
\r
40 public static implicit operator Constraint( ConstraintBuilder builder )
\r
42 return builder.Resolve();
\r
45 #region Constraints Without Arguments
\r
47 /// Resolves the chain of constraints using
\r
48 /// EqualConstraint(null) as base.
\r
50 public Constraint Null
\r
52 get { return Resolve(new EqualConstraint(null)); }
\r
56 /// Resolves the chain of constraints using
\r
57 /// EqualConstraint(true) as base.
\r
59 public Constraint True
\r
61 get { return Resolve(new EqualConstraint(true)); }
\r
65 /// Resolves the chain of constraints using
\r
66 /// EqualConstraint(false) as base.
\r
68 public Constraint False
\r
70 get { return Resolve(new EqualConstraint(false)); }
\r
74 /// Resolves the chain of constraints using
\r
77 public Constraint NaN
\r
79 get { return Resolve(new EqualConstraint(double.NaN)); }
\r
83 /// Resolves the chain of constraints using
\r
84 /// Is.Empty as base.
\r
86 public Constraint Empty
\r
88 get { return Resolve(new EmptyConstraint()); }
\r
92 /// Resolves the chain of constraints using
\r
93 /// Is.Unique as base.
\r
95 public Constraint Unique
\r
97 get { return Resolve(new UniqueItemsConstraint()); }
\r
101 #region Constraints with an expected value
\r
103 #region Equality and Identity
\r
105 /// Resolves the chain of constraints using an
\r
106 /// EqualConstraint as base.
\r
108 public Constraint EqualTo(object expected)
\r
110 return Resolve(new EqualConstraint(expected));
\r
114 /// Resolves the chain of constraints using a
\r
115 /// SameAsConstraint as base.
\r
117 public Constraint SameAs(object expected)
\r
119 return Resolve(new SameAsConstraint(expected));
\r
123 #region Comparison Constraints
\r
125 /// Resolves the chain of constraints using a
\r
126 /// LessThanConstraint as base.
\r
128 public Constraint LessThan(IComparable expected)
\r
130 return Resolve(new LessThanConstraint(expected));
\r
134 /// Resolves the chain of constraints using a
\r
135 /// GreaterThanConstraint as base.
\r
137 public Constraint GreaterThan(IComparable expected)
\r
139 return Resolve(new GreaterThanConstraint(expected));
\r
143 /// Resolves the chain of constraints using a
\r
144 /// LessThanOrEqualConstraint as base.
\r
146 public Constraint LessThanOrEqualTo(IComparable expected)
\r
148 return Resolve(new LessThanOrEqualConstraint(expected));
\r
152 /// Resolves the chain of constraints using a
\r
153 /// LessThanOrEqualConstraint as base.
\r
155 public Constraint AtMost(IComparable expected)
\r
157 return Resolve(new LessThanOrEqualConstraint(expected));
\r
161 /// Resolves the chain of constraints using a
\r
162 /// GreaterThanOrEqualConstraint as base.
\r
164 public Constraint GreaterThanOrEqualTo(IComparable expected)
\r
166 return Resolve(new GreaterThanOrEqualConstraint(expected));
\r
169 /// Resolves the chain of constraints using a
\r
170 /// GreaterThanOrEqualConstraint as base.
\r
172 public Constraint AtLeast(IComparable expected)
\r
174 return Resolve(new GreaterThanOrEqualConstraint(expected));
\r
178 #region Type Constraints
\r
180 /// Resolves the chain of constraints using an
\r
181 /// ExactTypeConstraint as base.
\r
183 public Constraint TypeOf(Type expectedType)
\r
185 return Resolve(new ExactTypeConstraint(expectedType));
\r
189 /// Resolves the chain of constraints using an
\r
190 /// InstanceOfTypeConstraint as base.
\r
192 public Constraint InstanceOfType(Type expectedType)
\r
194 return Resolve(new InstanceOfTypeConstraint(expectedType));
\r
198 /// Resolves the chain of constraints using an
\r
199 /// AssignableFromConstraint as base.
\r
201 public Constraint AssignableFrom(Type expectedType)
\r
203 return Resolve(new AssignableFromConstraint(expectedType));
\r
207 #region Containing Constraint
\r
209 /// Resolves the chain of constraints using a
\r
210 /// ContainsConstraint as base. This constraint
\r
211 /// will, in turn, make use of the appropriate
\r
212 /// second-level constraint, depending on the
\r
213 /// type of the actual argument.
\r
215 public Constraint Contains(object expected)
\r
217 return Resolve( new ContainsConstraint(expected) );
\r
221 /// Resolves the chain of constraints using a
\r
222 /// CollectionContainsConstraint as base.
\r
224 /// <param name="expected">The expected object</param>
\r
225 public Constraint Member( object expected )
\r
227 return Resolve( new CollectionContainsConstraint( expected ) );
\r
231 #region String Constraints
\r
233 /// Resolves the chain of constraints using a
\r
234 /// StartsWithConstraint as base.
\r
236 public Constraint StartsWith(string substring)
\r
238 return Resolve( new StartsWithConstraint(substring) );
\r
242 /// Resolves the chain of constraints using a
\r
243 /// StringEndingConstraint as base.
\r
245 public Constraint EndsWith(string substring)
\r
247 return Resolve( new EndsWithConstraint(substring) );
\r
251 /// Resolves the chain of constraints using a
\r
252 /// StringMatchingConstraint as base.
\r
254 public Constraint Matches(string pattern)
\r
256 return Resolve(new RegexConstraint(pattern));
\r
260 #region Collection Constraints
\r
262 /// Resolves the chain of constraints using a
\r
263 /// CollectionEquivalentConstraint as base.
\r
265 public Constraint EquivalentTo(ICollection expected)
\r
267 return Resolve( new CollectionEquivalentConstraint(expected) );
\r
271 /// Resolves the chain of constraints using a
\r
272 /// CollectionContainingConstraint as base.
\r
274 public Constraint CollectionContaining(object expected)
\r
276 return Resolve( new CollectionContainsConstraint(expected) );
\r
280 /// Resolves the chain of constraints using a
\r
281 /// CollectionSubsetConstraint as base.
\r
283 public Constraint SubsetOf(ICollection expected)
\r
285 return Resolve(new CollectionSubsetConstraint(expected));
\r
289 #region Property Constraints
\r
291 /// Resolves the chain of constraints using a
\r
292 /// PropertyConstraint as base
\r
294 public Constraint Property( string name, object expected )
\r
296 return Resolve( new PropertyConstraint( name, new EqualConstraint( expected ) ) );
\r
300 /// Resolves the chain of constraints using a
\r
301 /// PropertyCOnstraint on Length as base
\r
303 /// <param name="length"></param>
\r
304 /// <returns></returns>
\r
305 public Constraint Length(int length)
\r
307 return Property("Length", length);
\r
311 /// Resolves the chain of constraints using a
\r
312 /// PropertyCOnstraint on Length as base
\r
314 /// <param name="count"></param>
\r
315 /// <returns></returns>
\r
316 public Constraint Count(int count)
\r
318 return Property("Count", count);
\r
324 #region Prefix Operators
\r
326 /// Modifies the ConstraintBuilder by pushing a Not operator on the stack.
\r
328 public ConstraintBuilder Not
\r
338 /// Modifies the ConstraintBuilder by pushing a Not operator on the stack.
\r
340 public ConstraintBuilder No
\r
350 /// Modifies the ConstraintBuilder by pushing an All operator on the stack.
\r
352 public ConstraintBuilder All
\r
362 /// Modifies the ConstraintBuilder by pushing a Some operator on the stack.
\r
364 public ConstraintBuilder Some
\r
374 /// Modifies the constraint builder by pushing All and Not operators on the stack
\r
376 public ConstraintBuilder None
\r
386 /// Modifies the ConstraintBuilder by pushing a Prop operator on the
\r
387 /// ops stack and the name of the property on the opnds stack.
\r
389 /// <param name="name"></param>
\r
390 /// <returns></returns>
\r
391 public ConstraintBuilder Property(string name)
\r
393 ops.Push( Op.Prop );
\r
394 opnds.Push( name );
\r
399 #region Helper Methods
\r
401 /// Resolve a constraint that has been recognized by applying
\r
402 /// any pending operators and returning the resulting Constraint.
\r
404 /// <returns>A constraint that incorporates all pending operators</returns>
\r
405 private Constraint Resolve(Constraint constraint)
\r
407 while (ops.Count > 0)
\r
408 switch ((Op)ops.Pop())
\r
411 constraint = new NotConstraint(constraint);
\r
414 constraint = new AllItemsConstraint(constraint);
\r
417 constraint = new SomeItemsConstraint(constraint);
\r
420 constraint = new NoItemConstraint(constraint);
\r
423 constraint = new PropertyConstraint( (string)opnds.Pop(), constraint );
\r
430 private Constraint Resolve()
\r
432 return Resolve(null);
\r