1 module des.util.testsuite;
2 
3 import std.traits;
4 import std.math;
5 
6 bool isLikeArray(A)()
7 { return is( typeof( A.init[0] ) ) && is( typeof( A.init.length ) == size_t ); }
8 
9 bool eq(A,B)( in A a, in B b )
10     if( is(typeof(A.init!=B.init)) && !isLikeArray!A && !isLikeArray!B )
11 {
12     static if( isFloatingPoint!A || isFloatingPoint!B )
13     {
14         static if( isFloatingPoint!A && !isFloatingPoint!B )
15             auto epsilon = A.epsilon;
16         else static if( isFloatingPoint!B && !isFloatingPoint!A )
17             auto epsilon = B.epsilon;
18         else
19             auto epsilon = fmax( A.epsilon, B.epsilon );
20         if( abs( a - b ) > epsilon ) return false;
21     }
22     else
23     {
24         if( a != b ) return false;
25     }
26     return true;
27 }
28 
29 unittest
30 {
31     assert( eq(1,1.0) );
32     assert( eq("hello","hello"w) );
33 }
34 
35 bool eq(A,B)( in A a, in B b )
36     if( isLikeArray!A && isLikeArray!B && is(typeof(A.init[0]!=B.init[0])) )
37 {
38     static if( is(Unqual!A == void[] ) )
39         return a == b; 
40     else
41     {
42         if( a.length != b.length ) return false;
43         foreach( i; 0 .. a.length )
44             if( !eq(a[i],b[i]) ) return false;
45         return true;
46     }
47 }
48 
49 unittest
50 {
51     assert( eq( [1,2,3], [1.0,2,3] ) );
52     assert( eq( [1.0f,2,3], [1.0,2,3] ) );
53     assert( eq( [1,2,3], [1,2,3] ) );
54     assert( !eq( [1.0000001,2,3], [1,2,3] ) );
55     assert( eq( ["hello","world"], ["hello","world"] ) );
56     static assert( !__traits(compiles, eq(["hello"],1)) );
57 }
58 
59 bool eq_approx(A,B,E)( in A a, in B b, in E eps )
60     if( isLikeArray!A && isLikeArray!B && 
61         is(typeof(-E.init)) &&
62         is(typeof( (A.init[0]-B.init[0]) < eps )) )
63 {
64     if( a.length != b.length ) return false;
65     foreach( i; 0 .. a.length )
66         if( !eq_approx(a[i],b[i],eps) ) return false;
67     return true;
68 }
69 
70 bool eq_approx(A,B,E)( in A a, in B b, in E eps )
71     if( is(typeof( (A.init-B.init) < eps )) )
72 { return (a-b < eps) && (a-b > -eps); }
73 
74 bool mustExcept(E=Exception)( void delegate() fnc, bool throwUnexpected=false )
75 if( is( E : Throwable ) )
76 in { assert( fnc ); } body
77 {
78     try fnc();
79     catch( E e ) return true;
80     catch( Throwable t )
81         if( throwUnexpected ) throw t;
82     return false;
83 }
84 
85 unittest
86 {
87     assert( mustExcept!Exception( { throw new Exception("test"); } ) );
88     assert( !mustExcept!Exception( { throw new Throwable("test"); } ) );
89     assert( !mustExcept!Exception( { auto a = 4; } ) );
90 }