A game about forced loneliness, made by TACStudios
at master 868 lines 30 kB view raw
1using NUnit.Framework; 2using System; 3using System.Runtime.InteropServices; 4using Unity.Burst; 5using Unity.Collections; 6using Unity.Collections.LowLevel.Unsafe; 7using Unity.Collections.Tests; 8using Unity.Jobs; 9using Unity.Mathematics; 10using UnityEngine; 11using UnityEngine.TestTools; 12using System.Text.RegularExpressions; 13using Assert = FastAssert; 14 15internal class NativeBitArrayTests : CollectionsTestFixture 16{ 17 [Test] 18 public void NativeBitArray_Init() 19 { 20 var container = new NativeBitArray(0, Allocator.Persistent, NativeArrayOptions.ClearMemory); 21 Assert.True(container.IsCreated); 22 Assert.True(container.IsEmpty); 23 Assert.DoesNotThrow(() => container.Dispose()); 24 } 25 26 [Test] 27 public void NativeBitArray_Get_Set_Long() 28 { 29 var numBits = 256; 30 31 var test = new NativeBitArray(numBits, Allocator.Persistent, NativeArrayOptions.ClearMemory); 32 33 Assert.False(test.IsSet(123)); 34 test.Set(123, true); 35 Assert.True(test.IsSet(123)); 36 37 Assert.False(test.TestAll(0, numBits)); 38 Assert.False(test.TestNone(0, numBits)); 39 Assert.True(test.TestAny(0, numBits)); 40 Assert.AreEqual(1, test.CountBits(0, numBits)); 41 42 Assert.False(test.TestAll(0, 122)); 43 Assert.True(test.TestNone(0, 122)); 44 Assert.False(test.TestAny(0, 122)); 45 46 test.Clear(); 47 Assert.False(test.IsSet(123)); 48 Assert.AreEqual(0, test.CountBits(0, numBits)); 49 50 test.SetBits(40, true, 4); 51 Assert.AreEqual(4, test.CountBits(0, numBits)); 52 53 test.SetBits(0, true, numBits); 54 Assert.False(test.TestNone(0, numBits)); 55 Assert.True(test.TestAll(0, numBits)); 56 57 test.SetBits(0, false, numBits); 58 Assert.True(test.TestNone(0, numBits)); 59 Assert.False(test.TestAll(0, numBits)); 60 61 test.SetBits(123, true, 7); 62 Assert.True(test.TestAll(123, 7)); 63 64 test.Clear(); 65 test.SetBits(64, true, 64); 66 Assert.AreEqual(false, test.IsSet(63)); 67 Assert.AreEqual(true, test.TestAll(64, 64)); 68 Assert.AreEqual(false, test.IsSet(128)); 69 Assert.AreEqual(64, test.CountBits(64, 64)); 70 Assert.AreEqual(64, test.CountBits(0, numBits)); 71 72 test.Clear(); 73 test.SetBits(65, true, 62); 74 Assert.AreEqual(false, test.IsSet(64)); 75 Assert.AreEqual(true, test.TestAll(65, 62)); 76 Assert.AreEqual(false, test.IsSet(127)); 77 Assert.AreEqual(62, test.CountBits(64, 64)); 78 Assert.AreEqual(62, test.CountBits(0, numBits)); 79 80 test.Clear(); 81 test.SetBits(66, true, 64); 82 Assert.AreEqual(false, test.IsSet(65)); 83 Assert.AreEqual(true, test.TestAll(66, 64)); 84 Assert.AreEqual(false, test.IsSet(130)); 85 Assert.AreEqual(64, test.CountBits(66, 64)); 86 Assert.AreEqual(64, test.CountBits(0, numBits)); 87 88 test.Dispose(); 89 } 90 91 [Test] 92 public void NativeBitArray_Get_Set_Short() 93 { 94 var numBits = 31; 95 96 var test = new NativeBitArray(numBits, Allocator.Persistent, NativeArrayOptions.ClearMemory); 97 98 Assert.False(test.IsSet(13)); 99 test.Set(13, true); 100 Assert.True(test.IsSet(13)); 101 102 Assert.False(test.TestAll(0, numBits)); 103 Assert.False(test.TestNone(0, numBits)); 104 Assert.True(test.TestAny(0, numBits)); 105 Assert.AreEqual(1, test.CountBits(0, numBits)); 106 107 Assert.False(test.TestAll(0, 12)); 108 Assert.True(test.TestNone(0, 12)); 109 Assert.False(test.TestAny(0, 12)); 110 111 test.Clear(); 112 Assert.False(test.IsSet(13)); 113 Assert.AreEqual(0, test.CountBits(0, numBits)); 114 115 test.SetBits(4, true, 4); 116 Assert.AreEqual(4, test.CountBits(0, numBits)); 117 118 test.SetBits(0, true, numBits); 119 Assert.False(test.TestNone(0, numBits)); 120 Assert.True(test.TestAll(0, numBits)); 121 122 test.SetBits(0, false, numBits); 123 Assert.True(test.TestNone(0, numBits)); 124 Assert.False(test.TestAll(0, numBits)); 125 126 test.SetBits(13, true, 7); 127 Assert.True(test.TestAll(13, 7)); 128 129 test.Clear(); 130 test.SetBits(4, true, 4); 131 Assert.AreEqual(false, test.IsSet(3)); 132 Assert.AreEqual(true, test.TestAll(4, 4)); 133 Assert.AreEqual(false, test.IsSet(18)); 134 Assert.AreEqual(4, test.CountBits(4, 4)); 135 Assert.AreEqual(4, test.CountBits(0, numBits)); 136 137 test.Clear(); 138 test.SetBits(5, true, 2); 139 Assert.AreEqual(false, test.IsSet(4)); 140 Assert.AreEqual(true, test.TestAll(5, 2)); 141 Assert.AreEqual(false, test.IsSet(17)); 142 Assert.AreEqual(2, test.CountBits(4, 4)); 143 Assert.AreEqual(2, test.CountBits(0, numBits)); 144 145 test.Clear(); 146 test.SetBits(6, true, 4); 147 Assert.AreEqual(false, test.IsSet(5)); 148 Assert.AreEqual(true, test.TestAll(6, 4)); 149 Assert.AreEqual(false, test.IsSet(10)); 150 Assert.AreEqual(4, test.CountBits(6, 4)); 151 Assert.AreEqual(4, test.CountBits(0, numBits)); 152 153 test.Dispose(); 154 } 155 156 [Test] 157 public void NativeBitArray_Get_Set_Tiny() 158 { 159 var numBits = 7; 160 161 var test = new NativeBitArray(numBits, Allocator.Persistent, NativeArrayOptions.ClearMemory); 162 163 Assert.False(test.IsSet(3)); 164 test.Set(3, true); 165 Assert.True(test.IsSet(3)); 166 167 Assert.False(test.TestAll(0, numBits)); 168 Assert.False(test.TestNone(0, numBits)); 169 Assert.True(test.TestAny(0, numBits)); 170 Assert.AreEqual(1, test.CountBits(0, numBits)); 171 172 Assert.False(test.TestAll(0, 2)); 173 Assert.True(test.TestNone(0, 2)); 174 Assert.False(test.TestAny(0, 2)); 175 176 test.Clear(); 177 Assert.False(test.IsSet(3)); 178 Assert.AreEqual(0, test.CountBits(0, numBits)); 179 180 test.SetBits(3, true, 4); 181 Assert.AreEqual(4, test.CountBits(0, numBits)); 182 183 test.SetBits(0, true, numBits); 184 Assert.False(test.TestNone(0, numBits)); 185 Assert.True(test.TestAll(0, numBits)); 186 187 test.SetBits(0, false, numBits); 188 Assert.True(test.TestNone(0, numBits)); 189 Assert.False(test.TestAll(0, numBits)); 190 191 test.Dispose(); 192 } 193 194 [Test] 195 [TestRequiresDotsDebugOrCollectionChecks] 196 public unsafe void NativeBitArray_Throws() 197 { 198 var numBits = 256; 199 200 Assert.Throws<ArgumentException>(() => { new NativeBitArray(numBits, Allocator.None); }); 201 202 using (var test = new NativeBitArray(numBits, Allocator.Persistent, NativeArrayOptions.ClearMemory)) 203 { 204 Assert.DoesNotThrow(() => { test.TestAll(0, numBits); }); 205 Assert.DoesNotThrow(() => { test.TestAny(numBits - 1, numBits); }); 206 207 Assert.Throws<ArgumentException>(() => { test.IsSet(-1); }); 208 Assert.Throws<ArgumentException>(() => { test.IsSet(numBits); }); 209 Assert.Throws<ArgumentException>(() => { test.TestAny(0, 0); }); 210 Assert.Throws<ArgumentException>(() => { test.TestAny(numBits, 1); }); 211 Assert.Throws<ArgumentException>(() => { test.TestAny(numBits - 1, 0); }); 212 213 // GetBits numBits must be 1-64. 214 Assert.Throws<ArgumentException>(() => { test.GetBits(0, 0); }); 215 Assert.Throws<ArgumentException>(() => { test.GetBits(0, 65); }); 216 Assert.DoesNotThrow(() => { test.GetBits(63, 2); }); 217 } 218 } 219 220 void GetBitsTest(ref NativeBitArray test, int pos, int numBits) 221 { 222 test.SetBits(pos, true, numBits); 223 Assert.AreEqual(numBits, test.CountBits(0, test.Length)); 224 Assert.AreEqual(0xfffffffffffffffful >> (64 - numBits), test.GetBits(pos, numBits)); 225 test.Clear(); 226 } 227 228 [Test] 229 public void NativeBitArray_GetBits() 230 { 231 var numBits = 256; 232 233 var test = new NativeBitArray(numBits, Allocator.Persistent, NativeArrayOptions.ClearMemory); 234 235 GetBitsTest(ref test, 0, 5); 236 GetBitsTest(ref test, 1, 3); 237 GetBitsTest(ref test, 0, 63); 238 GetBitsTest(ref test, 0, 64); 239 GetBitsTest(ref test, 1, 63); 240 GetBitsTest(ref test, 1, 64); 241 GetBitsTest(ref test, 62, 5); 242 GetBitsTest(ref test, 127, 3); 243 GetBitsTest(ref test, 250, 6); 244 GetBitsTest(ref test, 254, 2); 245 246 test.Dispose(); 247 } 248 249 static void SetBitsTest(ref NativeBitArray test, int pos, ulong value, int numBits) 250 { 251 test.SetBits(pos, value, numBits); 252 if (value != test.GetBits(pos, numBits)) 253 throw new Exception("Assert.Equals(value, test.GetBits(pos, numBits)) failed"); 254 test.Clear(); 255 } 256 257 [Test] 258 public void NativeBitArray_SetBits() 259 { 260 var numBits = 256; 261 262 var test = new NativeBitArray(numBits, Allocator.Persistent, NativeArrayOptions.ClearMemory); 263 264 SetBitsTest(ref test, 0, 16, 5); 265 SetBitsTest(ref test, 1, 7, 3); 266 SetBitsTest(ref test, 1, 32, 64); 267 SetBitsTest(ref test, 62, 6, 5); 268 SetBitsTest(ref test, 127, 1, 3); 269 SetBitsTest(ref test, 60, 0xaa, 8); 270 271 test.Dispose(); 272 } 273 274 static void CopyBitsTest(ref NativeBitArray test, int dstPos, int srcPos, int numBits) 275 { 276 for (int pos = 0; pos < test.Length; pos += 64) 277 { 278 test.SetBits(pos, 0xaaaaaaaaaaaaaaaaul, 64); 279 } 280 281 test.SetBits(srcPos, true, numBits); 282 test.Copy(dstPos, srcPos, numBits); 283 Assert.AreEqual(true, test.TestAll(dstPos, numBits)); 284 285 for (int pos = 0; pos < test.Length; ++pos) 286 { 287 if ((pos >= dstPos && pos < dstPos + numBits) || 288 (pos >= srcPos && pos < srcPos + numBits)) 289 { 290 Assert.AreEqual(true, test.IsSet(pos)); 291 } 292 else 293 { 294 Assert.AreEqual((0 != (pos & 1)), test.IsSet(pos)); 295 } 296 } 297 298 test.Clear(); 299 } 300 301 static void CopyBitsTests(ref NativeBitArray test) 302 { 303 CopyBitsTest(ref test, 1, 16, 12); // short up to 64-bits copy 304 CopyBitsTest(ref test, 1, 80, 63); // short up to 64-bits copy 305 CopyBitsTest(ref test, 1, 11, 12); // short up to 64-bits copy overlapped 306 CopyBitsTest(ref test, 11, 1, 12); // short up to 64-bits copy overlapped 307 308 CopyBitsTest(ref test, 1, 16, 76); // short up to 128-bits copy 309 CopyBitsTest(ref test, 1, 80, 127); // short up to 128-bits copy 310 CopyBitsTest(ref test, 1, 11, 76); // short up to 128-bits copy overlapped 311 CopyBitsTest(ref test, 11, 1, 76); // short up to 128-bits copy overlapped 312 313 CopyBitsTest(ref test, 1, 81, 255); // long copy aligned 314 CopyBitsTest(ref test, 8, 0, 255); // long copy overlapped aligned 315 CopyBitsTest(ref test, 1, 80, 255); // long copy unaligned 316 CopyBitsTest(ref test, 80, 1, 255); // long copy overlapped unaligned 317 } 318 319 [Test] 320 public void NativeBitArray_Copy() 321 { 322 var numBits = 512; 323 324 var test = new NativeBitArray(numBits, Allocator.Persistent, NativeArrayOptions.ClearMemory); 325 CopyBitsTests(ref test); 326 327 test.Dispose(); 328 } 329 330 [Test] 331 public void UnsafeBitArray_Resize() 332 { 333 var test = new NativeBitArray(1, Allocator.Persistent, NativeArrayOptions.ClearMemory); 334 Assert.AreEqual(1, test.Length); 335 Assert.AreEqual(64, test.Capacity); 336 337 test.SetCapacity(200); // expand 338 Assert.AreEqual(1, test.Length); 339 Assert.AreEqual(256, test.Capacity); 340 341 test.Resize(100, NativeArrayOptions.ClearMemory); 342 Assert.True(test.TestNone(0, test.Length)); 343 344 // prepare survival test 345 test.Set(0, true); 346 test.Set(99, true); 347 Assert.True(test.IsSet(0)); 348 Assert.True(test.TestNone(1, 98)); 349 Assert.True(test.IsSet(99)); 350 351 test.SetCapacity(1000); // expand 352 Assert.AreEqual(100, test.Length); 353 Assert.AreEqual(1024, test.Capacity); 354 355 // test resize survival 356 Assert.True(test.IsSet(0)); 357 Assert.True(test.TestNone(1, 98)); 358 Assert.True(test.IsSet(99)); 359 360 // manual clear 361 test.Resize(1); 362 test.Set(0, false); 363 364 test.SetCapacity(200); // truncate capacity 365 Assert.AreEqual(1, test.Length); 366 Assert.AreEqual(256, test.Capacity); 367 368 test.Resize(512, NativeArrayOptions.ClearMemory); // resize 369 Assert.AreEqual(512, test.Length); 370 Assert.AreEqual(512, test.Capacity); 371 Assert.True(test.TestNone(0, test.Length)); 372 373 CopyBitsTests(ref test); 374 375 test.Resize(256); // truncate length 376 Assert.AreEqual(256, test.Length); 377 Assert.AreEqual(512, test.Capacity); 378 379 test.TrimExcess(); 380 Assert.AreEqual(256, test.Length); 381 Assert.AreEqual(256, test.Capacity); 382 383 test.Dispose(); 384 } 385 386 [Test] 387 public unsafe void NativeBitArray_CopyBetweenBitArrays() 388 { 389 var numBits = 512; 390 391 var str = new FixedString128Bytes("aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ"); 392 393 var test0 = NativeBitArrayUnsafeUtility.ConvertExistingDataToNativeBitArray(&str.bytes.offset0000, 64, Allocator.None); 394#if ENABLE_UNITY_COLLECTIONS_CHECKS 395 AtomicSafetyHandle ash = CollectionHelper.CreateSafetyHandle(Allocator.Temp); 396 NativeBitArrayUnsafeUtility.SetAtomicSafetyHandle(ref test0, ash); 397#endif 398 399 var test1 = new NativeBitArray(numBits, Allocator.Persistent, NativeArrayOptions.ClearMemory); 400 var test2 = new NativeBitArray(numBits, Allocator.Persistent, NativeArrayOptions.ClearMemory); 401 402 for (int pos = 0; pos < test0.Length; pos += 64) 403 { 404 test1.SetBits(pos, 0x5555555555555555ul, 64); 405 test2.SetBits(pos, 0xaaaaaaaaaaaaaaaaul, 64); 406 } 407 408 test1.Copy(1, ref test0, 205, 211); 409 test1.Copy(214, ref test0, 0, 205); 410 411 test2.Copy(205, ref test1, 1, 211); 412 test2.Copy(0, ref test1, 214, 205); 413 414 test0.Copy(0, ref test2, 0, 512); 415 416 Assert.AreEqual(str, "aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ"); 417 418 test0.Dispose(); 419 test1.Dispose(); 420 test2.Dispose(); 421 } 422 423 [Test] 424 [TestRequiresDotsDebugOrCollectionChecks] 425 public unsafe void NativeBitArray_Copy_Throws() 426 { 427 var numBits = 512; 428 429 var test = new NativeBitArray(numBits, Allocator.Persistent, NativeArrayOptions.ClearMemory); 430 431 Assert.Throws<ArgumentException>(() => { CopyBitsTest(ref test, 0, numBits - 1, 16); }); // short up to 64-bits copy out of bounds 432 Assert.Throws<ArgumentException>(() => { CopyBitsTest(ref test, numBits - 1, 0, 16); }); // short up to 64-bits copy out of bounds 433 434 Assert.Throws<ArgumentException>(() => { CopyBitsTest(ref test, 0, numBits - 1, 80); }); // short up to 128-bits copy out of bounds 435 Assert.Throws<ArgumentException>(() => { CopyBitsTest(ref test, numBits - 1, 0, 80); }); // short up to 128-bits copy out of bounds 436 437 Assert.Throws<ArgumentException>(() => { CopyBitsTest(ref test, 1, numBits - 7, 127); }); // long copy aligned 438 Assert.Throws<ArgumentException>(() => { CopyBitsTest(ref test, numBits - 7, 1, 127); }); // long copy aligned 439 440 Assert.Throws<ArgumentException>(() => { CopyBitsTest(ref test, 2, numBits - 1, 127); }); // long copy unaligned 441 Assert.Throws<ArgumentException>(() => { CopyBitsTest(ref test, numBits - 1, 2, 127); }); // long copy unaligned 442 443 test.Dispose(); 444 } 445 446 [Test] 447 public unsafe void NativeBitArray_Find() 448 { 449 var numBits = 512; 450 451 using (var test = new NativeBitArray(numBits, Allocator.Persistent, NativeArrayOptions.ClearMemory)) 452 { 453 test.SetBits(0, true, 11); 454 455 for (var i = 0; i < 256; ++i) 456 { 457 Assert.AreEqual(11, test.Find(0, i + 1)); 458 } 459 460 for (var j = 0; j < 64; ++j) 461 { 462 for (var i = 0; i < 256; ++i) 463 { 464 var numBitsToFind = 7 + i; 465 var pos = 37 + j; 466 467 test.SetBits(0, true, test.Length); 468 test.SetBits(pos, false, numBitsToFind); 469 470 Assert.AreEqual(pos, test.Find(0, numBitsToFind)); //, $"{j}/{i}: pos {pos}, numBitsToFind {numBitsToFind}"); 471 Assert.AreEqual(pos, test.Find(pos, numBitsToFind)); //, $"{j}/{i}:pos {pos}, numBitsToFind {numBitsToFind}"); 472 473 Assert.AreEqual(pos, test.Find(0, numBitsToFind)); //, $"{j}/{i}: pos {pos}, numBitsToFind {numBitsToFind}"); 474 Assert.AreEqual(pos, test.Find(pos, numBitsToFind)); //, $"{j}/{i}: pos {pos}, numBitsToFind {numBitsToFind}"); 475 476 Assert.IsTrue(test.TestNone(test.Find(0, numBitsToFind), numBitsToFind)); 477 478 Assert.AreEqual(int.MaxValue, test.Find(pos + 1, numBitsToFind)); //, $"{j}/{i}: pos {pos}, numBitsToFind {numBitsToFind}"); 479 } 480 } 481 } 482 } 483 484 [Test] 485 public unsafe void NativeBitArray_Find_With_Begin_End() 486 { 487 var numBits = 512; 488 489 using (var test = new NativeBitArray(numBits, Allocator.Persistent, NativeArrayOptions.ClearMemory)) 490 { 491 Assert.AreEqual(0, test.Find(0, 2, 1)); 492 Assert.AreEqual(1, test.Find(1, 2, 1)); 493 test.SetBits(0, true, 6); 494 Assert.AreEqual(int.MaxValue, test.Find(0, 2, 1)); 495 496 for (var j = 0; j < 64; ++j) 497 { 498 for (var i = 0; i < 256; ++i) 499 { 500 var numBitsToFind = 7 + i; 501 var padding = 11; 502 var begin = 37 + j; 503 var end = begin + padding + numBitsToFind; 504 var count = end - begin; 505 506 test.Clear(); 507 test.SetBits(begin, true, count); 508 test.SetBits(begin + padding + 1, false, numBitsToFind - 1); 509 510 Assert.AreEqual(begin + padding + 1, test.Find(begin, count, numBitsToFind - 1)); //, $"{j}/{i}: begin {begin}, end {end}, count {count}, numBitsToFind {numBitsToFind}"); 511 Assert.AreEqual(int.MaxValue, test.Find(begin, count, numBitsToFind)); //, $"{j}/{i}: begin {begin}, end {end}, count {count}, numBitsToFind {numBitsToFind}"); 512 } 513 } 514 } 515 } 516 517 [Test] 518 [TestRequiresDotsDebugOrCollectionChecks] 519 public unsafe void NativeBitArray_Find_Throws() 520 { 521 var numBits = 512; 522 523 using (var test = new NativeBitArray(numBits, Allocator.Persistent, NativeArrayOptions.ClearMemory)) 524 { 525 Assert.Throws<ArgumentException>(() => { test.Find(0, 0, 1); }); // empty range 526 Assert.Throws<ArgumentException>(() => { test.Find(0, 1, 0); }); // zero bits 527 Assert.Throws<ArgumentException>(() => { test.Find(0, 1, 2); }); // numBits is larger than range 528 Assert.Throws<ArgumentException>(() => { test.Find(10, 0, 0); }); // empty range, numBits is less than 1 529 Assert.Throws<ArgumentException>(() => { test.Find(1, 10, -2); }); // numBits can't be negative 530 } 531 } 532 533 [Test] 534 public void NativeBitArray_AsNativeArray_Byte() 535 { 536 var numBits = 64; 537 538 var test0 = new NativeBitArray(numBits, Allocator.Persistent, NativeArrayOptions.ClearMemory); 539 var test1 = test0.AsNativeArray<byte>(); 540 Assert.AreEqual(numBits / 8, test1.Length); 541 542 test1[0] = 0x10; 543 test1[1] = 0x32; 544 test1[2] = 0x54; 545 test1[3] = 0x76; 546 test1[4] = 0x98; 547 test1[5] = 0xba; 548 test1[6] = 0xdc; 549 test1[7] = 0xfe; 550 551 for (var i = 0; i < 16; ++i) 552 { 553 NUnit.Framework.Assert.AreEqual(i, test0.GetBits(i * 4, 4)); 554 } 555 556 test1.Dispose(); 557 test0.Dispose(); 558 } 559 560 [Test] 561 public void NativeBitArray_AsNativeArray_Uint() 562 { 563 var numBits = 64; 564 565 var test0 = new NativeBitArray(numBits, Allocator.Persistent, NativeArrayOptions.ClearMemory); 566 var test1 = test0.AsNativeArray<uint>(); 567 Assert.AreEqual(numBits / 32, test1.Length); 568 569 test1[0] = 0x76543210; 570 test1[1] = 0xfedcba98; 571 572 for (var i = 0; i < 16; ++i) 573 { 574 NUnit.Framework.Assert.AreEqual(i, test0.GetBits(i * 4, 4)); 575 } 576 577 test1.Dispose(); 578 test0.Dispose(); 579 } 580 581 [Test] 582 public void NativeBitArray_AsNativeArray_Ulong() 583 { 584 var numBits = 64; 585 586 var test0 = new NativeBitArray(numBits, Allocator.Persistent, NativeArrayOptions.ClearMemory); 587 var test1 = test0.AsNativeArray<ulong>(); 588 Assert.AreEqual(numBits / 64, test1.Length); 589 590 test1[0] = 0xfedcba9876543210; 591 592 for (var i = 0; i < 16; ++i) 593 { 594 NUnit.Framework.Assert.AreEqual(i, test0.GetBits(i * 4, 4)); 595 } 596 597 test1.Dispose(); 598 test0.Dispose(); 599 } 600 601 [StructLayout(LayoutKind.Explicit, Size = 16)] 602 internal struct SizeMismatch128 603 { 604 } 605 606 [StructLayout(LayoutKind.Explicit, Size=7)] 607 internal struct SizeMismatch56 608 { 609 } 610 611 [Test] 612 [TestRequiresDotsDebugOrCollectionChecks] 613 public void NativeBitArray_AsNativeArray_ThrowsOnSizeMismatch() 614 { 615 var numBits = 64; 616 617 var test0 = new NativeBitArray(numBits, Allocator.Persistent, NativeArrayOptions.ClearMemory); 618 619 Assert.Throws<InvalidOperationException>(() => { test0.AsNativeArray<SizeMismatch128>(); }); 620 Assert.Throws<InvalidOperationException>(() => { test0.AsNativeArray<SizeMismatch56>(); }); 621 622 test0.Dispose(); 623 } 624 625 // Burst error BC1071: Unsupported assert type 626 // [BurstCompile(CompileSynchronously = true)] 627 struct NativeBitArrayTestReadOnly : IJob 628 { 629 public NativeBitArray.ReadOnly reader; 630 631 public void Execute() 632 { 633 var rd = reader; 634 Assert.True(reader.IsSet(7)); 635 Assert.AreEqual(1, reader.CountBits(0, reader.Length)); 636 } 637 } 638 639 [Test] 640 [TestRequiresCollectionChecks] 641 public void NativeBitArray_ReadOnly() 642 { 643 var numBits = 256; 644 645 var reader = new NativeBitArray(numBits, Allocator.Persistent, NativeArrayOptions.ClearMemory); 646 reader.Set(7, true); 647 648 var readerJob = new NativeBitArrayTestReadOnly { reader = reader.AsReadOnly() }.Schedule(); 649 650 var from = new NativeBitArray(numBits, Allocator.Persistent, NativeArrayOptions.ClearMemory); 651 Assert.Throws<InvalidOperationException>(() => { reader.Copy(7, ref from, 30, 10); } /* attempt to write into reader after job is scheduled */); 652 from.Dispose(); 653 654 reader.Dispose(readerJob); 655 readerJob.Complete(); 656 } 657 658 [Test] 659 [TestRequiresCollectionChecks] 660 public void NativeBitArray_UseAfterFree_UsesCustomOwnerTypeName() 661 { 662 var numBits = 256; 663 664 var test = new NativeBitArray(numBits, Allocator.Persistent, NativeArrayOptions.ClearMemory); 665 SetBitsTest(ref test, 0, 16, 5); 666 test.Dispose(); 667 NUnit.Framework.Assert.That(() => test.IsSet(0), 668 Throws.Exception.TypeOf<ObjectDisposedException>() 669 .With.Message.Contains($"The {test.GetType()} has been deallocated")); 670 } 671 672 [Test] 673 [TestRequiresCollectionChecks] 674 public void NativeBitArray_AtomicSafetyHandle_AllocatorTemp_UniqueStaticSafetyIds() 675 { 676 var numBits = 256; 677 678 var test = new NativeBitArray(numBits, Allocator.Temp, NativeArrayOptions.ClearMemory); 679 680 // All collections that use Allocator.Temp share the same core AtomicSafetyHandle. 681 // This test verifies that containers can proceed to assign unique static safety IDs to each 682 // AtomicSafetyHandle value, which will not be shared by other containers using Allocator.Temp. 683 var test0 = new NativeBitArray(numBits, Allocator.Temp, NativeArrayOptions.ClearMemory); 684 var test1 = new NativeBitArray(numBits, Allocator.Temp, NativeArrayOptions.ClearMemory); 685 SetBitsTest(ref test0, 0, 16, 5); 686 test0.Dispose(); 687 688 NUnit.Framework.Assert.That(() => test0.IsSet(0), 689 Throws.Exception.With.TypeOf<ObjectDisposedException>() 690 .With.Message.Contains($"The {test0.GetType()} has been deallocated")); 691 SetBitsTest(ref test1, 0, 16, 5); 692 test1.Dispose(); 693 NUnit.Framework.Assert.That(() => test1.IsSet(0), 694 Throws.Exception.With.TypeOf<ObjectDisposedException>() 695 .With.Message.Contains($"The {test1.GetType()} has been deallocated")); 696 } 697 698 [BurstCompile(CompileSynchronously = true)] 699 struct NativeBitArrayCreateAndUseAfterFreeBurst : IJob 700 { 701 public void Execute() 702 { 703 var numBits = 256; 704 705 var test = new NativeBitArray(numBits, Allocator.Temp, NativeArrayOptions.ClearMemory); 706 SetBitsTest(ref test, 0, 16, 5); 707 test.Dispose(); 708 709 SetBitsTest(ref test, 0, 16, 5); 710 } 711 } 712 713 [Test] 714 [TestRequiresCollectionChecks] 715 public void NativeBitArray_CreateAndUseAfterFreeInBurstJob_UsesCustomOwnerTypeName() 716 { 717 // Make sure this isn't the first container of this type ever created, so that valid static safety data exists 718 var numBits = 256; 719 720 var test = new NativeBitArray(numBits, Allocator.Persistent, NativeArrayOptions.ClearMemory); 721 test.Dispose(); 722 723 var job = new NativeBitArrayCreateAndUseAfterFreeBurst 724 { 725 }; 726 727 // Two things: 728 // 1. This exception is logged, not thrown; thus, we use LogAssert to detect it. 729 // 2. Calling write operation after container.Dispose() emits an unintuitive error message. For now, all this test cares about is whether it contains the 730 // expected type name. 731 job.Run(); 732 LogAssert.Expect(LogType.Exception, 733 new Regex($"InvalidOperationException: The {Regex.Escape(test.GetType().ToString())} has been declared as \\[ReadOnly\\] in the job, but you are writing to it")); 734 } 735 void findWithPattern(ref NativeBitArray test, byte pattern, int numBits) 736 { 737 for (int pos = 0; pos < test.Length; pos += 8) 738 { 739 test.SetBits(pos, pattern, 8); 740 } 741 742 var bitCount = math.countbits((int)pattern); 743 var numEmptyBits = test.Length - (test.Length / 8 * bitCount); 744 745 for (int i = 0; i < numEmptyBits; i += numBits) 746 { 747 var pos = test.Find(0, numBits); 748 Assert.AreNotEqual(int.MaxValue, pos, $"{i}"); 749 test.SetBits(pos, true, numBits); 750 } 751 752 Assert.True(test.TestAll(0, test.Length)); 753 } 754 755 [Test] 756 public void NativeBitArray_FindWithPattern() 757 { 758 var test = new NativeBitArray(512, Allocator.Persistent, NativeArrayOptions.ClearMemory); 759 760 // Separated test for some more interesting patterns 761 findWithPattern(ref test, 0x81, 1); 762 findWithPattern(ref test, 0x81, 2); 763 findWithPattern(ref test, 0x81, 3); 764 findWithPattern(ref test, 0x81, 6); 765 findWithPattern(ref test, 0x88, 3); 766 findWithPattern(ref test, 0x99, 2); 767 findWithPattern(ref test, 0xaa, 1); 768 findWithPattern(ref test, 0xc3, 1); 769 findWithPattern(ref test, 0xc3, 2); 770 findWithPattern(ref test, 0xc3, 4); 771 findWithPattern(ref test, 0xe7, 1); 772 findWithPattern(ref test, 0xe7, 2); 773 774 // Test all patterns 775 for (int i = 0; i < 256; i++) 776 { 777 findWithPattern(ref test, (byte)i, 1); 778 } 779 780 test.Dispose(); 781 } 782 783 [Test] 784 public void NativeBitArray_FindInTinyBitArray() 785 { 786 var test = new NativeBitArray(3, Allocator.Persistent, NativeArrayOptions.ClearMemory); 787 Assert.AreEqual(3, test.Length); 788 789 test.SetBits(0, 0x55, test.Length); 790 791 Assert.AreEqual(1, test.Find(0, 1)); 792 Assert.AreEqual(1, test.Find(0, test.Length, 1)); 793 test.SetBits(1, true, 1); 794 Assert.True(test.TestAll(0, test.Length)); 795 Assert.AreEqual(int.MaxValue, test.Find(0, test.Length, 1)); 796 797 test.Dispose(); 798 } 799 800 [Test] 801 public void NativeBitArray_FindLastUnsetBit([NUnit.Framework.Range(1, 64)] int numBits) 802 { 803 using (var bits = new NativeBitArray(numBits, Allocator.Persistent)) 804 { 805 // Set all bits to one then unset a single bit to find. 806 for (int i = 0; i < numBits; ++i) 807 { 808 bits.SetBits(0, true, numBits); 809 bits.Set(i, false); 810 Assert.AreEqual(i, bits.Find(0, 1)); 811 } 812 } 813 } 814 815 [Test] 816 public void NativeBitArray_CustomAllocatorTest() 817 { 818 AllocatorManager.Initialize(); 819 var allocatorHelper = new AllocatorHelper<CustomAllocatorTests.CountingAllocator>(AllocatorManager.Persistent); 820 allocatorHelper.Allocator.Initialize(); 821 using (var bitset = new NativeBitArray(1, allocatorHelper.Allocator.Handle)) 822 { 823 } 824 825 Assert.IsTrue(allocatorHelper.Allocator.WasUsed); 826 allocatorHelper.Allocator.Dispose(); 827 allocatorHelper.Dispose(); 828 AllocatorManager.Shutdown(); 829 } 830 831 [BurstCompile] 832 struct BurstedCustomAllocatorJob : IJob 833 { 834 [NativeDisableUnsafePtrRestriction] 835 public unsafe CustomAllocatorTests.CountingAllocator* Allocator; 836 837 public void Execute() 838 { 839 unsafe 840 { 841 using (var container = new NativeBitArray(1, Allocator->Handle)) 842 { 843 } 844 } 845 } 846 } 847 848 [Test] 849 public unsafe void NativeBitArray_BurstedCustomAllocatorTest() 850 { 851 AllocatorManager.Initialize(); 852 var allocatorHelper = new AllocatorHelper<CustomAllocatorTests.CountingAllocator>(AllocatorManager.Persistent); 853 ref var allocator = ref allocatorHelper.Allocator; 854 allocatorHelper.Allocator.Initialize(); 855 856 var allocatorPtr = (CustomAllocatorTests.CountingAllocator*)UnsafeUtility.AddressOf<CustomAllocatorTests.CountingAllocator>(ref allocator); 857 unsafe 858 { 859 var handle = new BurstedCustomAllocatorJob {Allocator = allocatorPtr}.Schedule(); 860 handle.Complete(); 861 } 862 863 Assert.IsTrue(allocator.WasUsed); 864 allocator.Dispose(); 865 allocatorHelper.Dispose(); 866 AllocatorManager.Shutdown(); 867 } 868}