Separate non-documentation tests from the code

This commit is contained in:
Eugen Wissner 2019-03-18 13:03:52 +01:00
parent 5ab99cf887
commit 484cb13317
43 changed files with 1020 additions and 989 deletions

View File

@ -53,19 +53,21 @@ script:
dub build :sys -b ddox --compiler=$DC; dub build :sys -b ddox --compiler=$DC;
dub build :os -b ddox --compiler=$DC; dub build :os -b ddox --compiler=$DC;
dub build :encoding -b ddox --compiler=$DC; dub build :encoding -b ddox --compiler=$DC;
dub build :memory -b ddox --compiler=$DC; dub build :middle -b ddox --compiler=$DC;
dub build :test -b ddox --compiler=$DC;
dub build -b ddox --compiler=$DC; dub build -b ddox --compiler=$DC;
elif [ -z "$DSCANNER" ]; then elif [ -z "$DSCANNER" ]; then
dub test :meta -b ${UNITTEST:-unittest} --arch=$ARCH --compiler=$DC; dub test :meta -b ${UNITTEST:-unittest} --arch=$ARCH --compiler=$DC;
dub test :sys -b ${UNITTEST:-unittest} --arch=$ARCH --compiler=$DC; dub test :sys -b ${UNITTEST:-unittest} --arch=$ARCH --compiler=$DC;
dub test :os -b ${UNITTEST:-unittest} --arch=$ARCH --compiler=$DC; dub test :os -b ${UNITTEST:-unittest} --arch=$ARCH --compiler=$DC;
dub test :encoding -b ${UNITTEST:-unittest} --arch=$ARCH --compiler=$DC; dub test :encoding -b ${UNITTEST:-unittest} --arch=$ARCH --compiler=$DC;
dub test :memory -b ${UNITTEST:-unittest} --arch=$ARCH --compiler=$DC; dub test :middle -b ${UNITTEST:-unittest} --arch=$ARCH --compiler=$DC;
dub test :test -b ${UNITTEST:-unittest} --arch=$ARCH --compiler=$DC;
dub test -b ${UNITTEST:-unittest} --arch=$ARCH --compiler=$DC; dub test -b ${UNITTEST:-unittest} --arch=$ARCH --compiler=$DC;
else else
dub fetch dscanner --version=$DSCANNER; dub fetch dscanner --version=$DSCANNER;
FILES=$(find source */source -type f); FILES=$(find */tanya -type f);
dub run dscanner -- --styleCheck $FILES; dub run dscanner -- --styleCheck $FILES;
fi fi

View File

@ -61,5 +61,6 @@ test_script:
- dub test :sys -b unittest --arch=%Darch% --compiler=%DC% - dub test :sys -b unittest --arch=%Darch% --compiler=%DC%
- dub test :os -b unittest --arch=%Darch% --compiler=%DC% - dub test :os -b unittest --arch=%Darch% --compiler=%DC%
- dub test :encoding -b unittest --arch=%Darch% --compiler=%DC% - dub test :encoding -b unittest --arch=%Darch% --compiler=%DC%
- dub test :memory -b unittest --arch=%Darch% --compiler=%DC% - dub test :middle -b unittest --arch=%Darch% --compiler=%DC%
- dub test :test -b unittest --arch=%Darch% --compiler=%DC%
- dub test -b unittest --arch=%Darch% --compiler=%DC% - dub test -b unittest --arch=%Darch% --compiler=%DC%

View File

@ -14,7 +14,8 @@
"tanya:sys": "*", "tanya:sys": "*",
"tanya:os": "*", "tanya:os": "*",
"tanya:encoding": "*", "tanya:encoding": "*",
"tanya:memory": "*" "tanya:middle": "*",
"tanya:test": "*"
}, },
"dependencies-linux": { "dependencies-linux": {
@ -26,7 +27,8 @@
"./sys", "./sys",
"./os", "./os",
"./encoding", "./encoding",
"./memory" "./middle",
"./test"
], ],
"configurations": [ "configurations": [
@ -47,6 +49,17 @@
"preBuildCommands": ["ninja -C arch"], "preBuildCommands": ["ninja -C arch"],
"lflags": ["arch/tanya.a"], "lflags": ["arch/tanya.a"],
"versions": ["TanyaNative"] "versions": ["TanyaNative"]
},
{
"name": "unittest",
"importPaths": [
"./source",
"./tests"
],
"sourcePaths": [
"./source",
"./tests"
]
} }
], ],

View File

@ -1129,30 +1129,6 @@ if (__traits(isTemplate, cmp))
static assert(!isSorted!(cmp, long, byte, ubyte, short, uint)); static assert(!isSorted!(cmp, long, byte, ubyte, short, uint));
} }
@nogc nothrow pure @safe unittest
{
enum cmp(int x, int y) = x - y;
static assert(isSorted!(cmp));
static assert(isSorted!(cmp, 1));
static assert(isSorted!(cmp, 1, 2, 2));
static assert(isSorted!(cmp, 1, 2, 2, 4));
static assert(isSorted!(cmp, 1, 2, 2, 4, 8));
static assert(!isSorted!(cmp, 32, 2, 2, 4, 8));
static assert(isSorted!(cmp, 32, 32));
}
@nogc nothrow pure @safe unittest
{
enum cmp(int x, int y) = x < y;
static assert(isSorted!(cmp));
static assert(isSorted!(cmp, 1));
static assert(isSorted!(cmp, 1, 2, 2));
static assert(isSorted!(cmp, 1, 2, 2, 4));
static assert(isSorted!(cmp, 1, 2, 2, 4, 8));
static assert(!isSorted!(cmp, 32, 2, 2, 4, 8));
static assert(isSorted!(cmp, 32, 32));
}
/** /**
* Params: * Params:
* T = A template. * T = A template.

View File

@ -549,19 +549,6 @@ template isPointer(T)
static assert(!isPointer!bool); static assert(!isPointer!bool);
} }
// typeof(null) is not a pointer.
@nogc nothrow pure @safe unittest
{
static assert(!isPointer!(typeof(null)));
static assert(!isPointer!(const shared typeof(null)));
enum typeOfNull : typeof(null)
{
null_ = null,
}
static assert(!isPointer!typeOfNull);
}
/** /**
* Determines whether $(D_PARAM T) is an array type (dynamic or static, but * Determines whether $(D_PARAM T) is an array type (dynamic or static, but
* not an associative one). * not an associative one).
@ -1478,20 +1465,6 @@ if (F.length == 1)
static assert(!isCallable!I); static assert(!isCallable!I);
} }
@nogc nothrow pure @safe unittest
{
static struct S
{
@property int opCall()
{
return 0;
}
}
S s;
static assert(isCallable!S);
static assert(isCallable!s);
}
/** /**
* Determines whether $(D_PARAM T) defines a symbol $(D_PARAM member). * Determines whether $(D_PARAM T) defines a symbol $(D_PARAM member).
* *
@ -1676,63 +1649,6 @@ if (isCallable!F)
static assert(is(FunctionTypeOf!(() {}) == function)); static assert(is(FunctionTypeOf!(() {}) == function));
} }
@nogc nothrow pure @safe unittest
{
static assert(is(FunctionTypeOf!(void delegate()) == function));
static void staticFunc()
{
}
auto functionPointer = &staticFunc;
static assert(is(FunctionTypeOf!staticFunc == function));
static assert(is(FunctionTypeOf!functionPointer == function));
void func()
{
}
auto dg = &func;
static assert(is(FunctionTypeOf!func == function));
static assert(is(FunctionTypeOf!dg == function));
interface I
{
@property int prop();
}
static assert(is(FunctionTypeOf!(I.prop) == function));
static struct S
{
void opCall()
{
}
}
class C
{
static void opCall()
{
}
}
S s;
static assert(is(FunctionTypeOf!s == function));
static assert(is(FunctionTypeOf!C == function));
static assert(is(FunctionTypeOf!S == function));
}
@nogc nothrow pure @safe unittest
{
static struct S2
{
@property int opCall()
{
return 0;
}
}
S2 s2;
static assert(is(FunctionTypeOf!S2 == function));
static assert(is(FunctionTypeOf!s2 == function));
}
/** /**
* Determines the return type of the callable $(D_PARAM F). * Determines the return type of the callable $(D_PARAM F).
* *
@ -2552,44 +2468,6 @@ template hasElaborateAssign(T)
} }
} }
@nogc nothrow pure @safe unittest
{
static assert(!hasElaborateAssign!int);
static struct S1
{
void opAssign(S1)
{
}
}
static struct S2
{
void opAssign(int)
{
}
}
static struct S3
{
S1 s;
alias s this;
}
static assert(hasElaborateAssign!S1);
static assert(!hasElaborateAssign!(const S1));
static assert(hasElaborateAssign!(S1[1]));
static assert(!hasElaborateAssign!(S1[0]));
static assert(!hasElaborateAssign!S2);
static assert(hasElaborateAssign!S3);
static struct S4
{
void opAssign(S4)
{
}
@disable this(this);
}
static assert(hasElaborateAssign!S4);
}
/** /**
* Returns all members of $(D_KEYWORD enum) $(D_PARAM T). * Returns all members of $(D_KEYWORD enum) $(D_PARAM T).
* *
@ -2642,16 +2520,6 @@ if (is(T == enum))
static assert([EnumMembers!E] == [E.one, E.two, E.three]); static assert([EnumMembers!E] == [E.one, E.two, E.three]);
} }
// Produces a tuple for an enum with only one member
@nogc nothrow pure @safe unittest
{
enum E : int
{
one = 0,
}
static assert(EnumMembers!E == AliasSeq!0);
}
/** /**
* Different than $(D_INLINECODE T.alignof), which is the same for all class * Different than $(D_INLINECODE T.alignof), which is the same for all class
* types, $(D_PSYMBOL classInstanceOf) determines the alignment of the class * types, $(D_PSYMBOL classInstanceOf) determines the alignment of the class
@ -2996,14 +2864,6 @@ template isInnerClass(T)
static assert(!isInnerClass!(O.Fake)); static assert(!isInnerClass!(O.Fake));
} }
@nogc nothrow pure @safe unittest
{
class RefCountedStore(T)
{
}
static assert(!isInnerClass!(RefCountedStore!int));
}
/** /**
* Returns the types of all members of $(D_PARAM T). * Returns the types of all members of $(D_PARAM T).
* *
@ -3131,28 +2991,3 @@ enum bool isOrderingComparable(T) = ifTestable!(T, a => a > a);
{ {
static assert(isOrderingComparable!int); static assert(isOrderingComparable!int);
} }
@nogc nothrow pure @safe unittest
{
static struct DisabledOpEquals
{
@disable bool opEquals(typeof(this)) @nogc nothrow pure @safe;
int opCmp(typeof(this)) @nogc nothrow pure @safe
{
return 0;
}
}
static assert(!isEqualityComparable!DisabledOpEquals);
static assert(isOrderingComparable!DisabledOpEquals);
static struct OpEquals
{
bool opEquals(typeof(this)) @nogc nothrow pure @safe
{
return true;
}
}
static assert(isEqualityComparable!OpEquals);
static assert(!isOrderingComparable!OpEquals);
}

View File

@ -855,53 +855,6 @@ if (allSatisfy!(isType, Args))
static assert(is(CommonType!(const A, Object) == const Object)); static assert(is(CommonType!(const A, Object) == const Object));
} }
@nogc nothrow pure @safe unittest
{
static assert(is(CommonType!(void*, int*) == void*));
static assert(is(CommonType!(void*, const(int)*) == const(void)*));
static assert(is(CommonType!(void*, const(void)*) == const(void)*));
static assert(is(CommonType!(int*, void*) == void*));
static assert(is(CommonType!(const(int)*, void*) == const(void)*));
static assert(is(CommonType!(const(void)*, void*) == const(void)*));
static assert(is(CommonType!() == void));
static assert(is(CommonType!(int*, const(int)*) == const(int)*));
static assert(is(CommonType!(int**, const(int)**) == const(int*)*));
static assert(is(CommonType!(float, double) == double));
static assert(is(CommonType!(float, int) == void));
static assert(is(CommonType!(bool, const bool) == bool));
static assert(is(CommonType!(int, bool) == void));
static assert(is(CommonType!(int, void) == void));
static assert(is(CommonType!(Object, void*) == void));
class A
{
}
static assert(is(CommonType!(A, Object) == Object));
static assert(is(CommonType!(const(A)*, Object*) == const(Object)*));
static assert(is(CommonType!(A, typeof(null)) == A));
class B : A
{
}
class C : A
{
}
static assert(is(CommonType!(B, C) == A));
static struct S
{
int opCast(T : int)()
{
return 1;
}
}
static assert(is(CommonType!(S, int) == void));
static assert(is(CommonType!(const S, S) == const S));
}
/** /**
* Finds the type with the smallest size in the $(D_PARAM Args) list. If * Finds the type with the smallest size in the $(D_PARAM Args) list. If
* several types have the same type, the leftmost is returned. * several types have the same type, the leftmost is returned.

View File

@ -1,6 +1,6 @@
{ {
"name": "memory", "name": "middle",
"description": "Tools for manual memory management (allocators, smart pointers)", "description": "Runtime, middle-level utilities",
"targetType": "library", "targetType": "library",
"dependencies": { "dependencies": {
@ -9,6 +9,10 @@
"tanya:sys": "*" "tanya:sys": "*"
}, },
"dependencies-linux": {
"mir-linux-kernel": "~>1.0.0"
},
"sourcePaths": [ "sourcePaths": [
"." "."
], ],

View File

@ -12,7 +12,7 @@
* License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/, * License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
* Mozilla Public License, v. 2.0). * Mozilla Public License, v. 2.0).
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner) * Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
* Source: $(LINK2 https://github.com/caraus-ecms/tanya/blob/master/memory/tanya/memory/allocator.d, * Source: $(LINK2 https://github.com/caraus-ecms/tanya/blob/master/middle/tanya/memory/allocator.d,
* tanya/memory/allocator.d) * tanya/memory/allocator.d)
*/ */
module tanya.memory.allocator; module tanya.memory.allocator;

