1 import core
.stdc
.stdio
: fprintf
, stderr
;
2 import core
.internal
.dassert
: _d_assert_fail
;
4 void test(string comp
= "==", A
, B
)(A a
, B b
, string msg
, size_t line
= __LINE__
)
6 test(_d_assert_fail
!(A
)(comp
, a
, b
), msg
, line
);
9 void test(const string actual
, const string expected
, size_t line
= __LINE__
)
11 import core
.exception
: AssertError
;
13 if (actual
!= expected
)
15 const msg
= "Mismatch!\nExpected: <" ~ expected
~ ">\nActual: <" ~ actual
~ '>';
16 throw new AssertError(msg
, __FILE__
, line
);
23 test(-10, 8, "-10 != 8");
24 test(byte.min
, byte.max
, "-128 != 127");
25 test(ubyte.min
, ubyte.max
, "0 != 255");
26 test(short.min
, short.max
, "-32768 != 32767");
27 test(ushort.min
, ushort.max
, "0 != 65535");
28 test(int.min
, int.max
, "-2147483648 != 2147483647");
29 test(uint.min
, uint.max
, "0 != 4294967295");
30 test(long.min
, long.max
, "-9223372036854775808 != 9223372036854775807");
31 test(ulong.min
, ulong.max
, "0 != 18446744073709551615");
32 test(shared(ulong).min
, shared(ulong).max
, "0 != 18446744073709551615");
34 int testFun() { return 1; }
35 test(testFun(), 2, "1 != 2");
38 void testIntegerComparisons()
40 test!"!="(2, 2, "2 == 2");
41 test!"<"(2, 1, "2 >= 1");
42 test!"<="(2, 1, "2 > 1");
43 test!">"(1, 2, "1 <= 2");
44 test!">="(1, 2, "1 < 2");
47 void testFloatingPoint()
51 test(float.max
, -float.max
, "<float not supported> != <float not supported>");
52 test(double.max
, -double.max
, "<double not supported> != <double not supported>");
53 test(real(1), real(-1), "<real not supported> != <real not supported>");
57 test(1.5, 2.5, "1.5 != 2.5");
58 test(float.max
, -float.max
, "3.40282e+38 != -3.40282e+38");
59 test(double.max
, -double.max
, "1.79769e+308 != -1.79769e+308");
60 test(real(1), real(-1), "1 != -1");
68 string
toString() const { return "S(...)"; }
71 static if ((void*).sizeof
== 4)
72 enum ptr
= "0x12345670";
74 enum ptr
= "0x123456789abcdef0";
76 int* p
= cast(int*) mixin(ptr
);
77 test(cast(S
*) p
, p
, ptr
~ " != " ~ ptr
);
82 test("foo", "bar", `"foo" != "bar"`);
83 test("", "bar", `"" != "bar"`);
85 char[] dlang
= "dlang".dup
;
86 const(char)[] rust
= "rust";
87 test(dlang
, rust
, `"dlang" != "rust"`);
89 // https://issues.dlang.org/show_bug.cgi?id=20322
90 test("left"w
, "right"w
, `"left" != "right"`);
91 test("left"d
, "right"d
, `"left" != "right"`);
93 test('A', 'B', "'A' != 'B'");
94 test(wchar('❤'), wchar('∑'), "'❤' != '∑'");
95 test(dchar('❤'), dchar('∑'), "'❤' != '∑'");
97 // Detect invalid code points
98 test(char(255), 'B', "cast(char) 255 != 'B'");
99 test(wchar(0xD888), wchar('∑'), "cast(wchar) 55432 != '∑'");
100 test(dchar(0xDDDD), dchar('∑'), "cast(dchar) 56797 != '∑'");
107 this(string payload
) {
108 this.payload
= payload
;
112 override string
toString() {
113 return "Foo(" ~ payload
~ ")";
116 test(new Foo("a"), new Foo("b"), "Foo(a) != Foo(b)");
118 scope f
= cast(shared) new Foo("a");
119 if (!__ctfe
) // Ref somehow get's lost in CTFE
120 test!"!="(f
, f
, "Foo(a) == Foo(a)");
122 // Verifiy that the const toString is selected if present
123 static struct Overloaded
130 string
toString() const
136 test!"!="(Overloaded(), Overloaded(), "Const == Const");
139 test!"!is"(fnull
, fnull
, "`null` is `null`");
145 test([1], [0], "[1] != [0]");
146 test([1, 2, 3], [0], "[1, 2, 3] != [0]");
148 // test with long arrays
150 foreach (i
; 0 .. 100)
152 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]");
154 // Ignore fake arrays
158 int[] get() return { return arr
[]; }
163 test(a
, S([3, 4]), "S([1, 2]) != S([3, 4])");
170 test(S(0), S(1), "S(0) != S(1)");
171 test(T([T(null)]), T(null), "T([T([])]) != T([])");
173 // https://issues.dlang.org/show_bug.cgi?id=20323
180 test(_d_assert_fail
!(typeof(n
))("!=", n
, n
), "NoCopy() == NoCopy()");
183 test(_d_assert_fail
!(typeof(sn
))("!=", sn
, sn
), "NoCopy() == NoCopy()");
188 test([1:"one"], [2: "two"], `[1: "one"] != [2: "two"]`);
189 test!"in"(1, [2: 3], "1 !in [2: 3]");
190 test!"in"("foo", ["bar": true], `"foo" !in ["bar": true]`);
193 void testAttributes() @safe pure @nogc nothrow
196 string s
= _d_assert_fail
!(int, char)("==", a
, 'c', 1, 'd');
197 assert(s
== `(0, 'c') != (1, 'd')`);
199 string s2
= _d_assert_fail
!int("", a
);
200 assert(s2
== `0 != true`);
203 // https://issues.dlang.org/show_bug.cgi?id=20066
206 test!"!is"([], null, (__ctfe ?
"<void[] not supported>" : "[]") ~ " is `null`");
207 test!"!is"(null, null, "`null` is `null`");
208 test([1], null, "[1] != `null`");
209 test("s", null, "\"s\" != `null`");
210 test(['c'], null, "\"c\" != `null`");
211 test!"!="(null, null, "`null` == `null`");
213 const void[] chunk
= [byte(1), byte(2), byte(3)];
214 test(chunk
, null, (__ctfe ?
"<void[] not supported>" : "[1, 2, 3]") ~ " != `null`");
224 test!"!="(Bad(), Bad(), "Bad() == Bad()");
238 test(_d_assert_fail
!(ubyte[])("==", ctfe
.data
, data
), "[1] != []");
243 test(_d_assert_fail
!int("", 9), "9 != true");
244 test(_d_assert_fail
!(int[])("!", [1, 2, 3]), "[1, 2, 3] == true");
249 test(_d_assert_fail("=="), "() != ()");
250 test(_d_assert_fail("!="), "() == ()");
251 test(_d_assert_fail(">="), "() < ()");
254 void testStructEquals()
266 test!"!="(t1
, t1
, `T(false, 0, 2.5, 0, "bar", "") == T(false, 0, 2.5, 0, "bar", "")`);
268 test(t1
, t2
, `T(false, 0, 2.5, 0, "bar", "") != T(false, 0, 2.5, 0, "bari", "")`);
271 void testStructEquals2()
281 test!"!="(t1
, t1
, `T(false, 0, 2.5, 0) == T(false, 0, 2.5, 0)`);
283 test(t1
, t2
, `T(false, 0, 2.5, 0) != T(false, 2, 2.5, 0)`);
286 void testStructEquals3()
296 test!"!="(t1
, t1
, `T(false, 0, "bar", "") == T(false, 0, "bar", "")`);
298 test(t1
, t2
, `T(false, 0, "bar", "") != T(false, 0, "bari", "")`);
301 void testStructEquals4()
311 test!"!="(t1
, t1
, `T(2.5, 0, "bar", "") == T(2.5, 0, "bar", "")`);
313 test(t1
, t2
, `T(2.5, 0, "bar", "") != T(2.5, 0, "bari", "")`);
316 void testStructEquals5()
326 test!"!="(t1
, t1
, `T(false, 0, 0, "") == T(false, 0, 0, "")`);
328 test(t1
, t2
, `T(false, 0, 0, "") != T(true, 0, 0, "")`);
331 void testStructEquals6()
333 class C
{ override string
toString() { return "C()"; }}
344 test!"!="(t1
, t1
, "T(false, 0, 0, \"\", [], `null`) == T(false, 0, 0, \"\", [], `null`)");
346 test(t1
, t2
, "T(false, 0, 0, \"\", [], `null`) != T(false, 0, 0, \"\", [1], `null`)");
348 test(t1
, t3
, "T(false, 0, 0, \"\", [], `null`) != T(false, 0, 0, \"\", [], C())");
351 void testContextPointer()
363 t
.tupleof
[$-1] = cast(void*) 0xABCD; // Deterministic context pointer
364 test(t
, t
, `T(1, <context>: 0xabcd) != T(1, <context>: 0xabcd)`);
367 void testExternClasses()
370 extern(C
++) static class Cpp
373 this(int a
) { this.a
= a
; }
375 scope a
= new Cpp(1);
376 scope b
= new Cpp(2);
377 test(a
, b
, "Cpp(1) != Cpp(2)");
378 test(a
, Cpp
.init
, "Cpp(1) != null");
381 extern(C
++) static class CppToString
384 this(int a
) { this.a
= a
; }
385 extern(D
) string
toString() const { return a
== 0 ?
"hello" : "world"; }
387 scope a
= new CppToString(0);
388 scope b
= new CppToString(1);
389 test(a
, b
, "hello != world");
393 extern(C
++) static class Opaque
;
395 Opaque notNull
= cast(Opaque
) &null_
;
396 test(null_
, notNull
, "null != <Opaque>");
399 extern(C
++) static interface Stuff
{}
400 scope Stuff stuff
= new class Stuff
{};
401 test(stuff
, Stuff
.init
, "Stuff() != null");
412 auto s1
= shared Small(1);
413 const s2
= shared Small(2);
414 test(s1
, s2
, "Small(1) != Small(2)");
421 auto b1
= shared Big([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
422 const b2
= shared Big();
423 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])");
425 // Sanity check: Big shouldn't be supported by atomicLoad
426 import core
.atomic
: atomicLoad
;
427 static assert( __traits(compiles
, atomicLoad(s1
)));
428 static assert(!__traits(compiles
, atomicLoad(b1
)));
434 @safe pure nothrow @nogc:
435 bool opCast () shared const scope { return true; }
438 shared Fail fail
= { value
: 1 };
439 assert(_d_assert_fail
!(shared Fail
)("==", fail
) == "Fail(1) != true");
440 assert(_d_assert_fail
!(shared Fail
)("==", fail
, fail
) == "Fail(1) != Fail(1)");
445 static struct MayThrow
451 throw new Exception("Error");
452 return "Some message";
456 test(MayThrow(0), MayThrow(1), `Some message != <toString() failed: "Error", called on MayThrow(1)>`);
459 void testOverlappingFields()
466 immutable(char)[] name
;
470 test(S(1.0), S(2.0), "S(<overlapped field>, <overlapped field>) != S(<overlapped field>, <overlapped field>)");
478 immutable(char)[] name
;
482 test(S2(4, 1.0), S2(5, 2.0), "S2(4, <overlapped field>, <overlapped field>) != S2(5, <overlapped field>, <overlapped field>)");
489 immutable(char)[] name
;
502 test(a
, b
, "S3(<overlapped field>, <overlapped field>, 8) != S3(<overlapped field>, <overlapped field>, 8)");
505 void testDestruction()
509 __gshared string unary
, binary
;
515 unary
= _d_assert_fail
!int("", 1);
516 binary
= _d_assert_fail
!int("==", 1, 2);
520 static void createGarbage()
526 import core
.memory
: GC
;
531 assert(Test
.unary
== "Assertion failed (rich formatting is disabled in finalizers)");
532 assert(Test
.binary
== "Assertion failed (rich formatting is disabled in finalizers)");
538 testIntegerComparisons();
563 testContextPointer();
567 testOverlappingFields();
572 fprintf(stderr
, "success.\n");
576 enum forceCTFE
= main();