1 /** 2 Copyright: 2017 © LLC CERERIS 3 License: MIT 4 Authors: LLC CERERIS 5 */ 6 7 module checkit.assertion; 8 9 import checkit.exception; 10 import core.exception; 11 import core.time; 12 import std.algorithm.comparison: max, min; 13 import std.conv; 14 import std.datetime; 15 import std.range; 16 import std..string; 17 import std.traits; 18 19 private void fail(in string output, in string file, in size_t line) @safe pure 20 { 21 throw new UnitTestException([output], file, line); 22 } 23 24 /** Used to assert that one value is equal to null. 25 26 Params: 27 value = The value that should equal null. 28 message = The exception message. 29 file = The file name that the assert failed in. Should be left as default. 30 line = The file line that the assert failed in. Should be left as default. 31 Throws: 32 If value is NOT null, will throw an UnitTestException. 33 34 Examples: 35 --- 36 // Will throw an exception like "checkit.exception.UnitTestException@example.d(6): Expected <null>, got <blah>." 37 string test = "blah"; 38 test.shouldBeNull(); 39 --- 40 */ 41 void shouldBeNull(T)( in auto ref T value, 42 in string message = null, 43 in string file = __FILE__, 44 in size_t line = __LINE__) 45 { 46 if(value !is null) 47 { 48 fail(message !is null ? message : "Expected <null>", file, line); 49 } 50 } 51 52 /** Used to assert that one value is not equal to null. 53 54 Params: 55 value = The value that should not equal null. 56 message = The exception message. 57 file = The file name that the assert failed in. Should be left as default. 58 line = The file line that the assert failed in. Should be left as default. 59 Throws: 60 If value is null, will throw an UnitTestException. 61 62 Examples: 63 --- 64 // Will throw an exception like "checkit.exception.UnitTestException@example.d(6): Expected not <null>, got <null>" 65 string test = null; 66 test.shouldNotBeNull(); 67 --- 68 */ 69 void shouldNotBeNull(T)(in auto ref T value, 70 in string message = null, 71 in string file = __FILE__, 72 in size_t line = __LINE__) 73 { 74 if(value is null) 75 { 76 fail(message !is null ? message : "Expected not <null>, got <null>", file, line); 77 } 78 } 79 80 private enum isObject(T) = is(T == class) || is(T == interface); 81 82 private bool isEqual(V, E)(in auto ref V value, in auto ref E expected) 83 if(!isObject!V && 84 (!isInputRange!V || !isInputRange!E) && 85 !isFloatingPoint!V && !isFloatingPoint!E && 86 is(typeof(value == expected) == bool)) 87 { 88 return value == expected; 89 } 90 91 private bool isEqual(V, E)(in V value, in E expected) 92 if (!isObject!V && (isFloatingPoint!V || isFloatingPoint!E) && is(typeof(value == expected) == bool)) 93 { 94 return value == expected; 95 } 96 97 private bool isEqual(V, E)(V value, E expected) 98 if (!isObject!V && isInputRange!V && isInputRange!E && is(typeof(value.front == expected.front) == bool)) 99 { 100 import std.algorithm: equal; 101 return equal(value, expected); 102 } 103 104 private bool isEqual(V, E)(V value, E expected) 105 if (!isObject!V && 106 isInputRange!V && isInputRange!E && !is(typeof(value.front == expected.front) == bool) && 107 isInputRange!(ElementType!V) && isInputRange!(ElementType!E)) 108 { 109 import std.algorithm: equal; 110 111 while(!value.empty && !expected.empty) 112 { 113 if(!equal(value.front, expected.front)) 114 return false; 115 116 value.popFront; 117 expected.popFront; 118 } 119 120 return value.empty && expected.empty; 121 } 122 123 private bool isEqual(V, E)(V value, E expected) 124 if (isObject!V && isObject!E) 125 { 126 static assert(is(typeof(() 127 { 128 string s1 = value.toString; 129 string s2 = expected.toString; 130 })), "Cannot compare instances of " ~ V.stringof ~ " or " ~ E.stringof ~ " unless toString is overridden for both"); 131 132 return value.tupleof == expected.tupleof; 133 } 134 135 /** Used to assert that one value is equal to another value. 136 137 Params: 138 value = The value. 139 expected = The expected value. 140 message = The exception message. 141 file = The file name that the assert failed in. Should be left as default. 142 line = The file line that the assert failed in. Should be left as default. 143 Throws: 144 If values are not equal, will throw an UnitTestException with expected and actual values. 145 146 Examples: 147 --- 148 // Will throw an exception like "checkit.exception.UnitTestException@example.d(6): <3> expected to equal <5>." 149 int z = 3; 150 z.shouldEqual(5); 151 --- 152 */ 153 void shouldEqual(T, U)( auto ref T value, 154 auto ref U expected, 155 in string message = null, 156 in string file = __FILE__, 157 in size_t line = __LINE__) 158 { 159 if(!isEqual(value, expected)) 160 { 161 fail(message !is null ? message : "Expected <%s>, got <%s>".format(expected, value), file, line); 162 } 163 } 164 165 /** Used to assert that one value is not equal to another value. 166 167 Params: 168 value = The value to test. 169 expected = The value it should not be equal to. 170 message = The exception message. 171 file = The file name that the assert failed in. Should be left as default. 172 line = The file line that the assert failed in. Should be left as default. 173 Throws: 174 If values are equal, will throw an UnitTestException with expected and actual values. 175 176 Examples: 177 --- 178 // Will throw an exception like "checkit.exception.UnitTestException@example.d(6): Expected not <abc>, got <abc>" 179 "abc".shouldNotEqual("abc"); 180 --- 181 */ 182 void shouldNotEqual(T, U)(T value, U expected, 183 in string message = null, 184 in string file = __FILE__, 185 in size_t line = __LINE__) 186 { 187 if(isEqual(value, expected)) 188 { 189 fail(message !is null ? message : "Expected not <%s>, got <%s>".format(expected, value), file, line); 190 } 191 } 192 193 /** Used to assert that one value is equal to true. 194 195 Params: 196 condition = The value that should equal true. 197 message = The exception message. 198 file = The file name that the assert failed in. Should be left as default. 199 line = The file line that the assert failed in. Should be left as default. 200 Throws: 201 If values are not true, will throw an UnitTestException with expected and actual values. 202 203 Examples: 204 --- 205 // Will throw an exception like "checkit.exception.UnitTestException@example.d(6): Expected <true>, got <false>" 206 false.shouldBeTrue(); 207 --- 208 */ 209 void shouldBeTrue(T)(lazy T condition, in string message = null, in string file = __FILE__, in size_t line = __LINE__) 210 { 211 shouldEqual(cast(bool) condition, true, message, file, line); 212 } 213 214 /** Used to assert that one value is equal to false. 215 216 Params: 217 condition = The value that should equal false. 218 message = The exception message. 219 file = The file name that the assert failed in. Should be left as default. 220 line = The file line that the assert failed in. Should be left as default. 221 Throws: 222 If values are not false, will throw an UnitTestException with expected and actual values. 223 224 Examples: 225 --- 226 // Will throw an exception like "checkit.exception.UnitTestException@example.d(6): Expected <false>, got <true>" 227 true.shouldBeFalse(); 228 --- 229 */ 230 void shouldBeFalse(T)(lazy T condition, in string message = null, in string file = __FILE__, in size_t line = __LINE__) 231 { 232 shouldEqual(cast(bool) condition, false, message, file, line); 233 } 234 235 private auto threw(T: Throwable, E)(lazy E expr) @trusted 236 { 237 struct ThrowResult 238 { 239 bool threw; 240 TypeInfo typeInfo; 241 immutable(T) throwable; 242 243 T opCast(T)() const pure if (is(T == bool)) 244 { 245 return threw; 246 } 247 } 248 249 try 250 { 251 expr(); 252 } 253 catch(T e) 254 { 255 return ThrowResult(true, typeid(e), cast(immutable)e); 256 } 257 258 return ThrowResult(false); 259 } 260 261 /** Used for asserting that a expression will throw an exception. 262 263 Params: 264 condition = The expression that is expected to throw the exception. 265 file = The file name that the assert failed in. Should be left as default. 266 line = The file line that the assert failed in. Should be left as default. 267 Throws: 268 If expression does not throw, will throw an UnitTestException. 269 270 Examples: 271 --- 272 // Makes sure it throws with the message "test" 273 void noThrow(){}; 274 void withThrow(){throw new Exception("test");}; 275 276 // Will throw an exception like "checkit.exception.UnitTestException@test/example.d(7): Expression did not throw" 277 noThrow.shouldThrow(); 278 // Will throw an exception like "checkit.exception.UnitTestException@test/example.d(7): Expression did not throw" 279 noThrow.shouldThrow!Exception(); 280 281 // Will throw an exception like "checkit.exception.UnitTestException@test/example.d(7): Expected <UnitTestException>, but throw <object.Exception>" 282 withThrow.shouldThrow!UnitTestException(); 283 --- 284 */ 285 void shouldThrow(T: Throwable = Exception, E)(lazy E condition, in string file = __FILE__, in size_t line = __LINE__) 286 { 287 import std.conv: text; 288 289 bool isThrow = true; 290 291 () @trusted 292 { 293 try 294 { 295 if(!threw!T(condition)) 296 { 297 isThrow = false; 298 } 299 } 300 catch(Throwable t) 301 { 302 fail(text("Expected <", T.stringof, ">, but throw <", typeid(t), ">"), file, line); 303 } 304 }(); 305 306 if(!isThrow) 307 { 308 fail("Expression did not throw", file, line); 309 } 310 } 311 312 /** Used for asserting that a expression will not throw an exception. 313 314 Params: 315 condition = The expression that is expected to not throw the exception. 316 file = The file name that the assert failed in. Should be left as default. 317 line = The file line that the assert failed in. Should be left as default. 318 Throws: 319 If expression does throw, will throw an UnitTestException. 320 321 Examples: 322 --- 323 // Makes sure it throws with the message "test" 324 void noThrow(){}; 325 void withThrow(){throw new Exception("test");}; 326 327 // Will throw an exception like "checkit.exception.UnitTestException@test/example.d(7): Expression threw" 328 noThrow.shouldNotThrow(); 329 --- 330 */ 331 void shouldNotThrow(T: Throwable = Exception, E)(lazy E condition, in string file = __FILE__, in size_t line = __LINE__) 332 { 333 if(threw!T(condition)) 334 { 335 fail("Expression threw", file, line); 336 } 337 } 338 339 /** Used for asserting that a expression will throw an exception with message. 340 341 Params: 342 condition = The expression that is expected to throw the exception. 343 message = Expected message exception. 344 file = The file name that the assert failed in. Should be left as default. 345 line = The file line that the assert failed in. Should be left as default. 346 Throws: 347 If expression does throw and message not expected, will throw an UnitTestException. 348 349 Examples: 350 --- 351 // Makes sure it throws with the message "test" 352 void withThrow(){throw new Exception("test");}; 353 354 // Will throw an exception like "checkit.exception.UnitTestException@test/example.d(7): Expression did not throw" 355 withThrow.shouldThrowWithMessage("bar"); 356 --- 357 */ 358 void shouldThrowWithMessage(T: Throwable = Exception, E)( lazy E condition, 359 in string message, 360 in string file = __FILE__, 361 in size_t line = __LINE__) 362 { 363 auto threw = threw!T(condition); 364 365 if(!threw) 366 fail("Expression did not throw", file, line); 367 368 if(message != threw.throwable.msg) 369 { 370 fail("Expected exception message <%s>, but got <%s>".format(message, threw.throwable.msg), file, line); 371 } 372 } 373 374 /** Used to assert that object is instance of class. 375 376 Params: 377 T = Excepted instance class. 378 object = The object it should be instance of specific class. 379 message = The exception message. 380 file = The file name that the assert failed in. Should be left as default. 381 line = The file line that the assert failed in. Should be left as default. 382 Throws: 383 If object is not instance of class, will throw an UnitTestException. 384 385 Examples: 386 --- 387 interface DummyInterface 388 { 389 public: 390 void test(); 391 } 392 393 class Dummy: DummyInterface 394 { 395 public: 396 override test() 397 { 398 } 399 } 400 401 auto a = new Dummy; 402 auto b = cast(DummyInterface) a; 403 b.shouldBeInstanceOf!Dummy(); 404 --- 405 */ 406 void shouldBeInstanceOf(T, U)(U object, in string message = null, in string file = __FILE__, in size_t line = __LINE__) 407 { 408 if(cast(T)object is null) 409 { 410 fail(message ? message : "<%s> expected to be instance of <%s>".format(object, T.classinfo.name), file, line); 411 } 412 } 413 414 /** Used to assert that one value is greater than another value. 415 416 Params: 417 value = The value to test. 418 expected = The value it should be greater than. 419 message = Exception message. 420 file = The file name that the assert failed in. Should be left as default. 421 line = The file line that the assert failed in. Should be left as default. 422 423 Throws: 424 If the value is not greater, will throw an UnitTestException with expected and actual values. 425 426 Examples: 427 --- 428 // Will throw an exception like "UnitTestException@example.d(6): <5> expected to be greater than <10>." 429 5.shouldBeGreater(10); 430 --- 431 */ 432 void shouldBeGreater(T, U)( T value, 433 U expected, 434 in string message = null, 435 in string file = __FILE__, 436 in size_t line = __LINE__) 437 { 438 if(value <= expected) 439 { 440 fail(message ? message : "<%s> expected to be greater than <%s>".format(value, expected), file, line); 441 } 442 } 443 444 /** Used to assert that one value is greater or equal than another value. 445 446 Params: 447 value = The value to test. 448 expected = The value it should be greater or equal than. 449 message = Exception message. 450 file = The file name that the assert failed in. Should be left as default. 451 line = The file line that the assert failed in. Should be left as default. 452 453 Throws: 454 If the value is not greater or equal, will throw an UnitTestException with expected and actual values. 455 456 Examples: 457 --- 458 // Will throw an exception like "UnitTestException@example.d(6): <5> expected to be greater or equal to <10>." 459 5.shouldBeGreater(10); 460 --- 461 */ 462 void shouldBeGreaterOrEqual(T, U)(T value, 463 U expected, 464 in string message = null, 465 in string file = __FILE__, 466 in size_t line = __LINE__) 467 { 468 if(value < expected) 469 { 470 fail(message ? message : "<%s> expected to be greater or equal to <%s>".format(value, expected), file, line); 471 } 472 } 473 474 /** Used to assert that one value is less than another value. 475 476 Params: 477 value = The value to test. 478 expected = The value it should be less than. 479 message = Exception message. 480 file = The file name that the assert failed in. Should be left as default. 481 line = The file line that the assert failed in. Should be left as default. 482 483 Throws: 484 If the value is not less, will throw an UnitTestException with expected and actual values. 485 486 Examples: 487 --- 488 // Will throw an exception like "UnitTestException@example.d(6): <5> expected to be less than <10>." 489 10.shouldBeLess(5); 490 --- 491 */ 492 void shouldBeLess(T, U)(T value, 493 U expected, 494 in string message = null, 495 in string file = __FILE__, 496 in size_t line = __LINE__) 497 { 498 if(value >= expected) 499 { 500 fail(message ? message : "<%s> expected to be less than <%s>".format(value, expected), file, line); 501 } 502 } 503 504 /** Used to assert that one value is less or equal than another value. 505 506 Params: 507 value = The value to test. 508 expected = The value it should be less or equal than. 509 message = Exception message. 510 file = The file name that the assert failed in. Should be left as default. 511 line = The file line that the assert failed in. Should be left as default. 512 513 Throws: 514 If the value is not less or equal, will throw an UnitTestException with expected and actual values. 515 516 Examples: 517 --- 518 // Will throw an exception like "UnitTestException@example.d(6): <5> expected to be less or equal to <10>." 519 10.shouldBeLessOrEqual(5); 520 --- 521 */ 522 void shouldBeLessOrEqual(T, U)( T value, 523 U expected, 524 in string message = null, 525 in string file = __FILE__, 526 in size_t line = __LINE__) 527 { 528 if(value > expected) 529 { 530 fail(message ? message : "<%s> expected to be less or equal to <%s>".format(value, expected), file, line); 531 } 532 } 533 534 /** Used to assert that value is between two values. 535 536 Params: 537 value = The expected value 538 left = The expected left value of range. 539 right = The expected right value of range. 540 message = Exception message. 541 file = The file name that the assert failed in. Should be left as default. 542 line = The file line that the assert failed in. Should be left as default. 543 544 Throws: 545 If the value is not between, will throw an UnitTestException with expected and actual values. 546 547 Examples: 548 --- 549 // Will throw an exception like "UnitTestException@example.d(6): <5> expected to be between <15> and <20>." 550 10.shouldBeBetween(15, 20); 551 --- 552 */ 553 void shouldBeBetween(T, U, C)(T value, 554 U left, 555 C right, 556 in string message = null, 557 in string file = __FILE__, 558 in size_t line = __LINE__) 559 { 560 if(value >= max(left,right) || value <= min(left,right)) 561 { 562 fail( message ? message : "<%s> expected to be between <%s> and <%s>".format( value, 563 min(left, right), 564 max(left, right)), 565 file, 566 line); 567 } 568 } 569 570 /** Used to assert that value is between or equal two values. 571 572 Params: 573 value = The expected value 574 left = The expected left value of range. 575 right = The expected right value of range. 576 message = Exception message. 577 file = The file name that the assert failed in. Should be left as default. 578 line = The file line that the assert failed in. Should be left as default. 579 580 Throws: 581 If the value is not between or equal, will throw an UnitTestException with expected and actual values. 582 583 Examples: 584 --- 585 // Will throw an exception like "UnitTestException@example.d(6): <5> expected to be between <15> and <20>." 586 10.shouldBeBetweenOrEqual(15, 20); 587 --- 588 */ 589 void shouldBeBetweenOrEqual(T, U, C)( T value, 590 U left, 591 C right, 592 string message = null, 593 string file = __FILE__, 594 size_t line = __LINE__) 595 { 596 if(value > max(left,right) || value < min(left,right)) 597 { 598 fail( message ? message : "<%s> expected to be between or equal <%s> and <%s>".format( value, 599 min(left, right), 600 max(left, right)), 601 file, 602 line); 603 } 604 } 605 606 /** Used to assert that Range is empty. 607 608 Params: 609 rng = The expected Range. 610 message = Exception message. 611 file = The file name that the assert failed in. Should be left as default. 612 line = The file line that the assert failed in. Should be left as default. 613 614 Throws: 615 If the Range is not empty, will throw an UnitTestException with expected and actual values. 616 617 Examples: 618 --- 619 // Will throw an exception like "UnitTestException@example.d(6): Expected empty Range, but got <[1]>" 620 [1].shouldBeEmpty(); 621 --- 622 */ 623 void shouldBeEmpty(R)(in auto ref R rng, in string message = null, in string file = __FILE__, in size_t line = __LINE__) 624 if (isInputRange!R) 625 { 626 if(!rng.empty) 627 { 628 fail(message ? message : "Expected empty Range, but got <%s>".format(rng), file, line); 629 } 630 } 631 632 /** Used to assert that Associative array is empty. 633 634 Params: 635 aa = The expected associative array. 636 message = Exception message. 637 file = The file name that the assert failed in. Should be left as default. 638 line = The file line that the assert failed in. Should be left as default. 639 640 Throws: 641 If the Associative array is not empty, will throw an UnitTestException with expected and actual values. 642 643 Examples: 644 --- 645 // Will throw an exception like "UnitTestException@example.d(6): Expected empty Associative Array, but got <["test":12]>" 646 ["test":12].shouldBeEmpty(); 647 --- 648 */ 649 void shouldBeEmpty(T)(auto ref T aa, in string message = null, in string file = __FILE__, in size_t line = __LINE__) 650 if(isAssociativeArray!T) 651 { 652 () @trusted 653 { 654 if(!aa.keys.empty) 655 { 656 fail(message ? message : "Expected empty Associative Array, but got <%s>".format(aa), file, line); 657 } 658 }(); 659 } 660 661 /** Used to assert that Range is not empty. 662 663 Params: 664 rng = The expected Range. 665 message = Exception message. 666 file = The file name that the assert failed in. Should be left as default. 667 line = The file line that the assert failed in. Should be left as default. 668 669 Throws: 670 If the Range is empty, will throw an UnitTestException with expected and actual values. 671 672 Examples: 673 --- 674 // Will throw an exception like "UnitTestException@example.d(6): Expected is not empty Range" 675 [1].shouldBeEmpty(); 676 --- 677 */ 678 void shouldBeNotEmpty(R)( in auto ref R rng, 679 in string message = null, 680 in string file = __FILE__, 681 in size_t line = __LINE__) 682 if (isInputRange!R) 683 { 684 if(rng.empty) 685 { 686 fail(message ? message : "Expected is not empty Range", file, line); 687 } 688 } 689 690 /** Used to assert that Associative array is not empty. 691 692 Params: 693 aa = The expected associative array. 694 message = Exception message. 695 file = The file name that the assert failed in. Should be left as default. 696 line = The file line that the assert failed in. Should be left as default. 697 698 Throws: 699 If the Associative array is empty, will throw an UnitTestException with expected and actual values. 700 701 Examples: 702 --- 703 // Will throw an exception like "UnitTestException@example.d(6): Expected is not empty Associative Array" 704 ["test":12].shouldBeEmpty(); 705 --- 706 */ 707 void shouldBeNotEmpty(T)(auto ref T aa, in string message = null, in string file = __FILE__, in size_t line = __LINE__) 708 if(isAssociativeArray!T) 709 { 710 () @trusted 711 { 712 if(aa.keys.empty) 713 { 714 fail(message ? message : "Expected is not empty Associative Array", file, line); 715 } 716 }(); 717 } 718 719 /** Used to assert that one value is in an array of specified values. 720 721 Params: 722 value = The value to test. 723 expected = An array of valid values. 724 message = Exception message. 725 file = The file name that the assert failed in. Should be left as default. 726 line = The file line that the assert failed in. Should be left as default. 727 728 Throws: 729 If the value is not in the array, will throw an UnitTestException with the value and array values. 730 731 Examples: 732 --- 733 // Will throw an exception like "UnitTestException@example.d(6): <Peter> is not in <[Andrew, Anatoly]>." 734 "Peter".shouldBeIn(["Andrew", "Anatoly"]); 735 --- 736 */ 737 void shouldBeIn(T, U)(T value, 738 U expected, 739 in string message = null, 740 in string file = __FILE__, 741 in size_t line = __LINE__) 742 { 743 import std.algorithm: canFind; 744 745 if(!expected.canFind(value)) 746 { 747 fail(message ? message : "<%s> is not in <[%s]>".format(value, expected.join(", ")), file, line); 748 } 749 } 750 751 /** Used to assert that array is contain of specified value. 752 753 Params: 754 array = An array of values. 755 expected = The valid value. 756 message = Exception message. 757 file = The file name that the assert failed in. Should be left as default. 758 line = The file line that the assert failed in. Should be left as default. 759 760 Throws: 761 If an array is not contain the value, will throw an UnitTestException with the value and array values. 762 763 Examples: 764 --- 765 // Will throw an exception like "UnitTestException@example.d(6): <[Peter, Anatoliy]> is not contain <Andrew>." 766 ["Peter", "Anatoly"].shouldBeContain("Andrew"); 767 --- 768 */ 769 void shouldBeContain(T, U)( T[] array, 770 U expected, 771 in string message = null, 772 in string file = __FILE__, 773 in size_t line = __LINE__) 774 { 775 import std.algorithm: canFind; 776 777 if(!array.canFind(expected)) 778 { 779 fail(message ? message : "<[%s]> is not contain <%s>".format(array.join(", "), expected), file, line); 780 } 781 } 782 783 /** Used to assert that JSON object is equal. 784 785 Params: 786 actual = The actual JSON object. 787 expected = The excpected JSON. 788 message = Exception message. 789 file = The file name that the assert failed in. Should be left as default. 790 line = The file line that the assert failed in. Should be left as default. 791 792 Throws: 793 If an JSON objects is not equal, will throw an UnitTestException. 794 795 Examples: 796 --- 797 // Will throw an exception like "UnitTestException@example.d(6): Error parsing JSON: Unexpected end of data. (Line 1:10)" 798 `{"test" :1`.shouldBeEqualJSON(`{"test":1}`); 799 800 // Will throw an exception like "UnitTestException@example.d(6):`{"test" :1, "some" : "12"}`.shouldBeEqualJSON(`{"test":1}`); 801 `{"test" :1, "some" : "12"}`.shouldBeEqualJSON(`{"test":1}`); 802 --- 803 */ 804 void shouldBeEqualJSON( in string actual, 805 in string expected, 806 in string message = null, 807 in string file = __FILE__, 808 in size_t line = __LINE__) 809 { 810 import std.json: JSONException, JSONValue, parseJSON; 811 812 try 813 { 814 actual.parseJSON.toPrettyString.shouldEqual(expected.parseJSON.toPrettyString, message, file, line); 815 } 816 catch(JSONException e) 817 { 818 fail("Error parsing JSON: " ~ e.msg, file, line); 819 } 820 } 821 822 /** Used to assert that expression should be run less duration 823 824 Params: 825 condition = The run expression. 826 time = The maximum duration or running. 827 message = Exception message. 828 file = The file name that the assert failed in. Should be left as default. 829 line = The file line that the assert failed in. Should be left as default. 830 831 Throws: 832 If expression run greater time, will throw an UnitTestException. 833 834 Examples: 835 --- 836 // Will throw an exception like "UnitTestException@example.d(6): Expected run time <1 seconds>, but run <2 seconds> 837 {Thread.sleep(2.seconds)}.shouldRunLess(1.seconds); 838 --- 839 */ 840 void shouldRunLess(E)(lazy E condition, 841 in Duration time, 842 in string message = null, 843 in string file = __FILE__, 844 in size_t line = __LINE__) 845 { 846 immutable auto startTime = Clock.currTime(); 847 condition(); 848 849 auto delta = Clock.currTime() - startTime; 850 if(delta > time) 851 { 852 fail(message ? message : "Expected run time <%s>, but run <%s>".format(to!string(time), delta), file, line); 853 } 854 }