View File

@ -3,22 +3,21 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/** /**
* Lifecycle management functions, types and related exceptions. * Lifetime management functions, types and related exceptions.
* *
* Copyright: Eugene Wissner 2019. * Copyright: Eugene Wissner 2019.
* License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/, * License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
* Mozilla Public License, v. 2.0). * Mozilla Public License, v. 2.0).
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner) * Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
* Source: $(LINK2 https://github.com/caraus-ecms/tanya/blob/master/memory/tanya/memory/lifecycle.d, * Source: $(LINK2 https://github.com/caraus-ecms/tanya/blob/master/middle/tanya/memory/lifetime.d,
* tanya/memory/lifecycle.d) * tanya/memory/lifetime.d)
*/ */
module tanya.memory.lifecycle; module tanya.memory.lifetime;
import tanya.memory : defaultAllocator; import tanya.memory : defaultAllocator;
import tanya.memory.allocator; import tanya.memory.allocator;
import tanya.meta.trait;
import tanya.meta.metafunction; import tanya.meta.metafunction;
version (unittest) import tanya.test.stub; import tanya.meta.trait;
/** /**
* Error thrown if memory allocation fails. * Error thrown if memory allocation fails.
@ -114,23 +113,6 @@ package(tanya) T[] resize(T)(shared Allocator allocator,
return array; return array;
} }
@nogc nothrow pure @safe unittest
{
int[] p;
p = defaultAllocator.resize(p, 20);
assert(p.length == 20);
p = defaultAllocator.resize(p, 30);
assert(p.length == 30);
p = defaultAllocator.resize(p, 10);
assert(p.length == 10);
p = defaultAllocator.resize(p, 0);
assert(p is null);
}
/* /*
* Destroys the object. * Destroys the object.
* Returns the memory should be freed. * Returns the memory should be freed.
@ -236,35 +218,6 @@ void dispose(T)(shared Allocator allocator, auto ref T p)
p = null; p = null;
} }
@nogc nothrow pure @system unittest
{
static struct S
{
~this() @nogc nothrow pure @safe
{
}
}
auto p = cast(S[]) defaultAllocator.allocate(S.sizeof);
defaultAllocator.dispose(p);
}
// Works with interfaces.
@nogc nothrow pure @safe unittest
{
interface I
{
}
class C : I
{
}
auto c = defaultAllocator.make!C();
I i = c;
defaultAllocator.dispose(i);
defaultAllocator.dispose(i);
}
/** /**
* Constructs a new class instance of type $(D_PARAM T) using $(D_PARAM args) * Constructs a new class instance of type $(D_PARAM T) using $(D_PARAM args)
* as the parameter list for the constructor of $(D_PARAM T). * as the parameter list for the constructor of $(D_PARAM T).
@ -583,71 +536,6 @@ out (result; memory.ptr is result)
assert(s.i == 8); assert(s.i == 8);
} }
// Handles "Cannot access frame pointer" error.
@nogc nothrow pure @safe unittest
{
struct F
{
~this() @nogc nothrow pure @safe
{
}
}
static assert(is(typeof(emplace!F((void[]).init))));
}
// Can emplace structs without a constructor
@nogc nothrow pure @safe unittest
{
static assert(is(typeof(emplace!WithDtor(null, WithDtor()))));
static assert(is(typeof(emplace!WithDtor(null))));
}
// Doesn't call a destructor on uninitialized elements
@nogc nothrow pure @system unittest
{
static struct SWithDtor
{
private bool canBeInvoked = false;
~this() @nogc nothrow pure @safe
{
assert(this.canBeInvoked);
}
}
void[SWithDtor.sizeof] memory = void;
auto actual = emplace!SWithDtor(memory[], SWithDtor(true));
assert(actual.canBeInvoked);
}
// Initializes structs if no arguments are given
@nogc nothrow pure @safe unittest
{
static struct SEntry
{
byte content;
}
ubyte[1] mem = [3];
assert(emplace!SEntry(cast(void[]) mem[0 .. 1]).content == 0);
}
// Postblit is called when emplacing a struct
@nogc nothrow pure @system unittest
{
static struct S
{
bool called = false;
this(this) @nogc nothrow pure @safe
{
this.called = true;
}
}
S target;
S* sp = &target;
emplace!S(sp[0 .. 1], S());
assert(target.called);
}
private void deinitialize(bool zero, T)(ref T value) private void deinitialize(bool zero, T)(ref T value)
{ {
static if (is(T == U[S], U, size_t S)) static if (is(T == U[S], U, size_t S))
@ -764,55 +652,6 @@ do
assert(x2 == 5); assert(x2 == 5);
} }
// Is pure.
@nogc nothrow pure @system unittest
{
struct S
{
this(this)
{
}
}
S source, target = void;
static assert(is(typeof({ moveEmplace(source, target); })));
}
// Moves nested.
@nogc nothrow pure @system unittest
{
struct Nested
{
void method() @nogc nothrow pure @safe
{
}
}
Nested source, target = void;
moveEmplace(source, target);
assert(source == target);
}
// Emplaces static arrays.
@nogc nothrow pure @system unittest
{
static struct S
{
size_t member;
this(size_t i) @nogc nothrow pure @safe
{
this.member = i;
}
~this() @nogc nothrow pure @safe
{
}
}
S[2] source = [ S(5), S(5) ], target = void;
moveEmplace(source, target);
assert(source[0].member == 0);
assert(target[0].member == 5);
assert(source[1].member == 0);
assert(target[1].member == 5);
}
/** /**
* Moves $(D_PARAM source) into $(D_PARAM target) assuming that * Moves $(D_PARAM source) into $(D_PARAM target) assuming that
* $(D_PARAM target) isn't initialized. * $(D_PARAM target) isn't initialized.
@ -888,14 +727,6 @@ T move(T)(ref T source) @trusted
assert(move(x2) == 5); assert(move(x2) == 5);
} }
// Moves if source is target.
@nogc nothrow pure @safe unittest
{
int x = 5;
move(x, x);
assert(x == 5);
}
/** /**
* Exchanges the values of $(D_PARAM a) and $(D_PARAM b). * Exchanges the values of $(D_PARAM a) and $(D_PARAM b).
* *

View File

@ -10,7 +10,7 @@
* License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/, * License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
* Mozilla Public License, v. 2.0). * Mozilla Public License, v. 2.0).
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner) * Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
* Source: $(LINK2 https://github.com/caraus-ecms/tanya/blob/master/memory/tanya/memory/mallocator.d, * Source: $(LINK2 https://github.com/caraus-ecms/tanya/blob/master/middle/tanya/memory/mallocator.d,
* tanya/memory/mallocator.d) * tanya/memory/mallocator.d)
*/ */
module tanya.memory.mallocator; module tanya.memory.mallocator;
@ -172,16 +172,6 @@ final class Mallocator : Allocator
assert(p is null); assert(p is null);
} }
// Fails with false
@nogc nothrow pure @system unittest
{
void[] p = Mallocator.instance.allocate(20);
void[] oldP = p;
assert(!Mallocator.instance.reallocate(p, size_t.max - Mallocator.psize * 2));
assert(oldP is p);
Mallocator.instance.deallocate(p);
}
/** /**
* Returns: The alignment offered. * Returns: The alignment offered.
*/ */
@ -190,11 +180,6 @@ final class Mallocator : Allocator
return (void*).alignof; return (void*).alignof;
} }
private nothrow @nogc unittest
{
assert(Mallocator.instance.alignment == (void*).alignof);
}
static private shared(Mallocator) instantiate() @nogc nothrow @system static private shared(Mallocator) instantiate() @nogc nothrow @system
{ {
if (instance_ is null) if (instance_ is null)

View File

@ -9,7 +9,7 @@
* License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/, * License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
* Mozilla Public License, v. 2.0). * Mozilla Public License, v. 2.0).
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner) * Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
* Source: $(LINK2 https://github.com/caraus-ecms/tanya/blob/master/memory/tanya/memory/mmappool.d, * Source: $(LINK2 https://github.com/caraus-ecms/tanya/blob/master/middle/tanya/memory/mmappool.d,
* tanya/memory/mmappool.d) * tanya/memory/mmappool.d)
*/ */
module tanya.memory.mmappool; module tanya.memory.mmappool;
@ -114,33 +114,6 @@ final class MmapPool : Allocator
return data is null ? null : data[0 .. size]; return data is null ? null : data[0 .. size];
} }
@nogc nothrow pure @system unittest
{
auto p = MmapPool.instance.allocate(20);
assert(p);
MmapPool.instance.deallocate(p);
p = MmapPool.instance.allocate(0);
assert(p.length == 0);
}
@nogc nothrow pure @system unittest
{
// allocate() check.
size_t tooMuchMemory = size_t.max
- MmapPool.alignment_
- BlockEntry.sizeof * 2
- RegionEntry.sizeof
- pageSize;
assert(MmapPool.instance.allocate(tooMuchMemory) is null);
assert(MmapPool.instance.allocate(size_t.max) is null);
// initializeRegion() check.
tooMuchMemory = size_t.max - MmapPool.alignment_;
assert(MmapPool.instance.allocate(tooMuchMemory) is null);
}
/* /*
* Search for a block large enough to keep $(D_PARAM size) and split it * Search for a block large enough to keep $(D_PARAM size) and split it
* into two blocks if the block is too large. * into two blocks if the block is too large.
@ -257,13 +230,6 @@ final class MmapPool : Allocator
return true; return true;
} }
@nogc nothrow pure @system unittest
{
auto p = MmapPool.instance.allocate(20);
assert(MmapPool.instance.deallocate(p));
}
/* /*
* Reallocates a memory block in place if possible or returns * Reallocates a memory block in place if possible or returns
* $(D_KEYWORD false). This function cannot be used to allocate or * $(D_KEYWORD false). This function cannot be used to allocate or
@ -340,30 +306,6 @@ final class MmapPool : Allocator
return true; return true;
} }
@nogc nothrow pure @system unittest
{
void[] p;
assert(!MmapPool.instance.reallocateInPlace(p, 5));
assert(p is null);
p = MmapPool.instance.allocate(1);
auto orig = p.ptr;
assert(MmapPool.instance.reallocateInPlace(p, 2));
assert(p.length == 2);
assert(p.ptr == orig);
assert(MmapPool.instance.reallocateInPlace(p, 4));
assert(p.length == 4);
assert(p.ptr == orig);
assert(MmapPool.instance.reallocateInPlace(p, 2));
assert(p.length == 2);
assert(p.ptr == orig);
MmapPool.instance.deallocate(p);
}
/* /*
* Increases or decreases the size of a memory block. * Increases or decreases the size of a memory block.
* *
@ -406,34 +348,6 @@ final class MmapPool : Allocator
return true; return true;
} }
@nogc nothrow pure @system unittest
{
void[] p;
MmapPool.instance.reallocate(p, 10 * int.sizeof);
(cast(int[]) p)[7] = 123;
assert(p.length == 40);
MmapPool.instance.reallocate(p, 8 * int.sizeof);
assert(p.length == 32);
assert((cast(int[]) p)[7] == 123);
MmapPool.instance.reallocate(p, 20 * int.sizeof);
(cast(int[]) p)[15] = 8;
assert(p.length == 80);
assert((cast(int[]) p)[15] == 8);
assert((cast(int[]) p)[7] == 123);
MmapPool.instance.reallocate(p, 8 * int.sizeof);
assert(p.length == 32);
assert((cast(int[]) p)[7] == 123);
MmapPool.instance.deallocate(p);
}
static private shared(MmapPool) instantiate() @nogc nothrow @system static private shared(MmapPool) instantiate() @nogc nothrow @system
{ {
if (instance_ is null) if (instance_ is null)
@ -463,11 +377,6 @@ final class MmapPool : Allocator
return (cast(GetPureInstance!MmapPool) &instantiate)(); return (cast(GetPureInstance!MmapPool) &instantiate)();
} }
@nogc nothrow pure @system unittest
{
assert(instance is instance);
}
/* /*
* Initializes a region for one element. * Initializes a region for one element.
* *
@ -565,11 +474,6 @@ final class MmapPool : Allocator
return alignment_; return alignment_;
} }
@nogc nothrow pure @system unittest
{
assert(MmapPool.instance.alignment == MmapPool.alignment_);
}
private enum uint alignment_ = 8; private enum uint alignment_ = 8;
private shared static MmapPool instance_; private shared static MmapPool instance_;
@ -597,61 +501,3 @@ final class MmapPool : Allocator
} }
private alias Block = shared BlockEntry*; private alias Block = shared BlockEntry*;
} }
// A lot of allocations/deallocations, but it is the minimum caused a
// segmentation fault because MmapPool reallocateInPlace moves a block wrong.
@nogc nothrow pure @system unittest
{
auto a = MmapPool.instance.allocate(16);
auto d = MmapPool.instance.allocate(16);
auto b = MmapPool.instance.allocate(16);
auto e = MmapPool.instance.allocate(16);
auto c = MmapPool.instance.allocate(16);
auto f = MmapPool.instance.allocate(16);
MmapPool.instance.deallocate(a);
MmapPool.instance.deallocate(b);
MmapPool.instance.deallocate(c);
a = MmapPool.instance.allocate(50);
MmapPool.instance.reallocateInPlace(a, 64);
MmapPool.instance.deallocate(a);
a = MmapPool.instance.allocate(1);
auto tmp1 = MmapPool.instance.allocate(1);
auto h1 = MmapPool.instance.allocate(1);
auto tmp2 = cast(ubyte[]) MmapPool.instance.allocate(1);
auto h2 = MmapPool.instance.allocate(2);
tmp1 = MmapPool.instance.allocate(1);
MmapPool.instance.deallocate(h2);
MmapPool.instance.deallocate(h1);
h2 = MmapPool.instance.allocate(2);
h1 = MmapPool.instance.allocate(1);
MmapPool.instance.deallocate(h2);
auto rep = cast(void[]) tmp2;
MmapPool.instance.reallocate(rep, tmp1.length);
tmp2 = cast(ubyte[]) rep;
MmapPool.instance.reallocate(tmp1, 9);
rep = cast(void[]) tmp2;
MmapPool.instance.reallocate(rep, tmp1.length);
tmp2 = cast(ubyte[]) rep;
MmapPool.instance.reallocate(tmp1, 17);
tmp2[$ - 1] = 0;
MmapPool.instance.deallocate(tmp1);
b = MmapPool.instance.allocate(16);
MmapPool.instance.deallocate(h1);
MmapPool.instance.deallocate(a);
MmapPool.instance.deallocate(b);
MmapPool.instance.deallocate(d);
MmapPool.instance.deallocate(e);
MmapPool.instance.deallocate(f);
}

View File

@ -9,7 +9,7 @@
* License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/, * License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
* Mozilla Public License, v. 2.0). * Mozilla Public License, v. 2.0).
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner) * Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
* Source: $(LINK2 https://github.com/caraus-ecms/tanya/blob/master/memory/tanya/memory/op.d, * Source: $(LINK2 https://github.com/caraus-ecms/tanya/blob/master/middle/tanya/memory/op.d,
* tanya/memory/op.d) * tanya/memory/op.d)
*/ */
module tanya.memory.op; module tanya.memory.op;
@ -32,21 +32,6 @@ else
import core.stdc.string; import core.stdc.string;
} }
version (TanyaNative)
{
@nogc nothrow pure @system unittest
{
ubyte[2] buffer = 1;
fillMemory(buffer[1 .. $], 0);
assert(buffer[0] == 1 && buffer[1] == 0);
}
@nogc nothrow pure @safe unittest
{
assert(equal(null, null));
}
}
private enum alignMask = size_t.sizeof - 1; private enum alignMask = size_t.sizeof - 1;
/** /**
@ -94,26 +79,6 @@ do
assert(equal(source, target)); assert(equal(source, target));
} }
@nogc nothrow pure @safe unittest
{
{
ubyte[0] source, target;
source.copy(target);
}
{
ubyte[1] source = [1];
ubyte[1] target;
source.copy(target);
assert(target[0] == 1);
}
{
ubyte[8] source = [1, 2, 3, 4, 5, 6, 7, 8];
ubyte[8] target;
source.copy(target);
assert(equal(source, target));
}
}
/* /*
* size_t value each of which bytes is set to `Byte`. * size_t value each of which bytes is set to `Byte`.
*/ */
@ -215,15 +180,6 @@ do
assert(equal(expected, mem)); assert(equal(expected, mem));
} }
@nogc nothrow pure @safe unittest
{
ubyte[9] r1 = [ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i' ];
ubyte[9] r2;
copyBackward(r1, r2);
assert(equal(r1, r2));
}
/** /**
* Finds the first occurrence of $(D_PARAM needle) in $(D_PARAM haystack) if * Finds the first occurrence of $(D_PARAM needle) in $(D_PARAM haystack) if
* any. * any.
@ -417,21 +373,3 @@ do
assert(!equal("asdf", "asd")); assert(!equal("asdf", "asd"));
assert(!equal("asdf", "qwer")); assert(!equal("asdf", "qwer"));
} }
// Compares unanligned memory
@nogc nothrow pure @safe unittest
{
ubyte[16] r1 = [
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
];
ubyte[16] r2 = [
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
];
assert(equal(r1, r2));
assert(equal(r1[1 .. $], r2[1 .. $]));
assert(equal(r1[0 .. $ - 1], r2[0 .. $ - 1]));
assert(equal(r1[0 .. 8], r2[0 .. 8]));
}

View File

@ -9,13 +9,13 @@
* License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/, * License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
* Mozilla Public License, v. 2.0). * Mozilla Public License, v. 2.0).
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner) * Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
* Source: $(LINK2 https://github.com/caraus-ecms/tanya/blob/master/memory/tanya/memory/package.d, * Source: $(LINK2 https://github.com/caraus-ecms/tanya/blob/master/middle/tanya/memory/package.d,
* tanya/memory/package.d) * tanya/memory/package.d)
*/ */
module tanya.memory; module tanya.memory;
public import tanya.memory.allocator; public import tanya.memory.allocator;
public import tanya.memory.lifecycle; public import tanya.memory.lifetime;
import tanya.meta.trait; import tanya.meta.trait;
deprecated("Use tanya.meta.trait.stateSize instead") deprecated("Use tanya.meta.trait.stateSize instead")
public import tanya.meta.trait : stateSize; public import tanya.meta.trait : stateSize;

View File

@ -18,14 +18,13 @@
* License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/, * License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
* Mozilla Public License, v. 2.0). * Mozilla Public License, v. 2.0).
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner) * Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
* Source: $(LINK2 https://github.com/caraus-ecms/tanya/blob/master/memory/tanya/memory/smartref.d, * Source: $(LINK2 https://github.com/caraus-ecms/tanya/blob/master/middle/tanya/memory/smartref.d,
* tanya/memory/smartref.d) * tanya/memory/smartref.d)
*/ */
module tanya.memory.smartref; module tanya.memory.smartref;
import tanya.memory; import tanya.memory;
import tanya.meta.trait; import tanya.meta.trait;
version (unittest) import tanya.test.stub;
private template Payload(T) private template Payload(T)
{ {
@ -46,11 +45,7 @@ private final class RefCountedStore(T)
size_t opUnary(string op)() size_t opUnary(string op)()
if (op == "--" || op == "++") if (op == "--" || op == "++")
in in (this.counter > 0)
{
assert(this.counter > 0);
}
do
{ {
mixin("return " ~ op ~ "counter;"); mixin("return " ~ op ~ "counter;");
} }
@ -131,11 +126,7 @@ struct RefCounted(T)
/// ditto /// ditto
this(shared Allocator allocator) this(shared Allocator allocator)
in in (allocator !is null)
{
assert(allocator !is null);
}
do
{ {
this.allocator_ = allocator; this.allocator_ = allocator;
} }
@ -239,11 +230,7 @@ struct RefCounted(T)
* Precondition: $(D_INLINECODE cound > 0). * Precondition: $(D_INLINECODE cound > 0).
*/ */
inout(Payload!T) get() inout inout(Payload!T) get() inout
in in (count > 0, "Attempted to access an uninitialized reference")
{
assert(count > 0, "Attempted to access an uninitialized reference");
}
do
{ {
return this.storage.payload; return this.storage.payload;
} }
@ -301,174 +288,14 @@ struct RefCounted(T)
auto val = rc.get(); auto val = rc.get();
*val = 8; *val = 8;
assert(*rc.storage.payload == 8); assert(*rc.get == 8);
val = null; val = null;
assert(rc.storage.payload !is null); assert(rc.get !is null);
assert(*rc.storage.payload == 8); assert(*rc.get == 8);
*rc = 9; *rc = 9;
assert(*rc.storage.payload == 9); assert(*rc.get == 9);
}
@nogc @system unittest
{
auto rc = defaultAllocator.refCounted!int(5);
rc = defaultAllocator.make!int(7);
assert(*rc == 7);
}
@nogc @system unittest
{
RefCounted!int rc;
assert(!rc.isInitialized);
rc = null;
assert(!rc.isInitialized);
}
@nogc @system unittest
{
auto rc = defaultAllocator.refCounted!int(5);
void func(RefCounted!int param) @nogc
{
assert(param.count == 2);
param = defaultAllocator.make!int(7);
assert(param.count == 1);
assert(*param == 7);
}
func(rc);
assert(rc.count == 1);
assert(*rc == 5);
}
@nogc @system unittest
{
RefCounted!int rc;
void func(RefCounted!int param) @nogc
{
assert(param.count == 0);
param = defaultAllocator.make!int(7);
assert(param.count == 1);
assert(*param == 7);
}
func(rc);
assert(rc.count == 0);
}
@nogc @system unittest
{
RefCounted!int rc1, rc2;
static assert(is(typeof(rc1 = rc2)));
}
version (unittest)
{
private class A
{
uint *destroyed;
this(ref uint destroyed) @nogc
{
this.destroyed = &destroyed;
}
~this() @nogc
{
++(*destroyed);
}
}
private struct B
{
int prop;
@disable this();
this(int param1) @nogc
{
prop = param1;
}
}
}
@nogc @system unittest
{
uint destroyed;
auto a = defaultAllocator.make!A(destroyed);
assert(destroyed == 0);
{
auto rc = RefCounted!A(a, defaultAllocator);
assert(rc.count == 1);
void func(RefCounted!A rc) @nogc @system
{
assert(rc.count == 2);
}
func(rc);
assert(rc.count == 1);
}
assert(destroyed == 1);
RefCounted!int rc;
assert(rc.count == 0);
rc = defaultAllocator.make!int(8);
assert(rc.count == 1);
}
@nogc @system unittest
{
auto rc = RefCounted!int(defaultAllocator);
assert(!rc.isInitialized);
assert(rc.allocator is defaultAllocator);
}
@nogc @system unittest
{
auto rc = defaultAllocator.refCounted!int(5);
assert(rc.count == 1);
void func(RefCounted!int rc) @nogc
{
assert(rc.count == 2);
rc = null;
assert(!rc.isInitialized);
assert(rc.count == 0);
}
assert(rc.count == 1);
func(rc);
assert(rc.count == 1);
rc = null;
assert(!rc.isInitialized);
assert(rc.count == 0);
}
@nogc @system unittest
{
auto rc = defaultAllocator.refCounted!int(5);
assert(*rc == 5);
void func(RefCounted!int rc) @nogc
{
assert(rc.count == 2);
rc = defaultAllocator.refCounted!int(4);
assert(*rc == 4);
assert(rc.count == 1);
}
func(rc);
assert(*rc == 5);
}
@nogc nothrow pure @safe unittest
{
static assert(is(typeof(RefCounted!int.storage.payload) == int*));
static assert(is(typeof(RefCounted!A.storage.payload) == A));
static assert(is(RefCounted!B));
static assert(is(RefCounted!A));
} }
/** /**
@ -493,11 +320,7 @@ version (unittest)
RefCounted!T refCounted(T, A...)(shared Allocator allocator, auto ref A args) RefCounted!T refCounted(T, A...)(shared Allocator allocator, auto ref A args)
if (!is(T == interface) && !isAbstractClass!T if (!is(T == interface) && !isAbstractClass!T
&& !isAssociativeArray!T && !isArray!T) && !isAssociativeArray!T && !isArray!T)
in in (allocator !is null)
{
assert(allocator !is null);
}
do
{ {
auto rc = typeof(return)(allocator); auto rc = typeof(return)(allocator);
@ -565,51 +388,6 @@ in (size <= size_t.max / E.sizeof)
assert(rc.count == 1); assert(rc.count == 1);
} }
@nogc @system unittest
{
struct E
{
}
auto b = defaultAllocator.refCounted!B(15);
static assert(is(typeof(b.storage.payload) == B*));
static assert(is(typeof(b.prop) == int));
static assert(!is(typeof(defaultAllocator.refCounted!B())));
static assert(is(typeof(defaultAllocator.refCounted!E())));
static assert(!is(typeof(defaultAllocator.refCounted!E(5))));
{
auto rc = defaultAllocator.refCounted!B(3);
assert(rc.get().prop == 3);
}
{
auto rc = defaultAllocator.refCounted!E();
assert(rc.count);
}
}
@nogc @system unittest
{
auto rc = defaultAllocator.refCounted!(int[])(5);
assert(rc.length == 5);
}
@nogc @system unittest
{
auto p1 = defaultAllocator.make!int(5);
auto p2 = p1;
auto rc = RefCounted!int(p1, defaultAllocator);
assert(rc.get() is p2);
}
@nogc @system unittest
{
size_t destroyed;
{
auto rc = defaultAllocator.refCounted!WithDtor(destroyed);
}
assert(destroyed == 1);
}
/** /**
* $(D_PSYMBOL Unique) stores an object that gets destroyed at the end of its scope. * $(D_PSYMBOL Unique) stores an object that gets destroyed at the end of its scope.
* *
@ -644,11 +422,7 @@ struct Unique(T)
/// ditto /// ditto
this(shared Allocator allocator) this(shared Allocator allocator)
in in (allocator !is null)
{
assert(allocator !is null);
}
do
{ {
this.allocator_ = allocator; this.allocator_ = allocator;
} }
@ -829,11 +603,7 @@ struct Unique(T)
Unique!T unique(T, A...)(shared Allocator allocator, auto ref A args) Unique!T unique(T, A...)(shared Allocator allocator, auto ref A args)
if (!is(T == interface) && !isAbstractClass!T if (!is(T == interface) && !isAbstractClass!T
&& !isAssociativeArray!T && !isArray!T) && !isAssociativeArray!T && !isArray!T)
in in (allocator !is null)
{
assert(allocator !is null);
}
do
{ {
auto payload = allocator.make!(T, A)(args); auto payload = allocator.make!(T, A)(args);
return Unique!T(payload, allocator); return Unique!T(payload, allocator);
@ -862,42 +632,3 @@ in (size <= size_t.max / E.sizeof)
auto payload = allocator.resize!E(null, size); auto payload = allocator.resize!E(null, size);
return Unique!T(payload, allocator); return Unique!T(payload, allocator);
} }
@nogc nothrow pure @safe unittest
{
static assert(is(typeof(defaultAllocator.unique!B(5))));
static assert(is(typeof(defaultAllocator.unique!(int[])(5))));
}
@nogc nothrow pure @system unittest
{
auto s = defaultAllocator.unique!int(5);
assert(*s == 5);
s = null;
assert(s is null);
}
@nogc nothrow pure @system unittest
{
auto s = defaultAllocator.unique!int(5);
assert(*s == 5);
s = defaultAllocator.unique!int(4);
assert(*s == 4);
}
@nogc nothrow pure @system unittest
{
auto p1 = defaultAllocator.make!int(5);
auto p2 = p1;
auto rc = Unique!int(p1, defaultAllocator);
assert(rc.get() is p2);
}
@nogc nothrow pure @system unittest
{
auto rc = Unique!int(defaultAllocator);
assert(rc.allocator is defaultAllocator);
}

View File

@ -407,12 +407,6 @@ struct ErrorCode
assert(ec.toString() == "An invalid pointer address detected"); assert(ec.toString() == "An invalid pointer address detected");
} }
@nogc nothrow pure @safe unittest
{
ErrorCode ec = cast(ErrorCode.ErrorNo) -1;
assert(ec.toString() is null);
}
private ErrorNo value_ = ErrorNo.success; private ErrorNo value_ = ErrorNo.success;
alias ErrorNo this; alias ErrorNo this;

View File

@ -21,7 +21,7 @@
module tanya.algorithm.iteration; module tanya.algorithm.iteration;
import tanya.algorithm.comparison; import tanya.algorithm.comparison;
import tanya.memory.lifecycle; import tanya.memory.lifetime;
import tanya.meta.trait; import tanya.meta.trait;
import tanya.meta.transform; import tanya.meta.transform;
import tanya.range; import tanya.range;

View File

@ -14,21 +14,21 @@
*/ */
module tanya.algorithm.mutation; module tanya.algorithm.mutation;
static import tanya.memory.lifetime;
static import tanya.memory.op; static import tanya.memory.op;
static import tanya.memory.lifecycle;
import tanya.meta.trait; import tanya.meta.trait;
import tanya.meta.transform; import tanya.meta.transform;
import tanya.range; import tanya.range;
version (unittest) import tanya.test.stub; version (unittest) import tanya.test.stub;
deprecated("Use tanya.memory.lifecycle.swap instead") deprecated("Use tanya.memory.lifetime.swap instead")
alias swap = tanya.memory.lifecycle.swap; alias swap = tanya.memory.lifetime.swap;
deprecated("Use tanya.memory.lifecycle.moveEmplace instead") deprecated("Use tanya.memory.lifetime.moveEmplace instead")
alias moveEmplace = tanya.memory.lifecycle.moveEmplace; alias moveEmplace = tanya.memory.lifetime.moveEmplace;
deprecated("Use tanya.memory.lifecycle.move instead") deprecated("Use tanya.memory.lifetime.move instead")
alias move = tanya.memory.lifecycle.move; alias move = tanya.memory.lifetime.move;
/** /**
* Copies the $(D_PARAM source) range into the $(D_PARAM target) range. * Copies the $(D_PARAM source) range into the $(D_PARAM target) range.
@ -231,7 +231,7 @@ if (isInputRange!Range && hasLvalueElements!Range
for (; !range.empty; range.popFront()) for (; !range.empty; range.popFront())
{ {
ElementType!Range* p = &range.front; ElementType!Range* p = &range.front;
tanya.memory.lifecycle.emplace!(ElementType!Range)(cast(void[]) (p[0 .. 1]), value); tanya.memory.lifetime.emplace!(ElementType!Range)(cast(void[]) (p[0 .. 1]), value);
} }
} }
else else
@ -314,7 +314,7 @@ if (isInputRange!Range && hasLvalueElements!Range)
void destroyAll(Range)(Range range) void destroyAll(Range)(Range range)
if (isInputRange!Range && hasLvalueElements!Range) if (isInputRange!Range && hasLvalueElements!Range)
{ {
tanya.memory.lifecycle.destroyAllImpl!(Range, ElementType!Range)(range); tanya.memory.lifetime.destroyAllImpl!(Range, ElementType!Range)(range);
} }
/// ///
@ -363,7 +363,7 @@ if (isForwardRange!Range && hasSwappableElements!Range)
while (!front.empty && !next.empty && !sameHead(front, next)) while (!front.empty && !next.empty && !sameHead(front, next))
{ {
tanya.memory.lifecycle.swap(front.front, next.front); tanya.memory.lifetime.swap(front.front, next.front);
front.popFront(); front.popFront();
next.popFront(); next.popFront();

View File

@ -16,7 +16,7 @@ module tanya.container.entry;
import tanya.container.array; import tanya.container.array;
import tanya.memory.allocator; import tanya.memory.allocator;
import tanya.memory.lifecycle; import tanya.memory.lifetime;
import tanya.meta.trait; import tanya.meta.trait;
import tanya.meta.transform; import tanya.meta.transform;
import tanya.typecons; import tanya.typecons;

View File

@ -16,8 +16,8 @@ module tanya.conv;
import tanya.container.string; import tanya.container.string;
import tanya.memory; import tanya.memory;
deprecated("Use tanya.memory.lifecycle.emplace instead") deprecated("Use tanya.memory.lifetime.emplace instead")
public import tanya.memory.lifecycle : emplace; public import tanya.memory.lifetime : emplace;
import tanya.meta.trait; import tanya.meta.trait;
import tanya.meta.transform; import tanya.meta.transform;
import tanya.range; import tanya.range;

View File

@ -10,7 +10,7 @@
* Source: $(LINK2 https://github.com/caraus-ecms/tanya/blob/master/source/tanya/exception.d, * Source: $(LINK2 https://github.com/caraus-ecms/tanya/blob/master/source/tanya/exception.d,
* tanya/exception.d) * tanya/exception.d)
*/ */
deprecated("Use tanya.memory.lifecycle instead") deprecated("Use tanya.memory.lifetimeinstead")
module tanya.exception; module tanya.exception;
public import tanya.memory.lifecycle : onOutOfMemoryError, OutOfMemoryError; public import tanya.memory.lifetime : onOutOfMemoryError, OutOfMemoryError;

