A game about forced loneliness, made by TACStudios
at master 1030 lines 38 kB view raw
1using NUnit.Framework; 2using Unity.Collections; 3using Unity.Collections.LowLevel.Unsafe; 4using Unity.Collections.Tests; 5using Unity.Jobs; 6using System; 7using Unity.Jobs.Tests.ManagedJobs; 8 9[assembly: RegisterGenericJobType(typeof(GenericContainerJob<NativeArray<int>>))] 10[assembly: RegisterGenericJobType(typeof(GenericContainerJob<UnsafeAppendBuffer>))] 11[assembly: RegisterGenericJobType(typeof(GenericContainerJob<NativeBitArray>))] 12[assembly: RegisterGenericJobType(typeof(GenericContainerJob<UnsafeBitArray>))] 13[assembly: RegisterGenericJobType(typeof(GenericContainerJob<NativeHashMap<int, int>>))] 14[assembly: RegisterGenericJobType(typeof(GenericContainerJob<UnsafeHashMap<int, int>>))] 15[assembly: RegisterGenericJobType(typeof(GenericContainerJob<NativeHashSet<int>>))] 16[assembly: RegisterGenericJobType(typeof(GenericContainerJob<UnsafeHashSet<int>>))] 17[assembly: RegisterGenericJobType(typeof(GenericContainerJob<NativeList<int>>))] 18[assembly: RegisterGenericJobType(typeof(GenericContainerJob<UnsafeList<int>>))] 19[assembly: RegisterGenericJobType(typeof(GenericContainerJob<UnsafePtrList<int>>))] 20[assembly: RegisterGenericJobType(typeof(GenericContainerJob<NativeParallelHashMap<int, int>>))] 21[assembly: RegisterGenericJobType(typeof(GenericContainerJob<UnsafeParallelHashMap<int, int>>))] 22[assembly: RegisterGenericJobType(typeof(GenericContainerJob<NativeParallelHashSet<int>>))] 23[assembly: RegisterGenericJobType(typeof(GenericContainerJob<UnsafeParallelHashSet<int>>))] 24[assembly: RegisterGenericJobType(typeof(GenericContainerJob<NativeParallelMultiHashMap<int, int>>))] 25[assembly: RegisterGenericJobType(typeof(GenericContainerJob<UnsafeParallelMultiHashMap<int, int>>))] 26[assembly: RegisterGenericJobType(typeof(GenericContainerJob<NativeQueue<int>>))] 27[assembly: RegisterGenericJobType(typeof(GenericContainerJob<UnsafeQueue<int>>))] 28[assembly: RegisterGenericJobType(typeof(GenericContainerJob<NativeReference<int>>))] 29[assembly: RegisterGenericJobType(typeof(GenericContainerJob<NativeRingQueue<int>>))] 30[assembly: RegisterGenericJobType(typeof(GenericContainerJob<UnsafeRingQueue<int>>))] 31[assembly: RegisterGenericJobType(typeof(GenericContainerJob<NativeStream>))] 32[assembly: RegisterGenericJobType(typeof(GenericContainerJob<UnsafeStream>))] 33[assembly: RegisterGenericJobType(typeof(GenericContainerJob<NativeText>))] 34[assembly: RegisterGenericJobType(typeof(GenericContainerJob<UnsafeText>))] 35 36internal struct GenericContainerJob<T> : IJob 37{ 38 public T data; 39 public void Execute() 40 { 41 // We just care about creating job dependencies 42 } 43} 44 45internal struct GenericContainerReadonlyJob<T> : IJob 46{ 47 [ReadOnly] public T data; 48 public void Execute() 49 { 50 // We just care about creating job dependencies 51 } 52} 53 54internal class GenericContainerTests : CollectionsTestFixture 55{ 56 UnsafeAppendBuffer CreateEmpty_UnsafeAppendBuffer() 57 { 58 var container = new UnsafeAppendBuffer(0, 8, Allocator.Persistent); 59 Assert.True(container.IsCreated); 60 Assert.True(container.IsEmpty); 61 return container; 62 } 63 64 NativeBitArray CreateEmpty_NativeBitArray() 65 { 66 var container = new NativeBitArray(0, Allocator.Persistent); 67 Assert.True(container.IsCreated); 68 Assert.True(container.IsEmpty); 69 return container; 70 } 71 72 void NativeBitArray_IsCreated_Uninitialized() 73 { 74 NativeBitArray container = default; 75 Assert.False(container.IsCreated); 76 Assert.True(container.IsEmpty); 77 78 NativeBitArray.ReadOnly containerRo = default; 79 Assert.False(containerRo.IsCreated); 80 Assert.True(containerRo.IsEmpty); 81 } 82 83 UnsafeBitArray CreateEmpty_UnsafeBitArray() 84 { 85 var container = new UnsafeBitArray(0, Allocator.Persistent); 86 Assert.True(container.IsCreated); 87 Assert.True(container.IsEmpty); 88 return container; 89 } 90 91 void UnsafeBitArray_IsCreated_Uninitialized() 92 { 93 UnsafeBitArray container = default; 94 Assert.False(container.IsCreated); 95 Assert.True(container.IsEmpty); 96 97 UnsafeBitArray.ReadOnly containerRo = default; 98 Assert.False(containerRo.IsCreated); 99 Assert.True(containerRo.IsEmpty); 100 } 101 102 NativeHashMap<int, int> CreateEmpty_NativeHashMap() 103 { 104 var container = new NativeHashMap<int, int>(0, Allocator.Persistent); 105 Assert.True(container.IsCreated); 106 Assert.True(container.IsEmpty); 107 return container; 108 } 109 110 void NativeHashMap_IsCreated_Uninitialized() 111 { 112 NativeHashMap<int, int> container = default; 113 Assert.False(container.IsCreated); 114 Assert.True(container.IsEmpty); 115 116 NativeHashMap<int, int>.ReadOnly containerRo = default; 117 Assert.False(containerRo.IsCreated); 118 Assert.True(containerRo.IsEmpty); 119 } 120 121 UnsafeHashMap<int, int> CreateEmpty_UnsafeHashMap() 122 { 123 var container = new UnsafeHashMap<int, int>(0, Allocator.Persistent); 124 Assert.True(container.IsCreated); 125 Assert.True(container.IsEmpty); 126 return container; 127 } 128 129 void UnsafeHashMap_IsCreated_Uninitialized() 130 { 131 UnsafeHashMap<int, int> container = default; 132 Assert.False(container.IsCreated); 133 Assert.True(container.IsEmpty); 134 135 UnsafeHashMap<int, int>.ReadOnly containerRo = default; 136 Assert.False(containerRo.IsCreated); 137 Assert.True(containerRo.IsEmpty); 138 } 139 140 NativeHashSet<int> CreateEmpty_NativeHashSet() 141 { 142 var container = new NativeHashSet<int>(0, Allocator.Persistent); 143 Assert.True(container.IsCreated); 144 Assert.True(container.IsEmpty); 145 return container; 146 } 147 148 void NativeHashSet_IsCreated_Uninitialized() 149 { 150 NativeHashSet<int> container = default; 151 Assert.False(container.IsCreated); 152 Assert.True(container.IsEmpty); 153 154 NativeHashSet<int>.ReadOnly containerRo = default; 155 Assert.False(containerRo.IsCreated); 156 Assert.True(containerRo.IsEmpty); 157 } 158 159 UnsafeHashSet<int> CreateEmpty_UnsafeHashSet() 160 { 161 var container = new UnsafeHashSet<int>(0, Allocator.Persistent); 162 Assert.True(container.IsCreated); 163 Assert.True(container.IsEmpty); 164 return container; 165 } 166 167 void UnsafeHashSet_IsCreated_Uninitialized() 168 { 169 UnsafeHashSet<int> container = default; 170 Assert.False(container.IsCreated); 171 Assert.True(container.IsEmpty); 172 173 UnsafeHashSet<int>.ReadOnly containerRo = default; 174 Assert.False(containerRo.IsCreated); 175 Assert.True(containerRo.IsEmpty); 176 } 177 178 NativeList<int> CreateEmpty_NativeList() 179 { 180 var container = new NativeList<int>(0, Allocator.Persistent); 181 Assert.True(container.IsCreated); 182 Assert.True(container.IsEmpty); 183 return container; 184 } 185 186 void NativeList_IsCreated_Uninitialized() 187 { 188 NativeList<int> container = default; 189 Assert.False(container.IsCreated); 190 Assert.True(container.IsEmpty); 191 192 NativeArray<int>.ReadOnly containerRo = default; 193 Assert.False(containerRo.IsCreated); 194 // NativeArray doesn't have IsEmpty property -> Assert.True(containerRo.IsEmpty); 195 } 196 197 UnsafeList<int> CreateEmpty_UnsafeList() 198 { 199 var container = new UnsafeList<int>(0, Allocator.Persistent); 200 Assert.True(container.IsCreated); 201 Assert.True(container.IsEmpty); 202 return container; 203 } 204 205 void UnsafeList_IsCreated_Uninitialized() 206 { 207 UnsafeList<int> container = default; 208 Assert.False(container.IsCreated); 209 Assert.True(container.IsEmpty); 210 211 UnsafeList<int>.ReadOnly containerRo = default; 212 Assert.False(containerRo.IsCreated); 213 Assert.True(containerRo.IsEmpty); 214 } 215 216 UnsafePtrList<int> CreateEmpty_UnsafePtrList() 217 { 218 var container = new UnsafePtrList<int>(0, Allocator.Persistent); 219 Assert.True(container.IsCreated); 220 Assert.True(container.IsEmpty); 221 return container; 222 } 223 224 void UnsafePtrList_IsCreated_Uninitialized() 225 { 226 UnsafePtrList<int> container = default; 227 Assert.False(container.IsCreated); 228 Assert.True(container.IsEmpty); 229 230 UnsafePtrList<int>.ReadOnly containerRo = default; 231 Assert.False(containerRo.IsCreated); 232 Assert.True(containerRo.IsEmpty); 233 } 234 235 NativeParallelHashMap<int, int> CreateEmpty_NativeParallelHashMap() 236 { 237 var container = new NativeParallelHashMap<int, int>(0, Allocator.Persistent); 238 Assert.True(container.IsCreated); 239 Assert.True(container.IsEmpty); 240 return container; 241 } 242 243 void NativeParallelHashMap_IsCreated_Uninitialized() 244 { 245 NativeParallelHashMap<int, int> container = default; 246 Assert.False(container.IsCreated); 247 Assert.True(container.IsEmpty); 248 249 NativeParallelHashMap<int, int>.ReadOnly containerRo = default; 250 Assert.False(containerRo.IsCreated); 251 Assert.True(containerRo.IsEmpty); 252 } 253 254 UnsafeParallelHashMap<int, int> CreateEmpty_UnsafeParallelHashMap() 255 { 256 var container = new UnsafeParallelHashMap<int, int>(0, Allocator.Persistent); 257 Assert.True(container.IsCreated); 258 Assert.True(container.IsEmpty); 259 return container; 260 } 261 262 void UnsafeParallelHashMap_IsCreated_Uninitialized() 263 { 264 UnsafeParallelHashMap<int, int> container = default; 265 Assert.False(container.IsCreated); 266 Assert.True(container.IsEmpty); 267 268 UnsafeParallelHashMap<int, int>.ReadOnly containerRo = default; 269 Assert.False(containerRo.IsCreated); 270 Assert.True(containerRo.IsEmpty); 271 } 272 273 NativeParallelHashSet<int> CreateEmpty_NativeParallelHashSet() 274 { 275 var container = new NativeParallelHashSet<int>(0, Allocator.Persistent); 276 Assert.True(container.IsCreated); 277 Assert.True(container.IsEmpty); 278 return container; 279 } 280 281 void NativeParallelHashSet_IsCreated_Uninitialized() 282 { 283 NativeParallelHashSet<int> container = default; 284 Assert.False(container.IsCreated); 285 Assert.True(container.IsEmpty); 286 287 NativeParallelHashSet<int>.ReadOnly containerRo = default; 288 Assert.False(containerRo.IsCreated); 289 Assert.True(containerRo.IsEmpty); 290 } 291 292 UnsafeParallelHashSet<int> CreateEmpty_UnsafeParallelHashSet() 293 { 294 var container = new UnsafeParallelHashSet<int>(0, Allocator.Persistent); 295 Assert.True(container.IsCreated); 296 Assert.True(container.IsEmpty); 297 return container; 298 } 299 300 void UnsafeParallelHashSet_IsCreated_Uninitialized() 301 { 302 UnsafeParallelHashSet<int> container = default; 303 Assert.False(container.IsCreated); 304 Assert.True(container.IsEmpty); 305 306 UnsafeParallelHashSet<int>.ReadOnly containerRo = default; 307 Assert.False(containerRo.IsCreated); 308 Assert.True(containerRo.IsEmpty); 309 } 310 311 NativeParallelMultiHashMap<int, int> CreateEmpty_NativeParallelMultiHashMap() 312 { 313 var container = new NativeParallelMultiHashMap<int, int>(0, Allocator.Persistent); 314 Assert.True(container.IsCreated); 315 Assert.True(container.IsEmpty); 316 return container; 317 } 318 319 void NativeParallelMultiHashMap_IsCreated_Uninitialized() 320 { 321 NativeParallelMultiHashMap<int, int> container = default; 322 Assert.False(container.IsCreated); 323 Assert.True(container.IsEmpty); 324 325 NativeParallelMultiHashMap<int, int>.ReadOnly containerRo = default; 326 Assert.False(containerRo.IsCreated); 327 Assert.True(containerRo.IsEmpty); 328 } 329 330 UnsafeParallelMultiHashMap<int, int> CreateEmpty_UnsafeParallelMultiHashMap() 331 { 332 var container = new UnsafeParallelMultiHashMap<int, int>(0, Allocator.Persistent); 333 Assert.True(container.IsCreated); 334 Assert.True(container.IsEmpty); 335 return container; 336 } 337 338 void UnsafeParallelMultiHashMap_IsCreated_Uninitialized() 339 { 340 UnsafeParallelMultiHashMap<int, int> container = default; 341 Assert.False(container.IsCreated); 342 Assert.True(container.IsEmpty); 343 344 UnsafeParallelMultiHashMap<int, int>.ReadOnly containerRo = default; 345 Assert.False(containerRo.IsCreated); 346 Assert.True(containerRo.IsEmpty); 347 } 348 349 NativeQueue<int> CreateEmpty_NativeQueue() 350 { 351 var container = new NativeQueue<int>(Allocator.Persistent); 352 Assert.True(container.IsCreated); 353 Assert.True(container.IsEmpty()); 354 return container; 355 } 356 357 void NativeQueue_IsCreated_Uninitialized() 358 { 359 NativeQueue<int> container = default; 360 Assert.False(container.IsCreated); 361 362 NativeQueue<int>.ReadOnly containerRo = default; 363 Assert.False(containerRo.IsCreated); 364 } 365 366 UnsafeQueue<int> CreateEmpty_UnsafeQueue() 367 { 368 var container = new UnsafeQueue<int>(Allocator.Persistent); 369 Assert.True(container.IsCreated); 370 Assert.True(container.IsEmpty()); 371 return container; 372 } 373 374 void UnsafeQueue_IsCreated_Uninitialized() 375 { 376 UnsafeQueue<int> container = default; 377 Assert.False(container.IsCreated); 378 379 UnsafeQueue<int>.ReadOnly containerRo = default; 380 Assert.False(containerRo.IsCreated); 381 } 382 383 NativeReference<int> CreateEmpty_NativeReference() 384 { 385 var container = new NativeReference<int>(Allocator.Persistent); 386 Assert.True(container.IsCreated); 387 return container; 388 } 389 390 NativeRingQueue<int> CreateEmpty_NativeRingQueue() 391 { 392 var container = new NativeRingQueue<int>(0, Allocator.Persistent); 393 Assert.True(container.IsCreated); 394 Assert.True(container.IsEmpty); 395 return container; 396 } 397 398 void NativeRingQueue_IsCreated_Uninitialized() 399 { 400 NativeRingQueue<int> container = default; 401 Assert.False(container.IsCreated); 402 Assert.True(container.IsEmpty); 403 } 404 405 UnsafeRingQueue<int> CreateEmpty_UnsafeRingQueue() 406 { 407 var container = new UnsafeRingQueue<int>(0, Allocator.Persistent); 408 Assert.True(container.IsCreated); 409 Assert.True(container.IsEmpty); 410 return container; 411 } 412 413 void UnsafeRingQueue_IsCreated_Uninitialized() 414 { 415 UnsafeRingQueue<int> container = default; 416 Assert.False(container.IsCreated); 417 Assert.True(container.IsEmpty); 418 } 419 420 NativeStream CreateEmpty_NativeStream() 421 { 422 var container = new NativeStream(0, Allocator.Persistent); 423 Assert.True(container.IsCreated); 424 Assert.True(container.IsEmpty()); 425 return container; 426 } 427 428 UnsafeStream CreateEmpty_UnsafeStream() 429 { 430 var container = new UnsafeStream(0, Allocator.Persistent); 431 Assert.True(container.IsCreated); 432 Assert.True(container.IsEmpty()); 433 return container; 434 } 435 436 NativeText CreateEmpty_NativeText() 437 { 438 var container = new NativeText(0, Allocator.Persistent); 439 Assert.True(container.IsCreated); 440 Assert.True(container.IsEmpty); 441 return container; 442 } 443 444 UnsafeText CreateEmpty_UnsafeText() 445 { 446 var container = new UnsafeText(0, Allocator.Persistent); 447 Assert.True(container.IsCreated); 448 Assert.True(container.IsEmpty); 449 return container; 450 } 451 452 //------------------------------------------------------------------------------------------------------- 453 454 [Test] 455 public void Test_IsCreated_Uninitialized() 456 { 457 NativeBitArray_IsCreated_Uninitialized(); 458 UnsafeBitArray_IsCreated_Uninitialized(); 459 460 NativeHashMap_IsCreated_Uninitialized(); 461 UnsafeHashMap_IsCreated_Uninitialized(); 462 463 NativeHashSet_IsCreated_Uninitialized(); 464 UnsafeHashSet_IsCreated_Uninitialized(); 465 466 NativeList_IsCreated_Uninitialized(); 467 UnsafeList_IsCreated_Uninitialized(); 468 469 UnsafePtrList_IsCreated_Uninitialized(); 470 471 NativeParallelHashMap_IsCreated_Uninitialized(); 472 UnsafeParallelHashMap_IsCreated_Uninitialized(); 473 474 NativeParallelHashSet_IsCreated_Uninitialized(); 475 UnsafeParallelHashSet_IsCreated_Uninitialized(); 476 477 NativeParallelMultiHashMap_IsCreated_Uninitialized(); 478 UnsafeParallelMultiHashMap_IsCreated_Uninitialized(); 479 480 NativeQueue_IsCreated_Uninitialized(); 481 UnsafeQueue_IsCreated_Uninitialized(); 482 483 NativeRingQueue_IsCreated_Uninitialized(); 484 UnsafeRingQueue_IsCreated_Uninitialized(); 485 } 486 487 //------------------------------------------------------------------------------------------------------- 488 489 void Test_Dispose_Uninitialized<T>() 490 where T : INativeDisposable 491 { 492 T uninitialized = default; 493 Assert.DoesNotThrow(() => uninitialized.Dispose()); 494 Assert.DoesNotThrow(() => uninitialized.Dispose(default)); 495 } 496 497 [Test] 498 public void INativeDisposable_Dispose_Uninitialized() 499 { 500 Test_Dispose_Uninitialized<NativeBitArray>(); 501 Test_Dispose_Uninitialized<NativeHashMap<int, int>>(); 502 Test_Dispose_Uninitialized<NativeHashSet<int>>(); 503 Test_Dispose_Uninitialized<NativeList<int>>(); 504 Test_Dispose_Uninitialized<NativeParallelHashMap<int, int>>(); 505 Test_Dispose_Uninitialized<NativeParallelHashSet<int>>(); 506 Test_Dispose_Uninitialized<NativeParallelMultiHashMap<int, int>>(); 507 Test_Dispose_Uninitialized<NativeQueue<int>>(); 508 Test_Dispose_Uninitialized<NativeReference<int>>(); 509 Test_Dispose_Uninitialized<NativeRingQueue<int>>(); 510 Test_Dispose_Uninitialized<NativeStream>(); 511 Test_Dispose_Uninitialized<NativeText>(); 512 513 Test_Dispose_Uninitialized<UnsafeAppendBuffer>(); 514 Test_Dispose_Uninitialized<UnsafeBitArray>(); 515 Test_Dispose_Uninitialized<UnsafeHashMap<int, int>>(); 516 Test_Dispose_Uninitialized<UnsafeHashSet<int>>(); 517 Test_Dispose_Uninitialized<UnsafeList<int>>(); 518 Test_Dispose_Uninitialized<UnsafePtrList<int>>(); 519 Test_Dispose_Uninitialized<UnsafeParallelHashMap<int, int>>(); 520 Test_Dispose_Uninitialized<UnsafeParallelHashSet<int>>(); 521 Test_Dispose_Uninitialized<UnsafeParallelMultiHashMap<int, int>>(); 522 Test_Dispose_Uninitialized<UnsafeQueue<int>>(); 523 Test_Dispose_Uninitialized<UnsafeRingQueue<int>>(); 524 Test_Dispose_Uninitialized<UnsafeStream>(); 525 Test_Dispose_Uninitialized<UnsafeText>(); 526 } 527 528 //------------------------------------------------------------------------------------------------------- 529 530 void Test_Unsafe_Double_Dispose<T>(T container) 531 where T : INativeDisposable 532 { 533 Assert.DoesNotThrow(() => container.Dispose()); 534 Assert.DoesNotThrow(() => container.Dispose()); 535 } 536 537 void Test_Native_Double_Dispose<T>(T container) 538 where T : INativeDisposable 539 { 540 Assert.DoesNotThrow(() => container.Dispose()); 541#if ENABLE_UNITY_COLLECTIONS_CHECKS 542 Assert.Throws<ObjectDisposedException>(() => container.Dispose()); 543#else 544 Assert.DoesNotThrow(() => container.Dispose()); 545#endif 546 } 547 548 [Test] 549 public void INativeDisposable_Init_Double_Dispose() 550 { 551 Test_Native_Double_Dispose(CreateEmpty_NativeBitArray()); 552 Test_Native_Double_Dispose(CreateEmpty_NativeHashMap()); 553 Test_Native_Double_Dispose(CreateEmpty_NativeHashSet()); 554 Test_Native_Double_Dispose(CreateEmpty_NativeList()); 555 Test_Native_Double_Dispose(CreateEmpty_NativeParallelHashMap()); 556 Test_Native_Double_Dispose(CreateEmpty_NativeParallelHashSet()); 557 Test_Native_Double_Dispose(CreateEmpty_NativeParallelMultiHashMap()); 558 Test_Native_Double_Dispose(CreateEmpty_NativeQueue()); 559 Test_Native_Double_Dispose(CreateEmpty_NativeReference()); 560 Test_Native_Double_Dispose(CreateEmpty_NativeRingQueue()); 561 Test_Native_Double_Dispose(CreateEmpty_NativeStream()); 562 Test_Native_Double_Dispose(CreateEmpty_NativeText()); 563 564 Test_Unsafe_Double_Dispose(CreateEmpty_UnsafeAppendBuffer()); 565 Test_Unsafe_Double_Dispose(CreateEmpty_UnsafeBitArray()); 566 Test_Unsafe_Double_Dispose(CreateEmpty_UnsafeHashMap()); 567 Test_Unsafe_Double_Dispose(CreateEmpty_UnsafeHashSet()); 568 Test_Unsafe_Double_Dispose(CreateEmpty_UnsafeList()); 569 Test_Unsafe_Double_Dispose(CreateEmpty_UnsafePtrList()); 570 Test_Unsafe_Double_Dispose(CreateEmpty_UnsafeParallelHashMap()); 571 Test_Unsafe_Double_Dispose(CreateEmpty_UnsafeParallelHashSet()); 572 Test_Unsafe_Double_Dispose(CreateEmpty_UnsafeParallelMultiHashMap()); 573 Test_Unsafe_Double_Dispose(CreateEmpty_UnsafeQueue()); 574 Test_Unsafe_Double_Dispose(CreateEmpty_UnsafeRingQueue()); 575 Test_Unsafe_Double_Dispose(CreateEmpty_UnsafeStream()); 576 Test_Unsafe_Double_Dispose(CreateEmpty_UnsafeText()); 577 } 578 579 //------------------------------------------------------------------------------------------------------- 580 581 void Test_Unsafe_Double_Dispose_Job<T>(T container) 582 where T : INativeDisposable 583 { 584 Assert.DoesNotThrow(() => container.Dispose(default)); 585 Assert.DoesNotThrow(() => container.Dispose(default)); 586 } 587 588 void Test_Native_Double_Dispose_Job<T>(T container) 589 where T : INativeDisposable 590 { 591 Assert.DoesNotThrow(() => container.Dispose(default)); 592#if ENABLE_UNITY_COLLECTIONS_CHECKS 593 Assert.Throws<ObjectDisposedException>(() => container.Dispose(default)); 594#else 595 Assert.DoesNotThrow(() => container.Dispose(default)); 596#endif 597 } 598 599 [Test] 600 public void INativeDisposable_Init_Double_Dispose_Job() 601 { 602 Test_Native_Double_Dispose_Job(CreateEmpty_NativeBitArray()); 603 Test_Native_Double_Dispose_Job(CreateEmpty_NativeHashMap()); 604 Test_Native_Double_Dispose_Job(CreateEmpty_NativeHashSet()); 605 Test_Native_Double_Dispose_Job(CreateEmpty_NativeList()); 606 Test_Native_Double_Dispose_Job(CreateEmpty_NativeParallelHashMap()); 607 Test_Native_Double_Dispose_Job(CreateEmpty_NativeParallelHashSet()); 608 Test_Native_Double_Dispose_Job(CreateEmpty_NativeParallelMultiHashMap()); 609 Test_Native_Double_Dispose_Job(CreateEmpty_NativeQueue()); 610 Test_Native_Double_Dispose_Job(CreateEmpty_NativeReference()); 611 Test_Native_Double_Dispose_Job(CreateEmpty_NativeRingQueue()); 612 Test_Native_Double_Dispose_Job(CreateEmpty_NativeStream()); 613 Test_Native_Double_Dispose_Job(CreateEmpty_NativeText()); 614 615 Test_Unsafe_Double_Dispose_Job(CreateEmpty_UnsafeAppendBuffer()); 616 Test_Unsafe_Double_Dispose_Job(CreateEmpty_UnsafeBitArray()); 617 Test_Unsafe_Double_Dispose_Job(CreateEmpty_UnsafeHashMap()); 618 Test_Unsafe_Double_Dispose_Job(CreateEmpty_UnsafeHashSet()); 619 Test_Unsafe_Double_Dispose_Job(CreateEmpty_UnsafeList()); 620 Test_Unsafe_Double_Dispose_Job(CreateEmpty_UnsafePtrList()); 621 Test_Unsafe_Double_Dispose_Job(CreateEmpty_UnsafeParallelHashMap()); 622 Test_Unsafe_Double_Dispose_Job(CreateEmpty_UnsafeParallelHashSet()); 623 Test_Unsafe_Double_Dispose_Job(CreateEmpty_UnsafeParallelMultiHashMap()); 624 Test_Unsafe_Double_Dispose_Job(CreateEmpty_UnsafeQueue()); 625 Test_Unsafe_Double_Dispose_Job(CreateEmpty_UnsafeRingQueue()); 626 Test_Unsafe_Double_Dispose_Job(CreateEmpty_UnsafeStream()); 627 Test_Unsafe_Double_Dispose_Job(CreateEmpty_UnsafeText()); 628 } 629 630 //------------------------------------------------------------------------------------------------------- 631 632 void Test_Dispose_Job_Missing_Dependency<T>(T container) 633 where T : INativeDisposable 634 { 635 GenericContainerJob<T> job = new GenericContainerJob<T>() { data = container }; 636 JobHandle jobHandle = job.Schedule(); 637 Assert.Throws<InvalidOperationException>(() => container.Dispose(default)); 638 Assert.DoesNotThrow(() => jobHandle = container.Dispose(jobHandle)); 639 jobHandle.Complete(); 640 } 641 642 [Test] 643 [TestRequiresCollectionChecks("Tests dispose job while another job is scheduled - crashes without safety system")] 644 public void INativeDisposable_Dispose_Job_Missing_Dependency() 645 { 646 Test_Dispose_Job_Missing_Dependency(new NativeBitArray(16, Allocator.Persistent)); 647 Test_Dispose_Job_Missing_Dependency(new NativeHashMap<int, int>(16, Allocator.Persistent)); 648 Test_Dispose_Job_Missing_Dependency(new NativeHashSet<int>(16, Allocator.Persistent)); 649 Test_Dispose_Job_Missing_Dependency(new NativeList<int>(16, Allocator.Persistent)); 650 Test_Dispose_Job_Missing_Dependency(new NativeParallelHashMap<int, int>(16, Allocator.Persistent)); 651 Test_Dispose_Job_Missing_Dependency(new NativeParallelHashSet<int>(16, Allocator.Persistent)); 652 Test_Dispose_Job_Missing_Dependency(new NativeParallelMultiHashMap<int, int>(16, Allocator.Persistent)); 653 Test_Dispose_Job_Missing_Dependency(new NativeQueue<int>(Allocator.Persistent)); 654 Test_Dispose_Job_Missing_Dependency(new NativeReference<int>(16, Allocator.Persistent)); 655 Test_Dispose_Job_Missing_Dependency(new NativeRingQueue<int>(16, Allocator.Persistent)); 656 Test_Dispose_Job_Missing_Dependency(new NativeStream(16, Allocator.Persistent)); 657 Test_Dispose_Job_Missing_Dependency(new NativeText(16, Allocator.Persistent)); 658 } 659 660 //------------------------------------------------------------------------------------------------------- 661 662 void Test_Dispose_Job_Then_Schedule_Work<T>(T container) 663 where T : INativeDisposable 664 { 665 GenericContainerJob<T> job = new GenericContainerJob<T>() { data = container }; 666 JobHandle jobHandle = container.Dispose(default); 667 Assert.Throws<InvalidOperationException>(() => job.Schedule(jobHandle)); 668 jobHandle.Complete(); 669 } 670 671 [Test] 672 [TestRequiresCollectionChecks("Tests job depending on a dispose job with same data - crashes without safety system")] 673 public void INativeDisposable_Dispose_Job_Then_Schedule_Work() 674 { 675 Test_Dispose_Job_Then_Schedule_Work(new NativeBitArray(16, Allocator.Persistent)); 676 Test_Dispose_Job_Then_Schedule_Work(new NativeHashMap<int, int>(16, Allocator.Persistent)); 677 Test_Dispose_Job_Then_Schedule_Work(new NativeHashSet<int>(16, Allocator.Persistent)); 678 Test_Dispose_Job_Then_Schedule_Work(new NativeList<int>(16, Allocator.Persistent)); 679 Test_Dispose_Job_Then_Schedule_Work(new NativeParallelHashMap<int, int>(16, Allocator.Persistent)); 680 Test_Dispose_Job_Then_Schedule_Work(new NativeParallelHashSet<int>(16, Allocator.Persistent)); 681 Test_Dispose_Job_Then_Schedule_Work(new NativeParallelMultiHashMap<int, int>(16, Allocator.Persistent)); 682 Test_Dispose_Job_Then_Schedule_Work(new NativeQueue<int>(Allocator.Persistent)); 683 Test_Dispose_Job_Then_Schedule_Work(new NativeReference<int>(16, Allocator.Persistent)); 684 Test_Dispose_Job_Then_Schedule_Work(new NativeRingQueue<int>(16, Allocator.Persistent)); 685 Test_Dispose_Job_Then_Schedule_Work(new NativeStream(16, Allocator.Persistent)); 686 Test_Dispose_Job_Then_Schedule_Work(new NativeText(16, Allocator.Persistent)); 687 } 688 689 //------------------------------------------------------------------------------------------------------- 690 691 // Avoid running this test when on older unity releases since those editor versions 692 // used a global safety handle for temp allocations which could lead to invalid safety errors 693 // if we were to perform the safety checks when writing the Length that this test validates 694 // (The test uses Persistent allocations, but the code in NativeList.Length is conditional on 695 // this define so we make the tests conditional as well) 696#if UNITY_2022_2_16F1_OR_NEWER 697 void Test_Change_Length_Missing_Dependency<T, U>(T container) 698 where T : unmanaged, IIndexable<U> 699 where U : unmanaged 700 { 701 int localLength = 0; 702 // Readonly Job 703 { 704 var job = new GenericContainerReadonlyJob<T>() { data = container }; 705 var jobHandle = job.Schedule(); 706 Assert.DoesNotThrow(() => localLength = container.Length); // Reading is safe 707 Assert.Throws<InvalidOperationException>(() => container.Length = 0); // Writing while a job is in flight it not safe 708 jobHandle.Complete(); 709 Assert.DoesNotThrow(() => container.Length = 0); 710 } 711 712 // ReadWrite job 713 { 714 var job = new GenericContainerJob<T>() { data = container }; 715 var jobHandle = job.Schedule(); 716 Assert.Throws<InvalidOperationException>(() => localLength = container.Length); // Reading is not safe 717 Assert.Throws<InvalidOperationException>(() => container.Length = 0); // Writing while a job is in flight it not safe 718 jobHandle.Complete(); 719 Assert.DoesNotThrow(() => localLength = container.Length); 720 Assert.DoesNotThrow(() => container.Length = 0); 721 } 722 } 723 724 [Test] 725 [TestRequiresCollectionChecks()] 726 public void IIndexable_Change_Length_Missing_Dependency() 727 { 728 var container = new NativeList<int>(16, Allocator.Persistent); 729 Test_Change_Length_Missing_Dependency<NativeList<int>, int>(container); 730 container.Dispose(); 731 } 732#endif 733 //------------------------------------------------------------------------------------------------------- 734 735 struct NativeHashMapJobForEach : IJob 736 { 737 public NativeHashMap<int, int> input; 738 public void Execute() 739 { 740 foreach (var _ in input) { } 741 } 742 } 743 744 struct NativeHashMapJobForEachReadOnly : IJob 745 { 746 public NativeHashMap<int, int>.ReadOnly input; 747 public void Execute() 748 { 749 foreach (var _ in input) { } 750 } 751 } 752 753 struct NativeHashMapJobForEachEnumerator : IJob 754 { 755 [ReadOnly] 756 public NativeHashMap<int, int>.Enumerator input; 757 758 public void Execute() 759 { 760 while (input.MoveNext()) { } 761 } 762 } 763 764 [Test] 765 [TestRequiresCollectionChecks("Tests depend on safety system to catch incorrect use.")] 766 public void ForEach() 767 { 768 // CreateEmpty_NativeBitArray(); 769 770 { 771 var container = CreateEmpty_NativeHashMap(); 772 var ro = container.AsReadOnly(); 773 774 GCAllocRecorder.ValidateNoGCAllocs(() => 775 { 776 foreach (var item in container) { } 777 foreach (var item in ro) { } 778 new NativeHashMapJobForEach { input = container }.Run(); 779 new NativeHashMapJobForEachReadOnly { input = ro }.Run(); 780 new NativeHashMapJobForEachEnumerator { input = container.GetEnumerator() }.Run(); 781 new NativeHashMapJobForEachEnumerator { input = ro.GetEnumerator() }.Run(); 782 }); 783 784 { 785 var job = new NativeHashMapJobForEach { input = container }.Schedule(); 786 Assert.Throws<InvalidOperationException>(() => { container.Add(123, 456); }); 787 job.Complete(); 788 Assert.DoesNotThrow(() => container.Add(123, 456)); 789 container.Clear(); 790 } 791 792 { 793 var job = new NativeHashMapJobForEachReadOnly { input = ro }.Schedule(); 794 Assert.Throws<InvalidOperationException>(() => { container.Add(123, 456); }); 795 job.Complete(); 796 Assert.DoesNotThrow(() => container.Add(123, 456)); 797 container.Clear(); 798 } 799 800 { 801 var job = new NativeHashMapJobForEachEnumerator { input = container.GetEnumerator() }.Schedule(); 802 Assert.Throws<InvalidOperationException>(() => { container.Add(123, 456); }); 803 job.Complete(); 804 Assert.DoesNotThrow(() => container.Add(123, 456)); 805 container.Clear(); 806 } 807 808 { 809 var job = new NativeHashMapJobForEachEnumerator { input = ro.GetEnumerator() }.Schedule(); 810 Assert.Throws<InvalidOperationException>(() => { container.Add(123, 456); }); 811 job.Complete(); 812 Assert.DoesNotThrow(() => container.Add(123, 456)); 813 container.Clear(); 814 } 815 816 { 817 var iter = container.GetEnumerator(); 818 container.Add(123, 456); 819 Assert.Throws<ObjectDisposedException>(() => { while (iter.MoveNext()) { } }); 820 Assert.DoesNotThrow(() => container.Remove(123)); 821 Assert.AreEqual(0, container.Count); 822 } 823 824 { 825 var iter = container.AsReadOnly().GetEnumerator(); 826 container.Add(123, 456); 827 Assert.Throws<ObjectDisposedException>(() => { while (iter.MoveNext()) { } }); 828 Assert.DoesNotThrow(() => container.Remove(123)); 829 Assert.AreEqual(0, container.Count); 830 } 831 832 container.Dispose(); 833 } 834 835 { 836 var container = CreateEmpty_NativeHashSet(); 837 var ro = container.AsReadOnly(); 838 839 GCAllocRecorder.ValidateNoGCAllocs(() => 840 { 841 foreach (var item in container) { } 842 foreach (var item in ro) { } 843 }); 844 845 container.Dispose(); 846 } 847 848 { 849 var container = CreateEmpty_NativeList(); 850 var ro = container.AsReadOnly(); 851 852 GCAllocRecorder.ValidateNoGCAllocs(() => 853 { 854 foreach (var item in container) { } 855 foreach (var item in ro) { } 856 }); 857 858 container.Dispose(); 859 } 860 861 { 862 var container = CreateEmpty_NativeParallelHashMap(); 863 var ro = container.AsReadOnly(); 864 865 GCAllocRecorder.ValidateNoGCAllocs(() => 866 { 867 foreach (var item in container) { } 868 foreach (var item in ro) { } 869 }); 870 871 container.Dispose(); 872 } 873 874 { 875 var container = CreateEmpty_NativeParallelHashSet(); 876 var ro = container.AsReadOnly(); 877 878 GCAllocRecorder.ValidateNoGCAllocs(() => 879 { 880 foreach (var item in container) { } 881 foreach (var item in ro) { } 882 }); 883 884 container.Dispose(); 885 } 886 887 { 888 var container = CreateEmpty_NativeParallelMultiHashMap(); 889 var ro = container.AsReadOnly(); 890 891 GCAllocRecorder.ValidateNoGCAllocs(() => 892 { 893 foreach (var item in container) { } 894 foreach (var item in ro) { } 895 }); 896 897 container.Dispose(); 898 } 899 900 { 901 var container = CreateEmpty_NativeQueue(); 902 var ro = container.AsReadOnly(); 903 904 GCAllocRecorder.ValidateNoGCAllocs(() => 905 { 906// foreach (var item in container) { } 907 foreach (var item in ro) { } 908 }); 909 910 container.Dispose(); 911 } 912 913 // CreateEmpty_NativeReference(); 914 // CreateEmpty_NativeRingQueue(); 915 // CreateEmpty_NativeStream(); 916 917 { 918 var container = CreateEmpty_NativeText(); 919 var ro = container.AsReadOnly(); 920 921 GCAllocRecorder.ValidateNoGCAllocs(() => 922 { 923 foreach (var item in container) { } 924 foreach (var item in ro) { } 925 }); 926 927 container.Dispose(); 928 } 929 930 // CreateEmpty_UnsafeAppendBuffer(); 931 // CreateEmpty_UnsafeBitArray 932 933 { 934 var container = CreateEmpty_UnsafeHashMap(); 935 var ro = container.AsReadOnly(); 936 937 GCAllocRecorder.ValidateNoGCAllocs(() => 938 { 939 foreach (var item in container) { } 940 foreach (var item in ro) { } 941 }); 942 943 container.Dispose(); 944 } 945 946 { 947 var container = CreateEmpty_UnsafeHashSet(); 948 var ro = container.AsReadOnly(); 949 950 GCAllocRecorder.ValidateNoGCAllocs(() => 951 { 952 foreach (var item in container) { } 953 foreach (var item in ro) { } 954 }); 955 956 container.Dispose(); 957 } 958 959 { 960 var container = CreateEmpty_UnsafeList(); 961 var ro = container.AsReadOnly(); 962 963 GCAllocRecorder.ValidateNoGCAllocs(() => 964 { 965 foreach (var item in container) { } 966 foreach (var item in ro) { } 967 }); 968 969 container.Dispose(); 970 } 971 972 // CreateEmpty_UnsafePtrList(); - not possible to implement intefrace because container returns T*, and interface wants T as return value. 973 974 { 975 var container = CreateEmpty_UnsafeParallelHashMap(); 976 var ro = container.AsReadOnly(); 977 978 GCAllocRecorder.ValidateNoGCAllocs(() => 979 { 980 foreach (var item in container) { } 981 foreach (var item in ro) { } 982 }); 983 984 container.Dispose(); 985 } 986 987 { 988 var container = CreateEmpty_UnsafeParallelHashSet(); 989 var ro = container.AsReadOnly(); 990 991 GCAllocRecorder.ValidateNoGCAllocs(() => 992 { 993 foreach (var item in container) { } 994 foreach (var item in ro) { } 995 }); 996 997 container.Dispose(); 998 } 999 1000 { 1001 var container = CreateEmpty_UnsafeParallelMultiHashMap(); 1002 var ro = container.AsReadOnly(); 1003 1004 GCAllocRecorder.ValidateNoGCAllocs(() => 1005 { 1006 foreach (var item in container) { } 1007 foreach (var item in ro) { } 1008 }); 1009 1010 container.Dispose(); 1011 } 1012 1013 { 1014 var container = CreateEmpty_UnsafeQueue(); 1015 var ro = container.AsReadOnly(); 1016 1017 GCAllocRecorder.ValidateNoGCAllocs(() => 1018 { 1019// foreach (var item in container) { } 1020 foreach (var item in ro) { } 1021 }); 1022 1023 container.Dispose(); 1024 } 1025 1026 // CreateEmpty_UnsafeRingQueue 1027 // CreateEmpty_UnsafeStream 1028 // CreateEmpty_UnsafeText 1029 } 1030}