1 module unit_threaded.ut.should; 2 3 import unit_threaded.should; 4 import unit_threaded.asserts; 5 6 private void assertFail(E)(lazy E expression, in string file = __FILE__, in size_t line = __LINE__) 7 { 8 import std.exception: assertThrown; 9 assertThrown!UnitTestException(expression, null, file, line); 10 } 11 12 13 @safe pure unittest { 14 static struct Foo { 15 bool opCast(T: bool)() { 16 return true; 17 } 18 } 19 shouldBeTrue(Foo()); 20 } 21 22 23 @safe pure unittest { 24 static struct Foo { 25 bool opCast(T: bool)() { 26 return false; 27 } 28 } 29 shouldBeFalse(Foo()); 30 } 31 32 @safe unittest { 33 //impure comparisons 34 shouldEqual(1.0, 1.0) ; 35 shouldNotEqual(1.0, 1.0001); 36 } 37 38 @safe pure unittest { 39 import unit_threaded.asserts; 40 41 assertExceptionMsg(3.shouldEqual(5), 42 " tests/unit_threaded/ut/should.d:123 - Expected: 5\n" ~ 43 " tests/unit_threaded/ut/should.d:123 - Got: 3"); 44 45 assertExceptionMsg("foo".shouldEqual("bar"), 46 " tests/unit_threaded/ut/should.d:123 - Expected: \"bar\"\n" ~ 47 " tests/unit_threaded/ut/should.d:123 - Got: \"foo\""); 48 49 assertExceptionMsg([1, 2, 4].shouldEqual([1, 2, 3]), 50 " tests/unit_threaded/ut/should.d:123 - Expected: [1, 2, 3]\n" ~ 51 " tests/unit_threaded/ut/should.d:123 - Got: [1, 2, 4]"); 52 53 assertExceptionMsg([[0, 1, 2, 3, 4], [1], [2], [3], [4], [5]].shouldEqual([[0], [1], [2]]), 54 " tests/unit_threaded/ut/should.d:123 - Expected: [[0], [1], [2]]\n" ~ 55 " tests/unit_threaded/ut/should.d:123 - Got: [[0, 1, 2, 3, 4], [1], [2], [3], [4], [5]]"); 56 57 assertExceptionMsg([[0, 1, 2, 3, 4, 5], [1], [2], [3]].shouldEqual([[0], [1], [2]]), 58 " tests/unit_threaded/ut/should.d:123 - Expected: [[0], [1], [2]]\n" ~ 59 " tests/unit_threaded/ut/should.d:123 - Got: [[0, 1, 2, 3, 4, 5], [1], [2], [3]]"); 60 61 62 assertExceptionMsg([[0, 1, 2, 3, 4, 5], [1], [2], [3], [4], [5]].shouldEqual([[0]]), 63 " tests/unit_threaded/ut/should.d:123 - Expected: [[0]]\n" ~ 64 " tests/unit_threaded/ut/should.d:123 - Got: [\n" ~ 65 " tests/unit_threaded/ut/should.d:123 - [0, 1, 2, 3, 4, 5],\n" ~ 66 " tests/unit_threaded/ut/should.d:123 - [1],\n" ~ 67 " tests/unit_threaded/ut/should.d:123 - [2],\n" ~ 68 " tests/unit_threaded/ut/should.d:123 - [3],\n" ~ 69 " tests/unit_threaded/ut/should.d:123 - [4],\n" ~ 70 " tests/unit_threaded/ut/should.d:123 - [5],\n" ~ 71 " tests/unit_threaded/ut/should.d:123 - ]"); 72 73 assertExceptionMsg(1.shouldNotEqual(1), 74 " tests/unit_threaded/ut/should.d:123 - Value:\n" ~ 75 " tests/unit_threaded/ut/should.d:123 - 1\n" ~ 76 " tests/unit_threaded/ut/should.d:123 - is not expected to be equal to:\n" ~ 77 " tests/unit_threaded/ut/should.d:123 - 1"); 78 } 79 80 @safe pure unittest 81 { 82 ubyte[] arr; 83 ubyte[] empty; 84 arr.shouldEqual(empty); 85 } 86 87 88 @safe pure unittest 89 { 90 int[] ints = [1, 2, 3]; 91 byte[] bytes = [1, 2, 3]; 92 byte[] bytes2 = [1, 2, 4]; 93 shouldEqual(ints, bytes); 94 shouldEqual(bytes, ints) ; 95 shouldNotEqual(ints, bytes2) ; 96 97 const constIntToInts = [1 : 2, 3 : 7, 9 : 345]; 98 auto intToInts = [1 : 2, 3 : 7, 9 : 345]; 99 shouldEqual(intToInts, constIntToInts) ; 100 shouldEqual(constIntToInts, intToInts) ; 101 } 102 103 @safe unittest { 104 shouldEqual([1 : 2.0, 2 : 4.0], [1 : 2.0, 2 : 4.0]) ; 105 shouldNotEqual([1 : 2.0, 2 : 4.0], [1 : 2.2, 2 : 4.0]) ; 106 } 107 108 @system pure unittest { 109 import std.range: iota; 110 const constRange = 3.iota; 111 shouldEqual(constRange, constRange); 112 } 113 114 @system pure unittest 115 { 116 class Foo 117 { 118 this(int i) { this.i = i; } 119 override string toString() @safe const 120 { 121 import std.conv: to; 122 return i.to!string; 123 } 124 int i; 125 } 126 127 shouldNotBeNull(new Foo(4)); 128 assertFail(shouldNotBeNull(null)); 129 shouldEqual(new Foo(5), new Foo(5)); 130 assertFail(shouldEqual(new Foo(5), new Foo(4))); 131 shouldNotEqual(new Foo(5), new Foo(4)); 132 assertFail(shouldNotEqual(new Foo(5), new Foo(5))); 133 } 134 135 @safe pure unittest 136 { 137 shouldBeNull(null); 138 assertFail(shouldBeNull(new int)); 139 } 140 141 142 @safe pure unittest { 143 5.shouldBeIn([5: "foo"]); 144 145 struct AA { 146 int onlyKey; 147 bool opBinaryRight(string op)(in int key) const { 148 return key == onlyKey; 149 } 150 } 151 152 5.shouldBeIn(AA(5)); 153 assertFail(5.shouldBeIn(AA(4))); 154 } 155 156 @safe pure unittest 157 { 158 shouldBeIn(4, [1, 2, 4]); 159 shouldBeIn("foo", ["foo" : 1]); 160 assertFail("foo".shouldBeIn(["bar"])); 161 } 162 163 @safe pure unittest { 164 assertExceptionMsg("foo".shouldBeIn(["quux": "toto"]), 165 ` tests/unit_threaded/ut/should.d:123 - Value "foo"` ~ "\n" ~ 166 ` tests/unit_threaded/ut/should.d:123 - not in ["quux":"toto"]`); 167 } 168 169 @safe pure unittest { 170 assertExceptionMsg("foo".shouldBeIn("quux"), 171 ` tests/unit_threaded/ut/should.d:123 - Value "foo"` ~ "\n" ~ 172 ` tests/unit_threaded/ut/should.d:123 - not in "quux"`); 173 174 } 175 176 @safe pure unittest { 177 5.shouldNotBeIn([4: "foo"]); 178 179 struct AA { 180 int onlyKey; 181 bool opBinaryRight(string op)(in int key) const { 182 return key == onlyKey; 183 } 184 } 185 186 5.shouldNotBeIn(AA(4)); 187 assertFail(5.shouldNotBeIn(AA(5))); 188 } 189 190 @safe pure unittest { 191 assertExceptionMsg("quux".shouldNotBeIn(["quux": "toto"]), 192 ` tests/unit_threaded/ut/should.d:123 - Value "quux"` ~ "\n" ~ 193 ` tests/unit_threaded/ut/should.d:123 - is in ["quux":"toto"]`); 194 } 195 196 @safe pure unittest { 197 assertExceptionMsg("foo".shouldNotBeIn("foobar"), 198 ` tests/unit_threaded/ut/should.d:123 - Value "foo"` ~ "\n" ~ 199 ` tests/unit_threaded/ut/should.d:123 - is in "foobar"`); 200 201 } 202 203 204 @safe pure unittest { 205 assertExceptionMsg((1 == 2).shouldThrow, 206 ` tests/unit_threaded/ut/should.d:123 - Expression did not throw`); 207 } 208 209 210 @safe pure unittest { 211 static void oops() { throw new Exception("oops"); } 212 assertExceptionMsg(oops.shouldThrow!UnitTestException, 213 ` tests/unit_threaded/ut/should.d:123 - Expression threw object.Exception instead of the expected UnitTestException:` 214 ~ "\n" ~ `oops`); 215 } 216 217 218 @safe unittest 219 { 220 auto arrayRangeWithoutLength(T)(T[] array) 221 { 222 struct ArrayRangeWithoutLength(T) 223 { 224 private: 225 T[] array; 226 public: 227 T front() const @property 228 { 229 return array[0]; 230 } 231 232 void popFront() 233 { 234 array = array[1 .. $]; 235 } 236 237 bool empty() const @property 238 { 239 import std.array; 240 return array.empty; 241 } 242 } 243 return ArrayRangeWithoutLength!T(array); 244 } 245 shouldNotBeIn(3.5, [1.1, 2.2, 4.4]); 246 shouldNotBeIn(1.0, [2.0 : 1, 3.0 : 2]); 247 shouldNotBeIn(1, arrayRangeWithoutLength([2, 3, 4])); 248 assertFail(1.shouldNotBeIn(arrayRangeWithoutLength([1, 2, 3]))); 249 assertFail("foo".shouldNotBeIn(["foo"])); 250 } 251 252 @safe pure unittest { 253 import unit_threaded.asserts; 254 void funcThrows(string msg) { throw new Exception(msg); } 255 try { 256 auto exceptionInfo = funcThrows("foo bar").shouldThrow; 257 assertEqual(exceptionInfo.msg, "foo bar"); 258 } catch(Exception e) { 259 assert(false, "should not have thrown anything and threw: " ~ e.msg); 260 } 261 } 262 263 @safe pure unittest { 264 import unit_threaded.asserts; 265 void func() {} 266 try { 267 func.shouldThrow; 268 assert(false, "Should never get here"); 269 } catch(Exception e) 270 assertEqual(e.msg, "Expression did not throw"); 271 } 272 273 @safe pure unittest { 274 import unit_threaded.asserts; 275 void funcAsserts() { assert(false, "Oh noes"); } 276 try { 277 funcAsserts.shouldThrow; 278 assert(false, "Should never get here"); 279 } catch(Exception e) 280 assertEqual(e.msg, 281 "Expression threw core.exception.AssertError instead of the expected Exception:\nOh noes"); 282 } 283 284 unittest { 285 void func() {} 286 func.shouldNotThrow; 287 void funcThrows() { throw new Exception("oops"); } 288 assertFail(shouldNotThrow(funcThrows)); 289 } 290 291 @safe pure unittest { 292 void funcThrows(string msg) { throw new Exception(msg); } 293 funcThrows("foo bar").shouldThrowWithMessage!Exception("foo bar"); 294 funcThrows("foo bar").shouldThrowWithMessage("foo bar"); 295 assertFail(funcThrows("boo boo").shouldThrowWithMessage("foo bar")); 296 void func() {} 297 assertFail(func.shouldThrowWithMessage("oops")); 298 } 299 300 @("catch Throwables without compromising other safety checks") 301 unittest 302 { 303 int a = 3; 304 void foo() @system { assert(a == 4); } 305 void bar() @safe { assert(a == 4); } 306 static assert(!__traits(compiles, () @safe => foo.shouldThrow!Throwable)); 307 static assert(__traits(compiles, () => foo.shouldThrow!Throwable)); 308 static assert(__traits(compiles, () @safe => bar.shouldThrow!Throwable)); 309 static assert(__traits(compiles, () => bar.shouldThrow!Throwable)); 310 } 311 312 // can't be made pure because of throwExactly, which in turn 313 // can't be pure because of Object.opEquals 314 @safe unittest 315 { 316 class CustomException : Exception 317 { 318 this(string msg = "") 319 { 320 super(msg); 321 } 322 } 323 324 class ChildException : CustomException 325 { 326 this(string msg = "") 327 { 328 super(msg); 329 } 330 } 331 332 void throwCustom() 333 { 334 throw new CustomException(); 335 } 336 337 throwCustom.shouldThrow; 338 throwCustom.shouldThrow!CustomException; 339 340 void throwChild() 341 { 342 throw new ChildException(); 343 } 344 345 throwChild.shouldThrow; 346 throwChild.shouldThrow!CustomException; 347 throwChild.shouldThrow!ChildException; 348 throwChild.shouldThrowExactly!ChildException; 349 try 350 { 351 throwChild.shouldThrowExactly!CustomException; //should not succeed 352 assert(0, "shouldThrowExactly failed"); 353 } 354 catch (Exception ex) 355 { 356 } 357 358 void doesntThrow() {} 359 assertFail(doesntThrow.shouldThrowExactly!Exception); 360 } 361 362 @safe pure unittest 363 { 364 void throwRangeError() 365 { 366 ubyte[] bytes; 367 bytes = bytes[1 .. $]; 368 } 369 370 import core.exception : RangeError; 371 372 throwRangeError.shouldThrow!RangeError; 373 } 374 375 @safe pure unittest { 376 import std.stdio; 377 378 import core.exception: OutOfMemoryError; 379 380 class CustomException : Exception { 381 this(string msg = "", string file = __FILE__, in size_t line = __LINE__) { super(msg, file, line); } 382 } 383 384 void func() { throw new CustomException("oh noes"); } 385 386 func.shouldThrow!CustomException; 387 assertFail(func.shouldThrow!OutOfMemoryError); 388 } 389 390 391 unittest { 392 import unit_threaded.asserts; 393 class Foo { 394 override string toString() @safe pure nothrow const { 395 return "Foo"; 396 } 397 } 398 399 auto foo = new const Foo; 400 assertEqual(foo.convertToString, "Foo"); 401 } 402 403 @safe pure unittest { 404 assert(isEqual(1.0, 1.0)); 405 assert(!isEqual(1.0, 1.0001)); 406 } 407 408 409 @safe unittest { 410 1.0.shouldApproxEqual(1.0001); 411 1.0.shouldApproxEqual(1.0001, 1e-2, 1e-5); 412 assertFail(2.0.shouldApproxEqual(1.0)); 413 } 414 415 @safe pure unittest { 416 import std.conv: to; 417 import std.range: iota; 418 419 assert(isEqual(2, 2)); 420 assert(!isEqual(2, 3)); 421 422 assert(isEqual(2.1, 2.1)); 423 assert(!isEqual(2.1, 2.2)); 424 425 assert(isEqual("foo", "foo")); 426 assert(!isEqual("foo", "fooo")); 427 428 assert(isEqual([1, 2], [1, 2])); 429 assert(!isEqual([1, 2], [1, 2, 3])); 430 431 assert(isEqual(iota(2), [0, 1])); 432 assert(!isEqual(iota(2), [1, 2, 3])); 433 434 assert(isEqual([[0, 1], [0, 1, 2]], [iota(2), iota(3)])); 435 assert(isEqual([[0, 1], [0, 1, 2]], [[0, 1], [0, 1, 2]])); 436 assert(!isEqual([[0, 1], [0, 1, 4]], [iota(2), iota(3)])); 437 assert(!isEqual([[0, 1], [0]], [iota(2), iota(3)])); 438 439 assert(isEqual([0: 1], [0: 1])); 440 441 const constIntToInts = [1 : 2, 3 : 7, 9 : 345]; 442 auto intToInts = [1 : 2, 3 : 7, 9 : 345]; 443 444 assert(isEqual(intToInts, constIntToInts)); 445 assert(isEqual(constIntToInts, intToInts)); 446 447 class Foo 448 { 449 this(int i) { this.i = i; } 450 override string toString() const { return i.to!string; } 451 int i; 452 } 453 454 assert(isEqual(new Foo(5), new Foo(5))); 455 assert(!isEqual(new Foo(5), new Foo(4))); 456 457 ubyte[] arr; 458 ubyte[] empty; 459 assert(isEqual(arr, empty)); 460 } 461 462 @safe pure unittest 463 { 464 int[] ints; 465 string[] strings; 466 string[string] aa; 467 468 shouldBeEmpty(ints); 469 shouldBeEmpty(strings); 470 shouldBeEmpty(aa); 471 472 ints ~= 1; 473 strings ~= "foo"; 474 aa["foo"] = "bar"; 475 476 assertFail(shouldBeEmpty(ints)); 477 assertFail(shouldBeEmpty(strings)); 478 assertFail(shouldBeEmpty(aa)); 479 } 480 481 482 @safe pure unittest 483 { 484 int[] ints; 485 string[] strings; 486 string[string] aa; 487 488 assertFail(shouldNotBeEmpty(ints)); 489 assertFail(shouldNotBeEmpty(strings)); 490 assertFail(shouldNotBeEmpty(aa)); 491 492 ints ~= 1; 493 strings ~= "foo"; 494 aa["foo"] = "bar"; 495 496 shouldNotBeEmpty(ints); 497 shouldNotBeEmpty(strings); 498 shouldNotBeEmpty(aa); 499 } 500 501 @safe pure unittest 502 { 503 shouldBeGreaterThan(7, 5); 504 } 505 506 507 @safe pure unittest 508 { 509 shouldBeSmallerThan(5, 7); 510 assertFail(shouldBeSmallerThan(7, 5)); 511 assertFail(shouldBeSmallerThan(7, 7)); 512 } 513 514 @safe pure unittest { 515 "foo"w.shouldEqual("foo"); 516 } 517 518 @("Non-copyable types can be asserted on") 519 @safe pure unittest { 520 521 struct Move { 522 int i; 523 @disable this(this); 524 } 525 526 Move(5).shouldEqual(Move(5)); 527 } 528 529 @("issue 88") 530 @safe pure unittest { 531 532 class C { 533 int foo; 534 override string toString() @safe pure nothrow const { return null; } 535 } 536 537 C c = null; 538 c.shouldEqual(c); 539 C null_; 540 assertFail((new C).shouldEqual(null_)); 541 } 542 543 @("issue 89") 544 unittest { 545 class C { 546 override string toString() @safe pure nothrow const { return null; } 547 } 548 549 auto actual = new C; 550 auto expected = new C; 551 552 // these should both pass 553 actual.shouldEqual(expected); // passes: actual.tupleof == expected.tupleof 554 [actual].shouldEqual([expected]); // fails: actual != expected 555 } 556 557 @("non-const toString should compile") 558 @safe pure unittest { 559 class C { 560 override string toString() @safe pure nothrow { return null; } 561 } 562 (new C).shouldEqual(new C); 563 } 564 565 @safe pure unittest { 566 ['\xff'].shouldEqual(['\xff']); 567 } 568 569 @safe unittest { 570 // Object.opEquals isn't scope and therefore not @safe 571 () @trusted { 572 shouldNotEqual(new Object, new Object); 573 }(); 574 } 575 576 577 @("should ==") 578 @safe pure unittest { 579 1.should == 1; 580 2.should == 2; 581 assertFail(1.should == 2); 582 assertExceptionMsg(1.should == 2, 583 ` tests/unit_threaded/ut/should.d:123 - Expected: 2` ~ "\n" ~ 584 ` tests/unit_threaded/ut/should.d:123 - Got: 1`); 585 } 586 587 @("should.be ==") 588 @safe pure unittest { 589 1.should.be == 1; 590 2.should.be == 2; 591 assertFail(1.should.be == 2); 592 assertExceptionMsg(1.should.be == 2, 593 ` tests/unit_threaded/ut/should.d:123 - Expected: 2` ~ "\n" ~ 594 ` tests/unit_threaded/ut/should.d:123 - Got: 1`); 595 } 596 597 @("should.not ==") 598 @safe pure unittest { 599 1.should.not == 2; 600 assertFail(2.should.not == 2); 601 } 602 603 @("should.not.be ==") 604 @safe pure unittest { 605 1.should.not.be == 2; 606 assertFail(2.should.not.be == 2); 607 } 608 609 610 @("should.be in") 611 @safe pure unittest { 612 1.should.be in [1, 2, 3]; 613 2.should.be in [1, 2, 3]; 614 3.should.be in [1, 2, 3]; 615 assertFail(4.should.be in [1, 2, 3]); 616 } 617 618 @("should.not.be in") 619 @safe pure unittest { 620 4.should.not.be in [1, 2, 3]; 621 assertFail(1.should.not.be in [1, 2, 3]); 622 } 623 624 @("should ~ for range") 625 @safe pure unittest { 626 [1, 2, 3].should ~ [3, 2, 1]; 627 assertFail([1, 2, 3].should ~ [1, 2, 2]); 628 629 [1, 2, 3].should.not ~ [1, 2, 2]; 630 assertFail([1, 2, 3].should.not ~ [3, 2, 1]); 631 assertExceptionMsg([1, 2, 3].should.not ~ [3, 2, 1], 632 ` tests/unit_threaded/ut/should.d:123 - [1, 2, 3] should not be the same set as [3, 2, 1]` 633 ); 634 } 635 636 @("should ~ for float") 637 @safe unittest { 638 1.0.should ~ 1.0001; 639 assertFail(2.0.should ~ 1.0001); 640 641 1.0.should.not ~ 2.0; 642 assertFail(1.0.should.not ~ 1.0001); 643 assertExceptionMsg(1.0.should.not ~ 1.0001, 644 ` tests/unit_threaded/ut/should.d:123 - 1 should not be approximately equal to 1.0001` 645 ); 646 } 647 648 649 @("shouldBeBetween") 650 @safe pure unittest { 651 import std.datetime: seconds; 652 653 5.shouldBeBetween(4, 6); 654 assertExceptionMsg(3.shouldBeBetween(4, 6), 655 " tests/unit_threaded/ut/should.d:123 - 3 is not between 4 and 6\n"); 656 4.shouldBeBetween(4, 6); 657 assertFail(6.shouldBeBetween(4, 6)); 658 659 3.seconds.shouldBeBetween(2.seconds, 4.seconds); 660 assertFail(1.seconds.shouldBeBetween(2.seconds, 4.seconds)); 661 } 662 663 664 @("shouldBeSameSetAs") 665 @safe pure unittest { 666 [1, 2, 3].shouldBeSameSetAs([2, 3, 1]); 667 [1, 2, 3].shouldBeSameSetAs([3, 2, 1]); 668 assertExceptionMsg([1, 2, 3].shouldBeSameSetAs([2, 1, 4]), 669 ` tests/unit_threaded/ut/should.d:123 - Expected: [1, 2, 4]` ~ "\n" ~ 670 ` tests/unit_threaded/ut/should.d:123 - Got: [1, 2, 3]`); 671 }