Artifact Content
Not logged in

Artifact fc21831342965670c1f62c511658ad88c18bb0e7


     1  /**
     2   * Authors: k.inaba
     3   * License: NYSL 0.9982 http://www.kmonos.net/nysl/
     4   *
     5   * Unittest helpers.
     6   * TODO: use stderr instead of stdout. the problem is that std.cstream is xxxx....
     7   * TODO: is there any way to clearnly implement "assert_compiles" and "assert_not_compile"?
     8   */
     9  module tricks.test;
    10  import std.conv : to;
    11  import core.exception;
    12  
    13  version(unittest)
    14  {
    15  	import std.stdio;
    16  	import core.runtime;
    17  
    18  	// Install custom test runner
    19  	static this()
    20  	{
    21  		Runtime.moduleUnitTester = function()
    22  		{
    23  			Throwable ee = null;
    24  			size_t failed=0;
    25  			foreach(m; ModuleInfo) if(m) if(auto fp=m.unitTest)
    26  			{
    27  				writeln("[TEST] ", m.name);
    28  				try {
    29  					fp();
    30  				} catch( Throwable e ) {
    31  					if(ee is null)
    32  						ee = e;
    33  					failed++;
    34  					writeln("  !! ",e.file,"(",e.line,"): ",e.msg);
    35  				}
    36  			}
    37  			if(ee !is null)
    38  			{
    39  				writeln("[TEST] ",failed," modules failed. The first error was:");
    40  				writeln(ee);
    41  				write("[TEST] press enter to exit.");
    42  				readln();
    43  				return false;
    44  			}
    45  			return true;
    46  		};
    47  	}
    48  }
    49  
    50  /// Unittest helper that asserts an expression must throw something
    51  
    52  void assert_throw(ExcT=Throwable, T, string fn=__FILE__, size_t ln=__LINE__)(lazy T t, string msg="")
    53  {
    54  	static if( is(ExcT == Throwable) )
    55  		try
    56  			{ t(); }
    57  		catch(ExcT)
    58  			{ return; }
    59  	else
    60  		try
    61  			{ t(); }
    62  		catch(ExcT)
    63  			{ return; }
    64  		catch(Throwable e)
    65  			{ onAssertErrorMsg(fn, ln, msg.length ? msg : "bad exception \n  >> "~e.toString()); }
    66  	onAssertErrorMsg(fn, ln, msg.length ? msg : "not thrown");
    67  }
    68  
    69  /// Unittest helper that asserts an expression must not throw anything
    70  
    71  T assert_nothrow(T, string fn=__FILE__, size_t ln=__LINE__)(lazy T t, string msg="")
    72  {
    73  	try
    74  		{ return t(); }
    75  	catch(Throwable e)
    76  		{ onAssertErrorMsg(fn, ln, msg.length ? msg : "bad exception \n  >> "~e.toString()); }
    77  	assert(false);
    78  }
    79  
    80  unittest
    81  {
    82  	auto error = {throw new Error("hello");};
    83  	auto nothing = (){};
    84  	auto assertError = {assert(0);};
    85  
    86  	assert_nothrow          ( assert_nothrow(nothing()) );
    87  	assert_throw!AssertError( assert_nothrow(error()) );
    88  	assert_throw!AssertError( assert_nothrow(assertError()) );
    89  
    90  	assert_nothrow          ( assert_throw!Error(error()) );
    91  	assert_throw!AssertError( assert_throw!Error(nothing()) );
    92  	assert_nothrow          ( assert_throw!Error(assertError()) );
    93  	assert_throw!AssertError( assert_throw!AssertError(error()) );
    94  }
    95  
    96  template assertOp(string op)
    97  {
    98  	void assertOp(A, B, string fn=__FILE__, size_t ln=__LINE__)(A a, B b, string msg="")
    99  	{
   100  		try
   101  			{ if( mixin("a"~op~"b") ) return; }
   102  		catch(Throwable e)
   103  			{ onAssertErrorMsg(fn, ln, msg.length ? msg : "bad exception \n  >> "~e.toString()); }
   104  		onAssertErrorMsg(fn, ln, msg.length ? msg : to!string(a)~" !"~op~" "~to!string(b));
   105  	}
   106  }
   107  
   108  alias assertOp!(`==`) assert_eq; /// asserts two operands are ==
   109  alias assertOp!(`!=`) assert_ne; /// asserts two operands are !=
   110  alias assertOp!(`<`)  assert_lt; /// asserts two operands are <
   111  alias assertOp!(`<=`) assert_le; /// asserts two operands are <=
   112  alias assertOp!(`>`)  assert_gt; /// asserts two operands are >
   113  alias assertOp!(`>=`) assert_ge; /// asserts two operands are >=
   114  
   115  unittest
   116  {
   117  	assert_nothrow( assert_eq(1, 1) );
   118  	assert_nothrow( assert_ne(1, 0) );
   119  	assert_nothrow( assert_lt(0, 1) );
   120  	assert_nothrow( assert_le(0, 1) );
   121  	assert_nothrow( assert_le(0, 0) );
   122  	assert_nothrow( assert_gt(1, 0) );
   123  	assert_nothrow( assert_ge(1, 0) );
   124  	assert_nothrow( assert_ge(0, 0) );
   125  
   126  	assert_throw!AssertError( assert_eq(1, 0) );
   127  	assert_throw!AssertError( assert_ne(1, 1) );
   128  	assert_throw!AssertError( assert_lt(1, 1) );
   129  	assert_throw!AssertError( assert_lt(1, 0) );
   130  	assert_throw!AssertError( assert_le(1, 0) );
   131  	assert_throw!AssertError( assert_gt(0, 0) );
   132  	assert_throw!AssertError( assert_gt(0, 1) );
   133  	assert_throw!AssertError( assert_ge(0, 1) );
   134  
   135  	class Temp { bool opEquals(int x){return x/x==x;} }
   136  	assert_throw!AssertError( assert_eq(new Temp, 0) );
   137  	assert_nothrow          ( assert_eq(new Temp, 1) );
   138  	assert_throw!AssertError( assert_eq(new Temp, 2) );
   139  }