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);
        }
Exemplo n.º 2
0
        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();
        }
Exemplo n.º 6
0
        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);
        }
Exemplo n.º 7
0
        public void Instance_Handlers_Are_Called()
        {
            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);

            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);
        }
Exemplo n.º 9
0
        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);
        }
Exemplo n.º 10
0
        public void Handlers_Can_Be_Unsubscribed()
        {
            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);
            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 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);
        }