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