A game about forced loneliness, made by TACStudios
1using System; 2using NUnit.Framework; 3using Unity.Burst; 4using Unity.Collections; 5using Unity.Collections.LowLevel.Unsafe; 6using Unity.Collections.Tests; 7using Unity.Jobs; 8using Assert = FastAssert; 9 10[BurstCompile] 11internal class UnsafeQueueTests : CollectionsTestCommonBase 12{ 13 static void ExpectedCount<T>(ref UnsafeQueue<T> container, int expected) where T : unmanaged 14 { 15 Assert.AreEqual(expected == 0, container.IsEmpty()); 16 Assert.AreEqual(expected, container.Count); 17 } 18 19 [Test] 20 public void Enqueue_Dequeue() 21 { 22 var queue = new UnsafeQueue<int>(Allocator.Temp); 23 ExpectedCount(ref queue, 0); 24 25#if ENABLE_UNITY_COLLECTIONS_CHECKS || UNITY_DOTS_DEBUG 26 Assert.Throws<System.InvalidOperationException>(() => {queue.Dequeue(); }); 27#endif 28 29 for (int i = 0; i < 16; ++i) 30 queue.Enqueue(i); 31 ExpectedCount(ref queue, 16); 32 for (int i = 0; i < 16; ++i) 33 Assert.AreEqual(i, queue.Dequeue(), "Got the wrong value from the queue"); 34 ExpectedCount(ref queue, 0); 35 36#if ENABLE_UNITY_COLLECTIONS_CHECKS || UNITY_DOTS_DEBUG 37 Assert.Throws<System.InvalidOperationException>(() => {queue.Dequeue(); }); 38#endif 39 40 queue.Dispose(); 41 } 42 43 [Test] 44 public void ConcurrentEnqueue_Dequeue() 45 { 46 var queue = new UnsafeQueue<int>(Allocator.Temp); 47 var cQueue = queue.AsParallelWriter(); 48 ExpectedCount(ref queue, 0); 49 50#if ENABLE_UNITY_COLLECTIONS_CHECKS || UNITY_DOTS_DEBUG 51 Assert.Throws<System.InvalidOperationException>(() => {queue.Dequeue(); }); 52#endif 53 54 for (int i = 0; i < 16; ++i) 55 cQueue.Enqueue(i); 56 ExpectedCount(ref queue, 16); 57 for (int i = 0; i < 16; ++i) 58 Assert.AreEqual(i, queue.Dequeue(), "Got the wrong value from the queue"); 59 ExpectedCount(ref queue, 0); 60 61#if ENABLE_UNITY_COLLECTIONS_CHECKS || UNITY_DOTS_DEBUG 62 Assert.Throws<System.InvalidOperationException>(() => {queue.Dequeue(); }); 63#endif 64 65 queue.Dispose(); 66 } 67 68 [Test] 69 public void Enqueue_Dequeue_Peek() 70 { 71 var queue = new UnsafeQueue<int>(Allocator.Temp); 72 ExpectedCount(ref queue, 0); 73 74#if ENABLE_UNITY_COLLECTIONS_CHECKS || UNITY_DOTS_DEBUG 75 Assert.Throws<System.InvalidOperationException>(() => {queue.Dequeue(); }); 76#endif 77 78 for (int i = 0; i < 16; ++i) 79 queue.Enqueue(i); 80 ExpectedCount(ref queue, 16); 81 for (int i = 0; i < 16; ++i) 82 { 83 Assert.AreEqual(i, queue.Peek(), "Got the wrong value from the queue"); 84 queue.Dequeue(); 85 } 86 ExpectedCount(ref queue, 0); 87 88#if ENABLE_UNITY_COLLECTIONS_CHECKS || UNITY_DOTS_DEBUG 89 Assert.Throws<System.InvalidOperationException>(() => {queue.Dequeue(); }); 90#endif 91 92 queue.Dispose(); 93 } 94 95 [Test] 96 public void Enqueue_Dequeue_Clear() 97 { 98 var queue = new UnsafeQueue<int>(Allocator.Temp); 99 ExpectedCount(ref queue, 0); 100 101#if ENABLE_UNITY_COLLECTIONS_CHECKS || UNITY_DOTS_DEBUG 102 Assert.Throws<System.InvalidOperationException>(() => {queue.Dequeue(); }); 103#endif 104 105 for (int i = 0; i < 16; ++i) 106 queue.Enqueue(i); 107 ExpectedCount(ref queue, 16); 108 for (int i = 0; i < 8; ++i) 109 Assert.AreEqual(i, queue.Dequeue(), "Got the wrong value from the queue"); 110 ExpectedCount(ref queue, 8); 111 queue.Clear(); 112 ExpectedCount(ref queue, 0); 113 114#if ENABLE_UNITY_COLLECTIONS_CHECKS || UNITY_DOTS_DEBUG 115 Assert.Throws<System.InvalidOperationException>(() => {queue.Dequeue(); }); 116#endif 117 118 queue.Dispose(); 119 } 120 121 [Test] 122 public void Double_Deallocate_DoesNotThrow() 123 { 124 var queue = new UnsafeQueue<int>(CommonRwdAllocator.Handle); 125 queue.Dispose(); 126 Assert.DoesNotThrow( 127 () => { queue.Dispose(); }); 128 } 129 130 [Test] 131 public void EnqueueScalability() 132 { 133 var queue = new UnsafeQueue<int>(Allocator.Persistent); 134 for (int i = 0; i != 1000 * 100; i++) 135 { 136 queue.Enqueue(i); 137 } 138 139 ExpectedCount(ref queue, 1000 * 100); 140 141 for (int i = 0; i != 1000 * 100; i++) 142 Assert.AreEqual(i, queue.Dequeue()); 143 ExpectedCount(ref queue, 0); 144 145 queue.Dispose(); 146 } 147 148 [Test] 149 public void Enqueue_Wrap() 150 { 151 var queue = new UnsafeQueue<int>(Allocator.Temp); 152 ExpectedCount(ref queue, 0); 153 154#if ENABLE_UNITY_COLLECTIONS_CHECKS || UNITY_DOTS_DEBUG 155 Assert.Throws<System.InvalidOperationException>(() => {queue.Dequeue(); }); 156#endif 157 158 for (int i = 0; i < 256; ++i) 159 queue.Enqueue(i); 160 ExpectedCount(ref queue, 256); 161 162 for (int i = 0; i < 128; ++i) 163 Assert.AreEqual(i, queue.Dequeue(), "Got the wrong value from the queue"); 164 ExpectedCount(ref queue, 128); 165 166 for (int i = 0; i < 128; ++i) 167 queue.Enqueue(i); 168 ExpectedCount(ref queue, 256); 169 170 for (int i = 128; i < 256; ++i) 171 Assert.AreEqual(i, queue.Dequeue(), "Got the wrong value from the queue"); 172 ExpectedCount(ref queue, 128); 173 174 for (int i = 0; i < 128; ++i) 175 Assert.AreEqual(i, queue.Dequeue(), "Got the wrong value from the queue"); 176 ExpectedCount(ref queue, 0); 177 178#if ENABLE_UNITY_COLLECTIONS_CHECKS || UNITY_DOTS_DEBUG 179 Assert.Throws<System.InvalidOperationException>(() => {queue.Dequeue(); }); 180#endif 181 182 queue.Dispose(); 183 } 184 185 [Test] 186 public void ConcurrentEnqueue_Wrap() 187 { 188 var queue = new UnsafeQueue<int>(Allocator.Temp); 189 var cQueue = queue.AsParallelWriter(); 190 ExpectedCount(ref queue, 0); 191 192#if ENABLE_UNITY_COLLECTIONS_CHECKS || UNITY_DOTS_DEBUG 193 Assert.Throws<System.InvalidOperationException>(() => {queue.Dequeue(); }); 194#endif 195 196 for (int i = 0; i < 256; ++i) 197 cQueue.Enqueue(i); 198 ExpectedCount(ref queue, 256); 199 200 for (int i = 0; i < 128; ++i) 201 Assert.AreEqual(i, queue.Dequeue(), "Got the wrong value from the queue"); 202 ExpectedCount(ref queue, 128); 203 204 for (int i = 0; i < 128; ++i) 205 cQueue.Enqueue(i); 206 ExpectedCount(ref queue, 256); 207 208 for (int i = 128; i < 256; ++i) 209 Assert.AreEqual(i, queue.Dequeue(), "Got the wrong value from the queue"); 210 ExpectedCount(ref queue, 128); 211 212 for (int i = 0; i < 128; ++i) 213 Assert.AreEqual(i, queue.Dequeue(), "Got the wrong value from the queue"); 214 ExpectedCount(ref queue, 0); 215 216#if ENABLE_UNITY_COLLECTIONS_CHECKS || UNITY_DOTS_DEBUG 217 Assert.Throws<System.InvalidOperationException>(() => {queue.Dequeue(); }); 218#endif 219 220 queue.Dispose(); 221 } 222 223 [Test] 224 public void TryDequeue_OnEmptyQueueWhichHadElements_RetainsValidState() 225 { 226 using (var queue = new UnsafeQueue<int>(Allocator.Temp)) 227 { 228 for (int i = 0; i < 3; i++) 229 { 230 queue.Enqueue(i); 231 Assert.AreEqual(1, queue.Count); 232 233 int value; 234 while (queue.TryDequeue(out value)) 235 { 236 Assert.AreEqual(i, value); 237 } 238 239 Assert.AreEqual(0, queue.Count); 240 } 241 } 242 } 243 244 [Test] 245 public void TryDequeue_OnEmptyQueue_RetainsValidState() 246 { 247 using (var queue = new UnsafeQueue<int>(Allocator.Temp)) 248 { 249 Assert.IsFalse(queue.TryDequeue(out _)); 250 queue.Enqueue(1); 251 Assert.AreEqual(1, queue.Count); 252 } 253 } 254 255 [Test] 256 public void ToArray_ContainsCorrectElements() 257 { 258 using (var queue = new UnsafeQueue<int>(Allocator.Temp)) 259 { 260 for (int i = 0; i < 100; i++) 261 queue.Enqueue(i); 262 using (var array = queue.ToArray(Allocator.Temp)) 263 { 264 Assert.AreEqual(queue.Count, array.Length); 265 for (int i = 0; i < array.Length; i++) 266 Assert.AreEqual(i, array[i]); 267 } 268 } 269 } 270 271 [Test] 272 public void ToArray_RespectsDequeue() 273 { 274 using (var queue = new UnsafeQueue<int>(Allocator.Temp)) 275 { 276 for (int i = 0; i < 100; i++) 277 queue.Enqueue(i); 278 for (int i = 0; i < 50; i++) 279 queue.Dequeue(); 280 using (var array = queue.ToArray(Allocator.Temp)) 281 { 282 Assert.AreEqual(queue.Count, array.Length); 283 for (int i = 0; i < array.Length; i++) 284 Assert.AreEqual(50 + i, array[i]); 285 } 286 } 287 } 288 289 [Test] 290 public void UnsafeQueue_CustomAllocatorTest() 291 { 292 AllocatorManager.Initialize(); 293 var allocatorHelper = new AllocatorHelper<CustomAllocatorTests.CountingAllocator>(AllocatorManager.Persistent); 294 ref var allocator = ref allocatorHelper.Allocator; 295 allocator.Initialize(); 296 297 using (var container = new UnsafeQueue<int>(allocator.Handle)) 298 { 299 } 300 301 Assert.IsTrue(allocator.WasUsed); 302 allocator.Dispose(); 303 allocatorHelper.Dispose(); 304 AllocatorManager.Shutdown(); 305 } 306 307 [BurstCompile(CompileSynchronously = true)] 308 struct BurstedCustomAllocatorJob : IJob 309 { 310 [NativeDisableUnsafePtrRestriction] 311 public unsafe CustomAllocatorTests.CountingAllocator* Allocator; 312 313 public void Execute() 314 { 315 unsafe 316 { 317 using (var container = new UnsafeQueue<int>(Allocator->Handle)) 318 { 319 } 320 } 321 } 322 } 323 324 [Test] 325 public unsafe void UnsafeQueue_BurstedCustomAllocatorTest() 326 { 327 AllocatorManager.Initialize(); 328 var allocatorHelper = new AllocatorHelper<CustomAllocatorTests.CountingAllocator>(AllocatorManager.Persistent); 329 ref var allocator = ref allocatorHelper.Allocator; 330 331 allocator.Initialize(); 332 333 var allocatorPtr = (CustomAllocatorTests.CountingAllocator*)UnsafeUtility.AddressOf<CustomAllocatorTests.CountingAllocator>(ref allocator); 334 unsafe 335 { 336 var handle = new BurstedCustomAllocatorJob {Allocator = allocatorPtr}.Schedule(); 337 handle.Complete(); 338 } 339 340 Assert.IsTrue(allocator.WasUsed); 341 allocator.Dispose(); 342 allocatorHelper.Dispose(); 343 AllocatorManager.Shutdown(); 344 } 345 346 public struct NestedContainer 347 { 348 public UnsafeQueue<int> data; 349 } 350 351 [Test] 352 public void UnsafeQueue_Nested() 353 { 354 var inner = new UnsafeQueue<int>(CommonRwdAllocator.Handle); 355 NestedContainer nestedStruct = new NestedContainer { data = inner }; 356 357 var containerNestedStruct = new UnsafeQueue<NestedContainer>(CommonRwdAllocator.Handle); 358 var containerNested = new UnsafeQueue<UnsafeQueue<int>>(CommonRwdAllocator.Handle); 359 360 containerNested.Enqueue(inner); 361 containerNestedStruct.Enqueue(nestedStruct); 362 363 containerNested.Dispose(); 364 containerNestedStruct.Dispose(); 365 inner.Dispose(); 366 } 367}