A game about forced loneliness, made by TACStudios
at master 617 lines 18 kB view raw
1#if ENABLE_UNITY_COLLECTIONS_CHECKS 2using UnityEngine; 3using NUnit.Framework; 4using System; 5using Unity.Jobs; 6using Unity.Burst; 7using Unity.Collections; 8using Unity.Collections.NotBurstCompatible; 9using Unity.Collections.Tests; 10 11#pragma warning disable 0219 12#pragma warning disable 0414 13 14internal class NativeListJobDebuggerTests : CollectionsTestFixture 15{ 16 [BurstCompile(CompileSynchronously = true)] 17 struct NativeListAddJob : IJob 18 { 19 NativeList<int> list; 20 21 public NativeListAddJob(NativeList<int> list) { this.list = list; } 22 23 public void Execute() 24 { 25 list.Add(1); 26 } 27 } 28 29 [BurstCompile(CompileSynchronously = true)] 30 struct NativeArrayTest : IJob 31 { 32 NativeArray<int> array; 33 34 public NativeArrayTest(NativeArray<int> array) { this.array = array; } 35 36 public void Execute() 37 { 38 } 39 } 40 41 struct NestedContainerJob : IJob 42 { 43 public NativeList<NativeList<int>> nestedContainer; 44 45 public void Execute() 46 { 47 nestedContainer.Clear(); 48 } 49 } 50 51 [Test] 52 [TestRequiresCollectionChecks] 53 public void NativeList_NestedJob_Error() 54 { 55 var container = new NativeList<NativeList<int>>(CommonRwdAllocator.Handle); 56 57 var nestedJob = new NestedContainerJob 58 { 59 nestedContainer = container 60 }; 61 62 JobHandle job = default; 63 Assert.Throws<InvalidOperationException>(() => { job = nestedJob.Schedule(); }); 64 job.Complete(); 65 66 container.Dispose(); 67 } 68 69 [Test] 70 [TestRequiresCollectionChecks] 71 public void AddElementToListFromJobInvalidatesArray() 72 { 73 var list = new NativeList<int>(CommonRwdAllocator.Handle); 74 list.Add(0); 75 76 NativeArray<int> arrayBeforeSchedule = list.AsArray(); 77 Assert.AreEqual(list.Length, 1); 78 79 var jobData = new NativeListAddJob(list); 80 var job = jobData.Schedule(); 81 82 Assert.Throws<ObjectDisposedException>( 83 () => { 84 int readVal = arrayBeforeSchedule[0]; 85 }); 86 Assert.Throws<InvalidOperationException>(() => { NativeArray<int> array = list.AsArray(); Debug.Log(array.Length); }); 87 Assert.Throws<InvalidOperationException>(() => { int readVal = list.Capacity; }); 88 Assert.Throws<InvalidOperationException>(() => { list.Dispose(); }); 89 Assert.Throws<InvalidOperationException>(() => { int readVal = list[0]; }); 90 91 job.Complete(); 92 93 // Assert.AreEqual(1, arrayBeforeSchedule.Length); - temporarily commenting out updated assert checks to ensure editor version promotion succeeds 94 Assert.Throws<ObjectDisposedException>( 95 () => { 96 int readVal = arrayBeforeSchedule[0]; 97 }); 98 99 Assert.AreEqual(2, list.Length); 100 Assert.AreEqual(0, list[0]); 101 Assert.AreEqual(1, list[1]); 102 103 NativeArray<int> arrayAfter = list.AsArray(); 104 Assert.AreEqual(2, arrayAfter.Length); 105 Assert.AreEqual(0, arrayAfter[0]); 106 Assert.AreEqual(1, arrayAfter[1]); 107 108 list.Dispose(); 109 } 110 111 [Test] 112 [TestRequiresCollectionChecks] 113 public void AccessBefore() 114 { 115 var list = new NativeList<int>(CommonRwdAllocator.Handle); 116 117 var jobHandle = new NativeListAddJob(list).Schedule(); 118 Assert.Throws<InvalidOperationException>(() => 119 { 120 list.AsArray(); 121 }); 122 123 jobHandle.Complete(); 124 list.Dispose(); 125 } 126 127 [Test] 128 [TestRequiresCollectionChecks] 129 public void AccessAfter() 130 { 131 var list = new NativeList<int>(CommonRwdAllocator.Handle); 132 var array = list.AsArray(); 133 var jobHandle = new NativeListAddJob(list).Schedule(); 134 Assert.Throws<InvalidOperationException>(() => 135 { 136 new NativeArrayTest(array).Schedule(jobHandle); 137 }); 138 jobHandle.Complete(); 139 140 list.Dispose(); 141 } 142 143 [Test] 144 public void ScheduleDerivedArrayAllowDerivingArrayAgain() 145 { 146 var list = new NativeList<int>(1, Allocator.Persistent); 147 148 // The scheduled job only receives a NativeArray thus it can't be resized 149 var writeJobHandle = new NativeArrayTest(list.AsArray()).Schedule(); 150 151 // For that reason casting here is legal, as opposed to AddElementToListFromJobInvalidatesArray case where it is not legal 152 // Since we NativeList is passed to the job 153#pragma warning disable 0219 // assigned but its value is never used 154 NativeArray<int> array = list.AsArray(); 155#pragma warning restore 0219 156 157 list.Dispose(writeJobHandle); 158 } 159 160 [Test] 161 [TestRequiresCollectionChecks] 162 public void ScheduleDerivedArrayExceptions() 163 { 164 var list = new NativeList<int>(1, Allocator.Persistent); 165 166 var addListJobHandle = new NativeListAddJob(list).Schedule(); 167#pragma warning disable 0219 // assigned but its value is never used 168 Assert.Throws<InvalidOperationException>(() => { NativeArray<int> array = list.AsArray(); }); 169#pragma warning restore 0219 170 171 addListJobHandle.Complete(); 172 list.Dispose(); 173 } 174 175 [Test] 176 [TestRequiresCollectionChecks] 177 public void ScheduleDerivedArrayExceptions2() 178 { 179 var list = new NativeList<int>(1, Allocator.Persistent); 180 NativeArray<int> array = list.AsArray(); 181 182 var addListJobHandle = new NativeListAddJob(list).Schedule(); 183 // The array previously cast should become invalid 184 // as soon as the job is scheduled, since we can't predict if an element will be added or not 185 Assert.Throws<InvalidOperationException>(() => { new NativeArrayTest(array).Schedule(); }); 186 187 addListJobHandle.Complete(); 188 list.Dispose(); 189 } 190 191 [BurstCompile(CompileSynchronously = true)] 192 struct ReadOnlyListAccess : IJob 193 { 194 [ReadOnly] 195 NativeList<int> list; 196 197 public ReadOnlyListAccess(NativeList<int> list) { this.list = list; } 198 199 public void Execute() 200 { 201 } 202 } 203 204 [Test] 205 public void ReadOnlyListInJobKeepsAsArrayValid() 206 { 207 var list = new NativeList<int>(CommonRwdAllocator.Handle); 208 list.Add(0); 209 var arrayBeforeSchedule = list.AsArray(); 210 211 var jobData = new ReadOnlyListAccess(list); 212 var job = jobData.Schedule(); 213 job.Complete(); 214 215 Assert.AreEqual(0, arrayBeforeSchedule[0]); 216 217 list.Dispose(); 218 } 219 220 [Test] 221 public void AsArrayJobKeepsAsArrayValid() 222 { 223 var list = new NativeList<int>(CommonRwdAllocator.Handle); 224 list.Add(0); 225 var arrayBeforeSchedule = list.AsArray(); 226 227 var jobData = new NativeArrayTest(list.AsArray()); 228 var job = jobData.Schedule(); 229 job.Complete(); 230 231 Assert.AreEqual(0, arrayBeforeSchedule[0]); 232 233 list.Dispose(); 234 } 235 236 [BurstCompile(CompileSynchronously = true)] 237 struct NativeListToArrayConversionFromJob : IJob 238 { 239 public NativeList<int> list; 240 241 public void Execute() 242 { 243 list.Add(0); 244 list.Add(0); 245 246 NativeArray<int> arr = list.AsArray(); 247 arr[0] = 1; 248 arr[1] = 2; 249 } 250 } 251 252 [Test] 253 public void CastListToArrayInsideJob() 254 { 255 var jobData = new NativeListToArrayConversionFromJob(); 256 jobData.list = new NativeList<int>(1, Allocator.Persistent); 257 jobData.Schedule().Complete(); 258 259 Assert.AreEqual(new int[] { 1, 2 }, jobData.list.ToArrayNBC()); 260 jobData.list.Dispose(); 261 } 262 263 [BurstCompile(CompileSynchronously = true)] 264 struct WriteJob : IJobParallelFor 265 { 266 public NativeArray<float> output; 267 268 public void Execute(int i) 269 { 270 output[i] = i; 271 } 272 } 273 274 [Test] 275 [TestRequiresCollectionChecks] 276 public void WriteToArrayFromJobThenReadListFromMainThread() 277 { 278 var list = new NativeList<float>(1, Allocator.Persistent); 279 list.Add(0); 280 list.Add(1); 281 282 for (int i = 0; i < 2; i++) 283 { 284 var writeJob = new WriteJob(); 285 writeJob.output = list.AsArray(); 286 var writeJobHandle = writeJob.Schedule(list.Length, 1); 287 288 Assert.Throws<InvalidOperationException>(() => { float val = writeJob.output[0]; }); 289 290 writeJobHandle.Complete(); 291 } 292 list.Dispose(); 293 } 294 295 [Test] 296 public void NativeList_DisposeJob() 297 { 298 var list = new NativeList<int>(Allocator.Persistent); 299 var deps = new NativeListAddJob(list).Schedule(); 300 deps = list.Dispose(deps); 301 Assert.IsFalse(list.IsCreated); 302 deps.Complete(); 303 } 304 305 struct InvalidArrayAccessFromListJob : IJob 306 { 307 public NativeList<int> list; 308 309 public void Execute() 310 { 311 list.Add(1); 312 NativeArray<int> array = list.AsArray(); 313 list.Add(2); 314 315 // Assert.Throws<InvalidOperationException>(() => { array[0] = 5; }); - temporarily commenting out updated assert checks to ensure editor version promotion succeeds 316 } 317 } 318 319 [Test] 320 [TestRequiresCollectionChecks] 321 public void InvalidatedArrayAccessFromListThrowsInsideJob() 322 { 323 var job = new InvalidArrayAccessFromListJob { list = new NativeList<int>(CommonRwdAllocator.Handle) }; 324 job.Schedule().Complete(); 325 job.list.Dispose(); 326 } 327 328 [Test] 329 public void DisposeAliasedArrayDoesNotThrow() 330 { 331 var list = new NativeList<int>(Allocator.Persistent); 332 var array = list.AsArray(); 333 Assert.DoesNotThrow(() => { array.Dispose(); }); 334 335 list.Dispose(); 336 } 337 338 // Burst error BC1071: Unsupported assert type 339 // [BurstCompile(CompileSynchronously = true)] 340 struct NativeArrayTestReadOnly : IJob 341 { 342 [ReadOnly] 343 NativeArray<int> array; 344 345 public NativeArrayTestReadOnly(NativeArray<int> array) { this.array = array; } 346 347 public void Execute() 348 { 349 var arr = array; 350 Assert.Throws<InvalidOperationException>(() => { arr[0] = 5; }); 351 Assert.AreEqual(7, array[0]); 352 } 353 } 354 355 // Burst error BC1071: Unsupported assert type 356 // [BurstCompile(CompileSynchronously = true)] 357 struct NativeArrayTestAsReadOnly : IJob 358 { 359 [ReadOnly] 360 NativeArray<int>.ReadOnly array; 361 362 public NativeArrayTestAsReadOnly(NativeArray<int>.ReadOnly array) { this.array = array; } 363 364 public void Execute() 365 { 366 var arr = array; 367 Assert.AreEqual(7, array[0]); 368 } 369 } 370 371 [Test] 372 [TestRequiresCollectionChecks] 373 public void ReadOnlyAliasedArrayThrows() 374 { 375 var list = new NativeList<int>(Allocator.Persistent); 376 list.Add(7); 377 new NativeArrayTestReadOnly(list.AsArray()).Schedule().Complete(); 378 379 list.Dispose(); 380 } 381 382 // Burst error BC1071: Unsupported assert type 383 // [BurstCompile(CompileSynchronously = true)] 384 struct NativeArrayTestWriteOnly : IJob 385 { 386 [WriteOnly] 387 NativeArray<int> array; 388 389 public NativeArrayTestWriteOnly(NativeArray<int> array) { this.array = array; } 390 391 public void Execute() 392 { 393 var arr = array; 394 Assert.Throws<InvalidOperationException>(() => { int read = arr[0]; }); 395 arr[0] = 7; 396 } 397 } 398 399 [Test] 400 [TestRequiresCollectionChecks] 401 public void NativeList_AsArray_Jobs() 402 { 403 var list = new NativeList<int>(Allocator.Persistent); 404 list.Add(0); 405 406 var writer = list.AsArray(); 407 var writerJob = new NativeArrayTestWriteOnly(writer).Schedule(); 408 409 var reader = list.AsArray(); 410 var readerJob = new NativeArrayTestReadOnly(reader).Schedule(writerJob); 411 412 // Tests that read only container safety check trows... 413 var writerJob2 = new NativeArrayTestWriteOnly(reader).Schedule(readerJob); 414 415 // Tests that write only container safety check trows... 416 var readerJob2 = new NativeArrayTestReadOnly(writer).Schedule(writerJob2); 417 418 readerJob2.Complete(); 419 420 list.Dispose(); 421 } 422 423 [Test] 424 [TestRequiresCollectionChecks] 425 public void NativeList_AsReadOnly_Jobs() 426 { 427 var list = new NativeList<int>(Allocator.Persistent); 428 list.Add(0); 429 430 var writer = list.AsArray(); 431 var writerJob = new NativeArrayTestWriteOnly(writer).Schedule(); 432 433 var reader = list.AsReadOnly(); 434 var readerJob = new NativeArrayTestAsReadOnly(reader).Schedule(writerJob); 435 436 readerJob.Complete(); 437 438 list.Dispose(); 439 } 440 441 // Burst error BC1071: Unsupported assert type 442 // [BurstCompile(CompileSynchronously = true)] 443 struct NativeListTestReadOnly : IJob 444 { 445 [ReadOnly] 446 public NativeArray<int>.ReadOnly reader; 447 448 public void Execute() 449 { 450 Assert.True(reader.Contains(7)); 451 Assert.AreEqual(7, reader[0]); 452 } 453 } 454 455 [Test] 456 public void NativeList_AsReadOnly() 457 { 458 NativeList<int> list; 459 JobHandle readerJob; 460 461 { 462 list = new NativeList<int>(Allocator.Persistent); 463 list.Add(7); 464 465 var reader = list.AsReadOnly(); 466 list.Dispose(); // <- cause invalid use 467 Assert.Throws<InvalidOperationException>(() => { readerJob = new NativeListTestReadOnly { reader = reader }.Schedule(); }); 468 } 469 470 { 471 list = new NativeList<int>(Allocator.Persistent); 472 list.Add(7); 473 474 var reader = list.AsReadOnly(); 475 readerJob = new NativeListTestReadOnly { reader = reader }.Schedule(); 476 } 477 478 list.Dispose(readerJob); 479 readerJob.Complete(); 480 } 481 482 [BurstCompile(CompileSynchronously = true)] 483 struct NativeListTestParallelWriter : IJob 484 { 485 [WriteOnly] 486 public NativeList<int>.ParallelWriter writer; 487 488 public unsafe void Execute() 489 { 490 var range = stackalloc int[2] { 7, 3 }; 491 492 writer.AddNoResize(range[0]); 493 writer.AddRangeNoResize(range, 1); 494 } 495 } 496 497 [Test] 498 public void NativeList_ParallelWriter() 499 { 500 NativeList<int> list; 501 502 { 503 list = new NativeList<int>(2, Allocator.Persistent); 504 var writer = list.AsParallelWriter(); 505 list.Dispose(); // <- cause invalid use 506 Assert.Throws<InvalidOperationException>(() => 507 { 508 var writerJob = new NativeListTestParallelWriter { writer = writer }.Schedule(); 509 writerJob.Complete(); 510 }); 511 } 512 513 { 514 list = new NativeList<int>(2, Allocator.Persistent); 515 var writer = list.AsParallelWriter(); 516 var writerJob = new NativeListTestParallelWriter { writer = writer }.Schedule(); 517 writerJob.Complete(); 518 } 519 520 Assert.AreEqual(2, list.Length); 521 Assert.AreEqual(7, list[0]); 522 Assert.AreEqual(7, list[1]); 523 524 list.Dispose(); 525 } 526 527 [Test] 528 public void NativeList_ParallelWriter_NoPtrCaching() 529 { 530 NativeList<int> list; 531 532 { 533 list = new NativeList<int>(2, Allocator.Persistent); 534 var writer = list.AsParallelWriter(); 535 list.Capacity = 100; 536 var writerJob = new NativeListTestParallelWriter { writer = writer }.Schedule(); 537 writerJob.Complete(); 538 } 539 540 Assert.AreEqual(2, list.Length); 541 Assert.AreEqual(7, list[0]); 542 Assert.AreEqual(7, list[1]); 543 544 list.Dispose(); 545 } 546 547 [Test] 548 [TestRequiresCollectionChecks] 549 public void NativeList_AsReadOnlyAndParallelWriter() 550 { 551 NativeList<int> list; 552 JobHandle jobHandle; 553 554 list = new NativeList<int>(Allocator.Persistent); 555 list.Add(7); 556 557 jobHandle = new NativeListTestReadOnly { reader = list.AsReadOnly() }.Schedule(); 558 jobHandle = new NativeListTestParallelWriter { writer = list.AsParallelWriter() }.Schedule(jobHandle); 559 jobHandle = new NativeListTestReadOnly { reader = list.AsReadOnly() }.Schedule(jobHandle); 560 jobHandle = new NativeListTestParallelWriter { writer = list.AsParallelWriter() }.Schedule(jobHandle); 561 562 list.Dispose(jobHandle); 563 jobHandle.Complete(); 564 } 565 566 unsafe void Expected(ref NativeList<int> list, int expectedLength, int[] expected) 567 { 568 Assert.AreEqual(0 == expectedLength, list.IsEmpty); 569 Assert.AreEqual(list.Length, expectedLength); 570 for (var i = 0; i < list.Length; ++i) 571 { 572 var value = list[i]; 573 Assert.AreEqual(expected[i], value); 574 } 575 } 576 577 [Test] 578 public unsafe void NativeList_RemoveRange() 579 { 580 var list = new NativeList<int>(10, Allocator.Persistent); 581 582 int[] range = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; 583 584 // test removing from the end 585 fixed (int* r = range) list.AddRange(r, 10); 586 list.RemoveRange(6, 3); 587 Expected(ref list, 7, new int[] { 0, 1, 2, 3, 4, 5, 9 }); 588 list.Clear(); 589 590 // test removing all but one 591 fixed (int* r = range) list.AddRange(r, 10); 592 list.RemoveRange(0, 9); 593 Expected(ref list, 1, new int[] { 9 }); 594 list.Clear(); 595 596 // test removing from the front 597 fixed (int* r = range) list.AddRange(r, 10); 598 list.RemoveRange(0, 3); 599 Expected(ref list, 7, new int[] { 3, 4, 5, 6, 7, 8, 9 }); 600 list.Clear(); 601 602 // test removing from the middle 603 fixed (int* r = range) list.AddRange(r, 10); 604 list.RemoveRange(0, 3); 605 Expected(ref list, 7, new int[] { 3, 4, 5, 6, 7, 8, 9 }); 606 list.Clear(); 607 608 // test removing whole range 609 fixed (int* r = range) list.AddRange(r, 10); 610 list.RemoveRange(0, 10); 611 Expected(ref list, 0, new int[] { 0 }); 612 list.Clear(); 613 614 list.Dispose(); 615 } 616} 617#endif