Differences From Artifact [63ca5d91a9064dd8]:
- File
polemy/tricks.d
- 2010-11-08 06:19:57 - part of checkin [61998c472a] on branch trunk - Introduced unittest helpers (assert_eq, assert_throw, etc). Mmigration to it is not done yet. (user: kinaba) [annotate]
To Artifact [aa60c34591041ca2]:
- File
polemy/tricks.d
- 2010-11-08 08:01:27 - part of checkin [b0d8d7875b] on branch trunk - polemy.runtime renamed into polemy.value. Also, in process of changes to use unittest helpers. (user: kinaba) [annotate]
1 1 /**
2 2 * Authors: k.inaba
3 3 * License: NYSL 0.9982 http://www.kmonos.net/nysl/
4 4 *
5 5 * Common tricks and utilities for programming in D.
6 6 */
7 7 module polemy.tricks;
8 -static import std.array;
9 -static import std.format;
10 -static import core.exception;
8 +import std.array : appender;
9 +import std.format : formattedWrite;
10 +import core.exception : onAssertErrorMsg, AssertError;
11 11
12 12 /// Simple Wrapper for std.format.doFormat
13 13
14 14 string sprintf(string fmt, T...)(T params)
15 15 {
16 - auto writer = std.array.appender!string();
17 - std.format.formattedWrite(writer, fmt, params);
16 + auto writer = appender!string();
17 + formattedWrite(writer, fmt, params);
18 18 return writer.data;
19 19 }
20 20
21 21 unittest
22 22 {
23 23 assert( sprintf!"%s == %d"("1+2", 3) == "1+2 == 3" );
24 24 assert( sprintf!"%s == %04d"("1+2", 3) == "1+2 == 0003" );
25 25 }
26 +
27 +/// Unittest helper that asserts an expression must throw something
28 +
29 +void assert_throw(ExceptionType, T, string fn=__FILE__, int ln=__LINE__)(lazy T t, string msg="")
30 +{
31 + try {
32 + t();
33 + } catch(ExceptionType) {
34 + return;
35 + } catch(Throwable e) {
36 + onAssertErrorMsg(fn, ln, msg.length ? msg : sprintf!"exception [%s]"(e));
37 + }
38 + onAssertErrorMsg(fn, ln, msg.length ? msg : "no execption");
39 +}
40 +
41 +/// Unittest helper that asserts an expression must not throw anything
42 +
43 +void assert_nothrow(T, string fn=__FILE__, int ln=__LINE__)(lazy T t, string msg="")
44 +{
45 + try {
46 + t();
47 + } catch(Throwable e) {
48 + onAssertErrorMsg(fn, ln, msg.length ? msg : sprintf!"exception [%s]"(e));
49 + }
50 +}
51 +
52 +unittest
53 +{
54 + auto error = {throw new Error("hello");};
55 + auto nothing = (){};
56 + auto assertError = {assert(0);};
57 +
58 + assert_nothrow ( assert_nothrow(nothing()) );
59 + assert_throw!AssertError( assert_nothrow(error()) );
60 + assert_throw!AssertError( assert_nothrow(assertError()) );
61 +
62 + assert_nothrow ( assert_throw!Error(error()) );
63 + assert_throw!AssertError( assert_throw!Error(nothing()) );
64 + assert_nothrow ( assert_throw!Error(assertError()) );
65 + assert_throw!AssertError( assert_throw!AssertError(error()) );
66 +}
26 67
27 68 /// Unittest helpers asserting two values are in some relation ==, !=, <, <=, >, >=
28 69
29 70 template assertOp(string op)
30 71 {
31 72 void assertOp(A, B, string fn=__FILE__, int ln=__LINE__)(A a, B b, string msg="")
32 73 {
33 74 try {
34 75 if( mixin("a"~op~"b") ) return;
35 76 } catch(Throwable e) {
36 - core.exception.onAssertErrorMsg(fn, ln, msg.length ? msg : sprintf!"exception [%s]"(e));
77 + onAssertErrorMsg(fn, ln, msg.length ? msg : sprintf!"exception [%s]"(e));
37 78 }
38 - core.exception.onAssertErrorMsg(fn, ln, msg.length ? msg : sprintf!"%s !%s %s"(a,op,b));
79 + onAssertErrorMsg(fn, ln, msg.length ? msg : sprintf!"%s !%s %s"(a,op,b));
39 80 }
40 81 }
41 82
42 83 alias assertOp!(`==`) assert_eq;
43 84 alias assertOp!(`!=`) assert_ne;
44 85 alias assertOp!(`<`) assert_lt;
45 86 alias assertOp!(`<=`) assert_le;
46 87 alias assertOp!(`>`) assert_gt;
47 88 alias assertOp!(`>=`) assert_ge;
48 89
49 -/// Unittest helper that asserts an expression must throw something
50 -
51 -void assert_throw(ExceptionType, T, string fn=__FILE__, int ln=__LINE__)(lazy T t, string msg="")
90 +unittest
52 91 {
53 - try {
54 - t();
55 - } catch(ExceptionType) {
56 - return;
57 - } catch(Throwable e) {
58 - core.exception.onAssertErrorMsg(fn, ln, msg.length ? msg : sprintf!"exception [%s]"(e));
59 - }
60 - core.exception.onAssertErrorMsg(fn, ln, msg.length ? msg : "no execption");
61 -}
62 -
63 -/// Unittest helper that asserts an expression must not throw anything
64 -
65 -void assert_nothrow(ExceptionType, T, string fn=__FILE__, int ln=__LINE__)(lazy T t, string msg="")
66 -{
67 - try {
68 - t();
69 - } catch(Throwable e) {
70 - core.exception.onAssertErrorMsg(fn, ln, msg.length ? msg : sprintf!"exception [%s]"(e));
71 - }
92 + assert_nothrow( assert_eq("foo", "foo") );
93 + assert_nothrow( assert_ne("foo", "bar") );
94 + assert_nothrow( assert_lt("bar", "foo") );
95 + assert_nothrow( assert_le("bar", "foo") );
96 + assert_nothrow( assert_le("bar", "bar") );
97 + assert_nothrow( assert_gt("foo", "bar") );
98 + assert_nothrow( assert_ge("foo", "bar") );
99 + assert_nothrow( assert_ge("bar", "bar") );
100 +
101 + assert_throw!AssertError( assert_eq("foo", "bar") );
102 + assert_throw!AssertError( assert_ne("foo", "foo") );
103 + assert_throw!AssertError( assert_lt("foo", "foo") );
104 + assert_throw!AssertError( assert_lt("foo", "bar") );
105 + assert_throw!AssertError( assert_le("foo", "bar") );
106 + assert_throw!AssertError( assert_gt("bar", "bar") );
107 + assert_throw!AssertError( assert_gt("bar", "foo") );
108 + assert_throw!AssertError( assert_ge("bar", "foo") );
109 +
110 + class Temp { bool opEquals(int x){return x/x==x;} }
111 + assert_throw!AssertError( assert_eq(new Temp, 0) );
112 + assert_nothrow ( assert_eq(new Temp, 1) );
113 + assert_throw!AssertError( assert_eq(new Temp, 2) );
72 114 }
73 115
74 116 /* [Todo] is there any way to clearnly implement "assert_compiles" and "assert_not_compile"? */
75 117
76 118 /// Mixing-in the bean constructor for a class
77 119
78 120 template SimpleConstructor()
................................................................................
103 145 mixin SimpleConstructor;
104 146 }
105 147 assert_eq( (new Temp(1,"foo")).x, 1 );
106 148 assert_eq( (new Temp(1,"foo")).y, "foo" );
107 149 assert( !__traits(compiles, new Temp) );
108 150 assert( !__traits(compiles, new Temp(1)) );
109 151 assert( !__traits(compiles, new Temp("foo",1)) );
152 +
153 + class Tomp : Temp
154 + {
155 + real z;
156 + mixin SimpleConstructor;
157 + }
158 + assert_eq( (new Tomp(1,"foo",2.5)).x, 1 );
159 + assert_eq( (new Tomp(1,"foo",2.5)).y, "foo" );
160 + assert_eq( (new Tomp(1,"foo",2.5)).z, 2.5 );
161 + assert( !__traits(compiles, new Tomp(3.14)) );
162 +
163 + // shiyo- desu. Don't use in this way.
164 + // Tamp tries to call new Tomp(real) (because it only sees Tomp's members),
165 + // but it fails because Tomp takes (int,string,real).
166 + assert( !__traits(compiles, {
167 + class Tamp : Tomp
168 + {
169 + mixin SimpleConstructor;
170 + }
171 + }) );
110 172 }
111 173
112 174 /// Mixing-in the MOST-DERIVED-member-wise comparator for a class
113 175
114 176 template SimpleCompare()
115 177 {
116 178 override bool opEquals(Object rhs_) const
................................................................................
157 219 }
158 220 assert_eq( new Temp(1,"foo"), new Temp(1,"foo") );
159 221 assert_eq( (new Temp(1,"foo")).toHash, (new Temp(1,"foo")).toHash );
160 222 assert_ne( new Temp(1,"foo"), new Temp(2,"foo") );
161 223 assert_ne( new Temp(1,"foo"), new Temp(1,"bar") );
162 224 assert_gt( new Temp(1,"foo"), new Temp(1,"bar") );
163 225 assert_lt( new Temp(1,"foo"), new Temp(2,"bar") );
226 + assert_ge( new Temp(1,"foo"), new Temp(1,"foo") );
227 +
228 + class TempDummy
229 + {
230 + int x;
231 + string y;
232 + mixin SimpleConstructor;
233 + mixin SimpleCompare;
234 + }
235 + assert_throw!AssertError( new Temp(1,"foo") == new TempDummy(1,"foo") );
236 + assert_throw!AssertError( new Temp(1,"foo") <= new TempDummy(1,"foo") );
164 237 }