Artifact 1483c10390a22fc3a9b42d844bdbe0d3cc07faa6
1 /**
2 * Authors: k.inaba
3 * License: NYSL 0.9982 http://www.kmonos.net/nysl/
4 *
5 * Unittest helpers.
6 */
7 module tricks.test;
8 import std.conv : to;
9 import core.exception;
10
11 /// Unittest helper that asserts an expression must throw something
12
13 void assert_throw(ExceptionType=Throwable,
14 T, string fn=__FILE__, size_t ln=__LINE__)(lazy T t, string msg="")
15 {
16 static if( is(ExceptionType == Throwable) )
17 try
18 { t(); }
19 catch(ExceptionType)
20 { return; }
21 else
22 try
23 { t(); }
24 catch(ExceptionType)
25 { return; }
26 catch(Throwable e)
27 { onAssertErrorMsg(fn, ln, msg.length ? msg : "bad exception\n >> "~e.toString()); }
28 onAssertErrorMsg(fn, ln, msg.length ? msg : "not thrown");
29 }
30
31 /// Unittest helper that asserts an expression must not throw anything
32
33 T assert_nothrow(T, string fn=__FILE__, size_t ln=__LINE__)(lazy T t, string msg="")
34 {
35 try
36 { return t(); }
37 catch(Throwable e)
38 { onAssertErrorMsg(fn, ln, msg.length ? msg : "bad exception\n >> "~e.toString()); }
39 assert(false);
40 }
41
42 unittest
43 {
44 auto error = {throw new Error("hello");};
45 auto nothing = (){};
46 auto assertError = {assert(0);};
47
48 assert_nothrow ( assert_nothrow(nothing()) );
49 assert_throw!AssertError( assert_nothrow(error()) );
50 assert_throw!AssertError( assert_nothrow(assertError()) );
51
52 assert_nothrow ( assert_throw!Error(error()) );
53 assert_throw!AssertError( assert_throw!Error(nothing()) );
54 assert_nothrow ( assert_throw!Error(assertError()) );
55 assert_throw!AssertError( assert_throw!AssertError(error()) );
56 }
57
58 template assertOp(string op)
59 {
60 void assertOp(A, B, string fn=__FILE__, size_t ln=__LINE__)(A a, B b, string msg="")
61 {
62 try
63 { if( mixin("a"~op~"b") ) return; }
64 catch(Throwable e)
65 { onAssertErrorMsg(fn, ln, msg.length ? msg : "exception ["~e.toString()~"]"); }
66 onAssertErrorMsg(fn, ln, msg.length ? msg : to!string(a)~" !"~op~" "~to!string(b));
67 }
68 }
69
70 alias assertOp!(`==`) assert_eq; /// asserts two operands are ==
71 alias assertOp!(`!=`) assert_ne; /// asserts two operands are !=
72 alias assertOp!(`<`) assert_lt; /// asserts two operands are <
73 alias assertOp!(`<=`) assert_le; /// asserts two operands are <=
74 alias assertOp!(`>`) assert_gt; /// asserts two operands are >
75 alias assertOp!(`>=`) assert_ge; /// asserts two operands are >=
76
77 unittest
78 {
79 assert_nothrow( assert_eq(1, 1) );
80 assert_nothrow( assert_ne(1, 0) );
81 assert_nothrow( assert_lt(0, 1) );
82 assert_nothrow( assert_le(0, 1) );
83 assert_nothrow( assert_le(0, 0) );
84 assert_nothrow( assert_gt(1, 0) );
85 assert_nothrow( assert_ge(1, 0) );
86 assert_nothrow( assert_ge(0, 0) );
87
88 assert_throw!AssertError( assert_eq(1, 0) );
89 assert_throw!AssertError( assert_ne(1, 1) );
90 assert_throw!AssertError( assert_lt(1, 1) );
91 assert_throw!AssertError( assert_lt(1, 0) );
92 assert_throw!AssertError( assert_le(1, 0) );
93 assert_throw!AssertError( assert_gt(0, 0) );
94 assert_throw!AssertError( assert_gt(0, 1) );
95 assert_throw!AssertError( assert_ge(0, 1) );
96
97 class Temp { bool opEquals(int x){return x/x==x;} }
98 assert_throw!AssertError( assert_eq(new Temp, 0) );
99 assert_nothrow ( assert_eq(new Temp, 1) );
100 assert_throw!AssertError( assert_eq(new Temp, 2) );
101 }
102
103 /* [Todo] is there any way to clearnly implement "assert_compiles" and "assert_not_compile"? */