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 }