A game framework written with osu! in mind.
at master 3.0 kB view raw
1// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. 2// See the LICENCE file in the repository root for full licence text. 3 4using System; 5using System.Collections.Generic; 6using System.Linq; 7using System.Threading; 8using System.Threading.Tasks; 9using NUnit.Framework; 10using osu.Framework.Allocation; 11using osu.Framework.Logging; 12 13namespace osu.Framework.Tests.Threading 14{ 15 [TestFixture] 16 public class AsyncDisposalQueueTest 17 { 18 [Test] 19 public void TestManyAsyncDisposal() 20 { 21 var objects = new List<DisposableObject>(); 22 for (int i = 0; i < 10000; i++) 23 objects.Add(new DisposableObject()); 24 25 objects.ForEach(AsyncDisposalQueue.Enqueue); 26 27 int attempts = 1000; 28 29 while (!objects.All(o => o.IsDisposed)) 30 { 31 if (attempts-- == 0) 32 Assert.Fail("Expected all objects to dispose."); 33 Thread.Sleep(10); 34 } 35 36 Logger.Log(objects.Select(d => d.TaskId).Distinct().Count().ToString()); 37 38 // It's very unlikely for this to fail by chance due to the number of objects being disposed and computational time requirement of task scheduling 39 Assert.That(objects.Select(d => d.TaskId).Distinct().Count(), Is.LessThan(objects.Count)); 40 } 41 42 [Test] 43 public void TestManyAsyncDisposalUsingWait() 44 { 45 var objects = new List<DisposableObject>(); 46 for (int i = 0; i < 10000; i++) 47 objects.Add(new DisposableObject()); 48 49 objects.ForEach(AsyncDisposalQueue.Enqueue); 50 51 AsyncDisposalQueue.WaitForEmpty(); 52 53 Assert.That(objects.All(o => o.IsDisposed)); 54 } 55 56 [Test] 57 public void TestNestedAsyncDisposal() 58 { 59 var objects = new List<NestedDisposableObject>(); 60 for (int i = 0; i < 10000; i++) 61 objects.Add(new NestedDisposableObject()); 62 63 objects.ForEach(AsyncDisposalQueue.Enqueue); 64 65 int attempts = 1000; 66 67 while (!objects.All(o => o.IsDisposed && o.Nested?.IsDisposed == true)) 68 { 69 if (attempts-- == 0) 70 Assert.Fail("Expected all objects to dispose."); 71 Thread.Sleep(10); 72 } 73 } 74 75 private class NestedDisposableObject : DisposableObject 76 { 77 public DisposableObject Nested; 78 79 public override void Dispose() 80 { 81 base.Dispose(); 82 AsyncDisposalQueue.Enqueue(Nested = new DisposableObject()); 83 } 84 } 85 86 private class DisposableObject : IDisposable 87 { 88 public int? TaskId { get; private set; } 89 90 public bool IsDisposed { get; private set; } 91 92 public virtual void Dispose() 93 { 94 TaskId = Task.CurrentId; 95 IsDisposed = true; 96 } 97 } 98 } 99}