View File

@ -12,7 +12,7 @@
* Source: $(LINK2 https://github.com/caraus-ecms/tanya/blob/master/source/tanya/functional.d, * Source: $(LINK2 https://github.com/caraus-ecms/tanya/blob/master/source/tanya/functional.d,
* tanya/functional.d) * tanya/functional.d)
*/ */
deprecated("Use tanya.memory.lifecycle instead") deprecated("Use tanya.memory.lifetime instead")
module tanya.functional; module tanya.functional;
public import tanya.memory.lifecycle : forward; public import tanya.memory.lifetime : forward;

View File

@ -5,7 +5,7 @@
/** /**
* Arbitrary precision arithmetic. * Arbitrary precision arithmetic.
* *
* Copyright: Eugene Wissner 2016-2018. * Copyright: Eugene Wissner 2016-2019.
* License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/, * License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
* Mozilla Public License, v. 2.0). * Mozilla Public License, v. 2.0).
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner) * Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)

View File

@ -5,7 +5,7 @@
/** /**
* Number theory. * Number theory.
* *
* Copyright: Eugene Wissner 2017-2018. * Copyright: Eugene Wissner 2017-2019.
* License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/, * License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
* Mozilla Public License, v. 2.0). * Mozilla Public License, v. 2.0).
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner) * Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)

View File

@ -12,7 +12,7 @@
* be found in its submodules. $(D_PSYMBOL tanya.math) doesn't import any * be found in its submodules. $(D_PSYMBOL tanya.math) doesn't import any
* submodules publically, they should be imported explicitly. * submodules publically, they should be imported explicitly.
* *
* Copyright: Eugene Wissner 2016-2018. * Copyright: Eugene Wissner 2016-2019.
* License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/, * License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
* Mozilla Public License, v. 2.0). * Mozilla Public License, v. 2.0).
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner) * Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
@ -21,7 +21,6 @@
*/ */
module tanya.math; module tanya.math;
import tanya.algorithm.mutation;
import tanya.math.mp; import tanya.math.mp;
import tanya.math.nbtheory; import tanya.math.nbtheory;
import tanya.meta.trait; import tanya.meta.trait;

