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 * Authors: k.inaba 2 * Authors: k.inaba
3 * License: NYSL 0.9982 http://www.kmonos.net/nysl/ 3 * License: NYSL 0.9982 http://www.kmonos.net/nysl/
4 * 4 *
5 * Common tricks and utilities for programming in D. 5 * Common tricks and utilities for programming in D.
6 */ 6 */
7 module polemy.tricks; 7 module polemy.tricks;
8 static import std.array; | 8 import std.array : appender;
9 static import std.format; | 9 import std.format : formattedWrite;
10 static import core.exception; | 10 import core.exception : onAssertErrorMsg, AssertError;
11 11
12 /// Simple Wrapper for std.format.doFormat 12 /// Simple Wrapper for std.format.doFormat
13 13
14 string sprintf(string fmt, T...)(T params) 14 string sprintf(string fmt, T...)(T params)
15 { 15 {
16 auto writer = std.array.appender!string(); | 16 auto writer = appender!string();
17 std.format.formattedWrite(writer, fmt, params); | 17 formattedWrite(writer, fmt, params);
18 return writer.data; 18 return writer.data;
19 } 19 }
20 20
21 unittest 21 unittest
22 { 22 {
23 assert( sprintf!"%s == %d"("1+2", 3) == "1+2 == 3" ); 23 assert( sprintf!"%s == %d"("1+2", 3) == "1+2 == 3" );
24 assert( sprintf!"%s == %04d"("1+2", 3) == "1+2 == 0003" ); 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
> 30 {
> 31 try {
> 32 t();
> 33 } catch(ExceptionType) {
> 34 return;
> 35 } catch(Throwable e) {
> 36 onAssertErrorMsg(fn, ln, msg.length ? msg : sprintf!"exception [
> 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 [
> 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 /// Unittest helpers asserting two values are in some relation ==, !=, <, <=, >, 68 /// Unittest helpers asserting two values are in some relation ==, !=, <, <=, >,
28 69
29 template assertOp(string op) 70 template assertOp(string op)
30 { 71 {
31 void assertOp(A, B, string fn=__FILE__, int ln=__LINE__)(A a, B b, strin 72 void assertOp(A, B, string fn=__FILE__, int ln=__LINE__)(A a, B b, strin
32 { 73 {
33 try { 74 try {
34 if( mixin("a"~op~"b") ) return; 75 if( mixin("a"~op~"b") ) return;
35 } catch(Throwable e) { 76 } catch(Throwable e) {
36 core.exception.onAssertErrorMsg(fn, ln, msg.length ? msg | 77 onAssertErrorMsg(fn, ln, msg.length ? msg : sprintf!"exc
37 } 78 }
38 core.exception.onAssertErrorMsg(fn, ln, msg.length ? msg : sprin | 79 onAssertErrorMsg(fn, ln, msg.length ? msg : sprintf!"%s !%s %s"(
39 } 80 }
40 } 81 }
41 82
42 alias assertOp!(`==`) assert_eq; 83 alias assertOp!(`==`) assert_eq;
43 alias assertOp!(`!=`) assert_ne; 84 alias assertOp!(`!=`) assert_ne;
44 alias assertOp!(`<`) assert_lt; 85 alias assertOp!(`<`) assert_lt;
45 alias assertOp!(`<=`) assert_le; 86 alias assertOp!(`<=`) assert_le;
46 alias assertOp!(`>`) assert_gt; 87 alias assertOp!(`>`) assert_gt;
47 alias assertOp!(`>=`) assert_ge; 88 alias assertOp!(`>=`) assert_ge;
48 89
49 /// Unittest helper that asserts an expression must throw something | 90 unittest
50 <
51 void assert_throw(ExceptionType, T, string fn=__FILE__, int ln=__LINE__)(lazy T <
52 { 91 {
53 try { | 92 assert_nothrow( assert_eq("foo", "foo") );
54 t(); | 93 assert_nothrow( assert_ne("foo", "bar") );
55 } catch(ExceptionType) { | 94 assert_nothrow( assert_lt("bar", "foo") );
56 return; | 95 assert_nothrow( assert_le("bar", "foo") );
57 } catch(Throwable e) { | 96 assert_nothrow( assert_le("bar", "bar") );
58 core.exception.onAssertErrorMsg(fn, ln, msg.length ? msg : sprin | 97 assert_nothrow( assert_gt("foo", "bar") );
59 } <
> 98 assert_nothrow( assert_ge("foo", "bar") );
60 core.exception.onAssertErrorMsg(fn, ln, msg.length ? msg : "no execption | 99 assert_nothrow( assert_ge("bar", "bar") );
61 } | 100
62 <
> 101 assert_throw!AssertError( assert_eq("foo", "bar") );
63 /// Unittest helper that asserts an expression must not throw anything | 102 assert_throw!AssertError( assert_ne("foo", "foo") );
64 <
> 103 assert_throw!AssertError( assert_lt("foo", "foo") );
65 void assert_nothrow(ExceptionType, T, string fn=__FILE__, int ln=__LINE__)(lazy | 104 assert_throw!AssertError( assert_lt("foo", "bar") );
66 { <
> 105 assert_throw!AssertError( assert_le("foo", "bar") );
67 try { | 106 assert_throw!AssertError( assert_gt("bar", "bar") );
68 t(); | 107 assert_throw!AssertError( assert_gt("bar", "foo") );
69 } catch(Throwable e) { | 108 assert_throw!AssertError( assert_ge("bar", "foo") );
70 core.exception.onAssertErrorMsg(fn, ln, msg.length ? msg : sprin <
71 } | 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 /* [Todo] is there any way to clearnly implement "assert_compiles" and "assert_n 116 /* [Todo] is there any way to clearnly implement "assert_compiles" and "assert_n
75 117
76 /// Mixing-in the bean constructor for a class 118 /// Mixing-in the bean constructor for a class
77 119
78 template SimpleConstructor() 120 template SimpleConstructor()
................................................................................................................................................................................
103 mixin SimpleConstructor; 145 mixin SimpleConstructor;
104 } 146 }
105 assert_eq( (new Temp(1,"foo")).x, 1 ); 147 assert_eq( (new Temp(1,"foo")).x, 1 );
106 assert_eq( (new Temp(1,"foo")).y, "foo" ); 148 assert_eq( (new Temp(1,"foo")).y, "foo" );
107 assert( !__traits(compiles, new Temp) ); 149 assert( !__traits(compiles, new Temp) );
108 assert( !__traits(compiles, new Temp(1)) ); 150 assert( !__traits(compiles, new Temp(1)) );
109 assert( !__traits(compiles, new Temp("foo",1)) ); 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 memb
> 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 /// Mixing-in the MOST-DERIVED-member-wise comparator for a class 174 /// Mixing-in the MOST-DERIVED-member-wise comparator for a class
113 175
114 template SimpleCompare() 176 template SimpleCompare()
115 { 177 {
116 override bool opEquals(Object rhs_) const 178 override bool opEquals(Object rhs_) const
................................................................................................................................................................................
157 } 219 }
158 assert_eq( new Temp(1,"foo"), new Temp(1,"foo") ); 220 assert_eq( new Temp(1,"foo"), new Temp(1,"foo") );
159 assert_eq( (new Temp(1,"foo")).toHash, (new Temp(1,"foo")).toHash ); 221 assert_eq( (new Temp(1,"foo")).toHash, (new Temp(1,"foo")).toHash );
160 assert_ne( new Temp(1,"foo"), new Temp(2,"foo") ); 222 assert_ne( new Temp(1,"foo"), new Temp(2,"foo") );
161 assert_ne( new Temp(1,"foo"), new Temp(1,"bar") ); 223 assert_ne( new Temp(1,"foo"), new Temp(1,"bar") );
162 assert_gt( new Temp(1,"foo"), new Temp(1,"bar") ); 224 assert_gt( new Temp(1,"foo"), new Temp(1,"bar") );
163 assert_lt( new Temp(1,"foo"), new Temp(2,"bar") ); 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 }