1 module ut.lifetime; 2 import numem.lifetime; 3 4 class TestClass { 5 @nogc: 6 int value; 7 8 this(int value) { 9 this.value = value; 10 } 11 12 int func1() { return value; } 13 } 14 15 class SubClass : TestClass { 16 @nogc: 17 int value2; 18 19 this(int value, int value2) { 20 super(value); 21 this.value2 = value2; 22 } 23 24 override 25 int func1() { return value2; } 26 } 27 28 struct TestStruct { 29 int value; 30 } 31 32 @("Construct class") 33 @nogc 34 unittest { 35 TestClass a = nogc_new!TestClass(12); 36 assert(a.func1() == 12); 37 38 // also free. 39 nogc_delete(a); 40 } 41 42 @("Construct subclass") 43 @nogc 44 unittest { 45 TestClass klass1 = nogc_new!SubClass(1, 2); 46 assert(klass1.func1() == 2); 47 assert(cast(SubClass)klass1); 48 } 49 50 @("Construct class (nothrow)") 51 nothrow @nogc 52 unittest { 53 import numem.core.exception : assumeNoThrow; 54 55 TestClass a = assumeNoThrow(() => nogc_new!TestClass(12)); 56 assert(a.value == 12); 57 58 // also free. 59 nogc_delete(a); 60 } 61 62 @("Construct struct") 63 @nogc 64 unittest { 65 TestStruct* a = nogc_new!TestStruct(12); 66 assert(a.value == 12); 67 68 // also free. 69 nogc_delete(a); 70 } 71 72 @("Free struct") 73 @nogc 74 unittest { 75 TestStruct a = TestStruct(12); 76 assert(a.value == 12); 77 78 // also free. 79 nogc_delete(a); 80 } 81 82 @("Construct class (Slice list)") 83 @nogc 84 unittest { 85 TestClass[] classList; 86 classList.nu_resize(5).nogc_initialize(); 87 88 foreach(i; 0..classList.length) { 89 classList[i] = nogc_new!TestClass(cast(int)i); 90 } 91 92 foreach(i; 0..classList.length) { 93 assert(classList[i].value == i); 94 } 95 } 96 97 @("nogc_zeroinit") 98 unittest { 99 uint var1 = 42; 100 uint[8] var2 = [1, 2, 3, 4, 5, 6, 7, 8]; 101 102 // Single var ref. 103 nogc_zeroinit(var1); 104 assert(var1 == 0); 105 106 // Var range 107 nogc_zeroinit(var2); 108 foreach(i, value; var2) { 109 assert(value == 0); 110 } 111 } 112 113 @("nogc_initialize") 114 unittest { 115 import numem.casting : reinterpret_cast; 116 117 // Pointers should be initialized to null. 118 void* ptr = cast(void*)0xDEADBEEF; 119 assert(nogc_initialize(ptr) is null); 120 121 // NOTE: non-finite floats, even if the same bit pattern will never be equal. 122 // as such we reinterpret it to a uint to convert it to a bit pattern. 123 float f = 42.0; 124 uint f_bitpattern = reinterpret_cast!uint(float.init); 125 assert(reinterpret_cast!uint(nogc_initialize(f)) == f_bitpattern); 126 127 // Basic scalars. 128 ubyte u8 = ubyte.max; 129 byte i8 = byte.max; 130 ushort u16 = ushort.max; 131 short i16 = short.max; 132 uint u32 = uint.max; 133 int i32 = int.max; 134 ulong u64 = ulong.max; 135 long i64 = long.max; 136 assert(nogc_initialize(u8) == 0); 137 assert(nogc_initialize(i8) == 0); 138 assert(nogc_initialize(u16) == 0); 139 assert(nogc_initialize(i16) == 0); 140 assert(nogc_initialize(u32) == 0); 141 assert(nogc_initialize(i32) == 0); 142 assert(nogc_initialize(u64) == 0); 143 assert(nogc_initialize(i64) == 0); 144 145 // Class references 146 TestClass tclass = reinterpret_cast!TestClass(cast(void*)0xDEADBEEF); 147 assert(cast(void*)nogc_initialize(tclass) is null); 148 149 // Create new un-constructed class, allocated on the stack. 150 import numem.core.traits : AllocSize; 151 ubyte[AllocSize!TestClass] allocSpace; 152 auto klass = nogc_initialize!TestClass(cast(void[])allocSpace); 153 154 // Attempt to use the class. 155 // NOTE: In this case due to the simplicitly of the class, the constructor 156 // is not neccesary to run; but eg. NuRefCounted *would* need it. 157 klass.value = 42; 158 assert(&klass.func1 !is null); 159 assert(klass.func1() == 42); 160 161 // Initializing struct should blit its initial state back in. 162 TestStruct strukt = TestStruct(1000); 163 assert(strukt.value == 1000); 164 assert(nogc_initialize(strukt).value == 0); 165 } 166 167 // Test creating destroy-with 168 @nu_destroywith!((ref value) { value.i = 42; }) 169 struct ValueT { 170 int i = 0; 171 } 172 173 @("nu_destroywith") 174 unittest { 175 ValueT myvalue; 176 177 nogc_delete(myvalue); 178 assert(myvalue.i == 42); 179 } 180 181 extern(C++) 182 class TestCPPClass { 183 @nogc: 184 int value; 185 186 this(int value) { this.value = value; } 187 ~this() { } 188 } 189 190 extern(C++) 191 struct TestCPPStruct { 192 @nogc: 193 int value; 194 } 195 196 @("C++ ctor-dtor") 197 unittest { 198 199 // throwing 200 TestCPPClass myClass = cpp_new!TestCPPClass(42); 201 assert(myClass !is null); 202 assert(myClass.value == 42); 203 cpp_delete(myClass); 204 assert(myClass is null); 205 206 TestCPPStruct* myStruct = cpp_new!TestCPPStruct(42); 207 assert(myStruct !is null); 208 assert(myStruct.value == 42); 209 cpp_delete(myStruct); 210 assert(myStruct is null); 211 212 // nothrow 213 myClass = cpp_trynew!TestCPPClass(42); 214 assert(myClass !is null); 215 assert(myClass.value == 42); 216 cpp_trydelete(myClass); 217 assert(myClass is null); 218 219 myStruct = cpp_trynew!TestCPPStruct(42); 220 assert(myStruct !is null); 221 assert(myStruct.value == 42); 222 cpp_trydelete(myStruct); 223 assert(myStruct is null); 224 225 } 226 227 @("basic types") 228 unittest { 229 import numem.core.memory : nu_dup; 230 231 string myString = "Hello, world!".nu_dup(); 232 nogc_delete(myString); 233 } 234 235 @("emplace disabled-postblit struct") 236 unittest { 237 __gshared N = 0; 238 static struct DisabledPostblit { 239 @nogc: 240 this(int a) { N += 1; } 241 ~this() { N += 2; } 242 @disable this(this); 243 } 244 245 { 246 DisabledPostblit s; 247 nogc_construct(s, 1); 248 } 249 assert(N == 3); 250 }