View File

@ -5,7 +5,7 @@
/** /**
* Random number generator. * Random number generator.
* *
* Copyright: Eugene Wissner 2016-2018. * Copyright: Eugene Wissner 2016-2019.
* License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/, * License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/,
* Mozilla Public License, v. 2.0). * Mozilla Public License, v. 2.0).
* Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner) * Authors: $(LINK2 mailto:info@caraus.de, Eugene Wissner)
@ -14,7 +14,6 @@
*/ */
module tanya.math.random; module tanya.math.random;
import std.digest.sha;
import tanya.memory; import tanya.memory;
import tanya.typecons; import tanya.typecons;

View File

@ -21,7 +21,7 @@ import tanya.container.string;
import tanya.conv; import tanya.conv;
import tanya.encoding.ascii; import tanya.encoding.ascii;
import tanya.format; import tanya.format;
import tanya.memory.lifecycle; import tanya.memory.lifetime;
import tanya.meta.trait; import tanya.meta.trait;
import tanya.meta.transform; import tanya.meta.transform;
import tanya.net.iface; import tanya.net.iface;

View File

@ -15,7 +15,7 @@
module tanya.range.adapter; module tanya.range.adapter;
import tanya.algorithm.mutation; import tanya.algorithm.mutation;
import tanya.memory.lifecycle; import tanya.memory.lifetime;
import tanya.meta.trait; import tanya.meta.trait;
import tanya.range; import tanya.range;

