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