// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the Apache 2.0 License. // See the LICENSE file in the project root for more information. using System; using System.Reactive.Concurrency; using System.Reflection; using Xunit; namespace ReactiveTests.Tests { public class AsyncLockTest { [Fact] public void Wait_ArgumentChecking() { var asyncLock = new AsyncLock(); Assert.Throws(() => asyncLock.Wait(null)); } [Fact] public void Wait_Graceful() { var ok = false; new AsyncLock().Wait(() => { ok = true; }); Assert.True(ok); } [Fact] public void Wait_Fail() { var l = new AsyncLock(); var ex = new Exception(); try { l.Wait(() => { throw ex; }); Assert.True(false); } catch (Exception e) { Assert.Same(ex, e); } // has faulted; should not run l.Wait(() => { Assert.True(false); }); } [Fact] public void Wait_QueuesWork() { var l = new AsyncLock(); var l1 = false; var l2 = false; l.Wait(() => { l.Wait(() => { Assert.True(l1); l2 = true; }); l1 = true; }); Assert.True(l2); } [Fact] public void Dispose() { var l = new AsyncLock(); var l1 = false; var l2 = false; var l3 = false; var l4 = false; l.Wait(() => { l.Wait(() => { l.Wait(() => { l3 = true; }); l2 = true; l.Dispose(); l.Wait(() => { l4 = true; }); }); l1 = true; }); Assert.True(l1); Assert.True(l2); Assert.False(l3); Assert.False(l4); } public class AsyncLock { object instance; public AsyncLock() { instance = typeof(Scheduler).GetTypeInfo().Assembly.GetType("System.Reactive.Concurrency.AsyncLock").GetConstructor(new Type[] { }).Invoke(new object[] { }); } public void Wait(Action action) { try { instance.GetType().GetMethod(nameof(AsyncLock.Wait)).Invoke(instance, new object[] { action }); } catch (TargetInvocationException ex) { throw ex.InnerException; } } public void Dispose() { try { instance.GetType().GetMethod(nameof(AsyncLock.Dispose)).Invoke(instance, new object[0]); } catch (TargetInvocationException ex) { throw ex.InnerException; } } } } }