View File

@ -55,11 +55,7 @@ module tanya.range.array;
* Precondition: $(D_INLINECODE array.length > 0). * Precondition: $(D_INLINECODE array.length > 0).
*/ */
@property ref inout(T) front(T)(return scope inout(T)[] array) @property ref inout(T) front(T)(return scope inout(T)[] array)
in in (array.length > 0)
{
assert(array.length > 0);
}
do
{ {
return array[0]; return array[0];
} }
@ -95,11 +91,7 @@ do
* Precondition: $(D_INLINECODE array.length > 0). * Precondition: $(D_INLINECODE array.length > 0).
*/ */
@property ref inout(T) back(T)(return scope inout(T)[] array) @property ref inout(T) back(T)(return scope inout(T)[] array)
in in (array.length > 0)
{
assert(array.length > 0);
}
do
{ {
return array[$ - 1]; return array[$ - 1];
} }
@ -134,22 +126,14 @@ do
* Precondition: $(D_INLINECODE array.length > 0). * Precondition: $(D_INLINECODE array.length > 0).
*/ */
void popFront(T)(scope ref inout(T)[] array) void popFront(T)(scope ref inout(T)[] array)
in in (array.length > 0)
{
assert(array.length > 0);
}
do
{ {
array = array[1 .. $]; array = array[1 .. $];
} }
/// ditto /// ditto
void popBack(T)(scope ref inout(T)[] array) void popBack(T)(scope ref inout(T)[] array)
in in (array.length > 0)
{
assert(array.length > 0);
}
do
{ {
array = array[0 .. $ - 1]; array = array[0 .. $ - 1];
} }

