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 @safe unittest {
382     assert(isApproxEqual(1.0, 1.0));
383     assert(isApproxEqual(1.0, 1.0001));
384 }
385 
386 @safe unittest {
387     1.0.shouldApproxEqual(1.0001);
388     1.0.shouldApproxEqual(1.0001, 1e-2, 1e-5);
389     assertFail(2.0.shouldApproxEqual(1.0));
390 }
391 
392 @safe pure unittest {
393     import std.conv: to;
394     import std.range: iota;
395 
396     assert(isEqual(2, 2));
397     assert(!isEqual(2, 3));
398 
399     assert(isEqual(2.1, 2.1));
400     assert(!isEqual(2.1, 2.2));
401 
402     assert(isEqual("foo", "foo"));
403     assert(!isEqual("foo", "fooo"));
404 
405     assert(isEqual([1, 2], [1, 2]));
406     assert(!isEqual([1, 2], [1, 2, 3]));
407 
408     assert(isEqual(iota(2), [0, 1]));
409     assert(!isEqual(iota(2), [1, 2, 3]));
410 
411     assert(isEqual([[0, 1], [0, 1, 2]], [iota(2), iota(3)]));
412     assert(isEqual([[0, 1], [0, 1, 2]], [[0, 1], [0, 1, 2]]));
413     assert(!isEqual([[0, 1], [0, 1, 4]], [iota(2), iota(3)]));
414     assert(!isEqual([[0, 1], [0]], [iota(2), iota(3)]));
415 
416     assert(isEqual([0: 1], [0: 1]));
417 
418     const constIntToInts = [1 : 2, 3 : 7, 9 : 345];
419     auto intToInts = [1 : 2, 3 : 7, 9 : 345];
420 
421     assert(isEqual(intToInts, constIntToInts));
422     assert(isEqual(constIntToInts, intToInts));
423 
424     class Foo
425     {
426         this(int i) { this.i = i; }
427         override string toString() const { return i.to!string; }
428         int i;
429     }
430 
431     assert(isEqual(new Foo(5), new Foo(5)));
432     assert(!isEqual(new Foo(5), new Foo(4)));
433 
434     ubyte[] arr;
435     assert(isEqual(arr, []));
436 }
437 
438 @safe pure unittest
439 {
440     int[] ints;
441     string[] strings;
442     string[string] aa;
443 
444     shouldBeEmpty(ints);
445     shouldBeEmpty(strings);
446     shouldBeEmpty(aa);
447 
448     ints ~= 1;
449     strings ~= "foo";
450     aa["foo"] = "bar";
451 
452     assertFail(shouldBeEmpty(ints));
453     assertFail(shouldBeEmpty(strings));
454     assertFail(shouldBeEmpty(aa));
455 }
456 
457 
458 @safe pure unittest
459 {
460     int[] ints;
461     string[] strings;
462     string[string] aa;
463 
464     assertFail(shouldNotBeEmpty(ints));
465     assertFail(shouldNotBeEmpty(strings));
466     assertFail(shouldNotBeEmpty(aa));
467 
468     ints ~= 1;
469     strings ~= "foo";
470     aa["foo"] = "bar";
471 
472     shouldNotBeEmpty(ints);
473     shouldNotBeEmpty(strings);
474     shouldNotBeEmpty(aa);
475 }
476 
477 @safe pure unittest
478 {
479     shouldBeGreaterThan(7, 5);
480 }
481 
482 
483 @safe pure unittest
484 {
485     shouldBeSmallerThan(5, 7);
486     assertFail(shouldBeSmallerThan(7, 5));
487     assertFail(shouldBeSmallerThan(7, 7));
488 }
489 
490 @safe pure unittest {
491     "foo"w.shouldEqual("foo");
492 }
493 
494 @("Non-copyable types can be asserted on")
495 @safe pure unittest {
496 
497     struct Move {
498         int i;
499         @disable this(this);
500     }
501 
502     Move(5).shouldEqual(Move(5));
503 }
504 
505 @("issue 88")
506 @safe pure unittest {
507 
508     class C {
509         int foo;
510         override string toString() @safe pure nothrow const { return null; }
511     }
512 
513     C c = null;
514     c.shouldEqual(c);
515     C null_;
516     assertFail((new C).shouldEqual(null_));
517 }
518 
519 @("issue 89")
520 unittest {
521     class C {
522         override string toString() @safe pure nothrow const { return null; }
523     }
524 
525     auto actual = new C;
526     auto expected = new C;
527 
528     // these should both pass
529     actual.shouldEqual(expected);      // passes: actual.tupleof == expected.tupleof
530     [actual].shouldEqual([expected]);  // fails: actual != expected
531 }
532 
533 @("non-const toString should compile")
534 @safe pure unittest {
535     class C {
536         override string toString() @safe pure nothrow { return null; }
537     }
538     (new C).shouldEqual(new C);
539 }
540 
541 @safe pure unittest {
542     ['\xff'].shouldEqual(['\xff']);
543 }
544 
545 @safe unittest {
546     // Object.opEquals isn't scope and therefore not @safe
547     () @trusted {
548         shouldNotEqual(new Object, new Object);
549     }();
550 }
551 
552 
553 @("should ==")
554 @safe pure unittest {
555     1.should == 1;
556     2.should == 2;
557     assertFail(1.should == 2);
558     assertExceptionMsg(1.should == 2,
559                        `    tests/unit_threaded/ut/should.d:123 - Expected: 2` ~ "\n" ~
560                        `    tests/unit_threaded/ut/should.d:123 -      Got: 1`);
561 }
562 
563 @("should.be ==")
564 @safe pure unittest {
565     1.should.be == 1;
566     2.should.be == 2;
567     assertFail(1.should.be == 2);
568     assertExceptionMsg(1.should.be == 2,
569                        `    tests/unit_threaded/ut/should.d:123 - Expected: 2` ~ "\n" ~
570                        `    tests/unit_threaded/ut/should.d:123 -      Got: 1`);
571 }
572 
573 @("should.not ==")
574 @safe pure unittest {
575     1.should.not == 2;
576     assertFail(2.should.not == 2);
577 }
578 
579 @("should.not.be ==")
580 @safe pure unittest {
581     1.should.not.be == 2;
582     assertFail(2.should.not.be == 2);
583 }
584 
585 @("should.throw")
586 @safe pure unittest {
587 
588     void funcOk() {}
589 
590     void funcThrows() {
591         throw new Exception("oops");
592     }
593 
594     assertFail(funcOk.should.throw_);
595     funcThrows.should.throw_;
596 }
597 
598 @("should.be in")
599 @safe pure unittest {
600     1.should.be in [1, 2, 3];
601     2.should.be in [1, 2, 3];
602     3.should.be in [1, 2, 3];
603     assertFail(4.should.be in [1, 2, 3]);
604 }
605 
606 @("should.not.be in")
607 @safe pure unittest {
608     4.should.not.be in [1, 2, 3];
609     assertFail(1.should.not.be in [1, 2, 3]);
610 }
611 
612 @("should ~ for range")
613 @safe pure unittest {
614     [1, 2, 3].should ~ [3, 2, 1];
615     [1, 2, 3].should.not ~ [1, 2, 2];
616     assertFail([1, 2, 3].should ~ [1, 2, 2]);
617 }
618 
619 @("should ~ for float")
620 @safe unittest {
621     1.0.should ~ 1.0001;
622     1.0.should.not ~ 2.0;
623     assertFail(2.0.should ~ 1.0001);
624 }
625 
626 
627 @("void[] vs string")
628 @safe unittest {
629     auto voids = () @trusted { return cast(void[]) ['f', 'o', 'o']; }();
630     "foo".shouldEqual(voids);
631     voids.shouldEqual("foo");
632 }