public void Invoke_With_SyncCompletingHandler()
        {
            var service = new FooService();

            var    called = 0;
            String arg    = null;

            var subscription = service.Changed.Subscribe(
                async x => {
                arg = x;
                called++;
            }
                );

            Check.That(subscription)
            .IsInstanceOf <FuncSubscription <String> >();

            Check.That(((FuncSubscription <String>)subscription).TestingGetPreviousSubscription())
            .IsNull();

            Check.That(((FuncSubscription <String>)subscription).Target)
            .IsNotNull();

            Check.That(((FuncSubscription <String>)subscription).Method)
            .IsNotNull();

            var flag1 = service.Do("abc");

            Check.That(flag1)
            .IsTrue();

            Check.That(called)
            .IsEqualTo(1);

            Check.That(arg)
            .IsEqualTo("abc");

            called = 0;
            var flag2 = service.Do("def");

            Check.That(flag2)
            .IsTrue();

            Check.That(called)
            .IsEqualTo(1);

            Check.That(arg)
            .IsEqualTo("def");

            Check.That(service.ChangedSource.NumberOfSubscriptions)
            .IsEqualTo(1);

            Check.That(service.ChangedSource.IsDisposed)
            .IsFalse();
        }
        public void Invoke_With_HandlerThrowingException_BeforeAwait()
        {
            var service = new FooService();

            var    called = 0;
            String arg    = null;

            var subscription = service.Changed.SubscribeWeak(
                async x => {
                arg = x;
                called++;

                if (called == 1)
                {
                    throw new ApplicationException();
                }

                await Task.Yield();
            }
                );

            Check.That(subscription)
            .IsInstanceOf <FuncSubscription <String> >();

            Check.That(((FuncSubscription <String>)subscription).TestingGetPreviousSubscription())
            .IsInstanceOf <WeakSubscription <String> >();

            Exception exception = null;

            using (EventSystem.UnobservedException.SubscribeWeak(
                       x => Volatile.Write(ref exception, x)
                       ))
            {
                var flag1 = service.Do("abc");

                Check.That(flag1)
                .IsTrue();

                Check.That(called)
                .IsEqualTo(1);

                Check.That(arg)
                .IsEqualTo("abc");

                Check.That(Volatile.Read(ref exception))
                .IsInstanceOf <ApplicationException>();

                Check.That(service.ChangedSource.NumberOfSubscriptions)
                .IsEqualTo(1);

                Check.That(service.ChangedSource.IsDisposed)
                .IsFalse();
            }
        }
        public void Invoke_With_AlreadyCanceledHandler()
        {
            var service = new FooService();

            var    called = 0;
            String arg    = null;

            var subscription = service.Changed.SubscribeWeak(
                x => {
                arg = x;
                called++;
                var cts = new CancellationTokenSource();
                cts.Cancel();

                return(Task.FromCanceled(cts.Token));
            }
                );

            Check.That(subscription)
            .IsInstanceOf <FuncSubscription <String> >();

            Check.That(((FuncSubscription <String>)subscription).TestingGetPreviousSubscription())
            .IsInstanceOf <WeakSubscription <String> >();

            Exception exception = null;

            using (EventSystem.UnobservedException.SubscribeWeak(
                       x => Volatile.Write(ref exception, x)
                       ))
            {
                var flag1 = service.Do("abc");

                Check.That(flag1)
                .IsTrue();

                Check.That(called)
                .IsEqualTo(1);

                Check.That(arg)
                .IsEqualTo("abc");

                Check.That(Volatile.Read(ref exception))
                .IsNull();

                Check.That(service.ChangedSource.NumberOfSubscriptions)
                .IsEqualTo(1);

                Check.That(service.ChangedSource.IsDisposed)
                .IsFalse();
            }
        }
        public void Invoke_With_AsyncCompletingHandler()
        {
            var service = new FooService();

            var    called = 0;
            String arg    = null;

            var subscription = service.Changed.SubscribeWeak(
                async x => {
                await Task.Delay(100);
                arg = x;
                called++;
            }
                );

            Check.That(subscription)
            .IsInstanceOf <FuncSubscription <String> >();

            Check.That(((FuncSubscription <String>)subscription).TestingGetPreviousSubscription())
            .IsInstanceOf <WeakSubscription <String> >();

            var flag1 = service.Do("abc");

            Check.That(flag1)
            .IsTrue();

            Check.That(called)
            .IsEqualTo(0);

            SpinWait.SpinUntil(() => called == 1, 2000);

            Check.That(called)
            .IsEqualTo(1);

            Check.That(arg)
            .IsEqualTo("abc");

            Check.That(service.ChangedSource.NumberOfSubscriptions)
            .IsEqualTo(1);

            Check.That(service.ChangedSource.IsDisposed)
            .IsFalse();
        }
        public void Invoke_With_AlreadyCompletedHandler()
        {
            var service = new FooService();

            var    called = 0;
            String arg    = null;

            var subscription = service.Changed.SubscribeWeak(
                x => {
                arg = x;
                called++;

                return(Task.CompletedTask);
            }
                );

            Check.That(subscription)
            .IsInstanceOf <FuncSubscription <String> >();

            Check.That(((FuncSubscription <String>)subscription).TestingGetPreviousSubscription())
            .IsInstanceOf <WeakSubscription <String> >();

            var flag1 = service.Do("abc");

            Check.That(flag1)
            .IsTrue();

            Check.That(called)
            .IsEqualTo(1);

            Check.That(arg)
            .IsEqualTo("abc");

            Check.That(service.ChangedSource.NumberOfSubscriptions)
            .IsEqualTo(1);

            Check.That(service.ChangedSource.IsDisposed)
            .IsFalse();
        }
        public void Invoke_After_SubscriptionGCed()
        {
            var service = new FooService();

            var    called = 0;
            String arg    = null;

            var subscription = service.Changed.SubscribeWeak(
                async x => {
                arg = x;
                called++;
                await Task.Yield();
            }
                );

            Check.That(subscription)
            .IsNotNull();

            Check.That(subscription)
            .IsInstanceOf <FuncSubscription <String> >();

            Check.That(((FuncSubscription <String>)subscription).TestingGetPreviousSubscription())
            .IsInstanceOf <WeakSubscription <String> >();

            var strongSub = (FuncSubscription <String>)subscription;
            var weakSub   = (WeakSubscription <String>)strongSub.TestingGetPreviousSubscription();

            strongSub.TestingClearNextSubscription();
            weakSub.TestingClearNextSubscription();

            var flag1 = service.Do("abc");

            Check.That(flag1)
            .IsTrue();

            Check.That(called)
            .IsEqualTo(0);

            Check.That(service.ChangedSource.NumberOfSubscriptions)
            .IsEqualTo(0);

            Check.That(service.ChangedSource.IsDisposed)
            .IsFalse();

            var flag2 = service.Do("abc");

            Check.That(flag2)
            .IsFalse();

            Check.That(called)
            .IsEqualTo(0);

            Check.That(service.ChangedSource.NumberOfSubscriptions)
            .IsEqualTo(0);

            Check.That(subscription)
            .IsNotNull();

            Check.That(subscription)
            .IsInstanceOf <FuncSubscription <String> >();

            Check.That(((FuncSubscription <String>)subscription).TestingGetPreviousSubscription())
            .IsNull();
        }