A game framework written with osu! in mind.
at master 141 lines 4.1 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.Diagnostics; 6using NUnit.Framework; 7using osu.Framework.Allocation; 8using osu.Framework.Graphics; 9using osu.Framework.Graphics.Containers; 10using osu.Framework.Testing; 11using osu.Framework.Tests.Visual; 12 13namespace osu.Framework.Tests.Exceptions 14{ 15 [HeadlessTest] 16 public class TestSceneDependencyInjectionExceptions : FrameworkTestScene 17 { 18 [Test] 19 public void TestImmediateException() 20 { 21 Exception thrownException = null; 22 23 AddStep("add thrower", () => 24 { 25 try 26 { 27 Child = new Thrower(typeof(Exception)); 28 } 29 catch (Exception ex) 30 { 31 thrownException = ex; 32 } 33 }); 34 35 assertCorrectStack(() => thrownException); 36 } 37 38 [Test] 39 public void TestImmediateAggregateException() 40 { 41 Exception thrownException = null; 42 43 AddStep("add thrower", () => 44 { 45 try 46 { 47 Child = new Thrower(typeof(Exception), true); 48 } 49 catch (Exception ex) 50 { 51 thrownException = ex; 52 } 53 }); 54 55 assertCorrectStack(() => thrownException); 56 } 57 58 [Test] 59 public void TestAsyncException() 60 { 61 AsyncThrower thrower = null; 62 63 AddStep("add thrower", () => Child = thrower = new AsyncThrower(typeof(Exception))); 64 AddUntilStep("wait for exception", () => thrower.ThrownException != null); 65 66 assertCorrectStack(() => thrower.ThrownException); 67 } 68 69 private void assertCorrectStack(Func<Exception> exception) => AddAssert("exception has correct callstack", () => 70 { 71 var stackTrace = exception().StackTrace; 72 Debug.Assert(stackTrace != null); 73 74 return stackTrace.Contains($"{nameof(TestSceneDependencyInjectionExceptions)}.{nameof(Thrower)}"); 75 }); 76 77 private class AsyncThrower : CompositeDrawable 78 { 79 public Exception ThrownException { get; private set; } 80 81 private readonly Type exceptionType; 82 83 public AsyncThrower(Type exceptionType) 84 { 85 this.exceptionType = exceptionType; 86 } 87 88 protected override void LoadComplete() 89 { 90 base.LoadComplete(); 91 LoadComponentAsync(new Thrower(exceptionType), AddInternal); 92 } 93 94 public override bool UpdateSubTree() 95 { 96 try 97 { 98 return base.UpdateSubTree(); 99 } 100 catch (Exception ex) 101 { 102 ThrownException = ex; 103 } 104 105 return true; 106 } 107 } 108 109 private class Thrower : Drawable 110 { 111 private readonly Type exceptionType; 112 private readonly bool aggregate; 113 114 public Thrower(Type exceptionType, bool aggregate = false) 115 { 116 this.exceptionType = exceptionType; 117 this.aggregate = aggregate; 118 } 119 120 [BackgroundDependencyLoader] 121 private void load() 122 { 123 if (aggregate) 124 { 125 try 126 { 127 // ReSharper disable once PossibleNullReferenceException 128 throw (Exception)Activator.CreateInstance(exceptionType); 129 } 130 catch (Exception ex) 131 { 132 throw new AggregateException(ex); 133 } 134 } 135 136 // ReSharper disable once PossibleNullReferenceException 137 throw (Exception)Activator.CreateInstance(exceptionType); 138 } 139 } 140 } 141}