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 exception = funcThrows("foo bar").shouldThrow; 242 assertEqual(exception.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 // can't be made pure because of throwExactly, which in turn 286 // can't be pure because of Object.opEquals 287 @safe unittest 288 { 289 class CustomException : Exception 290 { 291 this(string msg = "") 292 { 293 super(msg); 294 } 295 } 296 297 class ChildException : CustomException 298 { 299 this(string msg = "") 300 { 301 super(msg); 302 } 303 } 304 305 void throwCustom() 306 { 307 throw new CustomException(); 308 } 309 310 throwCustom.shouldThrow; 311 throwCustom.shouldThrow!CustomException; 312 313 void throwChild() 314 { 315 throw new ChildException(); 316 } 317 318 throwChild.shouldThrow; 319 throwChild.shouldThrow!CustomException; 320 throwChild.shouldThrow!ChildException; 321 throwChild.shouldThrowExactly!ChildException; 322 try 323 { 324 throwChild.shouldThrowExactly!CustomException; //should not succeed 325 assert(0, "shouldThrowExactly failed"); 326 } 327 catch (Exception ex) 328 { 329 } 330 331 void doesntThrow() {} 332 assertFail(doesntThrow.shouldThrowExactly!Exception); 333 } 334 335 @safe pure unittest 336 { 337 void throwRangeError() 338 { 339 ubyte[] bytes; 340 bytes = bytes[1 .. $]; 341 } 342 343 import core.exception : RangeError; 344 345 throwRangeError.shouldThrow!RangeError; 346 } 347 348 @safe pure unittest { 349 import std.stdio; 350 351 import core.exception: OutOfMemoryError; 352 353 class CustomException : Exception { 354 this(string msg = "", in string file = __FILE__, in size_t line = __LINE__) { super(msg, file, line); } 355 } 356 357 void func() { throw new CustomException("oh noes"); } 358 359 func.shouldThrow!CustomException; 360 assertFail(func.shouldThrow!OutOfMemoryError); 361 } 362 363 364 unittest { 365 import unit_threaded.asserts; 366 class Foo { 367 override string toString() @safe pure nothrow const { 368 return "Foo"; 369 } 370 } 371 372 auto foo = new const Foo; 373 assertEqual(foo.convertToString, "Foo"); 374 } 375 376 @safe pure unittest { 377 assert(isEqual(1.0, 1.0)); 378 assert(!isEqual(1.0, 1.0001)); 379 } 380 381 382 @safe unittest { 383 1.0.shouldApproxEqual(1.0001); 384 1.0.shouldApproxEqual(1.0001, 1e-2, 1e-5); 385 assertFail(2.0.shouldApproxEqual(1.0)); 386 } 387 388 @safe pure unittest { 389 import std.conv: to; 390 import std.range: iota; 391 392 assert(isEqual(2, 2)); 393 assert(!isEqual(2, 3)); 394 395 assert(isEqual(2.1, 2.1)); 396 assert(!isEqual(2.1, 2.2)); 397 398 assert(isEqual("foo", "foo")); 399 assert(!isEqual("foo", "fooo")); 400 401 assert(isEqual([1, 2], [1, 2])); 402 assert(!isEqual([1, 2], [1, 2, 3])); 403 404 assert(isEqual(iota(2), [0, 1])); 405 assert(!isEqual(iota(2), [1, 2, 3])); 406 407 assert(isEqual([[0, 1], [0, 1, 2]], [iota(2), iota(3)])); 408 assert(isEqual([[0, 1], [0, 1, 2]], [[0, 1], [0, 1, 2]])); 409 assert(!isEqual([[0, 1], [0, 1, 4]], [iota(2), iota(3)])); 410 assert(!isEqual([[0, 1], [0]], [iota(2), iota(3)])); 411 412 assert(isEqual([0: 1], [0: 1])); 413 414 const constIntToInts = [1 : 2, 3 : 7, 9 : 345]; 415 auto intToInts = [1 : 2, 3 : 7, 9 : 345]; 416 417 assert(isEqual(intToInts, constIntToInts)); 418 assert(isEqual(constIntToInts, intToInts)); 419 420 class Foo 421 { 422 this(int i) { this.i = i; } 423 override string toString() const { return i.to!string; } 424 int i; 425 } 426 427 assert(isEqual(new Foo(5), new Foo(5))); 428 assert(!isEqual(new Foo(5), new Foo(4))); 429 430 ubyte[] arr; 431 assert(isEqual(arr, [])); 432 } 433 434 @safe pure unittest 435 { 436 int[] ints; 437 string[] strings; 438 string[string] aa; 439 440 shouldBeEmpty(ints); 441 shouldBeEmpty(strings); 442 shouldBeEmpty(aa); 443 444 ints ~= 1; 445 strings ~= "foo"; 446 aa["foo"] = "bar"; 447 448 assertFail(shouldBeEmpty(ints)); 449 assertFail(shouldBeEmpty(strings)); 450 assertFail(shouldBeEmpty(aa)); 451 } 452 453 454 @safe pure unittest 455 { 456 int[] ints; 457 string[] strings; 458 string[string] aa; 459 460 assertFail(shouldNotBeEmpty(ints)); 461 assertFail(shouldNotBeEmpty(strings)); 462 assertFail(shouldNotBeEmpty(aa)); 463 464 ints ~= 1; 465 strings ~= "foo"; 466 aa["foo"] = "bar"; 467 468 shouldNotBeEmpty(ints); 469 shouldNotBeEmpty(strings); 470 shouldNotBeEmpty(aa); 471 } 472 473 @safe pure unittest 474 { 475 shouldBeGreaterThan(7, 5); 476 } 477 478 479 @safe pure unittest 480 { 481 shouldBeSmallerThan(5, 7); 482 assertFail(shouldBeSmallerThan(7, 5)); 483 assertFail(shouldBeSmallerThan(7, 7)); 484 } 485 486 @safe pure unittest { 487 "foo"w.shouldEqual("foo"); 488 } 489 490 @("Non-copyable types can be asserted on") 491 @safe pure unittest { 492 493 struct Move { 494 int i; 495 @disable this(this); 496 } 497 498 Move(5).shouldEqual(Move(5)); 499 } 500 501 @("issue 88") 502 @safe pure unittest { 503 504 class C { 505 int foo; 506 override string toString() @safe pure nothrow const { return null; } 507 } 508 509 C c = null; 510 c.shouldEqual(c); 511 C null_; 512 assertFail((new C).shouldEqual(null_)); 513 } 514 515 @("issue 89") 516 unittest { 517 class C { 518 override string toString() @safe pure nothrow const { return null; } 519 } 520 521 auto actual = new C; 522 auto expected = new C; 523 524 // these should both pass 525 actual.shouldEqual(expected); // passes: actual.tupleof == expected.tupleof 526 [actual].shouldEqual([expected]); // fails: actual != expected 527 } 528 529 @("non-const toString should compile") 530 @safe pure unittest { 531 class C { 532 override string toString() @safe pure nothrow { return null; } 533 } 534 (new C).shouldEqual(new C); 535 } 536 537 @safe pure unittest { 538 ['\xff'].shouldEqual(['\xff']); 539 } 540 541 @safe unittest { 542 // Object.opEquals isn't scope and therefore not @safe 543 () @trusted { 544 shouldNotEqual(new Object, new Object); 545 }(); 546 } 547 548 549 @("should ==") 550 @safe pure unittest { 551 1.should == 1; 552 2.should == 2; 553 assertFail(1.should == 2); 554 assertExceptionMsg(1.should == 2, 555 ` tests/unit_threaded/ut/should.d:123 - Expected: 2` ~ "\n" ~ 556 ` tests/unit_threaded/ut/should.d:123 - Got: 1`); 557 } 558 559 @("should.be ==") 560 @safe pure unittest { 561 1.should.be == 1; 562 2.should.be == 2; 563 assertFail(1.should.be == 2); 564 assertExceptionMsg(1.should.be == 2, 565 ` tests/unit_threaded/ut/should.d:123 - Expected: 2` ~ "\n" ~ 566 ` tests/unit_threaded/ut/should.d:123 - Got: 1`); 567 } 568 569 @("should.not ==") 570 @safe pure unittest { 571 1.should.not == 2; 572 assertFail(2.should.not == 2); 573 } 574 575 @("should.not.be ==") 576 @safe pure unittest { 577 1.should.not.be == 2; 578 assertFail(2.should.not.be == 2); 579 } 580 581 582 @("should.be in") 583 @safe pure unittest { 584 1.should.be in [1, 2, 3]; 585 2.should.be in [1, 2, 3]; 586 3.should.be in [1, 2, 3]; 587 assertFail(4.should.be in [1, 2, 3]); 588 } 589 590 @("should.not.be in") 591 @safe pure unittest { 592 4.should.not.be in [1, 2, 3]; 593 assertFail(1.should.not.be in [1, 2, 3]); 594 } 595 596 @("should ~ for range") 597 @safe pure unittest { 598 [1, 2, 3].should ~ [3, 2, 1]; 599 [1, 2, 3].should.not ~ [1, 2, 2]; 600 assertFail([1, 2, 3].should ~ [1, 2, 2]); 601 } 602 603 @("should ~ for float") 604 @safe unittest { 605 1.0.should ~ 1.0001; 606 1.0.should.not ~ 2.0; 607 assertFail(2.0.should ~ 1.0001); 608 } 609 610 611 @("void[] vs string") 612 @safe unittest { 613 auto voids = () @trusted { return cast(void[]) ['f', 'o', 'o']; }(); 614 "foo".shouldEqual(voids); 615 voids.shouldEqual("foo"); 616 } 617 618 619 @("shouldBeBetween") 620 @safe pure unittest { 621 import std.datetime: seconds; 622 623 5.shouldBeBetween(4, 6); 624 assertExceptionMsg(3.shouldBeBetween(4, 6), 625 " tests/unit_threaded/ut/should.d:123 - 3 is not between 4 and 6\n"); 626 4.shouldBeBetween(4, 6); 627 assertFail(6.shouldBeBetween(4, 6)); 628 629 3.seconds.shouldBeBetween(2.seconds, 4.seconds); 630 assertFail(1.seconds.shouldBeBetween(2.seconds, 4.seconds)); 631 }