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