xref: /netbsd-src/external/gpl3/gcc/dist/libphobos/testsuite/libphobos.exceptions/assert_fail.d (revision b1e838363e3c6fc78a55519254d99869742dd33c)
1*b1e83836Smrg import core.stdc.stdio : fprintf, stderr;
2*b1e83836Smrg import core.internal.dassert : _d_assert_fail;
3*b1e83836Smrg 
4*b1e83836Smrg void test(string comp = "==", A, B)(A a, B b, string msg, size_t line = __LINE__)
5*b1e83836Smrg {
6*b1e83836Smrg     test(_d_assert_fail!(A)(comp, a, b), msg, line);
7*b1e83836Smrg }
8*b1e83836Smrg 
9*b1e83836Smrg void test(const string actual, const string expected, size_t line = __LINE__)
10*b1e83836Smrg {
11*b1e83836Smrg     import core.exception : AssertError;
12*b1e83836Smrg 
13*b1e83836Smrg     if (actual != expected)
14*b1e83836Smrg     {
15*b1e83836Smrg         const msg = "Mismatch!\nExpected: <" ~ expected ~ ">\nActual:   <" ~ actual ~ '>';
16*b1e83836Smrg         throw new AssertError(msg, __FILE__, line);
17*b1e83836Smrg     }
18*b1e83836Smrg }
19*b1e83836Smrg 
testIntegers()20*b1e83836Smrg void testIntegers()
21*b1e83836Smrg {
22*b1e83836Smrg     test(1, 2, "1 != 2");
23*b1e83836Smrg     test(-10, 8, "-10 != 8");
24*b1e83836Smrg     test(byte.min, byte.max, "-128 != 127");
25*b1e83836Smrg     test(ubyte.min, ubyte.max, "0 != 255");
26*b1e83836Smrg     test(short.min, short.max, "-32768 != 32767");
27*b1e83836Smrg     test(ushort.min, ushort.max, "0 != 65535");
28*b1e83836Smrg     test(int.min, int.max, "-2147483648 != 2147483647");
29*b1e83836Smrg     test(uint.min, uint.max, "0 != 4294967295");
30*b1e83836Smrg     test(long.min, long.max, "-9223372036854775808 != 9223372036854775807");
31*b1e83836Smrg     test(ulong.min, ulong.max, "0 != 18446744073709551615");
32*b1e83836Smrg     test(shared(ulong).min, shared(ulong).max, "0 != 18446744073709551615");
33*b1e83836Smrg 
34*b1e83836Smrg     int testFun() { return 1; }
35*b1e83836Smrg     test(testFun(), 2, "1 != 2");
36*b1e83836Smrg }
37*b1e83836Smrg 
testIntegerComparisons()38*b1e83836Smrg void testIntegerComparisons()
39*b1e83836Smrg {
40*b1e83836Smrg     test!"!="(2, 2, "2 == 2");
41*b1e83836Smrg     test!"<"(2, 1, "2 >= 1");
42*b1e83836Smrg     test!"<="(2, 1, "2 > 1");
43*b1e83836Smrg     test!">"(1, 2, "1 <= 2");
44*b1e83836Smrg     test!">="(1, 2, "1 < 2");
45*b1e83836Smrg }
46*b1e83836Smrg 
testFloatingPoint()47*b1e83836Smrg void testFloatingPoint()
48*b1e83836Smrg {
49*b1e83836Smrg     if (__ctfe)
50*b1e83836Smrg     {
51*b1e83836Smrg         test(float.max, -float.max, "<float not supported> != <float not supported>");
52*b1e83836Smrg         test(double.max, -double.max, "<double not supported> != <double not supported>");
53*b1e83836Smrg         test(real(1), real(-1), "<real not supported> != <real not supported>");
54*b1e83836Smrg     }
55*b1e83836Smrg     else
56*b1e83836Smrg     {
57*b1e83836Smrg         test(1.5, 2.5, "1.5 != 2.5");
58*b1e83836Smrg         test(float.max, -float.max, "3.40282e+38 != -3.40282e+38");
59*b1e83836Smrg         test(double.max, -double.max, "1.79769e+308 != -1.79769e+308");
60*b1e83836Smrg         test(real(1), real(-1), "1 != -1");
61*b1e83836Smrg     }
62*b1e83836Smrg }
63*b1e83836Smrg 
testPointers()64*b1e83836Smrg void testPointers()
65*b1e83836Smrg {
66*b1e83836Smrg     static struct S
67*b1e83836Smrg     {
68*b1e83836Smrg         string toString() const { return "S(...)"; }
69*b1e83836Smrg     }
70*b1e83836Smrg 
71*b1e83836Smrg     static if ((void*).sizeof == 4)
72*b1e83836Smrg         enum ptr = "0x12345670";
73*b1e83836Smrg     else
74*b1e83836Smrg         enum ptr = "0x123456789abcdef0";
75*b1e83836Smrg 
76*b1e83836Smrg     int* p = cast(int*) mixin(ptr);
77*b1e83836Smrg     test(cast(S*) p, p, ptr ~ " != " ~ ptr);
78*b1e83836Smrg }
79*b1e83836Smrg 
testStrings()80*b1e83836Smrg void testStrings()
81*b1e83836Smrg {
82*b1e83836Smrg     test("foo", "bar", `"foo" != "bar"`);
83*b1e83836Smrg     test("", "bar", `"" != "bar"`);
84*b1e83836Smrg 
85*b1e83836Smrg     char[] dlang = "dlang".dup;
86*b1e83836Smrg     const(char)[] rust = "rust";
87*b1e83836Smrg     test(dlang, rust, `"dlang" != "rust"`);
88*b1e83836Smrg 
89*b1e83836Smrg     // https://issues.dlang.org/show_bug.cgi?id=20322
90*b1e83836Smrg     test("left"w, "right"w, `"left" != "right"`);
91*b1e83836Smrg     test("left"d, "right"d, `"left" != "right"`);
92*b1e83836Smrg 
93*b1e83836Smrg     test('A', 'B', "'A' != 'B'");
94*b1e83836Smrg     test(wchar('❤'), wchar('∑'), "'❤' != '∑'");
95*b1e83836Smrg     test(dchar('❤'), dchar('∑'), "'❤' != '∑'");
96*b1e83836Smrg 
97*b1e83836Smrg     // Detect invalid code points
98*b1e83836Smrg     test(char(255), 'B', "cast(char) 255 != 'B'");
99*b1e83836Smrg     test(wchar(0xD888), wchar('∑'), "cast(wchar) 55432 != '∑'");
100*b1e83836Smrg     test(dchar(0xDDDD), dchar('∑'), "cast(dchar) 56797 != '∑'");
101*b1e83836Smrg }
102*b1e83836Smrg 
testToString()103*b1e83836Smrg void testToString()
104*b1e83836Smrg {
105*b1e83836Smrg     class Foo
106*b1e83836Smrg     {
107*b1e83836Smrg         this(string payload) {
108*b1e83836Smrg             this.payload = payload;
109*b1e83836Smrg         }
110*b1e83836Smrg 
111*b1e83836Smrg         string payload;
112*b1e83836Smrg         override string toString() {
113*b1e83836Smrg             return "Foo(" ~ payload ~ ")";
114*b1e83836Smrg         }
115*b1e83836Smrg     }
116*b1e83836Smrg     test(new Foo("a"), new Foo("b"), "Foo(a) != Foo(b)");
117*b1e83836Smrg 
118*b1e83836Smrg     scope f = cast(shared) new Foo("a");
119*b1e83836Smrg     if (!__ctfe) // Ref somehow get's lost in CTFE
120*b1e83836Smrg     test!"!="(f, f, "Foo(a) == Foo(a)");
121*b1e83836Smrg 
122*b1e83836Smrg     // Verifiy that the const toString is selected if present
123*b1e83836Smrg     static struct Overloaded
124*b1e83836Smrg     {
125*b1e83836Smrg         string toString()
126*b1e83836Smrg         {
127*b1e83836Smrg             return "Mutable";
128*b1e83836Smrg         }
129*b1e83836Smrg 
130*b1e83836Smrg         string toString() const
131*b1e83836Smrg         {
132*b1e83836Smrg             return "Const";
133*b1e83836Smrg         }
134*b1e83836Smrg     }
135*b1e83836Smrg 
136*b1e83836Smrg     test!"!="(Overloaded(), Overloaded(), "Const == Const");
137*b1e83836Smrg 
138*b1e83836Smrg     Foo fnull = null;
139*b1e83836Smrg     test!"!is"(fnull, fnull, "`null` is `null`");
140*b1e83836Smrg }
141*b1e83836Smrg 
142*b1e83836Smrg 
testArray()143*b1e83836Smrg void testArray()
144*b1e83836Smrg {
145*b1e83836Smrg     test([1], [0], "[1] != [0]");
146*b1e83836Smrg     test([1, 2, 3], [0], "[1, 2, 3] != [0]");
147*b1e83836Smrg 
148*b1e83836Smrg     // test with long arrays
149*b1e83836Smrg     int[] arr;
150*b1e83836Smrg     foreach (i; 0 .. 100)
151*b1e83836Smrg         arr ~= i;
152*b1e83836Smrg     test(arr, [0], "[0, 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, ...] != [0]");
153*b1e83836Smrg 
154*b1e83836Smrg     // Ignore fake arrays
155*b1e83836Smrg     static struct S
156*b1e83836Smrg     {
157*b1e83836Smrg         int[2] arr;
158*b1e83836Smrg         int[] get() return { return arr[]; }
159*b1e83836Smrg         alias get this;
160*b1e83836Smrg     }
161*b1e83836Smrg 
162*b1e83836Smrg     const a = S([1, 2]);
163*b1e83836Smrg     test(a, S([3, 4]), "S([1, 2]) != S([3, 4])");
164*b1e83836Smrg }
165*b1e83836Smrg 
testStruct()166*b1e83836Smrg void testStruct()
167*b1e83836Smrg {
168*b1e83836Smrg     struct S { int s; }
169*b1e83836Smrg     struct T { T[] t; }
170*b1e83836Smrg     test(S(0), S(1), "S(0) != S(1)");
171*b1e83836Smrg     test(T([T(null)]), T(null), "T([T([])]) != T([])");
172*b1e83836Smrg 
173*b1e83836Smrg     // https://issues.dlang.org/show_bug.cgi?id=20323
174*b1e83836Smrg     static struct NoCopy
175*b1e83836Smrg     {
176*b1e83836Smrg         @disable this(this);
177*b1e83836Smrg     }
178*b1e83836Smrg 
179*b1e83836Smrg     NoCopy n;
180*b1e83836Smrg     test(_d_assert_fail!(typeof(n))("!=", n, n), "NoCopy() == NoCopy()");
181*b1e83836Smrg 
182*b1e83836Smrg     shared NoCopy sn;
183*b1e83836Smrg     test(_d_assert_fail!(typeof(sn))("!=", sn, sn), "NoCopy() == NoCopy()");
184*b1e83836Smrg }
185*b1e83836Smrg 
testAA()186*b1e83836Smrg void testAA()
187*b1e83836Smrg {
188*b1e83836Smrg     test([1:"one"], [2: "two"], `[1: "one"] != [2: "two"]`);
189*b1e83836Smrg     test!"in"(1, [2: 3], "1 !in [2: 3]");
190*b1e83836Smrg     test!"in"("foo", ["bar": true], `"foo" !in ["bar": true]`);
191*b1e83836Smrg }
192*b1e83836Smrg 
testAttributes()193*b1e83836Smrg void testAttributes() @safe pure @nogc nothrow
194*b1e83836Smrg {
195*b1e83836Smrg     int a;
196*b1e83836Smrg     string s = _d_assert_fail!(int, char)("==", a, 'c', 1, 'd');
197*b1e83836Smrg     assert(s == `(0, 'c') != (1, 'd')`);
198*b1e83836Smrg 
199*b1e83836Smrg     string s2 = _d_assert_fail!int("", a);
200*b1e83836Smrg     assert(s2 == `0 != true`);
201*b1e83836Smrg }
202*b1e83836Smrg 
203*b1e83836Smrg // https://issues.dlang.org/show_bug.cgi?id=20066
testVoidArray()204*b1e83836Smrg void testVoidArray()
205*b1e83836Smrg {
206*b1e83836Smrg     test!"!is"([], null, (__ctfe ? "<void[] not supported>" : "[]") ~ " is `null`");
207*b1e83836Smrg     test!"!is"(null, null, "`null` is `null`");
208*b1e83836Smrg     test([1], null, "[1] != `null`");
209*b1e83836Smrg     test("s", null, "\"s\" != `null`");
210*b1e83836Smrg     test(['c'], null, "\"c\" != `null`");
211*b1e83836Smrg     test!"!="(null, null, "`null` == `null`");
212*b1e83836Smrg 
213*b1e83836Smrg     const void[] chunk = [byte(1), byte(2), byte(3)];
214*b1e83836Smrg     test(chunk, null, (__ctfe ? "<void[] not supported>" : "[1, 2, 3]") ~ " != `null`");
215*b1e83836Smrg }
216*b1e83836Smrg 
testTemporary()217*b1e83836Smrg void testTemporary()
218*b1e83836Smrg {
219*b1e83836Smrg     static struct Bad
220*b1e83836Smrg     {
221*b1e83836Smrg         ~this() @system {}
222*b1e83836Smrg     }
223*b1e83836Smrg 
224*b1e83836Smrg     test!"!="(Bad(), Bad(), "Bad() == Bad()");
225*b1e83836Smrg }
226*b1e83836Smrg 
testEnum()227*b1e83836Smrg void testEnum()
228*b1e83836Smrg {
229*b1e83836Smrg     static struct UUID {
230*b1e83836Smrg         union
231*b1e83836Smrg         {
232*b1e83836Smrg             ubyte[] data = [1];
233*b1e83836Smrg         }
234*b1e83836Smrg     }
235*b1e83836Smrg 
236*b1e83836Smrg     ubyte[] data;
237*b1e83836Smrg     enum ctfe = UUID();
238*b1e83836Smrg     test(_d_assert_fail!(ubyte[])("==", ctfe.data, data), "[1] != []");
239*b1e83836Smrg }
240*b1e83836Smrg 
241*b1e83836Smrg void testUnary()
242*b1e83836Smrg {
243*b1e83836Smrg     test(_d_assert_fail!int("", 9), "9 != true");
244*b1e83836Smrg     test(_d_assert_fail!(int[])("!", [1, 2, 3]), "[1, 2, 3] == true");
245*b1e83836Smrg }
246*b1e83836Smrg 
247*b1e83836Smrg void testTuple()
248*b1e83836Smrg {
249*b1e83836Smrg     test(_d_assert_fail("=="), "() != ()");
250*b1e83836Smrg     test(_d_assert_fail("!="), "() == ()");
251*b1e83836Smrg     test(_d_assert_fail(">="), "() < ()");
252*b1e83836Smrg }
253*b1e83836Smrg 
254*b1e83836Smrg void testStructEquals()
255*b1e83836Smrg {
256*b1e83836Smrg     struct T {
257*b1e83836Smrg         bool b;
258*b1e83836Smrg         int i;
259*b1e83836Smrg         float f1 = 2.5;
260*b1e83836Smrg         float f2 = 0;
261*b1e83836Smrg         string s1 = "bar";
262*b1e83836Smrg         string s2;
263*b1e83836Smrg     }
264*b1e83836Smrg 
265*b1e83836Smrg     T t1;
266*b1e83836Smrg     test!"!="(t1, t1, `T(false, 0, 2.5, 0, "bar", "") == T(false, 0, 2.5, 0, "bar", "")`);
267*b1e83836Smrg     T t2 = {s1: "bari"};
268*b1e83836Smrg     test(t1, t2, `T(false, 0, 2.5, 0, "bar", "") != T(false, 0, 2.5, 0, "bari", "")`);
269*b1e83836Smrg }
270*b1e83836Smrg 
271*b1e83836Smrg void testStructEquals2()
272*b1e83836Smrg {
273*b1e83836Smrg     struct T {
274*b1e83836Smrg         bool b;
275*b1e83836Smrg         int i;
276*b1e83836Smrg         float f1 = 2.5;
277*b1e83836Smrg         float f2 = 0;
278*b1e83836Smrg     }
279*b1e83836Smrg 
280*b1e83836Smrg     T t1;
281*b1e83836Smrg     test!"!="(t1, t1, `T(false, 0, 2.5, 0) == T(false, 0, 2.5, 0)`);
282*b1e83836Smrg     T t2 = {i: 2};
283*b1e83836Smrg     test(t1, t2, `T(false, 0, 2.5, 0) != T(false, 2, 2.5, 0)`);
284*b1e83836Smrg }
285*b1e83836Smrg 
286*b1e83836Smrg void testStructEquals3()
287*b1e83836Smrg {
288*b1e83836Smrg     struct T {
289*b1e83836Smrg         bool b;
290*b1e83836Smrg         int i;
291*b1e83836Smrg         string s1 = "bar";
292*b1e83836Smrg         string s2;
293*b1e83836Smrg     }
294*b1e83836Smrg 
295*b1e83836Smrg     T t1;
296*b1e83836Smrg     test!"!="(t1, t1, `T(false, 0, "bar", "") == T(false, 0, "bar", "")`);
297*b1e83836Smrg     T t2 = {s1: "bari"};
298*b1e83836Smrg     test(t1, t2, `T(false, 0, "bar", "") != T(false, 0, "bari", "")`);
299*b1e83836Smrg }
300*b1e83836Smrg 
301*b1e83836Smrg void testStructEquals4()
302*b1e83836Smrg {
303*b1e83836Smrg     struct T {
304*b1e83836Smrg         float f1 = 2.5;
305*b1e83836Smrg         float f2 = 0;
306*b1e83836Smrg         string s1 = "bar";
307*b1e83836Smrg         string s2;
308*b1e83836Smrg     }
309*b1e83836Smrg 
310*b1e83836Smrg     T t1;
311*b1e83836Smrg     test!"!="(t1, t1, `T(2.5, 0, "bar", "") == T(2.5, 0, "bar", "")`);
312*b1e83836Smrg     T t2 = {s1: "bari"};
313*b1e83836Smrg     test(t1, t2, `T(2.5, 0, "bar", "") != T(2.5, 0, "bari", "")`);
314*b1e83836Smrg }
315*b1e83836Smrg 
316*b1e83836Smrg void testStructEquals5()
317*b1e83836Smrg {
318*b1e83836Smrg     struct T {
319*b1e83836Smrg         bool b;
320*b1e83836Smrg         int i;
321*b1e83836Smrg         float f2 = 0;
322*b1e83836Smrg         string s2;
323*b1e83836Smrg     }
324*b1e83836Smrg 
325*b1e83836Smrg     T t1;
326*b1e83836Smrg     test!"!="(t1, t1, `T(false, 0, 0, "") == T(false, 0, 0, "")`);
327*b1e83836Smrg     T t2 = {b: true};
328*b1e83836Smrg     test(t1, t2, `T(false, 0, 0, "") != T(true, 0, 0, "")`);
329*b1e83836Smrg }
330*b1e83836Smrg 
331*b1e83836Smrg void testStructEquals6()
332*b1e83836Smrg {
333*b1e83836Smrg     class C { override string toString() { return "C()"; }}
334*b1e83836Smrg     struct T {
335*b1e83836Smrg         bool b;
336*b1e83836Smrg         int i;
337*b1e83836Smrg         float f2 = 0;
338*b1e83836Smrg         string s2;
339*b1e83836Smrg         int[] arr;
340*b1e83836Smrg         C c;
341*b1e83836Smrg     }
342*b1e83836Smrg 
343*b1e83836Smrg     T t1;
344*b1e83836Smrg     test!"!="(t1, t1, "T(false, 0, 0, \"\", [], `null`) == T(false, 0, 0, \"\", [], `null`)");
345*b1e83836Smrg     T t2 = {arr: [1]};
346*b1e83836Smrg     test(t1, t2, "T(false, 0, 0, \"\", [], `null`) != T(false, 0, 0, \"\", [1], `null`)");
347*b1e83836Smrg     T t3 = {c: new C()};
348*b1e83836Smrg     test(t1, t3, "T(false, 0, 0, \"\", [], `null`) != T(false, 0, 0, \"\", [], C())");
349*b1e83836Smrg }
350*b1e83836Smrg 
351*b1e83836Smrg void testContextPointer()
352*b1e83836Smrg {
353*b1e83836Smrg     int i;
354*b1e83836Smrg     struct T
355*b1e83836Smrg     {
356*b1e83836Smrg         int j;
357*b1e83836Smrg         int get()
358*b1e83836Smrg         {
359*b1e83836Smrg             return i * j;
360*b1e83836Smrg         }
361*b1e83836Smrg     }
362*b1e83836Smrg     T t = T(1);
363*b1e83836Smrg     t.tupleof[$-1] = cast(void*) 0xABCD; // Deterministic context pointer
364*b1e83836Smrg     test(t, t, `T(1, <context>: 0xabcd) != T(1, <context>: 0xabcd)`);
365*b1e83836Smrg }
366*b1e83836Smrg 
367*b1e83836Smrg void testExternClasses()
368*b1e83836Smrg {
369*b1e83836Smrg     {
370*b1e83836Smrg         extern(C++) static class Cpp
371*b1e83836Smrg         {
372*b1e83836Smrg             int a;
373*b1e83836Smrg             this(int a) { this.a = a; }
374*b1e83836Smrg         }
375*b1e83836Smrg         scope a = new Cpp(1);
376*b1e83836Smrg         scope b = new Cpp(2);
377*b1e83836Smrg         test(a, b, "Cpp(1) != Cpp(2)");
378*b1e83836Smrg         test(a, Cpp.init, "Cpp(1) != null");
379*b1e83836Smrg     }
380*b1e83836Smrg     {
381*b1e83836Smrg         extern(C++) static class CppToString
382*b1e83836Smrg         {
383*b1e83836Smrg             int a;
384*b1e83836Smrg             this(int a) { this.a = a; }
385*b1e83836Smrg             extern(D) string toString() const { return a == 0 ? "hello" : "world"; }
386*b1e83836Smrg         }
387*b1e83836Smrg         scope a = new CppToString(0);
388*b1e83836Smrg         scope b = new CppToString(1);
389*b1e83836Smrg         test(a, b, "hello != world");
390*b1e83836Smrg     }
391*b1e83836Smrg     if (!__ctfe)
392*b1e83836Smrg     {
393*b1e83836Smrg         extern(C++) static class Opaque;
394*b1e83836Smrg         Opaque null_ = null;
395*b1e83836Smrg         Opaque notNull = cast(Opaque) &null_;
396*b1e83836Smrg         test(null_, notNull, "null != <Opaque>");
397*b1e83836Smrg     }
398*b1e83836Smrg     {
399*b1e83836Smrg         extern(C++) static interface Stuff {}
400*b1e83836Smrg         scope Stuff stuff = new class Stuff {};
401*b1e83836Smrg         test(stuff, Stuff.init, "Stuff() != null");
402*b1e83836Smrg     }
403*b1e83836Smrg }
404*b1e83836Smrg 
405*b1e83836Smrg void testShared()
406*b1e83836Smrg {
407*b1e83836Smrg     static struct Small
408*b1e83836Smrg     {
409*b1e83836Smrg         int i;
410*b1e83836Smrg     }
411*b1e83836Smrg 
412*b1e83836Smrg     auto s1 = shared Small(1);
413*b1e83836Smrg     const s2 = shared Small(2);
414*b1e83836Smrg     test(s1, s2, "Small(1) != Small(2)");
415*b1e83836Smrg 
416*b1e83836Smrg     static struct Big
417*b1e83836Smrg     {
418*b1e83836Smrg         long[10] l;
419*b1e83836Smrg     }
420*b1e83836Smrg 
421*b1e83836Smrg     auto b1 = shared Big([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
422*b1e83836Smrg     const b2 = shared Big();
423*b1e83836Smrg     test(b1, b2, "Big([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) != Big([0, 0, 0, 0, 0, 0, 0, 0, 0, 0])");
424*b1e83836Smrg 
425*b1e83836Smrg     // Sanity check: Big shouldn't be supported by atomicLoad
426*b1e83836Smrg     import core.atomic : atomicLoad;
427*b1e83836Smrg     static assert( __traits(compiles, atomicLoad(s1)));
428*b1e83836Smrg     static assert(!__traits(compiles, atomicLoad(b1)));
429*b1e83836Smrg 
430*b1e83836Smrg     static struct Fail
431*b1e83836Smrg     {
432*b1e83836Smrg         int value;
433*b1e83836Smrg 
434*b1e83836Smrg         @safe pure nothrow @nogc:
435*b1e83836Smrg         bool opCast () shared const scope { return true; }
436*b1e83836Smrg     }
437*b1e83836Smrg 
438*b1e83836Smrg     shared Fail fail = { value: 1 };
439*b1e83836Smrg     assert(_d_assert_fail!(shared Fail)("==", fail) == "Fail(1) != true");
440*b1e83836Smrg     assert(_d_assert_fail!(shared Fail)("==", fail, fail) == "Fail(1) != Fail(1)");
441*b1e83836Smrg }
442*b1e83836Smrg 
443*b1e83836Smrg void testException()
444*b1e83836Smrg {
445*b1e83836Smrg     static struct MayThrow
446*b1e83836Smrg     {
447*b1e83836Smrg         int i;
448*b1e83836Smrg         string toString()
449*b1e83836Smrg         {
450*b1e83836Smrg             if (i == 1)
451*b1e83836Smrg                 throw new Exception("Error");
452*b1e83836Smrg             return "Some message";
453*b1e83836Smrg         }
454*b1e83836Smrg     }
455*b1e83836Smrg 
456*b1e83836Smrg     test(MayThrow(0), MayThrow(1), `Some message != <toString() failed: "Error", called on MayThrow(1)>`);
457*b1e83836Smrg }
458*b1e83836Smrg 
459*b1e83836Smrg void testOverlappingFields()
460*b1e83836Smrg {
461*b1e83836Smrg     static struct S
462*b1e83836Smrg     {
463*b1e83836Smrg         union
464*b1e83836Smrg         {
465*b1e83836Smrg             double num;
466*b1e83836Smrg             immutable(char)[] name;
467*b1e83836Smrg         }
468*b1e83836Smrg     }
469*b1e83836Smrg 
470*b1e83836Smrg     test(S(1.0), S(2.0), "S(<overlapped field>, <overlapped field>) != S(<overlapped field>, <overlapped field>)");
471*b1e83836Smrg 
472*b1e83836Smrg     static struct S2
473*b1e83836Smrg     {
474*b1e83836Smrg         int valid;
475*b1e83836Smrg         union
476*b1e83836Smrg         {
477*b1e83836Smrg             double num;
478*b1e83836Smrg             immutable(char)[] name;
479*b1e83836Smrg         }
480*b1e83836Smrg     }
481*b1e83836Smrg 
482*b1e83836Smrg     test(S2(4, 1.0), S2(5, 2.0), "S2(4, <overlapped field>, <overlapped field>) != S2(5, <overlapped field>, <overlapped field>)");
483*b1e83836Smrg 
484*b1e83836Smrg     static struct S3
485*b1e83836Smrg     {
486*b1e83836Smrg         union
487*b1e83836Smrg         {
488*b1e83836Smrg             double num;
489*b1e83836Smrg             immutable(char)[] name;
490*b1e83836Smrg         }
491*b1e83836Smrg         int valid;
492*b1e83836Smrg     }
493*b1e83836Smrg     S3 a = {
494*b1e83836Smrg         num: 1.0,
495*b1e83836Smrg         valid: 8
496*b1e83836Smrg     };
497*b1e83836Smrg 
498*b1e83836Smrg     S3 b = {
499*b1e83836Smrg         num: 1.0,
500*b1e83836Smrg         valid: 8
501*b1e83836Smrg     };
502*b1e83836Smrg     test(a, b, "S3(<overlapped field>, <overlapped field>, 8) != S3(<overlapped field>, <overlapped field>, 8)");
503*b1e83836Smrg }
504*b1e83836Smrg 
505*b1e83836Smrg void testDestruction()
506*b1e83836Smrg {
507*b1e83836Smrg     static class Test
508*b1e83836Smrg     {
509*b1e83836Smrg         __gshared string unary, binary;
510*b1e83836Smrg         __gshared bool run;
511*b1e83836Smrg 
512*b1e83836Smrg         ~this()
513*b1e83836Smrg         {
514*b1e83836Smrg             run = true;
515*b1e83836Smrg             unary = _d_assert_fail!int("", 1);
516*b1e83836Smrg             binary = _d_assert_fail!int("==", 1, 2);
517*b1e83836Smrg         }
518*b1e83836Smrg     }
519*b1e83836Smrg 
520*b1e83836Smrg     static void createGarbage()
521*b1e83836Smrg     {
522*b1e83836Smrg         new Test();
523*b1e83836Smrg         new long[100];
524*b1e83836Smrg     }
525*b1e83836Smrg 
526*b1e83836Smrg     import core.memory : GC;
527*b1e83836Smrg     createGarbage();
528*b1e83836Smrg     GC.collect();
529*b1e83836Smrg 
530*b1e83836Smrg     assert(Test.run);
531*b1e83836Smrg     assert(Test.unary == "Assertion failed (rich formatting is disabled in finalizers)");
532*b1e83836Smrg     assert(Test.binary == "Assertion failed (rich formatting is disabled in finalizers)");
533*b1e83836Smrg }
534*b1e83836Smrg 
535*b1e83836Smrg int main()
536*b1e83836Smrg {
537*b1e83836Smrg     testIntegers();
538*b1e83836Smrg     testIntegerComparisons();
539*b1e83836Smrg     testFloatingPoint();
540*b1e83836Smrg     testPointers();
541*b1e83836Smrg     testStrings();
542*b1e83836Smrg     testToString();
543*b1e83836Smrg     testArray();
544*b1e83836Smrg     testStruct();
545*b1e83836Smrg     testAA();
546*b1e83836Smrg     testAttributes();
547*b1e83836Smrg     testVoidArray();
548*b1e83836Smrg     testTemporary();
549*b1e83836Smrg     testEnum();
550*b1e83836Smrg     testUnary();
551*b1e83836Smrg     testTuple();
552*b1e83836Smrg     if (!__ctfe)
553*b1e83836Smrg         testStructEquals();
554*b1e83836Smrg     if (!__ctfe)
555*b1e83836Smrg         testStructEquals2();
556*b1e83836Smrg     testStructEquals3();
557*b1e83836Smrg     if (!__ctfe)
558*b1e83836Smrg         testStructEquals4();
559*b1e83836Smrg     if (!__ctfe)
560*b1e83836Smrg         testStructEquals5();
561*b1e83836Smrg     if (!__ctfe)
562*b1e83836Smrg         testStructEquals6();
563*b1e83836Smrg     testContextPointer();
564*b1e83836Smrg     testExternClasses();
565*b1e83836Smrg     testShared();
566*b1e83836Smrg     testException();
567*b1e83836Smrg     testOverlappingFields();
568*b1e83836Smrg     if (!__ctfe)
569*b1e83836Smrg         testDestruction();
570*b1e83836Smrg 
571*b1e83836Smrg     if (!__ctfe)
572*b1e83836Smrg         fprintf(stderr, "success.\n");
573*b1e83836Smrg     return 0;
574*b1e83836Smrg }
575*b1e83836Smrg 
576*b1e83836Smrg enum forceCTFE = main();
577