1 // ***********************************************************************
2 // Copyright (c) 2009 Charlie Poole
3 //
4 // Permission is hereby granted, free of charge, to any person obtaining
5 // a copy of this software and associated documentation files (the
6 // "Software"), to deal in the Software without restriction, including
7 // without limitation the rights to use, copy, modify, merge, publish,
8 // distribute, sublicense, and/or sell copies of the Software, and to
9 // permit persons to whom the Software is furnished to do so, subject to
10 // the following conditions:
11 //
12 // The above copyright notice and this permission notice shall be
13 // included in all copies or substantial portions of the Software.
14 //
15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 // ***********************************************************************
23 
24 using System;
25 using System.Collections;
26 
27 namespace NUnit.Framework.Constraints
28 {
29     /// <summary>
30     /// Helper class with properties and methods that supply
31     /// a number of constraints used in Asserts.
32     /// </summary>
33     public class ConstraintFactory
34     {
35         #region Not
36 
37         /// <summary>
38         /// Returns a ConstraintExpression that negates any
39         /// following constraint.
40         /// </summary>
41         public ConstraintExpression Not
42         {
43             get { return Is.Not; }
44         }
45 
46         /// <summary>
47         /// Returns a ConstraintExpression that negates any
48         /// following constraint.
49         /// </summary>
50         public ConstraintExpression No
51         {
52             get { return Has.No; }
53         }
54 
55         #endregion
56 
57         #region All
58 
59         /// <summary>
60         /// Returns a ConstraintExpression, which will apply
61         /// the following constraint to all members of a collection,
62         /// succeeding if all of them succeed.
63         /// </summary>
64         public ConstraintExpression All
65         {
66             get { return Is.All; }
67         }
68 
69         #endregion
70 
71         #region Some
72 
73         /// <summary>
74         /// Returns a ConstraintExpression, which will apply
75         /// the following constraint to all members of a collection,
76         /// succeeding if at least one of them succeeds.
77         /// </summary>
78         public ConstraintExpression Some
79         {
80             get { return Has.Some; }
81         }
82 
83         #endregion
84 
85         #region None
86 
87         /// <summary>
88         /// Returns a ConstraintExpression, which will apply
89         /// the following constraint to all members of a collection,
90         /// succeeding if all of them fail.
91         /// </summary>
92         public ConstraintExpression None
93         {
94             get { return Has.None; }
95         }
96 
97         #endregion
98 
99         #region Exactly(n)
100 
101         /// <summary>
102         /// Returns a ConstraintExpression, which will apply
103         /// the following constraint to all members of a collection,
104         /// succeeding only if a specified number of them succeed.
105         /// </summary>
Exactly(int expectedCount)106         public static ConstraintExpression Exactly(int expectedCount)
107         {
108             return Has.Exactly(expectedCount);
109         }
110 
111         #endregion
112 
113         #region Property
114 
115         /// <summary>
116         /// Returns a new PropertyConstraintExpression, which will either
117         /// test for the existence of the named property on the object
118         /// being tested or apply any following constraint to that property.
119         /// </summary>
Property(string name)120         public ResolvableConstraintExpression Property(string name)
121         {
122             return Has.Property(name);
123         }
124 
125         #endregion
126 
127         #region Length
128 
129         /// <summary>
130         /// Returns a new ConstraintExpression, which will apply the following
131         /// constraint to the Length property of the object being tested.
132         /// </summary>
133         public ResolvableConstraintExpression Length
134         {
135             get { return Has.Length; }
136         }
137 
138         #endregion
139 
140         #region Count
141 
142         /// <summary>
143         /// Returns a new ConstraintExpression, which will apply the following
144         /// constraint to the Count property of the object being tested.
145         /// </summary>
146         public ResolvableConstraintExpression Count
147         {
148             get { return Has.Count; }
149         }
150 
151         #endregion
152 
153         #region Message
154 
155         /// <summary>
156         /// Returns a new ConstraintExpression, which will apply the following
157         /// constraint to the Message property of the object being tested.
158         /// </summary>
159         public ResolvableConstraintExpression Message
160         {
161             get { return Has.Message; }
162         }
163 
164         #endregion
165 
166         #region InnerException
167 
168         /// <summary>
169         /// Returns a new ConstraintExpression, which will apply the following
170         /// constraint to the InnerException property of the object being tested.
171         /// </summary>
172         public ResolvableConstraintExpression InnerException
173         {
174             get { return Has.InnerException; }
175         }
176 
177         #endregion
178 
179         #region Attribute
180 
181         /// <summary>
182         /// Returns a new AttributeConstraint checking for the
183         /// presence of a particular attribute on an object.
184         /// </summary>
Attribute(Type expectedType)185         public ResolvableConstraintExpression Attribute(Type expectedType)
186         {
187             return Has.Attribute(expectedType);
188         }
189 
190 #if CLR_2_0 || CLR_4_0
191         /// <summary>
192         /// Returns a new AttributeConstraint checking for the
193         /// presence of a particular attribute on an object.
194         /// </summary>
Attribute()195         public ResolvableConstraintExpression Attribute<T>()
196         {
197             return Attribute(typeof(T));
198         }
199 #endif
200 
201         #endregion
202 
203         #region Null
204 
205         /// <summary>
206         /// Returns a constraint that tests for null
207         /// </summary>
208         public NullConstraint Null
209         {
210             get { return new NullConstraint(); }
211         }
212 
213         #endregion
214 
215         #region True
216 
217         /// <summary>
218         /// Returns a constraint that tests for True
219         /// </summary>
220         public TrueConstraint True
221         {
222             get { return new TrueConstraint(); }
223         }
224 
225         #endregion
226 
227         #region False
228 
229         /// <summary>
230         /// Returns a constraint that tests for False
231         /// </summary>
232         public FalseConstraint False
233         {
234             get { return new FalseConstraint(); }
235         }
236 
237         #endregion
238 
239         #region Positive
240 
241         /// <summary>
242         /// Returns a constraint that tests for a positive value
243         /// </summary>
244         public GreaterThanConstraint Positive
245         {
246             get { return new GreaterThanConstraint(0); }
247         }
248 
249         #endregion
250 
251         #region Negative
252 
253         /// <summary>
254         /// Returns a constraint that tests for a negative value
255         /// </summary>
256         public LessThanConstraint Negative
257         {
258             get { return new LessThanConstraint(0); }
259         }
260 
261         #endregion
262 
263         #region NaN
264 
265         /// <summary>
266         /// Returns a constraint that tests for NaN
267         /// </summary>
268         public NaNConstraint NaN
269         {
270             get { return new NaNConstraint(); }
271         }
272 
273         #endregion
274 
275         #region Empty
276 
277         /// <summary>
278         /// Returns a constraint that tests for empty
279         /// </summary>
280         public EmptyConstraint Empty
281         {
282             get { return new EmptyConstraint(); }
283         }
284 
285         #endregion
286 
287         #region Unique
288 
289         /// <summary>
290         /// Returns a constraint that tests whether a collection
291         /// contains all unique items.
292         /// </summary>
293         public UniqueItemsConstraint Unique
294         {
295             get { return new UniqueItemsConstraint(); }
296         }
297 
298         #endregion
299 
300         #region BinarySerializable
301 
302 #if !NETCF && !SILVERLIGHT
303         /// <summary>
304         /// Returns a constraint that tests whether an object graph is serializable in binary format.
305         /// </summary>
306         public BinarySerializableConstraint BinarySerializable
307         {
308             get { return new BinarySerializableConstraint(); }
309         }
310 #endif
311 
312         #endregion
313 
314         #region XmlSerializable
315 
316 #if !SILVERLIGHT
317         /// <summary>
318         /// Returns a constraint that tests whether an object graph is serializable in xml format.
319         /// </summary>
320         public XmlSerializableConstraint XmlSerializable
321         {
322             get { return new XmlSerializableConstraint(); }
323         }
324 #endif
325 
326         #endregion
327 
328         #region EqualTo
329 
330         /// <summary>
331         /// Returns a constraint that tests two items for equality
332         /// </summary>
EqualTo(object expected)333         public EqualConstraint EqualTo(object expected)
334         {
335             return new EqualConstraint(expected);
336         }
337 
338         #endregion
339 
340         #region SameAs
341 
342         /// <summary>
343         /// Returns a constraint that tests that two references are the same object
344         /// </summary>
SameAs(object expected)345         public SameAsConstraint SameAs(object expected)
346         {
347             return new SameAsConstraint(expected);
348         }
349 
350         #endregion
351 
352         #region GreaterThan
353 
354         /// <summary>
355         /// Returns a constraint that tests whether the
356         /// actual value is greater than the suppled argument
357         /// </summary>
GreaterThan(object expected)358         public GreaterThanConstraint GreaterThan(object expected)
359         {
360             return new GreaterThanConstraint(expected);
361         }
362 
363         #endregion
364 
365         #region GreaterThanOrEqualTo
366 
367         /// <summary>
368         /// Returns a constraint that tests whether the
369         /// actual value is greater than or equal to the suppled argument
370         /// </summary>
GreaterThanOrEqualTo(object expected)371         public GreaterThanOrEqualConstraint GreaterThanOrEqualTo(object expected)
372         {
373             return new GreaterThanOrEqualConstraint(expected);
374         }
375 
376         /// <summary>
377         /// Returns a constraint that tests whether the
378         /// actual value is greater than or equal to the suppled argument
379         /// </summary>
AtLeast(object expected)380         public GreaterThanOrEqualConstraint AtLeast(object expected)
381         {
382             return new GreaterThanOrEqualConstraint(expected);
383         }
384 
385         #endregion
386 
387         #region LessThan
388 
389         /// <summary>
390         /// Returns a constraint that tests whether the
391         /// actual value is less than the suppled argument
392         /// </summary>
LessThan(object expected)393         public LessThanConstraint LessThan(object expected)
394         {
395             return new LessThanConstraint(expected);
396         }
397 
398         #endregion
399 
400         #region LessThanOrEqualTo
401 
402         /// <summary>
403         /// Returns a constraint that tests whether the
404         /// actual value is less than or equal to the suppled argument
405         /// </summary>
LessThanOrEqualTo(object expected)406         public LessThanOrEqualConstraint LessThanOrEqualTo(object expected)
407         {
408             return new LessThanOrEqualConstraint(expected);
409         }
410 
411         /// <summary>
412         /// Returns a constraint that tests whether the
413         /// actual value is less than or equal to the suppled argument
414         /// </summary>
AtMost(object expected)415         public LessThanOrEqualConstraint AtMost(object expected)
416         {
417             return new LessThanOrEqualConstraint(expected);
418         }
419 
420         #endregion
421 
422         #region TypeOf
423 
424         /// <summary>
425         /// Returns a constraint that tests whether the actual
426         /// value is of the exact type supplied as an argument.
427         /// </summary>
TypeOf(Type expectedType)428         public ExactTypeConstraint TypeOf(Type expectedType)
429         {
430             return new ExactTypeConstraint(expectedType);
431         }
432 
433 #if CLR_2_0 || CLR_4_0
434         /// <summary>
435         /// Returns a constraint that tests whether the actual
436         /// value is of the exact type supplied as an argument.
437         /// </summary>
TypeOf()438         public ExactTypeConstraint TypeOf<T>()
439         {
440             return new ExactTypeConstraint(typeof(T));
441         }
442 #endif
443 
444         #endregion
445 
446         #region InstanceOf
447 
448         /// <summary>
449         /// Returns a constraint that tests whether the actual value
450         /// is of the type supplied as an argument or a derived type.
451         /// </summary>
InstanceOf(Type expectedType)452         public InstanceOfTypeConstraint InstanceOf(Type expectedType)
453         {
454             return new InstanceOfTypeConstraint(expectedType);
455         }
456 
457 #if CLR_2_0 || CLR_4_0
458         /// <summary>
459         /// Returns a constraint that tests whether the actual value
460         /// is of the type supplied as an argument or a derived type.
461         /// </summary>
InstanceOf()462         public InstanceOfTypeConstraint InstanceOf<T>()
463         {
464             return new InstanceOfTypeConstraint(typeof(T));
465         }
466 #endif
467 
468         #endregion
469 
470         #region AssignableFrom
471 
472         /// <summary>
473         /// Returns a constraint that tests whether the actual value
474         /// is assignable from the type supplied as an argument.
475         /// </summary>
AssignableFrom(Type expectedType)476         public AssignableFromConstraint AssignableFrom(Type expectedType)
477         {
478             return new AssignableFromConstraint(expectedType);
479         }
480 
481 #if CLR_2_0 || CLR_4_0
482         /// <summary>
483         /// Returns a constraint that tests whether the actual value
484         /// is assignable from the type supplied as an argument.
485         /// </summary>
AssignableFrom()486         public AssignableFromConstraint AssignableFrom<T>()
487         {
488             return new AssignableFromConstraint(typeof(T));
489         }
490 #endif
491 
492         #endregion
493 
494         #region AssignableTo
495 
496         /// <summary>
497         /// Returns a constraint that tests whether the actual value
498         /// is assignable from the type supplied as an argument.
499         /// </summary>
AssignableTo(Type expectedType)500         public AssignableToConstraint AssignableTo(Type expectedType)
501         {
502             return new AssignableToConstraint(expectedType);
503         }
504 
505 #if CLR_2_0 || CLR_4_0
506         /// <summary>
507         /// Returns a constraint that tests whether the actual value
508         /// is assignable from the type supplied as an argument.
509         /// </summary>
AssignableTo()510         public AssignableToConstraint AssignableTo<T>()
511         {
512             return new AssignableToConstraint(typeof(T));
513         }
514 #endif
515 
516         #endregion
517 
518         #region EquivalentTo
519 
520         /// <summary>
521         /// Returns a constraint that tests whether the actual value
522         /// is a collection containing the same elements as the
523         /// collection supplied as an argument.
524         /// </summary>
EquivalentTo(IEnumerable expected)525         public CollectionEquivalentConstraint EquivalentTo(IEnumerable expected)
526         {
527             return new CollectionEquivalentConstraint(expected);
528         }
529 
530         #endregion
531 
532         #region SubsetOf
533 
534         /// <summary>
535         /// Returns a constraint that tests whether the actual value
536         /// is a subset of the collection supplied as an argument.
537         /// </summary>
SubsetOf(IEnumerable expected)538         public CollectionSubsetConstraint SubsetOf(IEnumerable expected)
539         {
540             return new CollectionSubsetConstraint(expected);
541         }
542 
543         #endregion
544 
545         #region Ordered
546 
547         /// <summary>
548         /// Returns a constraint that tests whether a collection is ordered
549         /// </summary>
550         public CollectionOrderedConstraint Ordered
551         {
552             get { return new CollectionOrderedConstraint(); }
553         }
554 
555         #endregion
556 
557         #region Member
558 
559         /// <summary>
560         /// Returns a new CollectionContainsConstraint checking for the
561         /// presence of a particular object in the collection.
562         /// </summary>
Member(object expected)563         public CollectionContainsConstraint Member(object expected)
564         {
565             return new CollectionContainsConstraint(expected);
566         }
567 
568         /// <summary>
569         /// Returns a new CollectionContainsConstraint checking for the
570         /// presence of a particular object in the collection.
571         /// </summary>
Contains(object expected)572         public CollectionContainsConstraint Contains(object expected)
573         {
574             return new CollectionContainsConstraint(expected);
575         }
576 
577         #endregion
578 
579         #region Contains
580 
581         /// <summary>
582         /// Returns a new ContainsConstraint. This constraint
583         /// will, in turn, make use of the appropriate second-level
584         /// constraint, depending on the type of the actual argument.
585         /// This overload is only used if the item sought is a string,
586         /// since any other type implies that we are looking for a
587         /// collection member.
588         /// </summary>
Contains(string expected)589         public ContainsConstraint Contains(string expected)
590         {
591             return new ContainsConstraint(expected);
592         }
593 
594         #endregion
595 
596         #region StringContaining
597 
598         /// <summary>
599         /// Returns a constraint that succeeds if the actual
600         /// value contains the substring supplied as an argument.
601         /// </summary>
StringContaining(string expected)602         public SubstringConstraint StringContaining(string expected)
603         {
604             return new SubstringConstraint(expected);
605         }
606 
607         /// <summary>
608         /// Returns a constraint that succeeds if the actual
609         /// value contains the substring supplied as an argument.
610         /// </summary>
ContainsSubstring(string expected)611         public SubstringConstraint ContainsSubstring(string expected)
612         {
613             return new SubstringConstraint(expected);
614         }
615 
616         #endregion
617 
618         #region DoesNotContain
619 
620         /// <summary>
621         /// Returns a constraint that fails if the actual
622         /// value contains the substring supplied as an argument.
623         /// </summary>
DoesNotContain(string expected)624         public SubstringConstraint DoesNotContain(string expected)
625         {
626             return new ConstraintExpression().Not.ContainsSubstring(expected);
627         }
628 
629         #endregion
630 
631         #region StartsWith
632 
633         /// <summary>
634         /// Returns a constraint that succeeds if the actual
635         /// value starts with the substring supplied as an argument.
636         /// </summary>
StartsWith(string expected)637         public StartsWithConstraint StartsWith(string expected)
638         {
639             return new StartsWithConstraint(expected);
640         }
641 
642         /// <summary>
643         /// Returns a constraint that succeeds if the actual
644         /// value starts with the substring supplied as an argument.
645         /// </summary>
StringStarting(string expected)646         public StartsWithConstraint StringStarting(string expected)
647         {
648             return new StartsWithConstraint(expected);
649         }
650 
651         #endregion
652 
653         #region DoesNotStartWith
654 
655         /// <summary>
656         /// Returns a constraint that fails if the actual
657         /// value starts with the substring supplied as an argument.
658         /// </summary>
DoesNotStartWith(string expected)659         public StartsWithConstraint DoesNotStartWith(string expected)
660         {
661             return new ConstraintExpression().Not.StartsWith(expected);
662         }
663 
664         #endregion
665 
666         #region EndsWith
667 
668         /// <summary>
669         /// Returns a constraint that succeeds if the actual
670         /// value ends with the substring supplied as an argument.
671         /// </summary>
EndsWith(string expected)672         public EndsWithConstraint EndsWith(string expected)
673         {
674             return new EndsWithConstraint(expected);
675         }
676 
677         /// <summary>
678         /// Returns a constraint that succeeds if the actual
679         /// value ends with the substring supplied as an argument.
680         /// </summary>
StringEnding(string expected)681         public EndsWithConstraint StringEnding(string expected)
682         {
683             return new EndsWithConstraint(expected);
684         }
685 
686         #endregion
687 
688         #region DoesNotEndWith
689 
690         /// <summary>
691         /// Returns a constraint that fails if the actual
692         /// value ends with the substring supplied as an argument.
693         /// </summary>
DoesNotEndWith(string expected)694         public EndsWithConstraint DoesNotEndWith(string expected)
695         {
696             return new ConstraintExpression().Not.EndsWith(expected);
697         }
698 
699         #endregion
700 
701         #region Matches
702 
703 #if !NETCF
704         /// <summary>
705         /// Returns a constraint that succeeds if the actual
706         /// value matches the regular expression supplied as an argument.
707         /// </summary>
Matches(string pattern)708         public RegexConstraint Matches(string pattern)
709         {
710             return new RegexConstraint(pattern);
711         }
712 
713         /// <summary>
714         /// Returns a constraint that succeeds if the actual
715         /// value matches the regular expression supplied as an argument.
716         /// </summary>
StringMatching(string pattern)717         public RegexConstraint StringMatching(string pattern)
718         {
719             return new RegexConstraint(pattern);
720         }
721 #endif
722 
723         #endregion
724 
725         #region DoesNotMatch
726 
727 #if !NETCF
728         /// <summary>
729         /// Returns a constraint that fails if the actual
730         /// value matches the pattern supplied as an argument.
731         /// </summary>
DoesNotMatch(string pattern)732         public RegexConstraint DoesNotMatch(string pattern)
733         {
734             return new ConstraintExpression().Not.Matches(pattern);
735         }
736 #endif
737 
738         #endregion
739 
740         #region SamePath
741 
742         /// <summary>
743         /// Returns a constraint that tests whether the path provided
744         /// is the same as an expected path after canonicalization.
745         /// </summary>
SamePath(string expected)746         public SamePathConstraint SamePath(string expected)
747         {
748             return new SamePathConstraint(expected);
749         }
750 
751         #endregion
752 
753         #region SubPath
754 
755         /// <summary>
756         /// Returns a constraint that tests whether the path provided
757         /// is the same path or under an expected path after canonicalization.
758         /// </summary>
SubPath(string expected)759         public SubPathConstraint SubPath(string expected)
760         {
761             return new SubPathConstraint(expected);
762         }
763 
764         #endregion
765 
766         #region SamePathOrUnder
767 
768         /// <summary>
769         /// Returns a constraint that tests whether the path provided
770         /// is the same path or under an expected path after canonicalization.
771         /// </summary>
SamePathOrUnder(string expected)772         public SamePathOrUnderConstraint SamePathOrUnder(string expected)
773         {
774             return new SamePathOrUnderConstraint(expected);
775         }
776 
777         #endregion
778 
779         #region InRange
780 
781 #if CLR_2_0 || CLR_4_0
782         /// <summary>
783         /// Returns a constraint that tests whether the actual value falls
784         /// within a specified range.
785         /// </summary>
786         public RangeConstraint<T> InRange<T>(T from, T to) where T : IComparable<T>
787         {
788             return new RangeConstraint<T>(from, to);
789         }
790 #else
791         /// <summary>
792         /// Returns a constraint that tests whether the actual value falls
793         /// within a specified range.
794         /// </summary>
InRange(IComparable from, IComparable to)795         public RangeConstraint InRange(IComparable from, IComparable to)
796         {
797             return new RangeConstraint(from, to);
798         }
799 #endif
800 
801         #endregion
802 
803     }
804 }
805