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 }