public void Handlers_Can_Be_Unsubscribed() { var pub = new Publisher(); var calledSubscribers = new List<int>(); var sub1 = new InstanceSubscriber(1, pub, calledSubscribers.Add); var sub2 = new InstanceSubscriber(2, pub, calledSubscribers.Add); StaticSubscriber.FooWasRaised = false; StaticSubscriber.Subscribe(pub); // Make sure they really were subscribed pub.Raise(); calledSubscribers.Should().Equal(1, 2); StaticSubscriber.FooWasRaised.Should().BeTrue(); calledSubscribers.Clear(); sub1.Unsubscribe(pub); pub.Raise(); calledSubscribers.Should().Equal(2); StaticSubscriber.FooWasRaised = false; StaticSubscriber.Unsubscribe(pub); pub.Raise(); StaticSubscriber.FooWasRaised.Should().BeFalse(); calledSubscribers.Clear(); sub2.Unsubscribe(pub); pub.Raise(); calledSubscribers.Should().BeEmpty(); // Make sure subscribers are not collected before the end of the test GC.KeepAlive(sub1); GC.KeepAlive(sub2); }
public void Subscribers_Can_Be_Garbage_Collected() { var pub = new Publisher(); var calledSubscribers = new List <int>(); var sub1 = new InstanceSubscriber(1, calledSubscribers.Add); sub1.Subscribe(pub); var sub2 = new InstanceSubscriber(2, calledSubscribers.Add); sub2.Subscribe(pub); var weakSub1 = new WeakReference(sub1); var weakSub2 = new WeakReference(sub2); // ReSharper disable once RedundantAssignment sub2 = null; // only necessary in Debug GC.Collect(); GC.WaitForPendingFinalizers(); weakSub1.IsAlive.Should().BeTrue("because it is explicitly kept alive (sanity check)"); weakSub2.IsAlive.Should().BeFalse("because it should have been collected"); pub.Raise(); calledSubscribers.Should().Equal(1); // Make sure sub1 is not collected before the end of the test (sub2 can be collected) GC.KeepAlive(sub1); }
public async Task Can_Raise_Even_If_Delegates_List_Is_Unclean() { var pub = new Publisher(); var sub1 = new InstanceSubscriber(1, async i => await Task.Yield()); sub1.Subscribe(pub); var sub2 = new InstanceSubscriber(1, async i => await Task.Yield()); sub2.Subscribe(pub); var sub3 = new InstanceSubscriber(1, async i => await Task.Yield()); sub3.Subscribe(pub); var sub4 = new InstanceSubscriber(1, async i => await Task.Yield()); sub4.Subscribe(pub); var sub5 = new InstanceSubscriber(1, async i => await Task.Yield()); sub5.Subscribe(pub); var sub6 = new InstanceSubscriber(1, async i => await Task.Yield()); sub6.Subscribe(pub); var sub7 = new InstanceSubscriber(1, async i => await Task.Yield()); sub7.Subscribe(pub); var sub8 = new InstanceSubscriber(1, async i => await Task.Yield()); sub8.Subscribe(pub); sub8.Unsubscribe(pub); await pub.Raise(); }
public async Task Reentrant_Subscribers_Dont_Fire_Immediately() { var pub = new Publisher(); var calledSubscribers = new List <int>(); var sub2 = new InstanceSubscriber(2, i => AddAsync(calledSubscribers, i)); var sub1 = new InstanceSubscriber(1, async i => { await AddAsync(calledSubscribers, i); // This listener should not receive the event during the first round of notifications sub2.Subscribe(pub); // Make sure subscribers are not collected before the end of the test GC.KeepAlive(sub2); }); sub1.Subscribe(pub); await pub.Raise(); calledSubscribers.Should().Equal(1); // Make sure subscribers are not collected before the end of the test GC.KeepAlive(sub1); }
public void Can_Raise_Even_If_Delegates_List_Is_Unclean() { var pub = new Publisher(); var sub1 = new InstanceSubscriber(1, i => {}); sub1.Subscribe(pub); var sub2 = new InstanceSubscriber(1, i => {}); sub2.Subscribe(pub); var sub3 = new InstanceSubscriber(1, i => {}); sub3.Subscribe(pub); var sub4 = new InstanceSubscriber(1, i => {}); sub4.Subscribe(pub); var sub5 = new InstanceSubscriber(1, i => {}); sub5.Subscribe(pub); var sub6 = new InstanceSubscriber(1, i => {}); sub6.Subscribe(pub); var sub7 = new InstanceSubscriber(1, i => {}); sub7.Subscribe(pub); var sub8 = new InstanceSubscriber(1, i => {}); sub8.Subscribe(pub); sub8.Unsubscribe(pub); pub.Raise(); }
public void Only_The_Last_Matching_Handler_Is_Unsubscribed() { // Subscribe the same handlers multiple times var pub = new Publisher(); var calledSubscribers = new List <int>(); var sub1 = new InstanceSubscriber(1, calledSubscribers.Add); sub1.Subscribe(pub); sub1.Subscribe(pub); StaticSubscriber.CallCount = 0; StaticSubscriber.Subscribe(pub); StaticSubscriber.Subscribe(pub); // Make sure they really were subscribed pub.Raise(); calledSubscribers.Should().Equal(1, 1); StaticSubscriber.CallCount.Should().Be(2); // Unsubscribe one instance handler calledSubscribers.Clear(); sub1.Unsubscribe(pub); pub.Raise(); //calledSubscribers.Should().Equal(1); // Unsubscribe one static handler StaticSubscriber.CallCount = 0; StaticSubscriber.Unsubscribe(pub); pub.Raise(); StaticSubscriber.CallCount.Should().Be(1); // Make sure subscribers are not collected before the end of the test GC.KeepAlive(sub1); }
public async Task Can_Subscribe_While_Another_Thread_Is_Invoking() { var sub1CanFinish = new ManualResetEvent(false); var sub2CanSubscribe = new ManualResetEvent(false); var pub = new Publisher(); var sub1 = new InstanceSubscriber(1, async i => { sub2CanSubscribe.Set(); sub1CanFinish.WaitOne(); await Task.Yield(); }); var sub2 = new InstanceSubscriber(2, async i => await Task.Yield()); sub1.Subscribe(pub); var task1 = Task.Run(async() => { await pub.Raise(); }); var task2 = Task.Run(() => { sub2CanSubscribe.WaitOne(); sub2.Subscribe(pub); }); if (await Task.WhenAny(task2, Task.Delay(500)) != task2) { throw new Exception("timed out"); } sub1CanFinish.Set(); await task1; GC.KeepAlive(sub1); GC.KeepAlive(sub2); }
public void Handlers_Can_Be_Unsubscribed() { var pub = new Publisher(); var calledSubscribers = new List <int>(); var sub1 = new InstanceSubscriber(1, pub, calledSubscribers.Add); var sub2 = new InstanceSubscriber(2, pub, calledSubscribers.Add); StaticSubscriber.FooWasRaised = false; StaticSubscriber.Subscribe(pub); // Make sure they really were subscribed pub.Raise(); calledSubscribers.Should().Equal(1, 2); StaticSubscriber.FooWasRaised.Should().BeTrue(); calledSubscribers.Clear(); sub1.Unsubscribe(pub); pub.Raise(); calledSubscribers.Should().Equal(2); StaticSubscriber.FooWasRaised = false; StaticSubscriber.Unsubscribe(pub); pub.Raise(); StaticSubscriber.FooWasRaised.Should().BeFalse(); calledSubscribers.Clear(); sub2.Unsubscribe(pub); pub.Raise(); calledSubscribers.Should().BeEmpty(); // Make sure subscribers are not collected before the end of the test GC.KeepAlive(sub1); GC.KeepAlive(sub2); }
public void Instance_Handlers_Are_Called() { var pub = new Publisher(); var calledSubscribers = new List<int>(); var sub1 = new InstanceSubscriber(1, pub, calledSubscribers.Add); var sub2 = new InstanceSubscriber(2, pub, calledSubscribers.Add); pub.Raise(); calledSubscribers.Should().Equal(1, 2); // Make sure subscribers are not collected before the end of the test GC.KeepAlive(sub1); GC.KeepAlive(sub2); }
public void Instance_Handlers_Are_Called() { var pub = new Publisher(); var calledSubscribers = new List <int>(); var sub1 = new InstanceSubscriber(1, pub, calledSubscribers.Add); var sub2 = new InstanceSubscriber(2, pub, calledSubscribers.Add); pub.Raise(); calledSubscribers.Should().Equal(1, 2); // Make sure subscribers are not collected before the end of the test GC.KeepAlive(sub1); GC.KeepAlive(sub2); }
public async Task Instance_Handlers_Are_Called() { var pub = new Publisher(); var calledSubscribers = new List <int>(); var sub1 = new InstanceSubscriber(1, i => AddAsync(calledSubscribers, i)); sub1.Subscribe(pub); var sub2 = new InstanceSubscriber(2, i => AddAsync(calledSubscribers, i)); sub2.Subscribe(pub); await pub.Raise(); calledSubscribers.Should().Equal(1, 2); // Make sure subscribers are not collected before the end of the test GC.KeepAlive(sub1); GC.KeepAlive(sub2); }
public async Task Handlers_Can_Be_Unsubscribed() { var pub = new Publisher(); var calledSubscribers = new List <int>(); var sub1 = new InstanceSubscriber(1, i => AddAsync(calledSubscribers, i)); sub1.Subscribe(pub); var sub2 = new InstanceSubscriber(2, i => AddAsync(calledSubscribers, i)); sub2.Subscribe(pub); StaticSubscriber.CallCount = 0; StaticSubscriber.Subscribe(pub); // Make sure they really were subscribed await pub.Raise(); calledSubscribers.Should().Equal(1, 2); StaticSubscriber.CallCount.Should().Be(1); calledSubscribers.Clear(); sub1.Unsubscribe(pub); await pub.Raise(); calledSubscribers.Should().Equal(2); StaticSubscriber.CallCount = 0; StaticSubscriber.Unsubscribe(pub); await pub.Raise(); StaticSubscriber.CallCount.Should().Be(0); calledSubscribers.Clear(); sub2.Unsubscribe(pub); await pub.Raise(); calledSubscribers.Should().BeEmpty(); // Make sure subscribers are not collected before the end of the test GC.KeepAlive(sub1); GC.KeepAlive(sub2); }
public void Reentrant_Subscribers_Dont_Fire_Immediately() { var pub = new Publisher(); var calledSubscribers = new List <int>(); var sub1 = new InstanceSubscriber(1, pub, i => { calledSubscribers.Add(i); // This listener should not receive the event during the first round of notifications var sub2 = new InstanceSubscriber(i + 1, pub, calledSubscribers.Add); // Make sure subscribers are not collected before the end of the test GC.KeepAlive(sub2); }); pub.Raise(); calledSubscribers.Should().Equal(1); // Make sure subscribers are not collected before the end of the test GC.KeepAlive(sub1); }
public void Can_Subscribe_While_Another_Thread_Is_Invoking() { var sub1CanFinish = new ManualResetEvent(false); var sub2CanSubscribe = new ManualResetEvent(false); var pub = new Publisher(); var sub1 = new InstanceSubscriber(1, i => { sub2CanSubscribe.Set(); sub1CanFinish.WaitOne(); }); var sub2 = new InstanceSubscriber(2, i => { }); sub1.Subscribe(pub); var thread1 = new Thread(() => { pub.Raise(); }); var thread2 = new Thread(() => { sub2CanSubscribe.WaitOne(); sub2.Subscribe(pub); }); thread1.Start(); thread2.Start(); bool subscribeFinished = thread2.Join(500); sub1CanFinish.Set(); thread1.Join(); subscribeFinished.Should().BeTrue(); GC.KeepAlive(sub1); GC.KeepAlive(sub2); }
public async Task Can_Subscribe_While_Another_Thread_Is_Invoking() { var sub1CanFinish = new ManualResetEvent(false); var sub2CanSubscribe = new ManualResetEvent(false); var pub = new Publisher(); var sub1 = new InstanceSubscriber(1, async i => { sub2CanSubscribe.Set(); await sub1CanFinish.WaitOneAsync(); }); var sub2 = new InstanceSubscriber(2, async i => await Task.Yield()); sub1.Subscribe(pub); var task1 = Task.Run(async() => { await pub.Raise(); }); var task2 = Task.Run(async() => { await sub2CanSubscribe.WaitOneAsync(); sub2.Subscribe(pub); }); bool subscribeFinished = await Task.WhenAny(task2, Task.Delay(500)) == task2; sub1CanFinish.Set(); await task1; subscribeFinished.Should().BeTrue(); GC.KeepAlive(sub1); GC.KeepAlive(sub2); }
public void Subscribers_Can_Be_Garbage_Collected() { var pub = new Publisher(); var calledSubscribers = new List<int>(); var sub1 = new InstanceSubscriber(1, pub, calledSubscribers.Add); var sub2 = new InstanceSubscriber(2, pub, calledSubscribers.Add); var weakSub1 = new WeakReference(sub1); var weakSub2 = new WeakReference(sub2); // ReSharper disable once RedundantAssignment sub2 = null; // only necessary in Debug GC.Collect(); GC.WaitForPendingFinalizers(); weakSub1.IsAlive.Should().BeTrue("because it is explicitly kept alive (sanity check)"); weakSub2.IsAlive.Should().BeFalse("because it should have been collected"); pub.Raise(); calledSubscribers.Should().Equal(1); // Make sure sub1 is not collected before the end of the test (sub2 can be collected) GC.KeepAlive(sub1); }