View File

@ -15,7 +15,7 @@
module tanya.range.primitive; module tanya.range.primitive;
import tanya.algorithm.comparison; import tanya.algorithm.comparison;
import tanya.memory.lifecycle; import tanya.memory.lifetime;
import tanya.meta.trait; import tanya.meta.trait;
import tanya.meta.transform; import tanya.meta.transform;
import tanya.range.array; import tanya.range.array;

View File

@ -18,7 +18,7 @@
module tanya.typecons; module tanya.typecons;
import tanya.format; import tanya.format;
import tanya.memory.lifecycle; import tanya.memory.lifetime;
import tanya.meta.metafunction; import tanya.meta.metafunction;
import tanya.meta.trait; import tanya.meta.trait;
version (unittest) import tanya.test.stub; version (unittest) import tanya.test.stub;

16
test/dub.json Normal file
View File

@ -0,0 +1,16 @@
{
"name": "test",
"description": "Test suite for unittest-blocks",
"targetType": "library",
"dependencies": {
"tanya:middle": "*"
},
"sourcePaths": [
"."
],
"importPaths": [
"."
]
}

View File

@ -0,0 +1,173 @@
module tanya.memory.tests.lifetime;
import tanya.memory;
import tanya.test.stub;
@nogc nothrow pure @safe unittest
{
int[] p;
p = defaultAllocator.resize(p, 20);
assert(p.length == 20);
p = defaultAllocator.resize(p, 30);
assert(p.length == 30);
p = defaultAllocator.resize(p, 10);
assert(p.length == 10);
p = defaultAllocator.resize(p, 0);
assert(p is null);
}
@nogc nothrow pure @system unittest
{
static struct S
{
~this() @nogc nothrow pure @safe
{
}
}
auto p = cast(S[]) defaultAllocator.allocate(S.sizeof);
defaultAllocator.dispose(p);
}
// Works with interfaces.
@nogc nothrow pure @safe unittest
{
interface I
{
}
class C : I
{
}
auto c = defaultAllocator.make!C();
I i = c;
defaultAllocator.dispose(i);
defaultAllocator.dispose(i);
}
// Handles "Cannot access frame pointer" error.
@nogc nothrow pure @safe unittest
{
struct F
{
~this() @nogc nothrow pure @safe
{
}
}
static assert(is(typeof(emplace!F((void[]).init))));
}
// Can emplace structs without a constructor
@nogc nothrow pure @safe unittest
{
static assert(is(typeof(emplace!WithDtor(null, WithDtor()))));
static assert(is(typeof(emplace!WithDtor(null))));
}
// Doesn't call a destructor on uninitialized elements
@nogc nothrow pure @system unittest
{
static struct SWithDtor
{
private bool canBeInvoked = false;
~this() @nogc nothrow pure @safe
{
assert(this.canBeInvoked);
}
}
void[SWithDtor.sizeof] memory = void;
auto actual = emplace!SWithDtor(memory[], SWithDtor(true));
assert(actual.canBeInvoked);
}
// Initializes structs if no arguments are given
@nogc nothrow pure @safe unittest
{
static struct SEntry
{
byte content;
}
ubyte[1] mem = [3];
assert(emplace!SEntry(cast(void[]) mem[0 .. 1]).content == 0);
}
// Postblit is called when emplacing a struct
@nogc nothrow pure @system unittest
{
static struct S
{
bool called = false;
this(this) @nogc nothrow pure @safe
{
this.called = true;
}
}
S target;
S* sp = &target;
emplace!S(sp[0 .. 1], S());
assert(target.called);
}
// Is pure.
@nogc nothrow pure @system unittest
{
struct S
{
this(this)
{
}
}
S source, target = void;
static assert(is(typeof({ moveEmplace(source, target); })));
}
// Moves nested.
@nogc nothrow pure @system unittest
{
struct Nested
{
void method() @nogc nothrow pure @safe
{
}
}
Nested source, target = void;
moveEmplace(source, target);
assert(source == target);
}
// Emplaces static arrays.
@nogc nothrow pure @system unittest
{
static struct S
{
size_t member;
this(size_t i) @nogc nothrow pure @safe
{
this.member = i;
}
~this() @nogc nothrow pure @safe
{
}
}
S[2] source = [ S(5), S(5) ], target = void;
moveEmplace(source, target);
assert(source[0].member == 0);
assert(target[0].member == 5);
assert(source[1].member == 0);
assert(target[1].member == 5);
}
// Moves if source is target.
@nogc nothrow pure @safe unittest
{
int x = 5;
move(x, x);
assert(x == 5);
}

