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