mirror of
https://review.haiku-os.org/buildtools
synced 2025-02-06 22:04:45 +01:00
Updated dependencies: * GMP 6.2.1 * ISL 0.24 * MPL 1.2.1 * MPFR 4.1.0 The dependencies were pulled in by running the ./contrib/download_prerequisites script and then manually removing the symbolic links and archives, and renaming the directories (i.e mv isl-0.24 to isl)
577 lines
13 KiB
D
577 lines
13 KiB
D
import core.stdc.stdio : fprintf, stderr;
|
|
import core.internal.dassert : _d_assert_fail;
|
|
|
|
void test(string comp = "==", A, B)(A a, B b, string msg, size_t line = __LINE__)
|
|
{
|
|
test(_d_assert_fail!(A)(comp, a, b), msg, line);
|
|
}
|
|
|
|
void test(const string actual, const string expected, size_t line = __LINE__)
|
|
{
|
|
import core.exception : AssertError;
|
|
|
|
if (actual != expected)
|
|
{
|
|
const msg = "Mismatch!\nExpected: <" ~ expected ~ ">\nActual: <" ~ actual ~ '>';
|
|
throw new AssertError(msg, __FILE__, line);
|
|
}
|
|
}
|
|
|
|
void testIntegers()
|
|
{
|
|
test(1, 2, "1 != 2");
|
|
test(-10, 8, "-10 != 8");
|
|
test(byte.min, byte.max, "-128 != 127");
|
|
test(ubyte.min, ubyte.max, "0 != 255");
|
|
test(short.min, short.max, "-32768 != 32767");
|
|
test(ushort.min, ushort.max, "0 != 65535");
|
|
test(int.min, int.max, "-2147483648 != 2147483647");
|
|
test(uint.min, uint.max, "0 != 4294967295");
|
|
test(long.min, long.max, "-9223372036854775808 != 9223372036854775807");
|
|
test(ulong.min, ulong.max, "0 != 18446744073709551615");
|
|
test(shared(ulong).min, shared(ulong).max, "0 != 18446744073709551615");
|
|
|
|
int testFun() { return 1; }
|
|
test(testFun(), 2, "1 != 2");
|
|
}
|
|
|
|
void testIntegerComparisons()
|
|
{
|
|
test!"!="(2, 2, "2 == 2");
|
|
test!"<"(2, 1, "2 >= 1");
|
|
test!"<="(2, 1, "2 > 1");
|
|
test!">"(1, 2, "1 <= 2");
|
|
test!">="(1, 2, "1 < 2");
|
|
}
|
|
|
|
void testFloatingPoint()
|
|
{
|
|
if (__ctfe)
|
|
{
|
|
test(float.max, -float.max, "<float not supported> != <float not supported>");
|
|
test(double.max, -double.max, "<double not supported> != <double not supported>");
|
|
test(real(1), real(-1), "<real not supported> != <real not supported>");
|
|
}
|
|
else
|
|
{
|
|
test(1.5, 2.5, "1.5 != 2.5");
|
|
test(float.max, -float.max, "3.40282e+38 != -3.40282e+38");
|
|
test(double.max, -double.max, "1.79769e+308 != -1.79769e+308");
|
|
test(real(1), real(-1), "1 != -1");
|
|
}
|
|
}
|
|
|
|
void testPointers()
|
|
{
|
|
static struct S
|
|
{
|
|
string toString() const { return "S(...)"; }
|
|
}
|
|
|
|
static if ((void*).sizeof == 4)
|
|
enum ptr = "0x12345670";
|
|
else
|
|
enum ptr = "0x123456789abcdef0";
|
|
|
|
int* p = cast(int*) mixin(ptr);
|
|
test(cast(S*) p, p, ptr ~ " != " ~ ptr);
|
|
}
|
|
|
|
void testStrings()
|
|
{
|
|
test("foo", "bar", `"foo" != "bar"`);
|
|
test("", "bar", `"" != "bar"`);
|
|
|
|
char[] dlang = "dlang".dup;
|
|
const(char)[] rust = "rust";
|
|
test(dlang, rust, `"dlang" != "rust"`);
|
|
|
|
// https://issues.dlang.org/show_bug.cgi?id=20322
|
|
test("left"w, "right"w, `"left" != "right"`);
|
|
test("left"d, "right"d, `"left" != "right"`);
|
|
|
|
test('A', 'B', "'A' != 'B'");
|
|
test(wchar('❤'), wchar('∑'), "'❤' != '∑'");
|
|
test(dchar('❤'), dchar('∑'), "'❤' != '∑'");
|
|
|
|
// Detect invalid code points
|
|
test(char(255), 'B', "cast(char) 255 != 'B'");
|
|
test(wchar(0xD888), wchar('∑'), "cast(wchar) 55432 != '∑'");
|
|
test(dchar(0xDDDD), dchar('∑'), "cast(dchar) 56797 != '∑'");
|
|
}
|
|
|
|
void testToString()
|
|
{
|
|
class Foo
|
|
{
|
|
this(string payload) {
|
|
this.payload = payload;
|
|
}
|
|
|
|
string payload;
|
|
override string toString() {
|
|
return "Foo(" ~ payload ~ ")";
|
|
}
|
|
}
|
|
test(new Foo("a"), new Foo("b"), "Foo(a) != Foo(b)");
|
|
|
|
scope f = cast(shared) new Foo("a");
|
|
if (!__ctfe) // Ref somehow get's lost in CTFE
|
|
test!"!="(f, f, "Foo(a) == Foo(a)");
|
|
|
|
// Verifiy that the const toString is selected if present
|
|
static struct Overloaded
|
|
{
|
|
string toString()
|
|
{
|
|
return "Mutable";
|
|
}
|
|
|
|
string toString() const
|
|
{
|
|
return "Const";
|
|
}
|
|
}
|
|
|
|
test!"!="(Overloaded(), Overloaded(), "Const == Const");
|
|
|
|
Foo fnull = null;
|
|
test!"!is"(fnull, fnull, "`null` is `null`");
|
|
}
|
|
|
|
|
|
void testArray()
|
|
{
|
|
test([1], [0], "[1] != [0]");
|
|
test([1, 2, 3], [0], "[1, 2, 3] != [0]");
|
|
|
|
// test with long arrays
|
|
int[] arr;
|
|
foreach (i; 0 .. 100)
|
|
arr ~= i;
|
|
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]");
|
|
|
|
// Ignore fake arrays
|
|
static struct S
|
|
{
|
|
int[2] arr;
|
|
int[] get() return { return arr[]; }
|
|
alias get this;
|
|
}
|
|
|
|
const a = S([1, 2]);
|
|
test(a, S([3, 4]), "S([1, 2]) != S([3, 4])");
|
|
}
|
|
|
|
void testStruct()
|
|
{
|
|
struct S { int s; }
|
|
struct T { T[] t; }
|
|
test(S(0), S(1), "S(0) != S(1)");
|
|
test(T([T(null)]), T(null), "T([T([])]) != T([])");
|
|
|
|
// https://issues.dlang.org/show_bug.cgi?id=20323
|
|
static struct NoCopy
|
|
{
|
|
@disable this(this);
|
|
}
|
|
|
|
NoCopy n;
|
|
test(_d_assert_fail!(typeof(n))("!=", n, n), "NoCopy() == NoCopy()");
|
|
|
|
shared NoCopy sn;
|
|
test(_d_assert_fail!(typeof(sn))("!=", sn, sn), "NoCopy() == NoCopy()");
|
|
}
|
|
|
|
void testAA()
|
|
{
|
|
test([1:"one"], [2: "two"], `[1: "one"] != [2: "two"]`);
|
|
test!"in"(1, [2: 3], "1 !in [2: 3]");
|
|
test!"in"("foo", ["bar": true], `"foo" !in ["bar": true]`);
|
|
}
|
|
|
|
void testAttributes() @safe pure @nogc nothrow
|
|
{
|
|
int a;
|
|
string s = _d_assert_fail!(int, char)("==", a, 'c', 1, 'd');
|
|
assert(s == `(0, 'c') != (1, 'd')`);
|
|
|
|
string s2 = _d_assert_fail!int("", a);
|
|
assert(s2 == `0 != true`);
|
|
}
|
|
|
|
// https://issues.dlang.org/show_bug.cgi?id=20066
|
|
void testVoidArray()
|
|
{
|
|
test!"!is"([], null, (__ctfe ? "<void[] not supported>" : "[]") ~ " is `null`");
|
|
test!"!is"(null, null, "`null` is `null`");
|
|
test([1], null, "[1] != `null`");
|
|
test("s", null, "\"s\" != `null`");
|
|
test(['c'], null, "\"c\" != `null`");
|
|
test!"!="(null, null, "`null` == `null`");
|
|
|
|
const void[] chunk = [byte(1), byte(2), byte(3)];
|
|
test(chunk, null, (__ctfe ? "<void[] not supported>" : "[1, 2, 3]") ~ " != `null`");
|
|
}
|
|
|
|
void testTemporary()
|
|
{
|
|
static struct Bad
|
|
{
|
|
~this() @system {}
|
|
}
|
|
|
|
test!"!="(Bad(), Bad(), "Bad() == Bad()");
|
|
}
|
|
|
|
void testEnum()
|
|
{
|
|
static struct UUID {
|
|
union
|
|
{
|
|
ubyte[] data = [1];
|
|
}
|
|
}
|
|
|
|
ubyte[] data;
|
|
enum ctfe = UUID();
|
|
test(_d_assert_fail!(ubyte[])("==", ctfe.data, data), "[1] != []");
|
|
}
|
|
|
|
void testUnary()
|
|
{
|
|
test(_d_assert_fail!int("", 9), "9 != true");
|
|
test(_d_assert_fail!(int[])("!", [1, 2, 3]), "[1, 2, 3] == true");
|
|
}
|
|
|
|
void testTuple()
|
|
{
|
|
test(_d_assert_fail("=="), "() != ()");
|
|
test(_d_assert_fail("!="), "() == ()");
|
|
test(_d_assert_fail(">="), "() < ()");
|
|
}
|
|
|
|
void testStructEquals()
|
|
{
|
|
struct T {
|
|
bool b;
|
|
int i;
|
|
float f1 = 2.5;
|
|
float f2 = 0;
|
|
string s1 = "bar";
|
|
string s2;
|
|
}
|
|
|
|
T t1;
|
|
test!"!="(t1, t1, `T(false, 0, 2.5, 0, "bar", "") == T(false, 0, 2.5, 0, "bar", "")`);
|
|
T t2 = {s1: "bari"};
|
|
test(t1, t2, `T(false, 0, 2.5, 0, "bar", "") != T(false, 0, 2.5, 0, "bari", "")`);
|
|
}
|
|
|
|
void testStructEquals2()
|
|
{
|
|
struct T {
|
|
bool b;
|
|
int i;
|
|
float f1 = 2.5;
|
|
float f2 = 0;
|
|
}
|
|
|
|
T t1;
|
|
test!"!="(t1, t1, `T(false, 0, 2.5, 0) == T(false, 0, 2.5, 0)`);
|
|
T t2 = {i: 2};
|
|
test(t1, t2, `T(false, 0, 2.5, 0) != T(false, 2, 2.5, 0)`);
|
|
}
|
|
|
|
void testStructEquals3()
|
|
{
|
|
struct T {
|
|
bool b;
|
|
int i;
|
|
string s1 = "bar";
|
|
string s2;
|
|
}
|
|
|
|
T t1;
|
|
test!"!="(t1, t1, `T(false, 0, "bar", "") == T(false, 0, "bar", "")`);
|
|
T t2 = {s1: "bari"};
|
|
test(t1, t2, `T(false, 0, "bar", "") != T(false, 0, "bari", "")`);
|
|
}
|
|
|
|
void testStructEquals4()
|
|
{
|
|
struct T {
|
|
float f1 = 2.5;
|
|
float f2 = 0;
|
|
string s1 = "bar";
|
|
string s2;
|
|
}
|
|
|
|
T t1;
|
|
test!"!="(t1, t1, `T(2.5, 0, "bar", "") == T(2.5, 0, "bar", "")`);
|
|
T t2 = {s1: "bari"};
|
|
test(t1, t2, `T(2.5, 0, "bar", "") != T(2.5, 0, "bari", "")`);
|
|
}
|
|
|
|
void testStructEquals5()
|
|
{
|
|
struct T {
|
|
bool b;
|
|
int i;
|
|
float f2 = 0;
|
|
string s2;
|
|
}
|
|
|
|
T t1;
|
|
test!"!="(t1, t1, `T(false, 0, 0, "") == T(false, 0, 0, "")`);
|
|
T t2 = {b: true};
|
|
test(t1, t2, `T(false, 0, 0, "") != T(true, 0, 0, "")`);
|
|
}
|
|
|
|
void testStructEquals6()
|
|
{
|
|
class C { override string toString() { return "C()"; }}
|
|
struct T {
|
|
bool b;
|
|
int i;
|
|
float f2 = 0;
|
|
string s2;
|
|
int[] arr;
|
|
C c;
|
|
}
|
|
|
|
T t1;
|
|
test!"!="(t1, t1, "T(false, 0, 0, \"\", [], `null`) == T(false, 0, 0, \"\", [], `null`)");
|
|
T t2 = {arr: [1]};
|
|
test(t1, t2, "T(false, 0, 0, \"\", [], `null`) != T(false, 0, 0, \"\", [1], `null`)");
|
|
T t3 = {c: new C()};
|
|
test(t1, t3, "T(false, 0, 0, \"\", [], `null`) != T(false, 0, 0, \"\", [], C())");
|
|
}
|
|
|
|
void testContextPointer()
|
|
{
|
|
int i;
|
|
struct T
|
|
{
|
|
int j;
|
|
int get()
|
|
{
|
|
return i * j;
|
|
}
|
|
}
|
|
T t = T(1);
|
|
t.tupleof[$-1] = cast(void*) 0xABCD; // Deterministic context pointer
|
|
test(t, t, `T(1, <context>: 0xabcd) != T(1, <context>: 0xabcd)`);
|
|
}
|
|
|
|
void testExternClasses()
|
|
{
|
|
{
|
|
extern(C++) static class Cpp
|
|
{
|
|
int a;
|
|
this(int a) { this.a = a; }
|
|
}
|
|
scope a = new Cpp(1);
|
|
scope b = new Cpp(2);
|
|
test(a, b, "Cpp(1) != Cpp(2)");
|
|
test(a, Cpp.init, "Cpp(1) != null");
|
|
}
|
|
{
|
|
extern(C++) static class CppToString
|
|
{
|
|
int a;
|
|
this(int a) { this.a = a; }
|
|
extern(D) string toString() const { return a == 0 ? "hello" : "world"; }
|
|
}
|
|
scope a = new CppToString(0);
|
|
scope b = new CppToString(1);
|
|
test(a, b, "hello != world");
|
|
}
|
|
if (!__ctfe)
|
|
{
|
|
extern(C++) static class Opaque;
|
|
Opaque null_ = null;
|
|
Opaque notNull = cast(Opaque) &null_;
|
|
test(null_, notNull, "null != <Opaque>");
|
|
}
|
|
{
|
|
extern(C++) static interface Stuff {}
|
|
scope Stuff stuff = new class Stuff {};
|
|
test(stuff, Stuff.init, "Stuff() != null");
|
|
}
|
|
}
|
|
|
|
void testShared()
|
|
{
|
|
static struct Small
|
|
{
|
|
int i;
|
|
}
|
|
|
|
auto s1 = shared Small(1);
|
|
const s2 = shared Small(2);
|
|
test(s1, s2, "Small(1) != Small(2)");
|
|
|
|
static struct Big
|
|
{
|
|
long[10] l;
|
|
}
|
|
|
|
auto b1 = shared Big([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
|
|
const b2 = shared Big();
|
|
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])");
|
|
|
|
// Sanity check: Big shouldn't be supported by atomicLoad
|
|
import core.atomic : atomicLoad;
|
|
static assert( __traits(compiles, atomicLoad(s1)));
|
|
static assert(!__traits(compiles, atomicLoad(b1)));
|
|
|
|
static struct Fail
|
|
{
|
|
int value;
|
|
|
|
@safe pure nothrow @nogc:
|
|
bool opCast () shared const scope { return true; }
|
|
}
|
|
|
|
shared Fail fail = { value: 1 };
|
|
assert(_d_assert_fail!(shared Fail)("==", fail) == "Fail(1) != true");
|
|
assert(_d_assert_fail!(shared Fail)("==", fail, fail) == "Fail(1) != Fail(1)");
|
|
}
|
|
|
|
void testException()
|
|
{
|
|
static struct MayThrow
|
|
{
|
|
int i;
|
|
string toString()
|
|
{
|
|
if (i == 1)
|
|
throw new Exception("Error");
|
|
return "Some message";
|
|
}
|
|
}
|
|
|
|
test(MayThrow(0), MayThrow(1), `Some message != <toString() failed: "Error", called on MayThrow(1)>`);
|
|
}
|
|
|
|
void testOverlappingFields()
|
|
{
|
|
static struct S
|
|
{
|
|
union
|
|
{
|
|
double num;
|
|
immutable(char)[] name;
|
|
}
|
|
}
|
|
|
|
test(S(1.0), S(2.0), "S(<overlapped field>, <overlapped field>) != S(<overlapped field>, <overlapped field>)");
|
|
|
|
static struct S2
|
|
{
|
|
int valid;
|
|
union
|
|
{
|
|
double num;
|
|
immutable(char)[] name;
|
|
}
|
|
}
|
|
|
|
test(S2(4, 1.0), S2(5, 2.0), "S2(4, <overlapped field>, <overlapped field>) != S2(5, <overlapped field>, <overlapped field>)");
|
|
|
|
static struct S3
|
|
{
|
|
union
|
|
{
|
|
double num;
|
|
immutable(char)[] name;
|
|
}
|
|
int valid;
|
|
}
|
|
S3 a = {
|
|
num: 1.0,
|
|
valid: 8
|
|
};
|
|
|
|
S3 b = {
|
|
num: 1.0,
|
|
valid: 8
|
|
};
|
|
test(a, b, "S3(<overlapped field>, <overlapped field>, 8) != S3(<overlapped field>, <overlapped field>, 8)");
|
|
}
|
|
|
|
void testDestruction()
|
|
{
|
|
static class Test
|
|
{
|
|
__gshared string unary, binary;
|
|
__gshared bool run;
|
|
|
|
~this()
|
|
{
|
|
run = true;
|
|
unary = _d_assert_fail!int("", 1);
|
|
binary = _d_assert_fail!int("==", 1, 2);
|
|
}
|
|
}
|
|
|
|
static void createGarbage()
|
|
{
|
|
new Test();
|
|
new long[100];
|
|
}
|
|
|
|
import core.memory : GC;
|
|
createGarbage();
|
|
GC.collect();
|
|
|
|
assert(Test.run);
|
|
assert(Test.unary == "Assertion failed (rich formatting is disabled in finalizers)");
|
|
assert(Test.binary == "Assertion failed (rich formatting is disabled in finalizers)");
|
|
}
|
|
|
|
int main()
|
|
{
|
|
testIntegers();
|
|
testIntegerComparisons();
|
|
testFloatingPoint();
|
|
testPointers();
|
|
testStrings();
|
|
testToString();
|
|
testArray();
|
|
testStruct();
|
|
testAA();
|
|
testAttributes();
|
|
testVoidArray();
|
|
testTemporary();
|
|
testEnum();
|
|
testUnary();
|
|
testTuple();
|
|
if (!__ctfe)
|
|
testStructEquals();
|
|
if (!__ctfe)
|
|
testStructEquals2();
|
|
testStructEquals3();
|
|
if (!__ctfe)
|
|
testStructEquals4();
|
|
if (!__ctfe)
|
|
testStructEquals5();
|
|
if (!__ctfe)
|
|
testStructEquals6();
|
|
testContextPointer();
|
|
testExternClasses();
|
|
testShared();
|
|
testException();
|
|
testOverlappingFields();
|
|
if (!__ctfe)
|
|
testDestruction();
|
|
|
|
if (!__ctfe)
|
|
fprintf(stderr, "success.\n");
|
|
return 0;
|
|
}
|
|
|
|
enum forceCTFE = main();
|