1 module memutils.tests; 2 import memutils.all; 3 version(none): 4 // Test hashmap, freelists 5 void hashmapFreeListTest(ALLOC)() { 6 assert(getAllocator!(ALLOC.ident)().bytesAllocated() == 0); 7 { 8 import std.stdio; 9 HashMapRef!(string, string, ALLOC) hm; 10 hm["hey"] = "you"; 11 assert(getAllocator!(ALLOC.ident)().bytesAllocated() > 0); 12 void hello(HashMapRef!(string, string, ALLOC) map) { 13 assert(map["hey"] == "you"); 14 map["you"] = "hey"; 15 } 16 hello(hm); 17 assert(hm["you"] == "hey"); 18 hm.clear(); 19 assert(hm.empty); 20 } 21 assert(getAllocator!(ALLOC.ident)().bytesAllocated() == 0); 22 23 } 24 25 // Test Vector, FreeLists & Array 26 void vectorArrayTest(ALLOC)() { 27 { 28 assert(getAllocator!(ALLOC.ident)().bytesAllocated() == 0); 29 Vector!(ubyte, ALLOC) data; 30 data ~= "Hello there"; 31 32 assert(getAllocator!(ALLOC.ident)().bytesAllocated() > 0); 33 assert(data[] == "Hello there"); 34 35 Vector!(Array!(ubyte, ALLOC), ALLOC) arr; 36 arr ~= data.dupr; 37 assert(arr[0] == data && arr[0][] == "Hello there"); 38 assert(arr[0] == data); 39 assert(arr[0][] == "Hello there"); 40 { 41 Vector!(ubyte, ALLOC) outbuf_; 42 ubyte[] reference; 43 int i; 44 for (i = 0; i < 16; i++) { 45 string abc = "abcdefghijklmnop"; 46 outbuf_ ~= cast(ubyte[])abc; 47 reference ~= cast(ubyte[]) abc; 48 49 assert(outbuf_[] == reference, "realloc error"); 50 } 51 } 52 Array!ubyte def_buf; 53 def_buf.reserve(8); 54 } 55 scope(failure) getAllocator!(ALLOC.ident)().printMap(); 56 assert(getAllocator!(ALLOC.ident)().bytesAllocated() == 0, "we got " ~ getAllocator!(ALLOC.ident)().bytesAllocated().to!string ~ " bytes, expected 0"); 57 } 58 59 // Test HashMap, FreeLists & Array 60 void hashmapComplexTest(ALLOC)() { 61 assert(getAllocator!(ALLOC.ident)().bytesAllocated() == 0); 62 { 63 HashMap!(string, Array!dchar, ALLOC) hm; 64 hm["hey"] = array("you"d); 65 hm["hello"] = hm["hey"]; 66 assert(*hm["hello"] is *hm["hey"]); 67 hm["hello"] = hm["hey"].dupr; 68 assert(*hm["hello"] !is *hm["hey"]); 69 auto vec = hm["hey"].dup; 70 assert(vec[] == hm["hey"][]); 71 72 73 assert(!__traits(compiles, { void handler(HashMap!(string, Array!dchar, ALLOC) hm) { } handler(hm); })); 74 } 75 76 assert(getAllocator!(ALLOC.ident)().bytesAllocated() == 0); 77 } 78 79 // Test RBTree 80 void rbTreeTest(ALLOC)() { 81 assert(getAllocator!(ALLOC.ident)().bytesAllocated() == 0); 82 { 83 RBTree!(int, "a < b", true, ALLOC) rbtree; 84 85 rbtree.insert( [50, 51, 52, 53, 54] ); 86 auto vec = rbtree.lowerBoundRange(52).vector(); 87 assert(vec[] == [50, 51]); 88 } 89 assert(getAllocator!(ALLOC.ident)().bytesAllocated() == 0); 90 } 91 92 // Test Unique 93 void uniqueTest(ALLOC)() { 94 assert(getAllocator!(ALLOC.ident)().bytesAllocated() == 0); 95 { 96 class A { int a; } 97 Unique!(A, ALLOC) a; 98 auto inst = ObjectAllocator!(A, ALLOC).alloc(); 99 A a_check = inst; 100 inst.a = 10; 101 auto bytes = getAllocator!(ALLOC.ident)().bytesAllocated(); 102 assert(bytes > 0); 103 a = inst; 104 assert(!inst); 105 assert(a.a == 10); 106 a.free(); 107 } 108 assert(getAllocator!(ALLOC.ident)().bytesAllocated() == 0); 109 } 110 111 // Test FreeList casting 112 void refCountedCastTest(ALLOC)() { 113 class A { 114 this() { a=0; } 115 protected int a; 116 protected void incr() { 117 a += 1; 118 } 119 public final int get() { 120 return a; 121 } 122 } 123 class B : A { 124 int c; 125 int d; 126 long e; 127 override protected void incr() { 128 a += 3; 129 } 130 } 131 alias ARef = RefCounted!(A, ALLOC); 132 alias BRef = RefCounted!(B, ALLOC); 133 134 assert(getAllocator!(ALLOC.ident)().bytesAllocated() == 0); 135 { 136 { 137 ARef a = ARef(); 138 a.incr(); 139 assert(a.get() == 1); 140 destructRecurse(a); /// destruction test 141 assert(!a); 142 } 143 { 144 ARef a; 145 assert(getAllocator!(ALLOC.ident)().bytesAllocated() == 0); 146 147 { /// cast test 148 BRef b = BRef(); 149 a = cast(ARef) b; 150 static void doIncr(ARef a_ref) { a_ref.incr(); } 151 doIncr(a); 152 assert(a.get() == 3, "Got: " ~ a.get().to!string); 153 } 154 ARef c = a; 155 assert(c.get() == 3); 156 destructRecurse(c); 157 assert(a); 158 } 159 } 160 // The B object allocates a lot more. If A destructor called B's dtor we get 0 here. 161 assert(getAllocator!(ALLOC.ident)().bytesAllocated() == 0); 162 } 163 164 /// test Circular buffer 165 void circularBufferTest(ALLOC)() { 166 auto buf1 = CircularBuffer!(ubyte, 0, ALLOC)(65536); 167 ubyte[] data = new ubyte[150]; 168 data[50] = 'b'; 169 buf1.put(data); 170 assert(buf1.length == 150); 171 assert(buf1[50] == 'b'); 172 173 // pulled from vibe.d - vibe.utils.array 174 auto buf = CircularBuffer!(int, 0, ALLOC)(5); 175 assert(buf.length == 0 && buf.freeSpace == 5); buf.put(1); // |1 . . . . 176 assert(buf.length == 1 && buf.freeSpace == 4); buf.put(2); // |1 2 . . . 177 assert(buf.length == 2 && buf.freeSpace == 3); buf.put(3); // |1 2 3 . . 178 assert(buf.length == 3 && buf.freeSpace == 2); buf.put(4); // |1 2 3 4 . 179 assert(buf.length == 4 && buf.freeSpace == 1); buf.put(5); // |1 2 3 4 5 180 assert(buf.length == 5 && buf.freeSpace == 0); 181 assert(buf.front == 1); 182 buf.popFront(); // .|2 3 4 5 183 assert(buf.front == 2); 184 buf.popFrontN(2); // . . .|4 5 185 assert(buf.front == 4); 186 assert(buf.length == 2 && buf.freeSpace == 3); 187 buf.put([6, 7, 8]); // 6 7 8|4 5 188 assert(buf.length == 5 && buf.freeSpace == 0); 189 int[5] dst; 190 buf.read(dst); // . . .|. . 191 assert(dst == [4, 5, 6, 7, 8]); 192 assert(buf.length == 0 && buf.freeSpace == 5); 193 buf.put([1, 2]); // . . .|1 2 194 assert(buf.length == 2 && buf.freeSpace == 3); 195 buf.read(dst[0 .. 2]); //|. . . . . 196 assert(dst[0 .. 2] == [1, 2]); 197 } 198 199 void dictionaryListTest(ALLOC)() 200 { 201 DictionaryList!(string, int, ALLOC) a; 202 a.insert("a", 1); 203 a.insert("a", 2); 204 assert(a["a"] == 1); 205 assert(a.getValuesAt("a") == [1, 2]); 206 //logTrace("Done getValuesAt"); 207 a["a"] = 3; 208 assert(a["a"] == 3); 209 assert(a.getValuesAt("a") == [3, 2]); 210 a.removeAll("a"); 211 assert(a.getValuesAt("a").length == 0); 212 assert(a.get("a", 4) == 4); 213 a.insert("b", 2); 214 a.insert("b", 1); 215 a.remove("b"); 216 assert(a.getValuesAt("b") == [1]); 217 218 DictionaryList!(string, int, ALLOC, false) b; 219 b.insert("a", 1); 220 b.insert("A", 2); 221 assert(b["A"] == 1); 222 assert(b.getValuesAt("a") == [1, 2]); 223 224 foreach (int i; 0 .. 15_000) { 225 b.insert("a", i); 226 } 227 228 // TODO: Fix case insensitive comparison on x86 229 assert(b.getValuesAt("a").length >= 15_001, "Found " ~ b.getValuesAt("a").length.to!string); 230 231 } 232 233 void propagateTests(alias fct)() { 234 logDebug("Testing ", fct.stringof); 235 fct!ThreadMem(); 236 } 237 238 void highLevelAllocTest() { 239 logDebug("Testing High Level Allocators"); 240 class A { 241 int a; 242 243 ~this() { 244 a = 0; 245 } 246 } 247 A a = ThreadMem.alloc!A(); 248 a.a = 10; 249 ThreadMem.free(a); 250 assert(!a); 251 252 A appAllocated() { 253 A c = ThreadMem.alloc!A(); 254 c.a = 10; 255 return c; 256 } 257 258 assert(appAllocated().a == 10); 259 260 ubyte[] ub = ThreadMem.alloc!(ubyte[])(150); 261 262 assert(ub.length == 150); 263 ub[50] = 'a'; 264 ThreadMem.free(ub); 265 assert(ub is null); 266 } 267 struct A { 268 int a; 269 270 ~this() { 271 //logDebug("Dtor called"); 272 a = 0; 273 } 274 } 275 276 void scopedTest() { 277 278 279 logDebug("Testing ScopedPool"); 280 281 A* num; 282 { 283 PoolStack.push(); 284 num = alloc!A(0); 285 num.a = 2; 286 //logDebug("Freezing"); 287 PoolStack.disable(); PoolStack.enable(); 288 PoolStack.freeze(1); 289 //logDebug("Frozen"); 290 assert(PoolStack.empty, "Stack is not empty"); 291 PoolStack.pop(); 292 assert(num.a == 0, "Dtor not called"); 293 } 294 { 295 auto pool1 = ScopedPool(); 296 num = alloc!A(0); 297 } 298 299 300 } 301 302 alias StringObjRef = RefCounted!StringObj; 303 struct StringObj 304 { 305 void check_value(ref StringObjRef str_obj) { 306 assert(str_obj.m_str == m_str); 307 } 308 this(string a) { 309 m_str = a; 310 } 311 string m_str = "abc"; 312 } 313 314 void stringObjRefTest(ALLOC)() { 315 StringObjRef str_ref = StringObjRef(); 316 StringObjRef str_ref2 = StringObjRef("abc"); 317 str_ref2 = str_ref; 318 str_ref.check_value(str_ref2); 319 } 320 void rbTreeTestTwo(ALLOC)() { 321 auto m_trusted_hashes = RBTree!string(); 322 323 324 m_trusted_hashes.insert("SHA-224"); 325 m_trusted_hashes.insert("SHA-256"); 326 m_trusted_hashes.insert("SHA-384"); 327 m_trusted_hashes.insert("SHA-512"); 328 string[] strings = ["SHA-224","SHA-256","SHA-384","SHA-512"]; 329 int i; 330 foreach(str; m_trusted_hashes) 331 { 332 assert(str == strings[i], "invalid string: " ~ str); 333 i++; 334 } 335 } 336 337 unittest { 338 propagateTests!stringObjRefTest(); 339 propagateTests!hashmapFreeListTest(); 340 propagateTests!vectorArrayTest(); 341 propagateTests!hashmapComplexTest(); 342 propagateTests!rbTreeTest(); 343 propagateTests!uniqueTest(); 344 propagateTests!refCountedCastTest(); 345 propagateTests!circularBufferTest(); 346 propagateTests!dictionaryListTest(); 347 propagateTests!rbTreeTestTwo(); 348 349 scopedTest(); 350 351 highLevelAllocTest(); 352 353 354 }