Diff
Not logged in

Differences From Artifact [63ca5d91a9064dd8]:

To Artifact [aa60c34591041ca2]:


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 }