View File

@ -0,0 +1,23 @@
module tanya.memory.tests.mallocator;
version (TanyaNative)
{
}
else:
import tanya.memory.mallocator;
// Fails with false
@nogc nothrow pure @system unittest
{
void[] p = Mallocator.instance.allocate(20);
void[] oldP = p;
assert(!Mallocator.instance.reallocate(p, size_t.max - 16));
assert(oldP is p);
Mallocator.instance.deallocate(p);
}
@nogc nothrow pure unittest
{
assert(Mallocator.instance.alignment == (void*).alignof);
}

View File

@ -0,0 +1,159 @@
module tanya.memory.tests.mmappool;
version (TanyaNative):
import tanya.memory.mmappool;
@nogc nothrow pure @system unittest
{
auto p = MmapPool.instance.allocate(20);
assert(p);
MmapPool.instance.deallocate(p);
p = MmapPool.instance.allocate(0);
assert(p.length == 0);
}
@nogc nothrow pure @system unittest
{
// allocate() check.
size_t tooMuchMemory = size_t.max
- MmapPool.alignment_
- BlockEntry.sizeof * 2
- RegionEntry.sizeof
- pageSize;
assert(MmapPool.instance.allocate(tooMuchMemory) is null);
assert(MmapPool.instance.allocate(size_t.max) is null);
// initializeRegion() check.
tooMuchMemory = size_t.max - MmapPool.alignment_;
assert(MmapPool.instance.allocate(tooMuchMemory) is null);
}
@nogc nothrow pure @system unittest
{
auto p = MmapPool.instance.allocate(20);
assert(MmapPool.instance.deallocate(p));
}
@nogc nothrow pure @system unittest
{
void[] p;
assert(!MmapPool.instance.reallocateInPlace(p, 5));
assert(p is null);
p = MmapPool.instance.allocate(1);
auto orig = p.ptr;
assert(MmapPool.instance.reallocateInPlace(p, 2));
assert(p.length == 2);
assert(p.ptr == orig);
assert(MmapPool.instance.reallocateInPlace(p, 4));
assert(p.length == 4);
assert(p.ptr == orig);
assert(MmapPool.instance.reallocateInPlace(p, 2));
assert(p.length == 2);
assert(p.ptr == orig);
MmapPool.instance.deallocate(p);
}
@nogc nothrow pure @system unittest
{
void[] p;
MmapPool.instance.reallocate(p, 10 * int.sizeof);
(cast(int[]) p)[7] = 123;
assert(p.length == 40);
MmapPool.instance.reallocate(p, 8 * int.sizeof);
assert(p.length == 32);
assert((cast(int[]) p)[7] == 123);
MmapPool.instance.reallocate(p, 20 * int.sizeof);
(cast(int[]) p)[15] = 8;
assert(p.length == 80);
assert((cast(int[]) p)[15] == 8);
assert((cast(int[]) p)[7] == 123);
MmapPool.instance.reallocate(p, 8 * int.sizeof);
assert(p.length == 32);
assert((cast(int[]) p)[7] == 123);
MmapPool.instance.deallocate(p);
}
@nogc nothrow pure @system unittest
{
assert(instance is instance);
}
@nogc nothrow pure @system unittest
{
assert(MmapPool.instance.alignment == MmapPool.alignment_);
}
// A lot of allocations/deallocations, but it is the minimum caused a
// segmentation fault because MmapPool reallocateInPlace moves a block wrong.
@nogc nothrow pure @system unittest
{
auto a = MmapPool.instance.allocate(16);
auto d = MmapPool.instance.allocate(16);
auto b = MmapPool.instance.allocate(16);
auto e = MmapPool.instance.allocate(16);
auto c = MmapPool.instance.allocate(16);
auto f = MmapPool.instance.allocate(16);
MmapPool.instance.deallocate(a);
MmapPool.instance.deallocate(b);
MmapPool.instance.deallocate(c);
a = MmapPool.instance.allocate(50);
MmapPool.instance.reallocateInPlace(a, 64);
MmapPool.instance.deallocate(a);
a = MmapPool.instance.allocate(1);
auto tmp1 = MmapPool.instance.allocate(1);
auto h1 = MmapPool.instance.allocate(1);
auto tmp2 = cast(ubyte[]) MmapPool.instance.allocate(1);
auto h2 = MmapPool.instance.allocate(2);
tmp1 = MmapPool.instance.allocate(1);
MmapPool.instance.deallocate(h2);
MmapPool.instance.deallocate(h1);
h2 = MmapPool.instance.allocate(2);
h1 = MmapPool.instance.allocate(1);
MmapPool.instance.deallocate(h2);
auto rep = cast(void[]) tmp2;
MmapPool.instance.reallocate(rep, tmp1.length);
tmp2 = cast(ubyte[]) rep;
MmapPool.instance.reallocate(tmp1, 9);
rep = cast(void[]) tmp2;
MmapPool.instance.reallocate(rep, tmp1.length);
tmp2 = cast(ubyte[]) rep;
MmapPool.instance.reallocate(tmp1, 17);
tmp2[$ - 1] = 0;
MmapPool.instance.deallocate(tmp1);
b = MmapPool.instance.allocate(16);
MmapPool.instance.deallocate(h1);
MmapPool.instance.deallocate(a);
MmapPool.instance.deallocate(b);
MmapPool.instance.deallocate(d);
MmapPool.instance.deallocate(e);
MmapPool.instance.deallocate(f);
}

View File

