-
Notifications
You must be signed in to change notification settings - Fork 37
/
test.d
144 lines (130 loc) · 3.43 KB
/
test.d
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
/++
Testing utilities
Authors: Ilya Yaroshenko
+/
module mir.test;
import mir.exception: MirError;
private noreturn assumeAllAttrAndCall(scope const void delegate() t)
@nogc pure nothrow @trusted {
(cast(const void delegate() @safe pure nothrow @nogc) t)();
assert(0);
}
///
struct ShouldApprox(T)
if (__traits(isFloating, T))
{
///
T value;
///
T maxRelDiff = 0x1p-20f;
///
T maxAbsDiff = 0x1p-20f;
///
void opEquals(T expected, string file = __FILE__, int line = __LINE__) @safe pure nothrow @nogc
{
import mir.format: stringBuf, getData;
import mir.math.common: approxEqual;
if (value.approxEqual(expected, maxRelDiff, maxAbsDiff))
return;
auto buf = stringBuf;
assumeAllAttrAndCall({
throw new MirError(buf
<< "expected approximately " << expected
<< ", got " << value
<< ", maxRelDiff = " << maxRelDiff
<< ", maxAbsDiff = " << maxAbsDiff
<< getData, file, line);
});
assert(0);
}
}
/// ditto
ShouldApprox!T shouldApprox(T)(const T value, const T maxRelDiff = T(0x1p-20f), const T maxAbsDiff = T(0x1p-20f))
if (__traits(isFloating, T))
{
return typeof(return)(value, maxRelDiff, maxAbsDiff);
}
///
version(mir_test)
unittest
{
1.0.shouldApprox == 1 + 9e-7;
shouldApprox(1 + 9e-7, 1e-6, 1e-6) == 1;
}
///
struct Should(T)
{
///
T value;
static if(!is(immutable T == immutable ubyte[]))
///
void opEquals(R)(const R expected, string file = __FILE__, int line = __LINE__) @trusted
{
import mir.format: stringBuf, getData;
static if (__traits(isFloating, R))
{
if (expected != expected && value != value)
return;
}
if (value == expected)
return;
auto buf = stringBuf;
buf << "mir.test.should:\n";
buf << "expected " << expected << "\n"
<< " got " << value;
assumeAllAttrAndCall({ throw new MirError(buf << getData, file, line); });
}
else
/// ditto
void opEquals(scope const ubyte[] expected, string file = __FILE__, int line = __LINE__) @trusted
pure nothrow @nogc
{
import mir.format: stringBuf, getData;
if (value == expected)
return;
auto buf = stringBuf;
import mir.format: printHexArray;
import mir.ndslice.topology: map;
buf << "mir.test.should:\n";
buf << "expected ";
buf.printHexArray(expected);
buf << "\n";
buf << " got ";
buf.printHexArray( value);
assumeAllAttrAndCall({ throw new MirError(buf << getData, file, line); });
}
}
/// ditto
Should!T should(T)(T value)
{
return typeof(return)(value);
}
///
version(mir_test)
unittest
{
1.0.should == 1;
should(1) == 1;
ubyte[] val = [0, 2, 3];
val.should == [0, 2, 3];
}
///
void should(alias fun = "a == b", T, R)(const T value, const R expected, string file = __FILE__, int line = __LINE__)
{
import mir.functional;
import mir.format: stringBuf, getData;
if (naryFun!fun(value, expected))
return;
auto buf = stringBuf;
buf << fun.stringof
<< " returns false"
<< " for a = " << value
<< ", b = " << expected;
throw new MirError(buf << getData, file, line);
}
///
version(mir_test)
unittest
{
1.0.should!"a < b"(1.3);
}