1 #!/usr/bin/env rdmd-dev
2 
3 /** A Better assert.
4     Copyright: Per Nordlöw 2014-.
5     License: $(WEB boost.org/LICENSE_1_0.txt, Boost License 1.0).
6     Authors: $(WEB Per Nordlöw)
7 */
8 module assert_ex;
9 
10 // import std.string : format;
11 import core.exception : AssertError;
12 import std.conv: to;
13 
14 @trusted:
15 
16 /// Returns true if the expression throws.
17 bool assertThrows(T:Throwable = Exception, E)(lazy E expression,
18                                               string msg = T.stringof,
19                                               string file = __FILE__,
20                                               int line = __LINE__ )
21 {
22     try
23     {
24         std.exception.assertThrown!T(expression, msg, file, line);
25         return true;
26     }
27     catch (Throwable exc)
28     {
29         // FIXTHIS: unhelpful error message
30         writeln("failed at ", baseName(file), "(", line, "):",
31                 " Did not throw \"", msg, "\".");
32         return false;
33     }
34 }
35 
36 nothrow:
37 
38 /** A Better assert.
39     See also: http://poita.org/2012/09/02/a-better-assert-for-d.html?utm_source=feedburner&utm_medium=feed&utm_campaign=Feed%3A+poita+%28poita.org%29
40     TODO Can we convert args to strings like GCC's __STRING(expression)?
41     TODO Make these be able to be called in unittest placed in struct scopes
42 */
43 void assertTrue(T,
44                 string file = __FILE__, uint line = __LINE__,
45                 Args...) (T test, lazy Args args)
46 {
47     version (assert) if (!test)
48         throw new AssertError("at \n" ~file~ ":" ~to!string(line)~ ":\n  test: " ~to!string(test));
49 }
50 
51 void assertEqual(T, U,
52                  string file = __FILE__, uint line = __LINE__,
53                  Args...) (T lhs, U rhs, lazy Args args)
54 {
55     version (assert) if (lhs != rhs)
56         throw new AssertError("at \n" ~file~ ":" ~to!string(line)~ ":\n  lhs: " ~to!string(lhs)~ " !=\n  rhs: " ~to!string(rhs));
57 }
58 alias assertE = assertEqual;
59 
60 void assertLessThanOrEqual(T, U,
61                            string file = __FILE__,
62                            uint line = __LINE__,
63                            Args...) (T lhs, U rhs, lazy Args args)
64 {
65     version (assert) if (lhs > rhs)
66         throw new AssertError("at \n" ~file~ ":" ~to!string(line)~ ":\n  lhs: " ~to!string(lhs)~ " >\n  rhs: " ~to!string(rhs));
67 }
68 alias assertLTE = assertLessThanOrEqual;
69 
70 void assertLessThan(T, U,
71                     string file = __FILE__, uint line = __LINE__,
72                     Args...) (T lhs, U rhs, lazy Args args)
73 {
74     version (assert) if (lhs >= rhs)
75         throw new AssertError("at \n" ~file~ ":" ~to!string(line)~ ":\n  lhs: " ~to!string(lhs)~ " >=\n  rhs: " ~to!string(rhs));
76 }
77 alias assertLT = assertLessThan;
78 
79 void assertNotEqual(T, U,
80                     string file = __FILE__, uint line = __LINE__,
81                     Args...) (T lhs, U rhs, lazy Args args)
82 {
83     version (assert) if (lhs == rhs)
84         throw new AssertError("at \n" ~file~ ":" ~to!string(line)~ ":\n  lhs: " ~to!string(lhs)~ " ==\n  rhs: " ~to!string(rhs));
85 }
86 alias assertNE = assertNotEqual;