@ -0,0 +1,64 @@
module tanya.memory.tests.op;
import tanya.memory.op;
@nogc nothrow pure @system unittest
{
ubyte[2] buffer = 1;
fill!0(buffer[1 .. $]);
assert(buffer[0] == 1 && buffer[1] == 0);
}
@nogc nothrow pure @safe unittest
{
assert(equal(null, null));
}
@nogc nothrow pure @safe unittest
{
ubyte[0] source, target;
source.copy(target);
}
@nogc nothrow pure @safe unittest
{
ubyte[1] source = [1];
ubyte[1] target;
source.copy(target);
assert(target[0] == 1);
}
@nogc nothrow pure @safe unittest
{
ubyte[8] source = [1, 2, 3, 4, 5, 6, 7, 8];
ubyte[8] target;
source.copy(target);
assert(equal(source, target));
}
@nogc nothrow pure @safe unittest
{
ubyte[9] r1 = [ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i' ];
ubyte[9] r2;
copyBackward(r1, r2);
assert(equal(r1, r2));
}
// Compares unanligned memory
@nogc nothrow pure @safe unittest
{
ubyte[16] r1 = [
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
];
ubyte[16] r2 = [
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
];
assert(equal(r1, r2));
assert(equal(r1[1 .. $], r2[1 .. $]));
assert(equal(r1[0 .. $ - 1], r2[0 .. $ - 1]));
assert(equal(r1[0 .. 8], r2[0 .. 8]));
}

View File

@ -0,0 +1,250 @@
module tanya.memory.tests.smartref;
import tanya.memory;
import tanya.memory.smartref;
import tanya.meta.trait;
import tanya.test.stub;
@nogc @system unittest
{
auto rc = defaultAllocator.refCounted!int(5);
rc = defaultAllocator.make!int(7);
assert(*rc == 7);
}
@nogc @system unittest
{
RefCounted!int rc;
assert(!rc.isInitialized);
rc = null;
assert(!rc.isInitialized);
}
@nogc @system unittest
{
auto rc = defaultAllocator.refCounted!int(5);
void func(RefCounted!int param) @nogc
{
assert(param.count == 2);
param = defaultAllocator.make!int(7);
assert(param.count == 1);
assert(*param == 7);
}
func(rc);
assert(rc.count == 1);
assert(*rc == 5);
}
@nogc @system unittest
{
RefCounted!int rc;
void func(RefCounted!int param) @nogc
{
assert(param.count == 0);
param = defaultAllocator.make!int(7);
assert(param.count == 1);
assert(*param == 7);
}
func(rc);
assert(rc.count == 0);
}
@nogc @system unittest
{
RefCounted!int rc1, rc2;
static assert(is(typeof(rc1 = rc2)));
}
@nogc @system unittest
{
auto rc = RefCounted!int(defaultAllocator);
assert(!rc.isInitialized);
assert(rc.allocator is defaultAllocator);
}
@nogc @system unittest
{
auto rc = defaultAllocator.refCounted!int(5);
assert(rc.count == 1);
void func(RefCounted!int rc) @nogc
{
assert(rc.count == 2);
rc = null;
assert(!rc.isInitialized);
assert(rc.count == 0);
}
assert(rc.count == 1);
func(rc);
assert(rc.count == 1);
rc = null;
assert(!rc.isInitialized);
assert(rc.count == 0);
}
@nogc @system unittest
{
auto rc = defaultAllocator.refCounted!int(5);
assert(*rc == 5);
void func(RefCounted!int rc) @nogc
{
assert(rc.count == 2);
rc = defaultAllocator.refCounted!int(4);
assert(*rc == 4);
assert(rc.count == 1);
}
func(rc);
assert(*rc == 5);
}
@nogc @system unittest
{
auto rc = defaultAllocator.refCounted!(int[])(5);
assert(rc.length == 5);
}
@nogc @system unittest
{
auto p1 = defaultAllocator.make!int(5);
auto p2 = p1;
auto rc = RefCounted!int(p1, defaultAllocator);
assert(rc.get() is p2);
}
@nogc @system unittest
{
size_t destroyed;
{
auto rc = defaultAllocator.refCounted!WithDtor(destroyed);
}
assert(destroyed == 1);
}
@nogc nothrow pure @system unittest
{
auto s = defaultAllocator.unique!int(5);
assert(*s == 5);
s = null;
assert(s is null);
}
@nogc nothrow pure @system unittest
{
auto s = defaultAllocator.unique!int(5);
assert(*s == 5);
s = defaultAllocator.unique!int(4);
assert(*s == 4);
}
@nogc nothrow pure @system unittest
{
auto p1 = defaultAllocator.make!int(5);
auto p2 = p1;
auto rc = Unique!int(p1, defaultAllocator);
assert(rc.get() is p2);
}
@nogc nothrow pure @system unittest
{
auto rc = Unique!int(defaultAllocator);
assert(rc.allocator is defaultAllocator);
}
@nogc @system unittest
{
uint destroyed;
auto a = defaultAllocator.make!A(destroyed);
assert(destroyed == 0);
{
auto rc = RefCounted!A(a, defaultAllocator);
assert(rc.count == 1);
void func(RefCounted!A rc) @nogc @system
{
assert(rc.count == 2);
}
func(rc);
assert(rc.count == 1);
}
assert(destroyed == 1);
RefCounted!int rc;
assert(rc.count == 0);
rc = defaultAllocator.make!int(8);
assert(rc.count == 1);
}
@nogc nothrow pure @safe unittest
{
static assert(is(ReturnType!(RefCounted!int.get) == inout int*));
static assert(is(ReturnType!(RefCounted!A.get) == inout A));
static assert(is(ReturnType!(RefCounted!B.get) == inout B*));
}
@nogc nothrow pure @safe unittest
{
static assert(is(RefCounted!B));
static assert(is(RefCounted!A));
}
@nogc @system unittest
{
struct E
{
}
auto b = defaultAllocator.refCounted!B(15);
static assert(is(typeof(b.prop) == int));
static assert(!is(typeof(defaultAllocator.refCounted!B())));
static assert(is(typeof(defaultAllocator.refCounted!E())));
static assert(!is(typeof(defaultAllocator.refCounted!E(5))));
{
auto rc = defaultAllocator.refCounted!B(3);
assert(rc.get().prop == 3);
}
{
auto rc = defaultAllocator.refCounted!E();
assert(rc.count);
}
}
@nogc nothrow pure @safe unittest
{
static assert(is(typeof(defaultAllocator.unique!B(5))));
static assert(is(typeof(defaultAllocator.unique!(int[])(5))));
}
private class A
{
uint *destroyed;
this(ref uint destroyed) @nogc
{
this.destroyed = &destroyed;
}
~this() @nogc
{
++(*destroyed);
}
}
private struct B
{
int prop;
@disable this();
this(int param1) @nogc
{
prop = param1;
}
}

View File

@ -0,0 +1,27 @@
module tanya.meta.tests.metafunction;
import tanya.meta.metafunction;
@nogc nothrow pure @safe unittest
{
enum cmp(int x, int y) = x - y;
static assert(isSorted!(cmp));
static assert(isSorted!(cmp, 1));
static assert(isSorted!(cmp, 1, 2, 2));
static assert(isSorted!(cmp, 1, 2, 2, 4));
static assert(isSorted!(cmp, 1, 2, 2, 4, 8));
static assert(!isSorted!(cmp, 32, 2, 2, 4, 8));
static assert(isSorted!(cmp, 32, 32));
}
@nogc nothrow pure @safe unittest
{
enum cmp(int x, int y) = x < y;
static assert(isSorted!(cmp));
static assert(isSorted!(cmp, 1));
static assert(isSorted!(cmp, 1, 2, 2));
static assert(isSorted!(cmp, 1, 2, 2, 4));
static assert(isSorted!(cmp, 1, 2, 2, 4, 8));
static assert(!isSorted!(cmp, 32, 2, 2, 4, 8));
static assert(isSorted!(cmp, 32, 32));
}

View File

@ -0,0 +1,169 @@
module tanya.meta.tests.trait;
import tanya.meta.metafunction;
import tanya.meta.trait;
// typeof(null) is not a pointer.
@nogc nothrow pure @safe unittest
{
static assert(!isPointer!(typeof(null)));
static assert(!isPointer!(const shared typeof(null)));
enum typeOfNull : typeof(null)
{
null_ = null,
}
static assert(!isPointer!typeOfNull);
}
@nogc nothrow pure @safe unittest
{
static struct S
{
@property int opCall()
{
return 0;
}
}
S s;
static assert(isCallable!S);
static assert(isCallable!s);
}
@nogc nothrow pure @safe unittest
{
static assert(is(FunctionTypeOf!(void delegate()) == function));
static void staticFunc()
{
}
auto functionPointer = &staticFunc;
static assert(is(FunctionTypeOf!staticFunc == function));
static assert(is(FunctionTypeOf!functionPointer == function));
void func()
{
}
auto dg = &func;
static assert(is(FunctionTypeOf!func == function));
static assert(is(FunctionTypeOf!dg == function));
interface I
{
@property int prop();
}
static assert(is(FunctionTypeOf!(I.prop) == function));
static struct S
{
void opCall()
{
}
}
class C
{
static void opCall()
{
}
}
S s;
static assert(is(FunctionTypeOf!s == function));
static assert(is(FunctionTypeOf!C == function));
static assert(is(FunctionTypeOf!S == function));
}
@nogc nothrow pure @safe unittest
{
static struct S2
{
@property int opCall()
{
return 0;
}
}
S2 s2;
static assert(is(FunctionTypeOf!S2 == function));
static assert(is(FunctionTypeOf!s2 == function));
}
@nogc nothrow pure @safe unittest
{
static assert(!hasElaborateAssign!int);
static struct S1
{
void opAssign(S1)
{
}
}
static struct S2
{
void opAssign(int)
{
}
}
static struct S3
{
S1 s;
alias s this;
}
static assert(hasElaborateAssign!S1);
static assert(!hasElaborateAssign!(const S1));
static assert(hasElaborateAssign!(S1[1]));
static assert(!hasElaborateAssign!(S1[0]));
static assert(!hasElaborateAssign!S2);
static assert(hasElaborateAssign!S3);
static struct S4
{
void opAssign(S4)
{
}
@disable this(this);
}
static assert(hasElaborateAssign!S4);
}
// Produces a tuple for an enum with only one member
@nogc nothrow pure @safe unittest
{
enum E : int
{
one = 0,
}
static assert(EnumMembers!E == AliasSeq!0);
}
@nogc nothrow pure @safe unittest
{
class RefCountedStore(T)
{
}
static assert(!isInnerClass!(RefCountedStore!int));
}
@nogc nothrow pure @safe unittest
{
static struct DisabledOpEquals
{
@disable bool opEquals(typeof(this)) @nogc nothrow pure @safe;
int opCmp(typeof(this)) @nogc nothrow pure @safe
{
return 0;
}
}
static assert(!isEqualityComparable!DisabledOpEquals);
static assert(isOrderingComparable!DisabledOpEquals);
static struct OpEquals
{
bool opEquals(typeof(this)) @nogc nothrow pure @safe
{
return true;
}
}
static assert(isEqualityComparable!OpEquals);
static assert(!isOrderingComparable!OpEquals);
}

View File

@ -0,0 +1,50 @@
module tanya.meta.tests.transform;
import tanya.meta.transform;
@nogc nothrow pure @safe unittest
{
static assert(is(CommonType!(void*, int*) == void*));
static assert(is(CommonType!(void*, const(int)*) == const(void)*));
static assert(is(CommonType!(void*, const(void)*) == const(void)*));
static assert(is(CommonType!(int*, void*) == void*));
static assert(is(CommonType!(const(int)*, void*) == const(void)*));
static assert(is(CommonType!(const(void)*, void*) == const(void)*));
static assert(is(CommonType!() == void));
static assert(is(CommonType!(int*, const(int)*) == const(int)*));
static assert(is(CommonType!(int**, const(int)**) == const(int*)*));
static assert(is(CommonType!(float, double) == double));
static assert(is(CommonType!(float, int) == void));
static assert(is(CommonType!(bool, const bool) == bool));
static assert(is(CommonType!(int, bool) == void));
static assert(is(CommonType!(int, void) == void));
static assert(is(CommonType!(Object, void*) == void));
class A
{
}
static assert(is(CommonType!(A, Object) == Object));
static assert(is(CommonType!(const(A)*, Object*) == const(Object)*));
static assert(is(CommonType!(A, typeof(null)) == A));
class B : A
{
}
class C : A
{
}
static assert(is(CommonType!(B, C) == A));
static struct S
{
int opCast(T : int)()
{
return 1;
}
}
static assert(is(CommonType!(S, int) == void));
static assert(is(CommonType!(const S, S) == const S));
}

View File

@ -0,0 +1,9 @@
module tanya.os.tests.error;
import tanya.os.error;
@nogc nothrow pure @safe unittest
{
ErrorCode ec = cast(ErrorCode.ErrorNo) -1;
assert(ec.toString() is null);
}