Diff
Not logged in

Differences From Artifact [63ca5d91a9064dd8]:

To Artifact [aa60c34591041ca2]:


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 }