| 1 |
// SemiTwist Library |
|---|
| 2 |
// Written in the D programming language. |
|---|
| 3 |
|
|---|
| 4 |
module semitwist.util.unittests; |
|---|
| 5 |
|
|---|
| 6 |
// deferEnsure requires this to exist in the calling context |
|---|
| 7 |
public import semitwist.util.reflect : _deferAssert_ExprTypeOf = ExprTypeOf; |
|---|
| 8 |
|
|---|
| 9 |
import std.conv; |
|---|
| 10 |
import std.demangle; |
|---|
| 11 |
import std.stdio; |
|---|
| 12 |
import std.traits; |
|---|
| 13 |
|
|---|
| 14 |
import semitwist.util.all; |
|---|
| 15 |
|
|---|
| 16 |
/** |
|---|
| 17 |
Sounds like a contradiction of terms, but this is just |
|---|
| 18 |
intended to allow unittests to output ALL failures instead |
|---|
| 19 |
of only outputting the first one and then stopping. |
|---|
| 20 |
*/ |
|---|
| 21 |
template deferAssert(string condStr, string msg="") |
|---|
| 22 |
{ |
|---|
| 23 |
enum deferAssert = |
|---|
| 24 |
// The "_deferAssert_line" is a workaround for DMD Bug #2887 |
|---|
| 25 |
"{ enum long _deferAssert_line = __LINE__;\n"~ |
|---|
| 26 |
" try\n"~ |
|---|
| 27 |
" {\n"~ |
|---|
| 28 |
" bool _deferAssert_condResult = ("~condStr~")?true:false;\n"~ |
|---|
| 29 |
" _deferAssert!(_deferAssert_line, __FILE__, "~condStr.stringof~", "~msg.stringof~")(_deferAssert_condResult);\n"~ |
|---|
| 30 |
" }\n"~ |
|---|
| 31 |
" catch(Throwable _deferAssert_e)\n"~ |
|---|
| 32 |
" _deferAssertException!(_deferAssert_line, __FILE__, "~condStr.stringof~", "~msg.stringof~")(_deferAssert_e);\n"~ |
|---|
| 33 |
"}\n"; |
|---|
| 34 |
} |
|---|
| 35 |
|
|---|
| 36 |
bool _deferAssert(long line, string file, string condStr, string msg="")(bool condResult) |
|---|
| 37 |
{ |
|---|
| 38 |
if(!condResult) |
|---|
| 39 |
{ |
|---|
| 40 |
assertCount++; |
|---|
| 41 |
writefln("%s(%s): Assert Failed (%s)%s", |
|---|
| 42 |
file, line, condStr, |
|---|
| 43 |
msg=="" ? "" : ": " ~ msg); |
|---|
| 44 |
writeln(); |
|---|
| 45 |
} |
|---|
| 46 |
|
|---|
| 47 |
return condResult; |
|---|
| 48 |
} |
|---|
| 49 |
|
|---|
| 50 |
void _deferAssertException(long line, string file, string condStr, string msg="")(Object thrown) |
|---|
| 51 |
{ |
|---|
| 52 |
assertCount++; |
|---|
| 53 |
writef("%s(%s): Assert Threw (%s)%s:\nThrew: ", |
|---|
| 54 |
file, line, condStr, |
|---|
| 55 |
msg=="" ? "" : ": " ~ msg); |
|---|
| 56 |
Exception e = cast(Exception)thrown; |
|---|
| 57 |
if(e) |
|---|
| 58 |
writeln(thrown); |
|---|
| 59 |
else |
|---|
| 60 |
writefln("Object: type '%s': %s", thrown.classinfo.name, thrown); |
|---|
| 61 |
writeln(); |
|---|
| 62 |
} |
|---|
| 63 |
|
|---|
| 64 |
//TODO: Something like: mixin(blah!(`_1 == (_2 ~ _3)`, `"Hello"`, `"He"`, `"llo"`)); |
|---|
| 65 |
|
|---|
| 66 |
template deferEnsure(string value, string condStr, string msg="") |
|---|
| 67 |
{ |
|---|
| 68 |
enum deferEnsure = |
|---|
| 69 |
// The "_deferAssert_line" is a workaround for DMD Bug #2887 |
|---|
| 70 |
"{ enum long _deferAssert_line = __LINE__;\n"~ |
|---|
| 71 |
" try\n"~ |
|---|
| 72 |
" {\n"~ |
|---|
| 73 |
" auto _ = ("~value~");\n"~ |
|---|
| 74 |
" bool _deferAssert_condResult = ("~condStr~")?true:false;\n"~ |
|---|
| 75 |
" _deferEnsure!(_deferAssert_line, __FILE__, "~value.stringof~", "~condStr.stringof~", _deferAssert_ExprTypeOf!(typeof("~value~")), "~msg.stringof~")(_, _deferAssert_condResult);\n"~ |
|---|
| 76 |
" }\n"~ |
|---|
| 77 |
" catch(Throwable _deferAssert_e)\n"~ |
|---|
| 78 |
" _deferEnsureException!(_deferAssert_line, __FILE__, "~value.stringof~", "~condStr.stringof~", "~msg.stringof~")(_deferAssert_e);\n"~ |
|---|
| 79 |
"}\n"; |
|---|
| 80 |
} |
|---|
| 81 |
|
|---|
| 82 |
bool _deferEnsure(long line, string file, string valueStr, string condStr, T, string msg="")(T valueResult, bool condResult) |
|---|
| 83 |
{ |
|---|
| 84 |
if(!condResult) |
|---|
| 85 |
{ |
|---|
| 86 |
assertCount++; |
|---|
| 87 |
writefln("%s(%s): Ensure Failed%s\n"~ |
|---|
| 88 |
"Expression '%s':\n"~ |
|---|
| 89 |
"Expected: %s\n"~ |
|---|
| 90 |
"Actual: %s", |
|---|
| 91 |
file, line, msg=="" ? "" : ": " ~ msg, |
|---|
| 92 |
valueStr, condStr, valueResult); |
|---|
| 93 |
writeln(); |
|---|
| 94 |
} |
|---|
| 95 |
|
|---|
| 96 |
return condResult; |
|---|
| 97 |
} |
|---|
| 98 |
|
|---|
| 99 |
void _deferEnsureException(long line, string file, string valueStr, string condStr, string msg="")(Object thrown) |
|---|
| 100 |
{ |
|---|
| 101 |
assertCount++; |
|---|
| 102 |
writef("%s(%s): Ensure Threw%s:\n"~ |
|---|
| 103 |
"Expression '%s':\n"~ |
|---|
| 104 |
"Expected: %s\n"~ |
|---|
| 105 |
"Threw: ", |
|---|
| 106 |
file, line, msg=="" ? "" : ": " ~ msg, |
|---|
| 107 |
valueStr, condStr); |
|---|
| 108 |
Exception e = cast(Exception)thrown; |
|---|
| 109 |
if(e) |
|---|
| 110 |
writeln(thrown); |
|---|
| 111 |
else |
|---|
| 112 |
writefln("Object: type '%s': %s", thrown.classinfo.name, thrown); |
|---|
| 113 |
writeln(); |
|---|
| 114 |
} |
|---|
| 115 |
|
|---|
| 116 |
template deferEnsureThrows(string stmtStr, TExpected, string msg="") |
|---|
| 117 |
{ |
|---|
| 118 |
enum deferEnsureThrows = |
|---|
| 119 |
// The "_deferAssert_line" is a workaround for DMD Bug #2887 |
|---|
| 120 |
"{ enum long _deferAssert_line = __LINE__;\n"~ |
|---|
| 121 |
" Object _deferAssert_caught=null;\n"~ |
|---|
| 122 |
" try\n"~ |
|---|
| 123 |
" {"~stmtStr~"}\n"~ |
|---|
| 124 |
" catch(Throwable _deferAssert_e)\n"~ |
|---|
| 125 |
" _deferAssert_caught = _deferAssert_e;\n"~ |
|---|
| 126 |
" _deferEnsureThrows!(_deferAssert_line, __FILE__, "~stmtStr.stringof~", "~TExpected.stringof~", "~msg.stringof~")(_deferAssert_caught);\n"~ |
|---|
| 127 |
"}\n"; |
|---|
| 128 |
} |
|---|
| 129 |
|
|---|
| 130 |
void _deferEnsureThrows(long line, string file, string stmtStr, TExpected, string msg="")(Object thrown) |
|---|
| 131 |
{ |
|---|
| 132 |
string actualType = (thrown is null)? "{null}" : thrown.classinfo.name; |
|---|
| 133 |
|
|---|
| 134 |
if(actualType != TExpected.classinfo.name) |
|---|
| 135 |
{ |
|---|
| 136 |
assertCount++; |
|---|
| 137 |
writef("%s(%s): Ensure Throw Failed%s\n"~ |
|---|
| 138 |
"Statement '%s':\n"~ |
|---|
| 139 |
"Expected: %s\n"~ |
|---|
| 140 |
"Actual: ", |
|---|
| 141 |
file, line, msg=="" ? "" : ": " ~ msg, |
|---|
| 142 |
stmtStr, TExpected.classinfo.name, actualType); |
|---|
| 143 |
Throwable e = cast(Exception)thrown; |
|---|
| 144 |
if(e) |
|---|
| 145 |
writeln(e); //e.writeOut( (string msg) {Stdout(msg);} ); |
|---|
| 146 |
else |
|---|
| 147 |
writefln("%s: %s", actualType, thrown); |
|---|
| 148 |
writeln(); |
|---|
| 149 |
} |
|---|
| 150 |
} |
|---|
| 151 |
|
|---|
| 152 |
private uint assertCount=0; |
|---|
| 153 |
uint getAssertCount() |
|---|
| 154 |
{ |
|---|
| 155 |
return assertCount; |
|---|
| 156 |
} |
|---|
| 157 |
void resetAssertCount() |
|---|
| 158 |
{ |
|---|
| 159 |
assertCount = 0; |
|---|
| 160 |
} |
|---|
| 161 |
|
|---|
| 162 |
void flushAsserts() |
|---|
| 163 |
{ |
|---|
| 164 |
if(assertCount > 0) |
|---|
| 165 |
{ |
|---|
| 166 |
uint saveAssertCount = assertCount; |
|---|
| 167 |
assertCount = 0; |
|---|
| 168 |
stdout.flush(); |
|---|
| 169 |
assert(false, |
|---|
| 170 |
to!(string)(saveAssertCount) ~ |
|---|
| 171 |
" Assert Failure" ~ |
|---|
| 172 |
(saveAssertCount == 1 ? "" : "s") |
|---|
| 173 |
); |
|---|
| 174 |
} |
|---|
| 175 |
} |
|---|
| 176 |
|
|---|
| 177 |
/++ |
|---|
| 178 |
To be mixed in. |
|---|
| 179 |
|
|---|
| 180 |
Note that if DMD Issue #2887 ever gets fixed, the line numbers for errors |
|---|
| 181 |
in unittestBody may get messed up. |
|---|
| 182 |
|
|---|
| 183 |
Suggested Usage: |
|---|
| 184 |
------------------- |
|---|
| 185 |
alias unittestSection!"MyProject_unittest" unittestMyProject; |
|---|
| 186 |
|
|---|
| 187 |
mixin(unittestMyProject(q{ |
|---|
| 188 |
// put unittests here |
|---|
| 189 |
})); |
|---|
| 190 |
|
|---|
| 191 |
mixin(unittestMyProject("This is for class Foo", q{ |
|---|
| 192 |
// put unittests here |
|---|
| 193 |
})); |
|---|
| 194 |
------------------- |
|---|
| 195 |
|
|---|
| 196 |
That will create a named unittest section that will only run |
|---|
| 197 |
when -unittest and -debug=MyProject_unittest are passed to DMD. |
|---|
| 198 |
When run, the following headings will be displayed: |
|---|
| 199 |
|
|---|
| 200 |
== unittest: the.module.name |
|---|
| 201 |
== unittest: the.module.name: This is for class Foo |
|---|
| 202 |
+/ |
|---|
| 203 |
string unittestSection(string debugIdent, bool autoThrow=false)(string sectionName, string unittestBody=null) |
|---|
| 204 |
{ |
|---|
| 205 |
// Allow these two forms (without getting in the way of aliasing): |
|---|
| 206 |
// unittestSection!debugIdent(unittestBody) |
|---|
| 207 |
// unittestSection!debugIdent(sectionName, unittestBody) |
|---|
| 208 |
if(unittestBody==null) |
|---|
| 209 |
{ |
|---|
| 210 |
unittestBody = sectionName; |
|---|
| 211 |
sectionName = ""; |
|---|
| 212 |
} |
|---|
| 213 |
sectionName = ( sectionName==""? "" : ": "~sectionName ).escapeDDQS(); |
|---|
| 214 |
auto autoThrowStr = autoThrow? "true" : "false"; |
|---|
| 215 |
|
|---|
| 216 |
return |
|---|
| 217 |
"debug("~debugIdent~") "~ |
|---|
| 218 |
"{ "~ |
|---|
| 219 |
" unittest "~ |
|---|
| 220 |
" { "~ |
|---|
| 221 |
" auto saveAutoThrow = semitwist.util.unittests.autoThrow; "~ |
|---|
| 222 |
" semitwist.util.unittests.autoThrow = "~autoThrowStr~"; "~ |
|---|
| 223 |
" scope(exit) semitwist.util.unittests.autoThrow = saveAutoThrow; "~ |
|---|
| 224 |
" "~ |
|---|
| 225 |
" int _unittestSection_dummy_; "~ |
|---|
| 226 |
" auto _unittestSection_moduleName_ = "~ |
|---|
| 227 |
" unittestSection_demangle( qualifiedName!_unittestSection_dummy_() ) "~ |
|---|
| 228 |
" [ "~ |
|---|
| 229 |
" \"void \".length .. "~ |
|---|
| 230 |
" ctfe_find(unittestSection_demangle( qualifiedName!_unittestSection_dummy_() ), \".__unittest\") "~ |
|---|
| 231 |
" ]; "~ |
|---|
| 232 |
" "~ |
|---|
| 233 |
" writeUnittestSection( "~ |
|---|
| 234 |
" _unittestSection_moduleName_ ~ "~ |
|---|
| 235 |
" "~sectionName~" "~ |
|---|
| 236 |
" ); "~ |
|---|
| 237 |
" "~unittestBody~" "~ |
|---|
| 238 |
" } "~ |
|---|
| 239 |
"} "; |
|---|
| 240 |
} |
|---|
| 241 |
alias mangledName unittestSection_mangledName; |
|---|
| 242 |
alias demangle unittestSection_demangle; |
|---|
| 243 |
|
|---|
| 244 |
void writeUnittestSection(string sectionName) |
|---|
| 245 |
{ |
|---|
| 246 |
writeln("== unittest: ", sectionName); |
|---|
| 247 |
} |
|---|
| 248 |
|
|---|
| 249 |
alias unittestSection!"SemiTwistDLib_unittest" unittestSemiTwistDLib; |
|---|
| 250 |
|
|---|
| 251 |
/////////////////////////////////////////////////////////////////////////////// |
|---|
| 252 |
|
|---|
| 253 |
/// A modification of Jonathan M Davis's unittest routines below: |
|---|
| 254 |
|
|---|
| 255 |
//Ideally, this would be safe, I suppose, but it's enough of |
|---|
| 256 |
//a pain at the moment to make stuff safe that I'm just going to |
|---|
| 257 |
//mark it as trusted for the moment. |
|---|
| 258 |
@trusted |
|---|
| 259 |
|
|---|
| 260 |
|
|---|
| 261 |
import std.stdio; |
|---|
| 262 |
|
|---|
| 263 |
import core.exception; |
|---|
| 264 |
|
|---|
| 265 |
import std.algorithm; |
|---|
| 266 |
import std.array; |
|---|
| 267 |
import std.conv; |
|---|
| 268 |
import std.exception; |
|---|
| 269 |
import std.functional; |
|---|
| 270 |
import std.range; |
|---|
| 271 |
import std.string; |
|---|
| 272 |
import std.traits; |
|---|
| 273 |
|
|---|
| 274 |
/// This does not currently affect the defer* functions above. |
|---|
| 275 |
bool autoThrow = true; |
|---|
| 276 |
|
|---|
| 277 |
private void throwException(Throwable e) |
|---|
| 278 |
{ |
|---|
| 279 |
if(autoThrow) |
|---|
| 280 |
throw e; |
|---|
| 281 |
else |
|---|
| 282 |
{ |
|---|
| 283 |
assertCount++; |
|---|
| 284 |
writeln(e); |
|---|
| 285 |
writeln(); |
|---|
| 286 |
} |
|---|
| 287 |
} |
|---|
| 288 |
|
|---|
| 289 |
version(unittest) |
|---|
| 290 |
{ |
|---|
| 291 |
import std.datetime; |
|---|
| 292 |
} |
|---|
| 293 |
|
|---|
| 294 |
|
|---|
| 295 |
mixin(unittestSemiTwistDLib("assertPred: Overview Examples", q{ |
|---|
| 296 |
autoThrow = true; |
|---|
| 297 |
|
|---|
| 298 |
//Verify Examples. |
|---|
| 299 |
assertPred!"=="(5 * 7, 35); |
|---|
| 300 |
|
|---|
| 301 |
assertPred!("opCmp", ">")(std.datetime.Clock.currTime(), std.datetime.SysTime(Date(1970, 1, 1))); |
|---|
| 302 |
|
|---|
| 303 |
assertPred!"opAssign"(std.datetime.SysTime(Date(1970, 1, 1)), |
|---|
| 304 |
std.datetime.SysTime(Date(2010, 12, 31))); |
|---|
| 305 |
|
|---|
| 306 |
assertPred!"+"(5, 7, 12); |
|---|
| 307 |
|
|---|
| 308 |
assertPred!"+="(std.datetime.SysTime(Date(1970, 1, 1)), |
|---|
| 309 |
core.time.dur!"days"(3), |
|---|
| 310 |
std.datetime.SysTime(Date(1970, 1, 4))); |
|---|
| 311 |
|
|---|
| 312 |
assertPred!"a == 7"(12 - 5); |
|---|
| 313 |
|
|---|
| 314 |
assertPred!"a == b + 5"(12, 7); |
|---|
| 315 |
|
|---|
| 316 |
assertPred!((int a, int b, int c){return a + b < c;})(4, 12, 50); |
|---|
| 317 |
})); |
|---|
| 318 |
|
|---|
| 319 |
|
|---|
| 320 |
void assertPred(string op, L, R) |
|---|
| 321 |
(L lhs, R rhs, lazy string msg = null, string file = __FILE__, size_t line = __LINE__) |
|---|
| 322 |
if((op == "<" || |
|---|
| 323 |
op == "<=" || |
|---|
| 324 |
op == "==" || |
|---|
| 325 |
op == "!=" || |
|---|
| 326 |
op == ">=" || |
|---|
| 327 |
op == ">") && |
|---|
| 328 |
__traits(compiles, mixin("lhs " ~ op ~ " rhs")) && |
|---|
| 329 |
isPrintable!L && |
|---|
| 330 |
isPrintable!R) |
|---|
| 331 |
{ |
|---|
| 332 |
immutable result = mixin("lhs " ~ op ~ " rhs"); |
|---|
| 333 |
|
|---|
| 334 |
if(!result) |
|---|
| 335 |
{ |
|---|
| 336 |
immutable tail = msg.empty ? "." : ": " ~ msg; |
|---|
| 337 |
|
|---|
| 338 |
throwException( new AssertError(format("assertPred!\"%s\" failed:\n[%s] (lhs)\n[%s] (rhs)%s", op, lhs, rhs, tail), |
|---|
| 339 |
file, |
|---|
| 340 |
line) |
|---|
| 341 |
); |
|---|
| 342 |
} |
|---|
| 343 |
} |
|---|
| 344 |
|
|---|
| 345 |
mixin(unittestSemiTwistDLib("assertPred: Comparison Operators", q{ |
|---|
| 346 |
autoThrow = true; |
|---|
| 347 |
|
|---|
| 348 |
struct IntWrapper |
|---|
| 349 |
{ |
|---|
| 350 |
int value; |
|---|
| 351 |
|
|---|
| 352 |
this(int value) |
|---|
| 353 |
{ |
|---|
| 354 |
this.value = value; |
|---|
| 355 |
} |
|---|
| 356 |
|
|---|
| 357 |
string toString() |
|---|
| 358 |
{ |
|---|
| 359 |
return to!string(value); |
|---|
| 360 |
} |
|---|
| 361 |
} |
|---|
| 362 |
|
|---|
| 363 |
//Test ==. |
|---|
| 364 |
assertNotThrown!AssertError(assertPred!"=="(6, 6)); |
|---|
| 365 |
assertNotThrown!AssertError(assertPred!"=="(6, 6.0)); |
|---|
| 366 |
assertNotThrown!AssertError(assertPred!"=="(IntWrapper(6), IntWrapper(6))); |
|---|
| 367 |
|
|---|
| 368 |
assertThrown!AssertError(assertPred!"=="(6, 7)); |
|---|
| 369 |
assertThrown!AssertError(assertPred!"=="(6, 6.1)); |
|---|
| 370 |
assertThrown!AssertError(assertPred!"=="(IntWrapper(6), IntWrapper(7))); |
|---|
| 371 |
assertThrown!AssertError(assertPred!"=="(IntWrapper(7), IntWrapper(6))); |
|---|
| 372 |
|
|---|
| 373 |
assertPred!"=="(collectExceptionMsg(assertPred!"=="(6, 7)), |
|---|
| 374 |
"assertPred!\"==\" failed:\n[6] (lhs)\n[7] (rhs)."); |
|---|
| 375 |
assertPred!"=="(collectExceptionMsg(assertPred!"=="(6, 7, "It failed!")), |
|---|
| 376 |
"assertPred!\"==\" failed:\n[6] (lhs)\n[7] (rhs): It failed!"); |
|---|
| 377 |
|
|---|
| 378 |
//Test !=. |
|---|
| 379 |
assertNotThrown!AssertError(assertPred!"!="(6, 7)); |
|---|
| 380 |
assertNotThrown!AssertError(assertPred!"!="(6, 6.1)); |
|---|
| 381 |
assertNotThrown!AssertError(assertPred!"!="(IntWrapper(6), IntWrapper(7))); |
|---|
| 382 |
assertNotThrown!AssertError(assertPred!"!="(IntWrapper(7), IntWrapper(6))); |
|---|
| 383 |
|
|---|
| 384 |
assertThrown!AssertError(assertPred!"!="(6, 6)); |
|---|
| 385 |
assertThrown!AssertError(assertPred!"!="(6, 6.0)); |
|---|
| 386 |
assertThrown!AssertError(assertPred!"!="(IntWrapper(6), IntWrapper(6))); |
|---|
| 387 |
|
|---|
| 388 |
assertPred!"=="(collectExceptionMsg(assertPred!"!="(6, 6)), |
|---|
| 389 |
"assertPred!\"!=\" failed:\n[6] (lhs)\n[6] (rhs)."); |
|---|
| 390 |
assertPred!"=="(collectExceptionMsg(assertPred!"!="(6, 6, "It failed!")), |
|---|
| 391 |
"assertPred!\"!=\" failed:\n[6] (lhs)\n[6] (rhs): It failed!"); |
|---|
| 392 |
|
|---|
| 393 |
//Test <, <=, >=, >. |
|---|
| 394 |
assertNotThrown!AssertError(assertPred!"<"(5, 7)); |
|---|
| 395 |
assertNotThrown!AssertError(assertPred!"<="(5, 7)); |
|---|
| 396 |
assertNotThrown!AssertError(assertPred!"<="(5, 5)); |
|---|
| 397 |
assertNotThrown!AssertError(assertPred!">="(7, 7)); |
|---|
| 398 |
assertNotThrown!AssertError(assertPred!">="(7, 5)); |
|---|
| 399 |
assertNotThrown!AssertError(assertPred!">"(7, 5)); |
|---|
| 400 |
|
|---|
| 401 |
assertThrown!AssertError(assertPred!"<"(7, 5)); |
|---|
| 402 |
assertThrown!AssertError(assertPred!"<="(7, 5)); |
|---|
| 403 |
assertThrown!AssertError(assertPred!">="(5, 7)); |
|---|
| 404 |
assertThrown!AssertError(assertPred!">"(5, 7)); |
|---|
| 405 |
|
|---|
| 406 |
assertPred!"=="(collectExceptionMsg(assertPred!"<"(7, 5)), |
|---|
| 407 |
"assertPred!\"<\" failed:\n[7] (lhs)\n[5] (rhs)."); |
|---|
| 408 |
assertPred!"=="(collectExceptionMsg(assertPred!"<"(7, 5, "It failed!")), |
|---|
| 409 |
"assertPred!\"<\" failed:\n[7] (lhs)\n[5] (rhs): It failed!"); |
|---|
| 410 |
|
|---|
| 411 |
//Test default arguments. |
|---|
| 412 |
assertPred!"=="(12, 12); |
|---|
| 413 |
assertPred!"=="(12, 12, "msg"); |
|---|
| 414 |
assertPred!"=="(12, 12, "msg", "file"); |
|---|
| 415 |
assertPred!"=="(12, 12, "msg", "file", 42); |
|---|
| 416 |
|
|---|
| 417 |
//Verify Examples. |
|---|
| 418 |
assertPred!"<"(5 / 2 + 4, 27); |
|---|
| 419 |
|
|---|
| 420 |
assertPred!"<="(4, 5); |
|---|
| 421 |
|
|---|
| 422 |
assertPred!"=="(1 * 2.1, 2.1); |
|---|
| 423 |
|
|---|
| 424 |
assertPred!"!="("hello " ~ "world", "goodbye world"); |
|---|
| 425 |
|
|---|
| 426 |
assertPred!">="(14.2, 14); |
|---|
| 427 |
|
|---|
| 428 |
assertPred!">"(15, 2 + 1); |
|---|
| 429 |
|
|---|
| 430 |
assert(collectExceptionMsg(assertPred!"=="("hello", "goodbye")) == |
|---|
| 431 |
"assertPred!\"==\" failed:\n" ~ |
|---|
| 432 |
"[hello] (lhs)\n" ~ |
|---|
| 433 |
"[goodbye] (rhs)."); |
|---|
| 434 |
|
|---|
| 435 |
assert(collectExceptionMsg(assertPred!"<"(5, 2, "My test failed!")) == |
|---|
| 436 |
"assertPred!\"<\" failed:\n" ~ |
|---|
| 437 |
"[5] (lhs)\n" ~ |
|---|
| 438 |
"[2] (rhs): My test failed!"); |
|---|
| 439 |
})); |
|---|
| 440 |
|
|---|
| 441 |
|
|---|
| 442 |
void assertPred(string func, string expected, L, R) |
|---|
| 443 |
(L lhs, R rhs, lazy string msg = null, string file = __FILE__, size_t line = __LINE__) |
|---|
| 444 |
if(func == "opCmp" && |
|---|
| 445 |
(expected == "<" || |
|---|
| 446 |
expected == "==" || |
|---|
| 447 |
expected == ">") && |
|---|
| 448 |
__traits(compiles, lhs.opCmp(rhs)) && |
|---|
| 449 |
isPrintable!L && |
|---|
| 450 |
isPrintable!R) |
|---|
| 451 |
{ |
|---|
| 452 |
immutable result = lhs.opCmp(rhs); |
|---|
| 453 |
|
|---|
| 454 |
if(mixin("result " ~ expected ~ " 0")) |
|---|
| 455 |
return; |
|---|
| 456 |
|
|---|
| 457 |
immutable tail = msg.empty ? "." : ": " ~ msg; |
|---|
| 458 |
immutable actual = result < 0 ? "<" : (result == 0 ? "==" : ">"); |
|---|
| 459 |
|
|---|
| 460 |
throwException( new AssertError(format("assertPred!(\"opCmp\", \"%s\") failed:\n[%s] %s\n[%s]%s", expected, lhs, actual, rhs, tail), |
|---|
| 461 |
file, |
|---|
| 462 |
line) |
|---|
| 463 |
); |
|---|
| 464 |
} |
|---|
| 465 |
|
|---|
| 466 |
mixin(unittestSemiTwistDLib("assertPred: opCmp", q{ |
|---|
| 467 |
autoThrow = true; |
|---|
| 468 |
|
|---|
| 469 |
struct IntWrapper |
|---|
| 470 |
{ |
|---|
| 471 |
int value; |
|---|
| 472 |
|
|---|
| 473 |
this(int value) |
|---|
| 474 |
{ |
|---|
| 475 |
this.value = value; |
|---|
| 476 |
} |
|---|
| 477 |
|
|---|
| 478 |
int opCmp(const ref IntWrapper rhs) const |
|---|
| 479 |
{ |
|---|
| 480 |
if(value < rhs.value) |
|---|
| 481 |
return -1; |
|---|
| 482 |
else if(value > rhs.value) |
|---|
| 483 |
return 1; |
|---|
| 484 |
|
|---|
| 485 |
return 0; |
|---|
| 486 |
} |
|---|
| 487 |
|
|---|
| 488 |
string toString() |
|---|
| 489 |
{ |
|---|
| 490 |
return to!string(value); |
|---|
| 491 |
} |
|---|
| 492 |
} |
|---|
| 493 |
|
|---|
| 494 |
assertNotThrown!AssertError(assertPred!("opCmp", "<")(IntWrapper(0), IntWrapper(6))); |
|---|
| 495 |
assertNotThrown!AssertError(assertPred!("opCmp", "<")(IntWrapper(6), IntWrapper(7))); |
|---|
| 496 |
assertNotThrown!AssertError(assertPred!("opCmp", "==")(IntWrapper(6), IntWrapper(6))); |
|---|
| 497 |
assertNotThrown!AssertError(assertPred!("opCmp", "==")(IntWrapper(0), IntWrapper(0))); |
|---|
| 498 |
assertNotThrown!AssertError(assertPred!("opCmp", ">")(IntWrapper(6), IntWrapper(0))); |
|---|
| 499 |
assertNotThrown!AssertError(assertPred!("opCmp", ">")(IntWrapper(7), IntWrapper(6))); |
|---|
| 500 |
|
|---|
| 501 |
assertThrown!AssertError(assertPred!("opCmp", "<")(IntWrapper(6), IntWrapper(6))); |
|---|
| 502 |
assertThrown!AssertError(assertPred!("opCmp", "<")(IntWrapper(7), IntWrapper(6))); |
|---|
| 503 |
assertThrown!AssertError(assertPred!("opCmp", "==")(IntWrapper(6), IntWrapper(7))); |
|---|
| 504 |
assertThrown!AssertError(assertPred!("opCmp", "==")(IntWrapper(7), IntWrapper(6))); |
|---|
| 505 |
assertThrown!AssertError(assertPred!("opCmp", ">")(IntWrapper(6), IntWrapper(6))); |
|---|
| 506 |
assertThrown!AssertError(assertPred!("opCmp", ">")(IntWrapper(6), IntWrapper(7))); |
|---|
| 507 |
|
|---|
| 508 |
assertPred!"=="(collectExceptionMsg(assertPred!("opCmp", "<")(IntWrapper(5), IntWrapper(5))), |
|---|
| 509 |
"assertPred!(\"opCmp\", \"<\") failed:\n[5] ==\n[5]."); |
|---|
| 510 |
assertPred!"=="(collectExceptionMsg(assertPred!("opCmp", "<")(IntWrapper(5), IntWrapper(5), "It failed!")), |
|---|
| 511 |
"assertPred!(\"opCmp\", \"<\") failed:\n[5] ==\n[5]: It failed!"); |
|---|
| 512 |
|
|---|
| 513 |
assertPred!"=="(collectExceptionMsg(assertPred!("opCmp", "<")(IntWrapper(14), IntWrapper(7))), |
|---|
| 514 |
"assertPred!(\"opCmp\", \"<\") failed:\n[14] >\n[7]."); |
|---|
| 515 |
assertPred!"=="(collectExceptionMsg(assertPred!("opCmp", "<")(IntWrapper(14), IntWrapper(7), "It failed!")), |
|---|
| 516 |
"assertPred!(\"opCmp\", \"<\") failed:\n[14] >\n[7]: It failed!"); |
|---|
| 517 |
|
|---|
| 518 |
assertPred!"=="(collectExceptionMsg(assertPred!("opCmp", "==")(IntWrapper(5), IntWrapper(7))), |
|---|
| 519 |
"assertPred!(\"opCmp\", \"==\") failed:\n[5] <\n[7]."); |
|---|
| 520 |
assertPred!"=="(collectExceptionMsg(assertPred!("opCmp", "==")(IntWrapper(5), IntWrapper(7), "It failed!")), |
|---|
| 521 |
"assertPred!(\"opCmp\", \"==\") failed:\n[5] <\n[7]: It failed!"); |
|---|
| 522 |
|
|---|
| 523 |
assertPred!"=="(collectExceptionMsg(assertPred!("opCmp", "==")(IntWrapper(14), IntWrapper(7))), |
|---|
| 524 |
"assertPred!(\"opCmp\", \"==\") failed:\n[14] >\n[7]."); |
|---|
| 525 |
assertPred!"=="(collectExceptionMsg(assertPred!("opCmp", "==")(IntWrapper(14), IntWrapper(7), "It failed!")), |
|---|
| 526 |
"assertPred!(\"opCmp\", \"==\") failed:\n[14] >\n[7]: It failed!"); |
|---|
| 527 |
|
|---|
| 528 |
assertPred!"=="(collectExceptionMsg(assertPred!("opCmp", ">")(IntWrapper(5), IntWrapper(7))), |
|---|
| 529 |
"assertPred!(\"opCmp\", \">\") failed:\n[5] <\n[7]."); |
|---|
| 530 |
assertPred!"=="(collectExceptionMsg(assertPred!("opCmp", ">")(IntWrapper(5), IntWrapper(7), "It failed!")), |
|---|
| 531 |
"assertPred!(\"opCmp\", \">\") failed:\n[5] <\n[7]: It failed!"); |
|---|
| 532 |
|
|---|
| 533 |
assertPred!"=="(collectExceptionMsg(assertPred!("opCmp", ">")(IntWrapper(7), IntWrapper(7))), |
|---|
| 534 |
"assertPred!(\"opCmp\", \">\") failed:\n[7] ==\n[7]."); |
|---|
| 535 |
assertPred!"=="(collectExceptionMsg(assertPred!("opCmp", ">")(IntWrapper(7), IntWrapper(7), "It failed!")), |
|---|
| 536 |
"assertPred!(\"opCmp\", \">\") failed:\n[7] ==\n[7]: It failed!"); |
|---|
| 537 |
|
|---|
| 538 |
//Test default arguments. |
|---|
| 539 |
assertPred!("opCmp", "<")(Date(2010, 11, 30), Date(2010, 12, 31)); |
|---|
| 540 |
assertPred!("opCmp", "<")(Date(2010, 11, 30), Date(2010, 12, 31), "msg"); |
|---|
| 541 |
assertPred!("opCmp", "<")(Date(2010, 11, 30), Date(2010, 12, 31), "msg", "file"); |
|---|
| 542 |
assertPred!("opCmp", "<")(Date(2010, 11, 30), Date(2010, 12, 31), "msg", "file", 42); |
|---|
| 543 |
|
|---|
| 544 |
assertPred!("opCmp", "==")(Date(2010, 12, 31), Date(2010, 12, 31)); |
|---|
| 545 |
assertPred!("opCmp", "==")(Date(2010, 12, 31), Date(2010, 12, 31), "msg"); |
|---|
| 546 |
assertPred!("opCmp", "==")(Date(2010, 12, 31), Date(2010, 12, 31), "msg", "file"); |
|---|
| 547 |
assertPred!("opCmp", "==")(Date(2010, 12, 31), Date(2010, 12, 31), "msg", "file", 42); |
|---|
| 548 |
|
|---|
| 549 |
assertPred!("opCmp", ">")(Date(2010, 12, 31), Date(2010, 11, 30)); |
|---|
| 550 |
assertPred!("opCmp", ">")(Date(2010, 12, 31), Date(2010, 11, 30), "msg"); |
|---|
| 551 |
assertPred!("opCmp", ">")(Date(2010, 12, 31), Date(2010, 11, 30), "msg", "file"); |
|---|
| 552 |
assertPred!("opCmp", ">")(Date(2010, 12, 31), Date(2010, 11, 30), "msg", "file", 42); |
|---|
| 553 |
})); |
|---|
| 554 |
|
|---|
| 555 |
mixin(unittestSemiTwistDLib("assertPred: opCmp: Examples", q{ |
|---|
| 556 |
autoThrow = true; |
|---|
| 557 |
|
|---|
| 558 |
//Verify Examples |
|---|
| 559 |
assertPred!("opCmp", "<")(std.datetime.SysTime(Date(1970, 1, 1)), |
|---|
| 560 |
std.datetime.SysTime(Date(2010, 12, 31))); |
|---|
| 561 |
|
|---|
| 562 |
assertPred!("opCmp", "==")(std.datetime.SysTime(Date(1970, 1, 1)), |
|---|
| 563 |
std.datetime.SysTime(Date(1970, 1, 1))); |
|---|
| 564 |
|
|---|
| 565 |
assertPred!("opCmp", ">")(std.datetime.SysTime(Date(2010, 12, 31)), |
|---|
| 566 |
std.datetime.SysTime(Date(1970, 1, 1))); |
|---|
| 567 |
|
|---|
| 568 |
assert(collectExceptionMsg(assertPred!("opCmp", "<")(std.datetime.SysTime(Date(2010, 12, 31)), |
|---|
| 569 |
std.datetime.SysTime(Date(1970, 1, 1)))) == |
|---|
| 570 |
"assertPred!(\"opCmp\", \"<\") failed:\n" ~ |
|---|
| 571 |
"[2010-Dec-31 00:00:00] >\n" ~ |
|---|
| 572 |
"[1970-Jan-01 00:00:00]."); |
|---|
| 573 |
|
|---|
| 574 |
assert(collectExceptionMsg(assertPred!("opCmp", "==")(std.datetime.SysTime(Date(1970, 1, 1)), |
|---|
| 575 |
std.datetime.SysTime(Date(2010, 12, 31)))) == |
|---|
| 576 |
"assertPred!(\"opCmp\", \"==\") failed:\n" ~ |
|---|
| 577 |
"[1970-Jan-01 00:00:00] <\n" ~ |
|---|
| 578 |
"[2010-Dec-31 00:00:00]."); |
|---|
| 579 |
|
|---|
| 580 |
assert(collectExceptionMsg(assertPred!("opCmp", ">")(std.datetime.SysTime(Date(1970, 1, 1)), |
|---|
| 581 |
std.datetime.SysTime(Date(1970, 1, 1)))) == |
|---|
| 582 |
"assertPred!(\"opCmp\", \">\") failed:\n" ~ |
|---|
| 583 |
"[1970-Jan-01 00:00:00] ==\n" ~ |
|---|
| 584 |
"[1970-Jan-01 00:00:00]."); |
|---|
| 585 |
})); |
|---|
| 586 |
|
|---|
| 587 |
|
|---|
| 588 |
void assertPred(string func, L, R) |
|---|
| 589 |
(L lhs, R rhs, lazy string msg = null, string file = __FILE__, size_t line = __LINE__) |
|---|
| 590 |
if(func == "opAssign" && |
|---|
| 591 |
__traits(compiles, lhs = rhs) && |
|---|
| 592 |
__traits(compiles, lhs == rhs) && |
|---|
| 593 |
__traits(compiles, (lhs = rhs) == rhs) && |
|---|
| 594 |
isPrintable!L && |
|---|
| 595 |
isPrintable!R) |
|---|
| 596 |
{ |
|---|
| 597 |
auto result = lhs = rhs; |
|---|
| 598 |
|
|---|
| 599 |
if(lhs != rhs) |
|---|
| 600 |
{ |
|---|
| 601 |
immutable tail = msg.empty ? "." : ": " ~ msg; |
|---|
| 602 |
|
|---|
| 603 |
throwException( new AssertError(format("assertPred!\"opAssign\" failed: lhs was assigned to\n[%s] instead of\n[%s]%s", |
|---|
| 604 |
lhs, |
|---|
| 605 |
rhs, |
|---|
| 606 |
tail), |
|---|
| 607 |
file, |
|---|
| 608 |
line) |
|---|
| 609 |
); |
|---|
| 610 |
} |
|---|
| 611 |
|
|---|
| 612 |
if(result != rhs) |
|---|
| 613 |
{ |
|---|
| 614 |
immutable tail = msg.empty ? "." : ": " ~ msg; |
|---|
| 615 |
|
|---|
| 616 |
throwException( new AssertError(format("assertPred!\"opAssign\" failed:\n[%s] (return value) !=\n[%s] (assigned value)%s", |
|---|
| 617 |
result, |
|---|
| 618 |
rhs, |
|---|
| 619 |
tail), |
|---|
| 620 |
file, |
|---|
| 621 |
line) |
|---|
| 622 |
); |
|---|
| 623 |
} |
|---|
| 624 |
} |
|---|
| 625 |
|
|---|
| 626 |
mixin(unittestSemiTwistDLib("assertPred: opAssign", q{ |
|---|
| 627 |
autoThrow = true; |
|---|
| 628 |
|
|---|
| 629 |
struct IntWrapper |
|---|
| 630 |
{ |
|---|
| 631 |
int value; |
|---|
| 632 |
|
|---|
| 633 |
this(int value) |
|---|
| 634 |
{ |
|---|
| 635 |
this.value = value; |
|---|
| 636 |
} |
|---|
| 637 |
|
|---|
| 638 |
IntWrapper opAssign(IntWrapper rhs) |
|---|
| 639 |
{ |
|---|
| 640 |
this.value = rhs.value; |
|---|
| 641 |
|
|---|
| 642 |
return this; |
|---|
| 643 |
} |
|---|
| 644 |
|
|---|
| 645 |
string toString() |
|---|
| 646 |
{ |
|---|
| 647 |
return to!string(value); |
|---|
| 648 |
} |
|---|
| 649 |
} |
|---|
| 650 |
|
|---|
| 651 |
struct IntWrapper_BadAssign |
|---|
| 652 |
{ |
|---|
| 653 |
int value; |
|---|
| 654 |
|
|---|
| 655 |
this(int value) |
|---|
| 656 |
{ |
|---|
| 657 |
this.value = value; |
|---|
| 658 |
} |
|---|
| 659 |
|
|---|
| 660 |
IntWrapper_BadAssign opAssign(IntWrapper_BadAssign rhs) |
|---|
| 661 |
{ |
|---|
| 662 |
this.value = -rhs.value; |
|---|
| 663 |
|
|---|
| 664 |
return IntWrapper_BadAssign(rhs.value); |
|---|
| 665 |
} |
|---|
| 666 |
|
|---|
| 667 |
string toString() |
|---|
| 668 |
{ |
|---|
| 669 |
return to!string(value); |
|---|
| 670 |
} |
|---|
| 671 |
} |
|---|
| 672 |
|
|---|
| 673 |
struct IntWrapper_BadReturn |
|---|
| 674 |
{ |
|---|
| 675 |
int value; |
|---|
| 676 |
|
|---|
| 677 |
this(int value) |
|---|
| 678 |
{ |
|---|
| 679 |
this.value = value; |
|---|
| 680 |
} |
|---|
| 681 |
|
|---|
| 682 |
IntWrapper_BadReturn opAssign(IntWrapper_BadReturn rhs) |
|---|
| 683 |
{ |
|---|
| 684 |
this.value = rhs.value; |
|---|
| 685 |
|
|---|
| 686 |
return IntWrapper_BadReturn(-rhs.value); |
|---|
| 687 |
} |
|---|
| 688 |
|
|---|
| 689 |
string toString() |
|---|
| 690 |
{ |
|---|
| 691 |
return to!string(value); |
|---|
| 692 |
} |
|---|
| 693 |
} |
|---|
| 694 |
|
|---|
| 695 |
assertNotThrown!AssertError(assertPred!"opAssign"(IntWrapper(5), IntWrapper(2))); |
|---|
| 696 |
|
|---|
| 697 |
assertThrown!AssertError(assertPred!"opAssign"(IntWrapper_BadAssign(5), IntWrapper_BadAssign(2))); |
|---|
| 698 |
assertThrown!AssertError(assertPred!"opAssign"(IntWrapper_BadReturn(5), IntWrapper_BadReturn(2))); |
|---|
| 699 |
|
|---|
| 700 |
assertPred!"=="(collectExceptionMsg(assertPred!"opAssign"(IntWrapper_BadAssign(5), IntWrapper_BadAssign(2))), |
|---|
| 701 |
"assertPred!\"opAssign\" failed: lhs was assigned to\n[-2] instead of\n[2]."); |
|---|
| 702 |
assertPred!"=="(collectExceptionMsg(assertPred!"opAssign"(IntWrapper_BadAssign(5), |
|---|
| 703 |
IntWrapper_BadAssign(2), |
|---|
| 704 |
"It failed!")), |
|---|
| 705 |
"assertPred!\"opAssign\" failed: lhs was assigned to\n[-2] instead of\n[2]: It failed!"); |
|---|
| 706 |
|
|---|
| 707 |
assertPred!"=="(collectExceptionMsg(assertPred!"opAssign"(IntWrapper_BadReturn(5), IntWrapper_BadReturn(2))), |
|---|
| 708 |
"assertPred!\"opAssign\" failed:\n[-2] (return value) !=\n[2] (assigned value)."); |
|---|
| 709 |
assertPred!"=="(collectExceptionMsg(assertPred!"opAssign"(IntWrapper_BadReturn(5), |
|---|
| 710 |
IntWrapper_BadReturn(2), |
|---|
| 711 |
"It failed!")), |
|---|
| 712 |
"assertPred!\"opAssign\" failed:\n[-2] (return value) !=\n[2] (assigned value): It failed!"); |
|---|
| 713 |
|
|---|
| 714 |
//Test default arguments. |
|---|
| 715 |
assertPred!"opAssign"(0, 12); |
|---|
| 716 |
assertPred!"opAssign"(0, 12, "msg"); |
|---|
| 717 |
assertPred!"opAssign"(0, 12, "msg", "file"); |
|---|
| 718 |
assertPred!"opAssign"(0, 12, "msg", "file", 42); |
|---|
| 719 |
})); |
|---|
| 720 |
|
|---|
| 721 |
mixin(unittestSemiTwistDLib("assertPred: opAssign: Examples", q{ |
|---|
| 722 |
autoThrow = true; |
|---|
| 723 |
|
|---|
| 724 |
//Verify Examples |
|---|
| 725 |
assertPred!"opAssign"(std.datetime.SysTime(Date(1970, 1, 1)), std.datetime.SysTime(Date(2000, 12, 12))); |
|---|
| 726 |
|
|---|
| 727 |
struct IntWrapper_BadAssign |
|---|
| 728 |
{ |
|---|
| 729 |
int value; |
|---|
| 730 |
|
|---|
| 731 |
IntWrapper_BadAssign opAssign(IntWrapper_BadAssign rhs) |
|---|
| 732 |
{ |
|---|
| 733 |
this.value = -rhs.value; |
|---|
| 734 |
|
|---|
| 735 |
return IntWrapper_BadAssign(rhs.value); |
|---|
| 736 |
} |
|---|
| 737 |
|
|---|
| 738 |
string toString() { return to!string(value); } |
|---|
| 739 |
} |
|---|
| 740 |
|
|---|
| 741 |
assert(collectExceptionMsg(assertPred!"opAssign"(IntWrapper_BadAssign(5), IntWrapper_BadAssign(2))) == |
|---|
| 742 |
"assertPred!\"opAssign\" failed: lhs was assigned to\n" ~ |
|---|
| 743 |
"[-2] instead of\n" ~ |
|---|
| 744 |
"[2]."); |
|---|
| 745 |
|
|---|
| 746 |
assert(collectExceptionMsg(assertPred!"opAssign"(IntWrapper_BadAssign(5), |
|---|
| 747 |
IntWrapper_BadAssign(2), |
|---|
| 748 |
"It failed!")) == |
|---|
| 749 |
"assertPred!\"opAssign\" failed: lhs was assigned to\n" ~ |
|---|
| 750 |
"[-2] instead of\n" ~ |
|---|
| 751 |
"[2]: It failed!"); |
|---|
| 752 |
|
|---|
| 753 |
|
|---|
| 754 |
struct IntWrapper_BadReturn |
|---|
| 755 |
{ |
|---|
| 756 |
int value; |
|---|
| 757 |
|
|---|
| 758 |
IntWrapper_BadReturn opAssign(IntWrapper_BadReturn rhs) |
|---|
| 759 |
{ |
|---|
| 760 |
this.value = rhs.value; |
|---|
| 761 |
|
|---|
| 762 |
return IntWrapper_BadReturn(-rhs.value); |
|---|
| 763 |
} |
|---|
| 764 |
|
|---|
| 765 |
string toString() { return to!string(value); } |
|---|
| 766 |
} |
|---|
| 767 |
|
|---|
| 768 |
assert(collectExceptionMsg(assertPred!"opAssign"(IntWrapper_BadReturn(5), IntWrapper_BadReturn(2))) == |
|---|
| 769 |
"assertPred!\"opAssign\" failed:\n" ~ |
|---|
| 770 |
"[-2] (return value) !=\n" ~ |
|---|
| 771 |
"[2] (assigned value)."); |
|---|
| 772 |
|
|---|
| 773 |
assert(collectExceptionMsg(assertPred!"opAssign"(IntWrapper_BadReturn(5), |
|---|
| 774 |
IntWrapper_BadReturn(2), |
|---|
| 775 |
"It failed!")) == |
|---|
| 776 |
"assertPred!\"opAssign\" failed:\n" ~ |
|---|
| 777 |
"[-2] (return value) !=\n" ~ |
|---|
| 778 |
"[2] (assigned value): It failed!"); |
|---|
| 779 |
})); |
|---|
| 780 |
|
|---|
| 781 |
|
|---|
| 782 |
void assertPred(string op, L, R, E) |
|---|
| 783 |
(L lhs, R rhs, E expected, lazy string msg = null, string file = __FILE__, size_t line = __LINE__) |
|---|
| 784 |
if((op == "+" || |
|---|
| 785 |
op == "-" || |
|---|
| 786 |
op == "*" || |
|---|
| 787 |
op == "/" || |
|---|
| 788 |
op == "%" || |
|---|
| 789 |
op == "^^" || |
|---|
| 790 |
op == "&" || |
|---|
| 791 |
op == "|" || |
|---|
| 792 |
op == "^" || |
|---|
| 793 |
op == "<<" || |
|---|
| 794 |
op == ">>" || |
|---|
| 795 |
op == ">>>" || |
|---|
| 796 |
op == "~") && |
|---|
| 797 |
__traits(compiles, mixin("lhs " ~ op ~ " rhs")) && |
|---|
| 798 |
__traits(compiles, mixin("(lhs " ~ op ~ " rhs) == expected")) && |
|---|
| 799 |
isPrintable!L && |
|---|
| 800 |
isPrintable!R) |
|---|
| 801 |
{ |
|---|
| 802 |
const result = mixin("lhs " ~ op ~ " rhs"); |
|---|
| 803 |
|
|---|
| 804 |
if(result != expected) |
|---|
| 805 |
{ |
|---|
| 806 |
immutable tail = msg.empty ? "." : ": " ~ msg; |
|---|
| 807 |
|
|---|
| 808 |
throwException( new AssertError(format("assertPred!\"%s\" failed: [%s] %s [%s]:\n[%s] (actual)\n[%s] (expected)%s", |
|---|
| 809 |
op, |
|---|
| 810 |
lhs, |
|---|
| 811 |
op, |
|---|
| 812 |
rhs, |
|---|
| 813 |
result, |
|---|
| 814 |
expected, |
|---|
| 815 |
tail), |
|---|
| 816 |
file, |
|---|
| 817 |
line) |
|---|
| 818 |
); |
|---|
| 819 |
} |
|---|
| 820 |
} |
|---|
| 821 |
|
|---|
| 822 |
mixin(unittestSemiTwistDLib("assertPred: Operators", q{ |
|---|
| 823 |
autoThrow = true; |
|---|
| 824 |
|
|---|
| 825 |
assertNotThrown!AssertError(assertPred!"+"(7, 5, 12)); |
|---|
| 826 |
assertNotThrown!AssertError(assertPred!"-"(7, 5, 2)); |
|---|
| 827 |
assertNotThrown!AssertError(assertPred!"*"(7, 5, 35)); |
|---|
| 828 |
assertNotThrown!AssertError(assertPred!"/"(7, 5, 1)); |
|---|
| 829 |
assertNotThrown!AssertError(assertPred!"%"(7, 5, 2)); |
|---|
| 830 |
assertNotThrown!AssertError(assertPred!"^^"(7, 5, 16_807)); |
|---|
| 831 |
assertNotThrown!AssertError(assertPred!"&"(7, 5, 5)); |
|---|
| 832 |
assertNotThrown!AssertError(assertPred!"|"(7, 5, 7)); |
|---|
| 833 |
assertNotThrown!AssertError(assertPred!"^"(7, 5, 2)); |
|---|
| 834 |
assertNotThrown!AssertError(assertPred!"<<"(7, 1, 14)); |
|---|
| 835 |
assertNotThrown!AssertError(assertPred!">>"(7, 1, 3)); |
|---|
| 836 |
assertNotThrown!AssertError(assertPred!">>>"(-7, 1, 2_147_483_644)); |
|---|
| 837 |
assertNotThrown!AssertError(assertPred!"~"("hello ", "world", "hello world")); |
|---|
| 838 |
|
|---|
| 839 |
assertThrown!AssertError(assertPred!"+"(7, 5, 0)); |
|---|
| 840 |
assertThrown!AssertError(assertPred!"-"(7, 5, 0)); |
|---|
| 841 |
assertThrown!AssertError(assertPred!"*"(7, 5, 0)); |
|---|
| 842 |
assertThrown!AssertError(assertPred!"/"(7, 5, 0)); |
|---|
| 843 |
assertThrown!AssertError(assertPred!"%"(7, 5, 0)); |
|---|
| 844 |
assertThrown!AssertError(assertPred!"^^"(7, 5, 0)); |
|---|
| 845 |
assertThrown!AssertError(assertPred!"&"(7, 5, 0)); |
|---|
| 846 |
assertThrown!AssertError(assertPred!"|"(7, 5, 0)); |
|---|
| 847 |
assertThrown!AssertError(assertPred!"^"(7, 5, 0)); |
|---|
| 848 |
assertThrown!AssertError(assertPred!"<<"(7, 1, 0)); |
|---|
| 849 |
assertThrown!AssertError(assertPred!">>"(7, 1, 0)); |
|---|
| 850 |
assertThrown!AssertError(assertPred!">>>"(-7, 1, 0)); |
|---|
| 851 |
assertThrown!AssertError(assertPred!"~"("hello ", "world", "goodbye world")); |
|---|
| 852 |
|
|---|
| 853 |
assertPred!"=="(collectExceptionMsg(assertPred!"+"(7, 5, 11)), |
|---|
| 854 |
"assertPred!\"+\" failed: [7] + [5]:\n[12] (actual)\n[11] (expected)."); |
|---|
| 855 |
assertPred!"=="(collectExceptionMsg(assertPred!"+"(7, 5, 11, "It failed!")), |
|---|
| 856 |
"assertPred!\"+\" failed: [7] + [5]:\n[12] (actual)\n[11] (expected): It failed!"); |
|---|
| 857 |
|
|---|
| 858 |
assertPred!"=="(collectExceptionMsg(assertPred!"^^"(7, 5, 42)), |
|---|
| 859 |
"assertPred!\"^^\" failed: [7] ^^ [5]:\n[16807] (actual)\n[42] (expected)."); |
|---|
| 860 |
assertPred!"=="(collectExceptionMsg(assertPred!"^^"(7, 5, 42, "It failed!")), |
|---|
| 861 |
"assertPred!\"^^\" failed: [7] ^^ [5]:\n[16807] (actual)\n[42] (expected): It failed!"); |
|---|
| 862 |
|
|---|
| 863 |
assertPred!"=="(collectExceptionMsg(assertPred!"~"("hello ", "world", "goodbye world")), |
|---|
| 864 |
"assertPred!\"~\" failed: [hello ] ~ [world]:\n[hello world] (actual)\n[goodbye world] (expected)."); |
|---|
| 865 |
assertPred!"=="(collectExceptionMsg(assertPred!"~"("hello ", "world", "goodbye world", "It failed!")), |
|---|
| 866 |
"assertPred!\"~\" failed: [hello ] ~ [world]:\n[hello world] (actual)\n[goodbye world] (expected): It failed!"); |
|---|
| 867 |
|
|---|
| 868 |
//Verify Examples |
|---|
| 869 |
assertPred!"+"(7, 5, 12); |
|---|
| 870 |
assertPred!"-"(7, 5, 2); |
|---|
| 871 |
assertPred!"*"(7, 5, 35); |
|---|
| 872 |
assertPred!"/"(7, 5, 1); |
|---|
| 873 |
assertPred!"%"(7, 5, 2); |
|---|
| 874 |
assertPred!"^^"(7, 5, 16_807); |
|---|
| 875 |
assertPred!"&"(7, 5, 5); |
|---|
| 876 |
assertPred!"|"(7, 5, 7); |
|---|
| 877 |
assertPred!"^"(7, 5, 2); |
|---|
| 878 |
assertPred!"<<"(7, 1, 14); |
|---|
| 879 |
assertPred!">>"(7, 1, 3); |
|---|
| 880 |
assertPred!">>>"(-7, 1, 2_147_483_644); |
|---|
| 881 |
assertPred!"~"("hello ", "world", "hello world"); |
|---|
| 882 |
|
|---|
| 883 |
assert(collectExceptionMsg(assertPred!"+"(7, 5, 11)) == |
|---|
| 884 |
"assertPred!\"+\" failed: [7] + [5]:\n" ~ |
|---|
| 885 |
"[12] (actual)\n" ~ |
|---|
| 886 |
"[11] (expected)."); |
|---|
| 887 |
|
|---|
| 888 |
assert(collectExceptionMsg(assertPred!"/"(11, 2, 6, "It failed!")) == |
|---|
| 889 |
"assertPred!\"/\" failed: [11] / [2]:\n" ~ |
|---|
| 890 |
"[5] (actual)\n" ~ |
|---|
| 891 |
"[6] (expected): It failed!"); |
|---|
| 892 |
|
|---|
| 893 |
//Test default arguments. |
|---|
| 894 |
assertPred!"+"(0, 12, 12); |
|---|
| 895 |
assertPred!"+"(0, 12, 12, "msg"); |
|---|
| 896 |
assertPred!"+"(0, 12, 12, "msg", "file"); |
|---|
| 897 |
assertPred!"+"(0, 12, 12, "msg", "file", 42); |
|---|
| 898 |
})); |
|---|
| 899 |
|
|---|
| 900 |
|
|---|
| 901 |
void assertPred(string op, L, R, E) |
|---|
| 902 |
(L lhs, R rhs, E expected, lazy string msg = null, string file = __FILE__, size_t line = __LINE__) |
|---|
| 903 |
if((op == "+=" || |
|---|
| 904 |
op == "-=" || |
|---|
| 905 |
op == "*=" || |
|---|
| 906 |
op == "/=" || |
|---|
| 907 |
op == "%=" || |
|---|
| 908 |
op == "^^=" || |
|---|
| 909 |
op == "&=" || |
|---|
| 910 |
op == "|=" || |
|---|
| 911 |
op == "^=" || |
|---|
| 912 |
op == "<<=" || |
|---|
| 913 |
op == ">>=" || |
|---|
| 914 |
op == ">>>=" || |
|---|
| 915 |
op == "~=") && |
|---|
| 916 |
__traits(compiles, mixin("lhs " ~ op ~ " rhs")) && |
|---|
| 917 |
__traits(compiles, mixin("(lhs " ~ op ~ " rhs) == expected")) && |
|---|
| 918 |
isPrintable!L && |
|---|
| 919 |
isPrintable!R) |
|---|
| 920 |
{ |
|---|
| 921 |
immutable origLHSStr = to!string(lhs); |
|---|
| 922 |
const result = mixin("lhs " ~ op ~ " rhs"); |
|---|
| 923 |
|
|---|
| 924 |
if(lhs != expected) |
|---|
| 925 |
{ |
|---|
| 926 |
immutable tail = msg.empty ? "." : ": " ~ msg; |
|---|
| 927 |
|
|---|
| 928 |
throwException( new AssertError(format("assertPred!\"%s\" failed: After [%s] %s [%s], lhs was assigned to\n[%s] instead of\n[%s]%s", |
|---|
| 929 |
op, |
|---|
| 930 |
origLHSStr, |
|---|
| 931 |
op, |
|---|
| 932 |
rhs, |
|---|
| 933 |
lhs, |
|---|
| 934 |
expected, |
|---|
| 935 |
tail), |
|---|
| 936 |
file, |
|---|
| 937 |
line) |
|---|
| 938 |
); |
|---|
| 939 |
} |
|---|
| 940 |
|
|---|
| 941 |
if(result != expected) |
|---|
| 942 |
{ |
|---|
| 943 |
immutable tail = msg.empty ? "." : ": " ~ msg; |
|---|
| 944 |
|
|---|
| 945 |
throwException( new AssertError(format("assertPred!\"%s\" failed: Return value of [%s] %s [%s] was\n[%s] instead of\n[%s]%s", |
|---|
| 946 |
op, |
|---|
| 947 |
origLHSStr, |
|---|
| 948 |
op, |
|---|
| 949 |
rhs, |
|---|
| 950 |
result, |
|---|
| 951 |
expected, |
|---|
| 952 |
tail), |
|---|
| 953 |
file, |
|---|
| 954 |
line) |
|---|
| 955 |
); |
|---|
| 956 |
} |
|---|
| 957 |
} |
|---|
| 958 |
|
|---|
| 959 |
mixin(unittestSemiTwistDLib("assertPred: Assignment Operators", q{ |
|---|
| 960 |
autoThrow = true; |
|---|
| 961 |
|
|---|
| 962 |
assertNotThrown!AssertError(assertPred!"+="(7, 5, 12)); |
|---|
| 963 |
assertNotThrown!AssertError(assertPred!"-="(7, 5, 2)); |
|---|
| 964 |
assertNotThrown!AssertError(assertPred!"*="(7, 5, 35)); |
|---|
| 965 |
assertNotThrown!AssertError(assertPred!"/="(7, 5, 1)); |
|---|
| 966 |
assertNotThrown!AssertError(assertPred!"%="(7, 5, 2)); |
|---|
| 967 |
assertNotThrown!AssertError(assertPred!"^^="(7, 5, 16_807)); |
|---|
| 968 |
assertNotThrown!AssertError(assertPred!"&="(7, 5, 5)); |
|---|
| 969 |
assertNotThrown!AssertError(assertPred!"|="(7, 5, 7)); |
|---|
| 970 |
assertNotThrown!AssertError(assertPred!"^="(7, 5, 2)); |
|---|
| 971 |
assertNotThrown!AssertError(assertPred!"<<="(7, 1, 14)); |
|---|
| 972 |
assertNotThrown!AssertError(assertPred!">>="(7, 1, 3)); |
|---|
| 973 |
assertNotThrown!AssertError(assertPred!">>>="(-7, 1, 2_147_483_644)); |
|---|
| 974 |
assertNotThrown!AssertError(assertPred!"~="("hello ", "world", "hello world")); |
|---|
| 975 |
|
|---|
| 976 |
assertThrown!AssertError(assertPred!"+="(7, 5, 0)); |
|---|
| 977 |
assertThrown!AssertError(assertPred!"-="(7, 5, 0)); |
|---|
| 978 |
assertThrown!AssertError(assertPred!"*="(7, 5, 0)); |
|---|
| 979 |
assertThrown!AssertError(assertPred!"/="(7, 5, 0)); |
|---|
| 980 |
assertThrown!AssertError(assertPred!"%="(7, 5, 0)); |
|---|
| 981 |
assertThrown!AssertError(assertPred!"^^="(7, 5, 0)); |
|---|
| 982 |
assertThrown!AssertError(assertPred!"&="(7, 5, 0)); |
|---|
| 983 |
assertThrown!AssertError(assertPred!"|="(7, 5, 0)); |
|---|
| 984 |
assertThrown!AssertError(assertPred!"^="(7, 5, 0)); |
|---|
| 985 |
assertThrown!AssertError(assertPred!"<<="(7, 1, 0)); |
|---|
| 986 |
assertThrown!AssertError(assertPred!">>="(7, 1, 0)); |
|---|
| 987 |
assertThrown!AssertError(assertPred!">>>="(-7, 1, 0)); |
|---|
| 988 |
assertThrown!AssertError(assertPred!"~="("hello ", "world", "goodbye world")); |
|---|
| 989 |
|
|---|
| 990 |
assertPred!"=="(collectExceptionMsg(assertPred!"+="(7, 5, 11)), |
|---|
| 991 |
"assertPred!\"+=\" failed: After [7] += [5], lhs was assigned to\n[12] instead of\n[11]."); |
|---|
| 992 |
assertPred!"=="(collectExceptionMsg(assertPred!"+="(7, 5, 11, "It failed!")), |
|---|
| 993 |
"assertPred!\"+=\" failed: After [7] += [5], lhs was assigned to\n[12] instead of\n[11]: It failed!"); |
|---|
| 994 |
|
|---|
| 995 |
assertPred!"=="(collectExceptionMsg(assertPred!"^^="(7, 5, 42)), |
|---|
| 996 |
"assertPred!\"^^=\" failed: After [7] ^^= [5], lhs was assigned to\n[16807] instead of\n[42]."); |
|---|
| 997 |
assertPred!"=="(collectExceptionMsg(assertPred!"^^="(7, 5, 42, "It failed!")), |
|---|
| 998 |
"assertPred!\"^^=\" failed: After [7] ^^= [5], lhs was assigned to\n[16807] instead of\n[42]: It failed!"); |
|---|
| 999 |
|
|---|
| 1000 |
assertPred!"=="(collectExceptionMsg(assertPred!"~="("hello ", "world", "goodbye world")), |
|---|
| 1001 |
"assertPred!\"~=\" failed: After [hello ] ~= [world], lhs was assigned to\n[hello world] instead of\n[goodbye world]."); |
|---|
| 1002 |
assertPred!"=="(collectExceptionMsg(assertPred!"~="("hello ", "world", "goodbye world", "It failed!")), |
|---|
| 1003 |
"assertPred!\"~=\" failed: After [hello ] ~= [world], lhs was assigned to\n[hello world] instead of\n[goodbye world]: It failed!"); |
|---|
| 1004 |
|
|---|
| 1005 |
struct IntWrapper |
|---|
| 1006 |
{ |
|---|
| 1007 |
int value; |
|---|
| 1008 |
|
|---|
| 1009 |
this(int value) |
|---|
| 1010 |
{ |
|---|
| 1011 |
this.value = value; |
|---|
| 1012 |
} |
|---|
| 1013 |
|
|---|
| 1014 |
IntWrapper opOpAssign(string op)(IntWrapper rhs) |
|---|
| 1015 |
{ |
|---|
| 1016 |
mixin("this.value " ~ op ~ "= rhs.value;"); |
|---|
| 1017 |
|
|---|
| 1018 |
return this; |
|---|
| 1019 |
} |
|---|
| 1020 |
|
|---|
| 1021 |
string toString() |
|---|
| 1022 |
{ |
|---|
| 1023 |
return to!string(value); |
|---|
| 1024 |
} |
|---|
| 1025 |
} |
|---|
| 1026 |
|
|---|
| 1027 |
struct IntWrapper_BadAssign |
|---|
| 1028 |
{ |
|---|
| 1029 |
int value; |
|---|
| 1030 |
|
|---|
| 1031 |
this(int value) |
|---|
| 1032 |
{ |
|---|
| 1033 |
this.value = value; |
|---|
| 1034 |
} |
|---|
| 1035 |
|
|---|
| 1036 |
IntWrapper_BadAssign opOpAssign(string op)(IntWrapper_BadAssign rhs) |
|---|
| 1037 |
{ |
|---|
| 1038 |
auto old = this.value; |
|---|
| 1039 |
|
|---|
| 1040 |
mixin("this.value " ~ op ~ "= -rhs.value;"); |
|---|
| 1041 |
|
|---|
| 1042 |
return IntWrapper_BadAssign(mixin("old " ~ op ~ " rhs.value")); |
|---|
| 1043 |
} |
|---|
| 1044 |
|
|---|
| 1045 |
string toString() |
|---|
| 1046 |
{ |
|---|
| 1047 |
return to!string(value); |
|---|
| 1048 |
} |
|---|
| 1049 |
} |
|---|
| 1050 |
|
|---|
| 1051 |
struct IntWrapper_BadReturn |
|---|
| 1052 |
{ |
|---|
| 1053 |
int value; |
|---|
| 1054 |
|
|---|
| 1055 |
this(int value) |
|---|
| 1056 |
{ |
|---|
| 1057 |
this.value = value; |
|---|
| 1058 |
} |
|---|
| 1059 |
|
|---|
| 1060 |
IntWrapper_BadReturn opOpAssign(string op)(IntWrapper_BadReturn rhs) |
|---|
| 1061 |
{ |
|---|
| 1062 |
mixin("this.value " ~ op ~ "= rhs.value;"); |
|---|
| 1063 |
|
|---|
| 1064 |
return IntWrapper_BadReturn(rhs.value); |
|---|
| 1065 |
} |
|---|
| 1066 |
|
|---|
| 1067 |
string toString() |
|---|
| 1068 |
{ |
|---|
| 1069 |
return to!string(value); |
|---|
| 1070 |
} |
|---|
| 1071 |
} |
|---|
| 1072 |
|
|---|
| 1073 |
assertNotThrown!AssertError(assertPred!"+="(IntWrapper(5), IntWrapper(2), IntWrapper(7))); |
|---|
| 1074 |
assertNotThrown!AssertError(assertPred!"*="(IntWrapper(5), IntWrapper(2), IntWrapper(10))); |
|---|
| 1075 |
|
|---|
| 1076 |
assertThrown!AssertError(assertPred!"+="(IntWrapper_BadAssign(5), IntWrapper_BadAssign(2), IntWrapper_BadAssign(7))); |
|---|
| 1077 |
assertThrown!AssertError(assertPred!"+="(IntWrapper_BadReturn(5), IntWrapper_BadReturn(2), IntWrapper_BadReturn(7))); |
|---|
| 1078 |
assertThrown!AssertError(assertPred!"*="(IntWrapper_BadAssign(5), IntWrapper_BadAssign(2), IntWrapper_BadAssign(10))); |
|---|
| 1079 |
assertThrown!AssertError(assertPred!"*="(IntWrapper_BadReturn(5), IntWrapper_BadReturn(2), IntWrapper_BadReturn(10))); |
|---|
| 1080 |
|
|---|
| 1081 |
assertPred!"=="(collectExceptionMsg(assertPred!"+="(IntWrapper_BadAssign(5), IntWrapper_BadAssign(2), IntWrapper_BadAssign(7))), |
|---|
| 1082 |
"assertPred!\"+=\" failed: After [5] += [2], lhs was assigned to\n[3] instead of\n[7]."); |
|---|
| 1083 |
assertPred!"=="(collectExceptionMsg(assertPred!"+="(IntWrapper_BadAssign(5), IntWrapper_BadAssign(2), IntWrapper_BadAssign(7), "It failed!")), |
|---|
| 1084 |
"assertPred!\"+=\" failed: After [5] += [2], lhs was assigned to\n[3] instead of\n[7]: It failed!"); |
|---|
| 1085 |
|
|---|
| 1086 |
assertPred!"=="(collectExceptionMsg(assertPred!"+="(IntWrapper_BadReturn(5), IntWrapper_BadReturn(2), IntWrapper_BadReturn(7))), |
|---|
| 1087 |
"assertPred!\"+=\" failed: Return value of [5] += [2] was\n[2] instead of\n[7]."); |
|---|
| 1088 |
assertPred!"=="(collectExceptionMsg(assertPred!"+="(IntWrapper_BadReturn(5), IntWrapper_BadReturn(2), IntWrapper_BadReturn(7), "It failed!")), |
|---|
| 1089 |
"assertPred!\"+=\" failed: Return value of [5] += [2] was\n[2] instead of\n[7]: It failed!"); |
|---|
| 1090 |
|
|---|
| 1091 |
assertPred!"=="(collectExceptionMsg(assertPred!"*="(IntWrapper_BadAssign(5), IntWrapper_BadAssign(2), IntWrapper_BadAssign(10))), |
|---|
| 1092 |
"assertPred!\"*=\" failed: After [5] *= [2], lhs was assigned to\n[-10] instead of\n[10]."); |
|---|
| 1093 |
assertPred!"=="(collectExceptionMsg(assertPred!"*="(IntWrapper_BadAssign(5), IntWrapper_BadAssign(2), IntWrapper_BadAssign(10), "It failed!")), |
|---|
| 1094 |
"assertPred!\"*=\" failed: After [5] *= [2], lhs was assigned to\n[-10] instead of\n[10]: It failed!"); |
|---|
| 1095 |
|
|---|
| 1096 |
assertPred!"=="(collectExceptionMsg(assertPred!"*="(IntWrapper_BadReturn(5), IntWrapper_BadReturn(2), IntWrapper_BadReturn(10))), |
|---|
| 1097 |
"assertPred!\"*=\" failed: Return value of [5] *= [2] was\n[2] instead of\n[10]."); |
|---|
| 1098 |
assertPred!"=="(collectExceptionMsg(assertPred!"*="(IntWrapper_BadReturn(5), IntWrapper_BadReturn(2), IntWrapper_BadReturn(10), "It failed!")), |
|---|
| 1099 |
"assertPred!\"*=\" failed: Return value of [5] *= [2] was\n[2] instead of\n[10]: It failed!"); |
|---|
| 1100 |
|
|---|
| 1101 |
//Test default arguments. |
|---|
| 1102 |
assertPred!"+="(0, 12, 12); |
|---|
| 1103 |
assertPred!"+="(0, 12, 12, "msg"); |
|---|
| 1104 |
assertPred!"+="(0, 12, 12, "msg", "file"); |
|---|
| 1105 |
assertPred!"+="(0, 12, 12, "msg", "file", 42); |
|---|
| 1106 |
})); |
|---|
| 1107 |
|
|---|
| 1108 |
mixin(unittestSemiTwistDLib("assertPred: Assignment Operators: Examples", q{ |
|---|
| 1109 |
autoThrow = true; |
|---|
| 1110 |
|
|---|
| 1111 |
//Verify Examples |
|---|
| 1112 |
assertPred!"+="(5, 7, 12); |
|---|
| 1113 |
assertPred!"-="(7, 5, 2); |
|---|
| 1114 |
assertPred!"*="(7, 5, 35); |
|---|
| 1115 |
assertPred!"/="(7, 5, 1); |
|---|
| 1116 |
assertPred!"%="(7, 5, 2); |
|---|
| 1117 |
assertPred!"^^="(7, 5, 16_807); |
|---|
| 1118 |
assertPred!"&="(7, 5, 5); |
|---|
| 1119 |
assertPred!"|="(7, 5, 7); |
|---|
| 1120 |
assertPred!"^="(7, 5, 2); |
|---|
| 1121 |
assertPred!"<<="(7, 1, 14); |
|---|
| 1122 |
assertPred!">>="(7, 1, 3); |
|---|
| 1123 |
assertPred!">>>="(-7, 1, 2_147_483_644); |
|---|
| 1124 |
assertPred!"~="("hello ", "world", "hello world"); |
|---|
| 1125 |
|
|---|
| 1126 |
struct IntWrapper_BadAssign |
|---|
| 1127 |
{ |
|---|
| 1128 |
int value; |
|---|
| 1129 |
|
|---|
| 1130 |
IntWrapper_BadAssign opOpAssign(string op)(IntWrapper_BadAssign rhs) |
|---|
| 1131 |
{ |
|---|
| 1132 |
auto old = this.value; |
|---|
| 1133 |
|
|---|
| 1134 |
mixin("this.value " ~ op ~ "= -rhs.value;"); |
|---|
| 1135 |
|
|---|
| 1136 |
return IntWrapper_BadAssign(mixin("old " ~ op ~ " rhs.value")); |
|---|
| 1137 |
} |
|---|
| 1138 |
|
|---|
| 1139 |
string toString() { return to!string(value); } |
|---|
| 1140 |
} |
|---|
| 1141 |
|
|---|
| 1142 |
assert(collectExceptionMsg(assertPred!"+="(IntWrapper_BadAssign(5), |
|---|
| 1143 |
IntWrapper_BadAssign(2), |
|---|
| 1144 |
IntWrapper_BadAssign(7))) == |
|---|
| 1145 |
"assertPred!\"+=\" failed: After [5] += [2], lhs was assigned to\n" ~ |
|---|
| 1146 |
"[3] instead of\n" ~ |
|---|
| 1147 |
"[7]."); |
|---|
| 1148 |
|
|---|
| 1149 |
assert(collectExceptionMsg(assertPred!"+="(IntWrapper_BadAssign(5), |
|---|
| 1150 |
IntWrapper_BadAssign(2), |
|---|
| 1151 |
IntWrapper_BadAssign(7), |
|---|
| 1152 |
"It failed!")) == |
|---|
| 1153 |
"assertPred!\"+=\" failed: After [5] += [2], lhs was assigned to\n" ~ |
|---|
| 1154 |
"[3] instead of\n" ~ |
|---|
| 1155 |
"[7]: It failed!"); |
|---|
| 1156 |
|
|---|
| 1157 |
struct IntWrapper_BadReturn |
|---|
| 1158 |
{ |
|---|
| 1159 |
int value; |
|---|
| 1160 |
|
|---|
| 1161 |
IntWrapper_BadReturn opOpAssign(string op)(IntWrapper_BadReturn rhs) |
|---|
| 1162 |
{ |
|---|
| 1163 |
mixin("this.value " ~ op ~ "= rhs.value;"); |
|---|
| 1164 |
|
|---|
| 1165 |
return IntWrapper_BadReturn(rhs.value); |
|---|
| 1166 |
} |
|---|
| 1167 |
|
|---|
| 1168 |
string toString() { return to!string(value); } |
|---|
| 1169 |
} |
|---|
| 1170 |
|
|---|
| 1171 |
assert(collectExceptionMsg(assertPred!"+="(IntWrapper_BadReturn(5), |
|---|
| 1172 |
IntWrapper_BadReturn(2), |
|---|
| 1173 |
IntWrapper_BadReturn(7))) == |
|---|
| 1174 |
"assertPred!\"+=\" failed: Return value of [5] += [2] was\n" ~ |
|---|
| 1175 |
"[2] instead of\n" ~ |
|---|
| 1176 |
"[7]."); |
|---|
| 1177 |
|
|---|
| 1178 |
assert(collectExceptionMsg(assertPred!"+="(IntWrapper_BadReturn(5), |
|---|
| 1179 |
IntWrapper_BadReturn(2), |
|---|
| 1180 |
IntWrapper_BadReturn(7), |
|---|
| 1181 |
"It failed!")) == |
|---|
| 1182 |
"assertPred!\"+=\" failed: Return value of [5] += [2] was\n" ~ |
|---|
| 1183 |
"[2] instead of\n" ~ |
|---|
| 1184 |
"[7]: It failed!"); |
|---|
| 1185 |
})); |
|---|
| 1186 |
|
|---|
| 1187 |
|
|---|
| 1188 |
void assertPred(string pred, string msg = null, string file = __FILE__, size_t line = __LINE__, T) |
|---|
| 1189 |
(T a) |
|---|
| 1190 |
if(__traits(compiles, unaryFun!pred(a)) && |
|---|
| 1191 |
is(typeof(unaryFun!pred(a)) : bool) && |
|---|
| 1192 |
isPrintable!T) |
|---|
| 1193 |
{ |
|---|
| 1194 |
if(!unaryFun!pred(a)) |
|---|
| 1195 |
{ |
|---|
| 1196 |
immutable tail = msg.empty ? "." : ": " ~ msg; |
|---|
| 1197 |
|
|---|
| 1198 |
throwException( new AssertError(format(`assertPred!"%s" failed: [%s] (a)%s`, pred, a, tail), |
|---|
| 1199 |
file, |
|---|
| 1200 |
line) |
|---|
| 1201 |
); |
|---|
| 1202 |
} |
|---|
| 1203 |
} |
|---|
| 1204 |
|
|---|
| 1205 |
mixin(unittestSemiTwistDLib("assertPred: unaryFun", q{ |
|---|
| 1206 |
autoThrow = true; |
|---|
| 1207 |
|
|---|
| 1208 |
assertNotThrown!AssertError(assertPred!"a == 1"(1)); |
|---|
| 1209 |
assertNotThrown!AssertError(assertPred!"a"(true)); |
|---|
| 1210 |
assertNotThrown!AssertError(assertPred!"!a"(false)); |
|---|
| 1211 |
|
|---|
| 1212 |
assertThrown!AssertError(assertPred!"a == 1"(2)); |
|---|
| 1213 |
assertThrown!AssertError(assertPred!"a"(false)); |
|---|
| 1214 |
assertThrown!AssertError(assertPred!"!a"(true)); |
|---|
| 1215 |
|
|---|
| 1216 |
assertPred!"=="(collectExceptionMsg(assertPred!"a == 1"(2)), |
|---|
| 1217 |
`assertPred!"a == 1" failed: [2] (a).`); |
|---|
| 1218 |
assertPred!"=="(collectExceptionMsg(assertPred!("a == 1", "It failed!")(2)), |
|---|
| 1219 |
`assertPred!"a == 1" failed: [2] (a): It failed!`); |
|---|
| 1220 |
|
|---|
| 1221 |
//Test default arguments. |
|---|
| 1222 |
assertPred!"a == 7"(7); |
|---|
| 1223 |
assertPred!("a == 7", "msg")(7); |
|---|
| 1224 |
assertPred!("a == 7", "msg", "file")(7); |
|---|
| 1225 |
assertPred!("a == 7", "msg", "file", 42)(7); |
|---|
| 1226 |
|
|---|
| 1227 |
//Verify Examples. |
|---|
| 1228 |
assertPred!"a == 1"(1); |
|---|
| 1229 |
|
|---|
| 1230 |
assertPred!"a * 2.0 == 4.0"(2); |
|---|
| 1231 |
|
|---|
| 1232 |
assert(collectExceptionMsg(assertPred!"a == 1"(2)), |
|---|
| 1233 |
`assertPred!"a == 1" failed: [2] (a).`); |
|---|
| 1234 |
|
|---|
| 1235 |
assert(collectExceptionMsg(assertPred!("a * 2.0 == 4.0", "Woe is me!")(7)), |
|---|
| 1236 |
`assertPred!"a * 2.0 == 4.0" failed: [7] (a): Woe is me!`); |
|---|
| 1237 |
})); |
|---|
| 1238 |
|
|---|
| 1239 |
|
|---|
| 1240 |
void assertPred(string pred, string msg = null, string file = __FILE__, size_t line = __LINE__, T, U) |
|---|
| 1241 |
(T a, U b) |
|---|
| 1242 |
if(__traits(compiles, binaryFun!pred(a, b)) && |
|---|
| 1243 |
is(typeof(binaryFun!pred(a, b)) : bool) && |
|---|
| 1244 |
isPrintable!T) |
|---|
| 1245 |
{ |
|---|
| 1246 |
if(!binaryFun!pred(a, b)) |
|---|
| 1247 |
{ |
|---|
| 1248 |
immutable tail = msg.empty ? "." : ": " ~ msg; |
|---|
| 1249 |
|
|---|
| 1250 |
throwException( new AssertError(format(`assertPred!"%s" failed: [%s] (a), [%s] (b)%s`, pred, a, b, tail), |
|---|
| 1251 |
file, |
|---|
| 1252 |
line) |
|---|
| 1253 |
); |
|---|
| 1254 |
} |
|---|
| 1255 |
} |
|---|
| 1256 |
|
|---|
| 1257 |
mixin(unittestSemiTwistDLib("assertPred: binaryFun", q{ |
|---|
| 1258 |
autoThrow = true; |
|---|
| 1259 |
|
|---|
| 1260 |
assertNotThrown!AssertError(assertPred!"a == b"(1, 1)); |
|---|
| 1261 |
assertNotThrown!AssertError(assertPred!"a * b == 2.0"(1, 2.0)); |
|---|
| 1262 |
|
|---|
| 1263 |
assertThrown!AssertError(assertPred!"a == b"(1, 2)); |
|---|
| 1264 |
assertThrown!AssertError(assertPred!"a * b == 2.0"(2, 2.0)); |
|---|
| 1265 |
|
|---|
| 1266 |
assertPred!"=="(collectExceptionMsg(assertPred!"a == b"(1, 2)), |
|---|
| 1267 |
`assertPred!"a == b" failed: [1] (a), [2] (b).`); |
|---|
| 1268 |
assertPred!"=="(collectExceptionMsg(assertPred!("a == b", "It failed!")(1, 2)), |
|---|
| 1269 |
`assertPred!"a == b" failed: [1] (a), [2] (b): It failed!`); |
|---|
| 1270 |
|
|---|
| 1271 |
//Test default arguments. |
|---|
| 1272 |
assertPred!"a == b"(7, 7); |
|---|
| 1273 |
assertPred!("a == b", "msg")(7, 7); |
|---|
| 1274 |
assertPred!("a == b", "msg", "file")(7, 7); |
|---|
| 1275 |
assertPred!("a == b", "msg", "file", 42)(7, 7); |
|---|
| 1276 |
|
|---|
| 1277 |
//Verify Examples. |
|---|
| 1278 |
assertPred!"a == b"(42, 42); |
|---|
| 1279 |
|
|---|
| 1280 |
assertPred!`a ~ b == "hello world"`("hello ", "world"); |
|---|
| 1281 |
|
|---|
| 1282 |
assertPred!"=="(collectExceptionMsg(assertPred!"a == b"(1, 2)), |
|---|
| 1283 |
`assertPred!"a == b" failed: [1] (a), [2] (b).`); |
|---|
| 1284 |
|
|---|
| 1285 |
assertPred!"=="(collectExceptionMsg(assertPred!("a * b == 7", "It failed!")(2, 3)), |
|---|
| 1286 |
`assertPred!"a * b == 7" failed: [2] (a), [3] (b): It failed!`); |
|---|
| 1287 |
})); |
|---|
| 1288 |
|
|---|
| 1289 |
|
|---|
| 1290 |
void assertPred(alias pred, string msg = null, string file = __FILE__, size_t line = __LINE__, T...) |
|---|
| 1291 |
(T args) |
|---|
| 1292 |
if(isCallable!pred && |
|---|
| 1293 |
is(ReturnType!pred == bool) && |
|---|
| 1294 |
__traits(compiles, pred(args)) && |
|---|
| 1295 |
isPrintable!T) |
|---|
| 1296 |
{ |
|---|
| 1297 |
immutable result = pred(args); |
|---|
| 1298 |
|
|---|
| 1299 |
if(!result) |
|---|
| 1300 |
{ |
|---|
| 1301 |
string argsStr; |
|---|
| 1302 |
|
|---|
| 1303 |
if(args.length > 0) |
|---|
| 1304 |
{ |
|---|
| 1305 |
foreach(value; args) |
|---|
| 1306 |
argsStr ~= format("[%s], ", to!string(value)); |
|---|
| 1307 |
|
|---|
| 1308 |
argsStr.popBackN(", ".length); |
|---|
| 1309 |
} |
|---|
| 1310 |
else |
|---|
| 1311 |
argsStr = "none"; |
|---|
| 1312 |
|
|---|
| 1313 |
immutable tail = msg.empty ? "." : ": " ~ msg; |
|---|
| 1314 |
|
|---|
| 1315 |
throwException( new AssertError(format("assertPred failed: arguments: %s%s", argsStr, tail), file, line) ); |
|---|
| 1316 |
} |
|---|
| 1317 |
} |
|---|
| 1318 |
|
|---|
| 1319 |
mixin(unittestSemiTwistDLib("assertPred: Delegates", q{ |
|---|
| 1320 |
autoThrow = true; |
|---|
| 1321 |
|
|---|
| 1322 |
assertNotThrown!AssertError(assertPred!({return true;})()); |
|---|
| 1323 |
assertNotThrown!AssertError(assertPred!((bool a){return a;})(true)); |
|---|
| 1324 |
assertNotThrown!AssertError(assertPred!((int a, int b){return a == b;})(5, 5)); |
|---|
| 1325 |
assertNotThrown!AssertError(assertPred!((int a, int b, int c){return a == b && b == c;})(5, 5, 5)); |
|---|
| 1326 |
assertNotThrown!AssertError(assertPred!((int a, int b, int c, float d){return a * b < c * d;})(2, 4, 5, 1.7)); |
|---|
| 1327 |
|
|---|
| 1328 |
assertThrown!AssertError(assertPred!({return false;})()); |
|---|
| 1329 |
assertThrown!AssertError(assertPred!((bool a){return a;})(false)); |
|---|
| 1330 |
assertThrown!AssertError(assertPred!((int a, int b){return a == b;})(5, 6)); |
|---|
| 1331 |
assertThrown!AssertError(assertPred!((int a, int b, int c){return a == b && b == c;})(5, 5, 6)); |
|---|
| 1332 |
assertThrown!AssertError(assertPred!((int a, int b, int c, float d){return a * b < c * d;})(3, 4, 5, 1.7)); |
|---|
| 1333 |
|
|---|
| 1334 |
//Test default arguments. |
|---|
| 1335 |
assertPred!((int a, int b){return a == b;})(7, 7); |
|---|
| 1336 |
assertPred!((int a, int b){return a == b;}, "msg")(7, 7); |
|---|
| 1337 |
assertPred!((int a, int b){return a == b;}, "msg", "file")(7, 7); |
|---|
| 1338 |
assertPred!((int a, int b){return a == b;}, "msg", "file", 42)(7, 7); |
|---|
| 1339 |
|
|---|
| 1340 |
//Verify Examples. |
|---|
| 1341 |
assertPred!((int[] range, int i){return canFind(range, i);})([1, 5, 7, 2], 7); |
|---|
| 1342 |
|
|---|
| 1343 |
assertPred!((int a, int b, int c){return a == b && b == c;})(5, 5, 5); |
|---|
| 1344 |
|
|---|
| 1345 |
assert(collectExceptionMsg(assertPred!((int a, int b, int c, float d){return a * b < c * d;}) |
|---|
| 1346 |
(22, 4, 5, 1.7)) == |
|---|
| 1347 |
"assertPred failed: arguments: [22], [4], [5], [1.7]."); |
|---|
| 1348 |
|
|---|
| 1349 |
// Crashes DMD 2.054 (DMD Issue #6351): |
|---|
| 1350 |
//assert(collectExceptionMsg(assertPred!((string[] s...){return canFind(s, "hello");}, "Failure!") |
|---|
| 1351 |
// ("goodbye", "old", "friend")) == |
|---|
| 1352 |
// "assertPred failed: arguments: [goodbye], [old], [friend]: Failure!"); |
|---|
| 1353 |
|
|---|
| 1354 |
})); |
|---|
| 1355 |
|
|---|
| 1356 |
//============================================================================== |
|---|
| 1357 |
// Private Section. |
|---|
| 1358 |
// |
|---|
| 1359 |
// Note: assertNotThrown, assertThrown and collectExceptionMsg are included in |
|---|
| 1360 |
// this module because they're used by assertPred's unittests and haven't been |
|---|
| 1361 |
// added to Phobos just yet. But they're private becuase they're going to be |
|---|
| 1362 |
// in Phobos soon. |
|---|
| 1363 |
//============================================================================== |
|---|
| 1364 |
private: |
|---|
| 1365 |
|
|---|
| 1366 |
void assertNotThrown(T : Throwable = Exception, F) |
|---|
| 1367 |
(lazy F funcToCall, string msg = null, string file = __FILE__, size_t line = __LINE__) |
|---|
| 1368 |
{ |
|---|
| 1369 |
try |
|---|
| 1370 |
funcToCall(); |
|---|
| 1371 |
catch(T t) |
|---|
| 1372 |
{ |
|---|
| 1373 |
immutable tail = msg.empty ? "." : ": " ~ msg; |
|---|
| 1374 |
|
|---|
| 1375 |
throwException( new AssertError(format("assertNotThrown failed: %s was thrown%s", T.stringof, tail), file, line, t) ); |
|---|
| 1376 |
} |
|---|
| 1377 |
} |
|---|
| 1378 |
|
|---|
| 1379 |
mixin(unittestSemiTwistDLib("private assertNotThrown", q{ |
|---|
| 1380 |
autoThrow = true; |
|---|
| 1381 |
|
|---|
| 1382 |
void throwEx(Throwable t) |
|---|
| 1383 |
{ |
|---|
| 1384 |
throw t; |
|---|
| 1385 |
} |
|---|
| 1386 |
|
|---|
| 1387 |
void nothrowEx() |
|---|
| 1388 |
{ |
|---|
| 1389 |
} |
|---|
| 1390 |
|
|---|
| 1391 |
try |
|---|
| 1392 |
assertNotThrown!Exception(nothrowEx()); |
|---|
| 1393 |
catch(AssertError) |
|---|
| 1394 |
assert(0); |
|---|
| 1395 |
|
|---|
| 1396 |
try |
|---|
| 1397 |
assertNotThrown!Exception(nothrowEx(), "It's a message"); |
|---|
| 1398 |
catch(AssertError) |
|---|
| 1399 |
assert(0); |
|---|
| 1400 |
|
|---|
| 1401 |
try |
|---|
| 1402 |
assertNotThrown!AssertError(nothrowEx()); |
|---|
| 1403 |
catch(AssertError) |
|---|
| 1404 |
assert(0); |
|---|
| 1405 |
|
|---|
| 1406 |
try |
|---|
| 1407 |
assertNotThrown!AssertError(nothrowEx(), "It's a message"); |
|---|
| 1408 |
catch(AssertError) |
|---|
| 1409 |
assert(0); |
|---|
| 1410 |
|
|---|
| 1411 |
|
|---|
| 1412 |
{ |
|---|
| 1413 |
bool thrown = false; |
|---|
| 1414 |
try |
|---|
| 1415 |
assertNotThrown!Exception(throwEx(new Exception("It's an Exception"))); |
|---|
| 1416 |
catch(AssertError) |
|---|
| 1417 |
thrown = true; |
|---|
| 1418 |
|
|---|
| 1419 |
assert(thrown); |
|---|
| 1420 |
} |
|---|
| 1421 |
|
|---|
| 1422 |
{ |
|---|
| 1423 |
bool thrown = false; |
|---|
| 1424 |
try |
|---|
| 1425 |
assertNotThrown!Exception(throwEx(new Exception("It's an Exception")), "It's a message"); |
|---|
| 1426 |
catch(AssertError) |
|---|
| 1427 |
thrown = true; |
|---|
| 1428 |
|
|---|
| 1429 |
assert(thrown); |
|---|
| 1430 |
} |
|---|
| 1431 |
|
|---|
| 1432 |
{ |
|---|
| 1433 |
bool thrown = false; |
|---|
| 1434 |
try |
|---|
| 1435 |
assertNotThrown!AssertError(throwEx(new AssertError("It's an AssertError", __FILE__, __LINE__))); |
|---|
| 1436 |
catch(AssertError) |
|---|
| 1437 |
thrown = true; |
|---|
| 1438 |
|
|---|
| 1439 |
assert(thrown); |
|---|
| 1440 |
} |
|---|
| 1441 |
|
|---|
| 1442 |
{ |
|---|
| 1443 |
bool thrown = false; |
|---|
| 1444 |
try |
|---|
| 1445 |
assertNotThrown!AssertError(throwEx(new AssertError("It's an AssertError", __FILE__, __LINE__)), "It's a message"); |
|---|
| 1446 |
catch(AssertError) |
|---|
| 1447 |
thrown = true; |
|---|
| 1448 |
|
|---|
| 1449 |
assert(thrown); |
|---|
| 1450 |
} |
|---|
| 1451 |
|
|---|
| 1452 |
//Verify Examples. |
|---|
| 1453 |
assertNotThrown!DateTimeException(std.datetime.TimeOfDay(0, 0, 0)); |
|---|
| 1454 |
assertNotThrown!DateTimeException(std.datetime.TimeOfDay(12, 30, 27)); |
|---|
| 1455 |
assertNotThrown(std.datetime.TimeOfDay(23, 59, 59)); //Exception is default. |
|---|
| 1456 |
|
|---|
| 1457 |
assert(collectExceptionMsg(assertNotThrown!TimeException(std.datetime.TimeOfDay(12, 0, 60))) == |
|---|
| 1458 |
"assertNotThrown failed: TimeException was thrown."); |
|---|
| 1459 |
|
|---|
| 1460 |
assert(collectExceptionMsg(assertNotThrown!TimeException(std.datetime.TimeOfDay(25, 0, 0), "error!")) == |
|---|
| 1461 |
"assertNotThrown failed: TimeException was thrown: error!"); |
|---|
| 1462 |
})); |
|---|
| 1463 |
|
|---|
| 1464 |
|
|---|
| 1465 |
void assertThrown(T : Throwable = Exception, F) |
|---|
| 1466 |
(lazy F funcToCall, string msg = null, string file = __FILE__, size_t line = __LINE__) |
|---|
| 1467 |
{ |
|---|
| 1468 |
bool thrown = false; |
|---|
| 1469 |
|
|---|
| 1470 |
try |
|---|
| 1471 |
funcToCall(); |
|---|
| 1472 |
catch(T t) |
|---|
| 1473 |
thrown = true; |
|---|
| 1474 |
|
|---|
| 1475 |
if(!thrown) |
|---|
| 1476 |
{ |
|---|
| 1477 |
immutable tail = msg.empty ? "." : ": " ~ msg; |
|---|
| 1478 |
|
|---|
| 1479 |
throwException( new AssertError(format("assertThrown failed: No %s was thrown%s", T.stringof, tail), file, line) ); |
|---|
| 1480 |
} |
|---|
| 1481 |
} |
|---|
| 1482 |
|
|---|
| 1483 |
mixin(unittestSemiTwistDLib("private assertThrown", q{ |
|---|
| 1484 |
autoThrow = true; |
|---|
| 1485 |
|
|---|
| 1486 |
void throwEx(Throwable t) |
|---|
| 1487 |
{ |
|---|
| 1488 |
throw t; |
|---|
| 1489 |
} |
|---|
| 1490 |
|
|---|
| 1491 |
void nothrowEx() |
|---|
| 1492 |
{ |
|---|
| 1493 |
} |
|---|
| 1494 |
|
|---|
| 1495 |
try |
|---|
| 1496 |
assertThrown!Exception(throwEx(new Exception("It's an Exception"))); |
|---|
| 1497 |
catch(AssertError) |
|---|
| 1498 |
assert(0); |
|---|
| 1499 |
|
|---|
| 1500 |
try |
|---|
| 1501 |
assertThrown!Exception(throwEx(new Exception("It's an Exception")), "It's a message"); |
|---|
| 1502 |
catch(AssertError) |
|---|
| 1503 |
assert(0); |
|---|
| 1504 |
|
|---|
| 1505 |
try |
|---|
| 1506 |
assertThrown!AssertError(throwEx(new AssertError("It's an AssertError", __FILE__, __LINE__))); |
|---|
| 1507 |
catch(AssertError) |
|---|
| 1508 |
assert(0); |
|---|
| 1509 |
|
|---|
| 1510 |
try |
|---|
| 1511 |
assertThrown!AssertError(throwEx(new AssertError("It's an AssertError", __FILE__, __LINE__)), "It's a message"); |
|---|
| 1512 |
catch(AssertError) |
|---|
| 1513 |
assert(0); |
|---|
| 1514 |
|
|---|
| 1515 |
|
|---|
| 1516 |
{ |
|---|
| 1517 |
bool thrown = false; |
|---|
| 1518 |
try |
|---|
| 1519 |
assertThrown!Exception(nothrowEx()); |
|---|
| 1520 |
catch(AssertError) |
|---|
| 1521 |
thrown = true; |
|---|
| 1522 |
|
|---|
| 1523 |
assert(thrown); |
|---|
| 1524 |
} |
|---|
| 1525 |
|
|---|
| 1526 |
{ |
|---|
| 1527 |
bool thrown = false; |
|---|
| 1528 |
try |
|---|
| 1529 |
assertThrown!Exception(nothrowEx(), "It's a message"); |
|---|
| 1530 |
catch(AssertError) |
|---|
| 1531 |
thrown = true; |
|---|
| 1532 |
|
|---|
| 1533 |
assert(thrown); |
|---|
| 1534 |
} |
|---|
| 1535 |
|
|---|
| 1536 |
{ |
|---|
| 1537 |
bool thrown = false; |
|---|
| 1538 |
try |
|---|
| 1539 |
assertThrown!AssertError(nothrowEx()); |
|---|
| 1540 |
catch(AssertError) |
|---|
| 1541 |
thrown = true; |
|---|
| 1542 |
|
|---|
| 1543 |
assert(thrown); |
|---|
| 1544 |
} |
|---|
| 1545 |
|
|---|
| 1546 |
{ |
|---|
| 1547 |
bool thrown = false; |
|---|
| 1548 |
try |
|---|
| 1549 |
assertThrown!AssertError(nothrowEx(), "It's a message"); |
|---|
| 1550 |
catch(AssertError) |
|---|
| 1551 |
thrown = true; |
|---|
| 1552 |
|
|---|
| 1553 |
assert(thrown); |
|---|
| 1554 |
} |
|---|
| 1555 |
|
|---|
| 1556 |
//Verify Examples. |
|---|
| 1557 |
assertThrown!DateTimeException(std.datetime.TimeOfDay(-1, 15, 30)); |
|---|
| 1558 |
assertThrown!DateTimeException(std.datetime.TimeOfDay(12, 60, 30)); |
|---|
| 1559 |
assertThrown(std.datetime.TimeOfDay(12, 15, 60)); //Exception is default. |
|---|
| 1560 |
|
|---|
| 1561 |
|
|---|
| 1562 |
assert(collectExceptionMsg(assertThrown!AssertError(std.datetime.TimeOfDay(12, 0, 0))) == |
|---|
| 1563 |
"assertThrown failed: No AssertError was thrown."); |
|---|
| 1564 |
|
|---|
| 1565 |
assert(collectExceptionMsg(assertThrown!AssertError(std.datetime.TimeOfDay(12, 0, 0), "error!")) == |
|---|
| 1566 |
"assertThrown failed: No AssertError was thrown: error!"); |
|---|
| 1567 |
})); |
|---|
| 1568 |
|
|---|
| 1569 |
|
|---|
| 1570 |
string collectExceptionMsg(T)(lazy T funcCall) |
|---|
| 1571 |
{ |
|---|
| 1572 |
try |
|---|
| 1573 |
{ |
|---|
| 1574 |
funcCall(); |
|---|
| 1575 |
|
|---|
| 1576 |
return cast(string)null; |
|---|
| 1577 |
} |
|---|
| 1578 |
catch(Throwable t) |
|---|
| 1579 |
return t.msg; |
|---|
| 1580 |
} |
|---|
| 1581 |
|
|---|
| 1582 |
mixin(unittestSemiTwistDLib("private collectExceptionMsg", q{ |
|---|
| 1583 |
autoThrow = true; |
|---|
| 1584 |
|
|---|
| 1585 |
//Verify Example. |
|---|
| 1586 |
void throwFunc() {throw new Exception("My Message.");} |
|---|
| 1587 |
assert(collectExceptionMsg(throwFunc()) == "My Message."); |
|---|
| 1588 |
|
|---|
| 1589 |
void nothrowFunc() {} |
|---|
| 1590 |
assert(collectExceptionMsg(nothrowFunc()) is null); |
|---|
| 1591 |
})); |
|---|
| 1592 |
|
|---|
| 1593 |
|
|---|
| 1594 |
/+ |
|---|
| 1595 |
Whether the given type can be converted to a string. |
|---|
| 1596 |
+/ |
|---|
| 1597 |
template isPrintable(T...) |
|---|
| 1598 |
{ |
|---|
| 1599 |
static if(T.length == 0) |
|---|
| 1600 |
enum isPrintable = true; |
|---|
| 1601 |
else static if(T.length == 1) |
|---|
| 1602 |
{ |
|---|
| 1603 |
enum isPrintable = (!isArray!(T[0]) && __traits(compiles, to!string(T[0].init))) || |
|---|
| 1604 |
(isArray!(T[0]) && __traits(compiles, to!string(T[0].init[0]))); |
|---|
| 1605 |
} |
|---|
| 1606 |
else |
|---|
| 1607 |
{ |
|---|
| 1608 |
enum isPrintable = isPrintable!(T[0]) && isPrintable!(T[1 .. $]); |
|---|
| 1609 |
} |
|---|
| 1610 |
} |
|---|