public void CallsOnErrorOnException()
        {
            // Arrange
            var mre               = new ManualResetEventSlim(false);
            var onErrorCalled     = false;
            var dbProviderFactory = new MockDbProviderFactory();
            var dbBehavior        = new Mock <IDbBehavior>();

            dbBehavior.Setup(db => db.UpdateLoopRetryDelays).Returns(_defaultRetryDelays);
            dbBehavior.Setup(db => db.StartSqlDependencyListener()).Returns(false);
            dbProviderFactory.MockDataReader.Setup(r => r.Read()).Throws(new ApplicationException("test"));
            var operation = new ObservableDbOperation("test", "test", new TraceSource("test"), dbProviderFactory, dbBehavior.Object);

            operation.Faulted += _ =>
            {
                onErrorCalled = true;
                mre.Set();
            };

            // Act
            ThreadPool.QueueUserWorkItem(_ => operation.ExecuteReaderWithUpdates((record, o) => { }));
            mre.Wait();
            operation.Dispose();

            // Assert
            Assert.True(onErrorCalled);
        }
示例#2
0
        public void ExecuteReaderWithUpdates_Fail()
        {
            var fakeOracleDependencyManager    = A.Fake <IOracleDependencyManager>();
            var fakeSignalrDbDependencyFactory = A.Fake <ISignalrDbDependencyFactory>();

            ObservableDbOperation dbOperation = new ObservableDbOperation(string.Empty, string.Empty,
                                                                          new TraceSource("ss"),
                                                                          null,
                                                                          A.Fake <IDbProviderFactory>(),
                                                                          fakeOracleDependencyManager,
                                                                          fakeSignalrDbDependencyFactory,
                                                                          true);

            dbOperation.Queried += () => { throw new Exception(); };
            int counter = 0;

            dbOperation.Faulted += (ex) => { counter++; };

            using (var cts = new CancellationTokenSource())
            {
                Task.Run(() => dbOperation.ExecuteReaderWithUpdates(A.Fake <Action <IDataRecord, IDbOperation> >()),
                         cts.Token);
                Thread.Sleep(1000);
                dbOperation.Dispose();
                cts.Cancel();
            }

            Assert.IsTrue(counter > 0);
        }
        public void ExecuteReaderSetsNotificationStateCorrectlyUpToAwaitingNotification()
        {
            // Arrange
            var retryLoopDelays   = new[] { Tuple.Create(0, 1) };
            var dbProviderFactory = new MockDbProviderFactory();
            var dbBehavior        = new Mock <IDbBehavior>();
            var logger            = new Mock <ILogger>();

            dbBehavior.Setup(db => db.UpdateLoopRetryDelays).Returns(retryLoopDelays);
            dbBehavior.Setup(db => db.StartSqlDependencyListener()).Returns(true);
            dbBehavior.Setup(db => db.AddSqlDependency(It.IsAny <IDbCommand>(), It.IsAny <Action <SqlNotificationEventArgs> >()));
            var operation = new ObservableDbOperation("test", "test", logger.Object, dbProviderFactory, dbBehavior.Object);

            operation.Queried += () =>
            {
                // Currently in the query loop
                Assert.Equal(ObservableDbOperation.NotificationState.ProcessingUpdates, operation.CurrentNotificationState);
            };

            // Act
            operation.ExecuteReaderWithUpdates((_, __) => { });

            // Assert
            Assert.Equal(ObservableDbOperation.NotificationState.AwaitingNotification, operation.CurrentNotificationState);

            operation.Dispose();
        }
        public void ExecuteReaderSetsNotificationStateCorrectlyWhenNotificationReceivedBeforeChangingStateToAwaitingNotification()
        {
            // Arrange
            var mre                = new ManualResetEventSlim(false);
            var retryLoopDelays    = new[] { Tuple.Create(0, 1) };
            var dbProviderFactory  = new MockDbProviderFactory();
            var sqlDependencyAdded = false;
            var dbBehavior         = new Mock <IDbBehavior>();
            var logger             = new Mock <ILogger>();

            dbBehavior.Setup(db => db.UpdateLoopRetryDelays).Returns(retryLoopDelays);
            dbBehavior.Setup(db => db.StartSqlDependencyListener()).Returns(true);
            dbBehavior.Setup(db => db.AddSqlDependency(It.IsAny <IDbCommand>(), It.IsAny <Action <SqlNotificationEventArgs> >()))
            .Callback(() => sqlDependencyAdded = true);
            var operation = new ObservableDbOperation("test", "test", logger.Object, dbProviderFactory, dbBehavior.Object);

            dbProviderFactory.MockDataReader.Setup(r => r.Read()).Returns(() =>
            {
                if (sqlDependencyAdded)
                {
                    // Fake the SQL dependency firing while we're setting it up
                    operation.CurrentNotificationState = ObservableDbOperation.NotificationState.NotificationReceived;
                    sqlDependencyAdded = false;
                }
                return(false);
            });
            long?stateOnLoopRestart = null;
            var  queriedCount       = 0;

            operation.Queried += () =>
            {
                queriedCount++;

                if (queriedCount == 3)
                {
                    // First query after the loop starts again, capture the state
                    stateOnLoopRestart = operation.CurrentNotificationState;
                    mre.Set();
                }
            };

            // Act
            ThreadPool.QueueUserWorkItem(_ => operation.ExecuteReaderWithUpdates((__, ___) => { }));

            mre.Wait();

            Assert.True(stateOnLoopRestart.HasValue);
            Assert.Equal(ObservableDbOperation.NotificationState.ProcessingUpdates, stateOnLoopRestart.Value);

            operation.Dispose();
        }
        public void DoesRetryLoopConfiguredNumberOfTimes(int?length1, int?length2, int?length3)
        {
            // Arrange
            var retryLoopCount       = 0;
            var mre                  = new ManualResetEventSlim();
            var retryLoopArgs        = new List <int?>(new[] { length1, length2, length3 }).Where(l => l.HasValue);
            var retryLoopTotal       = retryLoopArgs.Sum().Value;
            var retryLoopDelays      = new List <Tuple <int, int> >(retryLoopArgs.Select(l => new Tuple <int, int>(0, l.Value)));
            var sqlDependencyCreated = false;
            var dbProviderFactory    = new MockDbProviderFactory();
            var dbBehavior           = new Mock <IDbBehavior>();
            var logger               = new Mock <ILogger>();

            dbBehavior.Setup(db => db.UpdateLoopRetryDelays).Returns(retryLoopDelays);
            dbBehavior.Setup(db => db.StartSqlDependencyListener()).Returns(true);
            dbBehavior.Setup(db => db.AddSqlDependency(It.IsAny <IDbCommand>(), It.IsAny <Action <SqlNotificationEventArgs> >()))
            .Callback(() =>
            {
                sqlDependencyCreated = true;
                mre.Set();
            });
            var operation = new ObservableDbOperation("test", "test", logger.Object, dbProviderFactory, dbBehavior.Object);

            operation.Faulted += _ => mre.Set();
            operation.Queried += () =>
            {
                if (!sqlDependencyCreated)
                {
                    // Only update the loop count if the SQL dependency hasn't been created yet (we're still in the loop)
                    retryLoopCount++;
                }
                if (retryLoopCount == retryLoopTotal)
                {
                    mre.Set();
                }
            };

            // Act
            ThreadPool.QueueUserWorkItem(_ => operation.ExecuteReaderWithUpdates((record, o) => { }));
            mre.Wait();
            operation.Dispose();

            // Assert
            Assert.Equal(retryLoopTotal, retryLoopCount);
        }
示例#6
0
        public void ExecuteReaderSetsNotificationStateCorrectlyWhenRecordsReceivedWhileSettingUpSqlDependency()
        {
            // Arrange
            var mre                     = new ManualResetEventSlim(false);
            var retryLoopDelays         = new[] { Tuple.Create(0, 1) };
            var dbProviderFactory       = new MockDbProviderFactory();
            var readCount               = 0;
            var sqlDependencyAddedCount = 0;

            dbProviderFactory.MockDataReader.Setup(r => r.Read()).Returns(() => ++ readCount == 2 && sqlDependencyAddedCount == 1);
            var dbBehavior = new Mock <IDbBehavior>();

            dbBehavior.Setup(db => db.UpdateLoopRetryDelays).Returns(retryLoopDelays);
            dbBehavior.Setup(db => db.StartSqlDependencyListener()).Returns(true);
            dbBehavior.Setup(db => db.AddSqlDependency(It.IsAny <IDbCommand>(), It.IsAny <Action <SqlNotificationEventArgs> >())).Callback(() => sqlDependencyAddedCount++);
            var  operation          = new ObservableDbOperation("test", "test", new TraceSource("test"), dbProviderFactory, dbBehavior.Object);
            long?stateOnLoopRestart = null;
            var  queriedCount       = 0;

            operation.Queried += () =>
            {
                queriedCount++;

                if (queriedCount == 3)
                {
                    // First query after the loop starts again, check the state is reset
                    stateOnLoopRestart = operation.CurrentNotificationState;
                    mre.Set();
                }
            };

            // Act
            ThreadPool.QueueUserWorkItem(_ => operation.ExecuteReaderWithUpdates((__, ___) => { }));

            Assert.True(mre.Wait(5000));

            Assert.True(stateOnLoopRestart.HasValue);
            Assert.Equal(ObservableDbOperation.NotificationState.ProcessingUpdates, stateOnLoopRestart.Value);

            operation.Dispose();
        }
        public void UseSqlNotificationsIfAvailable(bool supportSqlNotifications)
        {
            // Arrange
            var sqlDependencyAdded = false;
            var retryLoopCount     = 0;
            var mre = new ManualResetEventSlim();
            var dbProviderFactory = new MockDbProviderFactory();
            var dbBehavior        = new Mock <IDbBehavior>();
            var logger            = new Mock <ILogger>();

            dbBehavior.Setup(db => db.UpdateLoopRetryDelays).Returns(_defaultRetryDelays);
            dbBehavior.Setup(db => db.StartSqlDependencyListener()).Returns(supportSqlNotifications);
            dbBehavior.Setup(db => db.AddSqlDependency(It.IsAny <IDbCommand>(), It.IsAny <Action <SqlNotificationEventArgs> >()))
            .Callback(() =>
            {
                sqlDependencyAdded = true;
                mre.Set();
            });
            var operation = new ObservableDbOperation("test", "test", logger.Object, dbProviderFactory, dbBehavior.Object);

            operation.Faulted += _ => mre.Set();
            operation.Queried += () =>
            {
                retryLoopCount++;
                if (retryLoopCount > 1)
                {
                    mre.Set();
                }
            };

            // Act
            ThreadPool.QueueUserWorkItem(_ => operation.ExecuteReaderWithUpdates((record, o) => { }));
            mre.Wait();
            operation.Dispose();

            // Assert
            Assert.Equal(supportSqlNotifications, sqlDependencyAdded);
        }
示例#8
0
        public void Pooling_Success()
        {
            var fakeDbReader         = A.Fake <IDataReader>();
            var fakeDbReaderReadCall = A.CallTo(() => fakeDbReader.Read());

            fakeDbReaderReadCall.ReturnsNextFromSequence(true, true, false);

            var fakeEmptyDbReader = A.Fake <IDataReader>();

            A.CallTo(() => fakeEmptyDbReader.Read()).Returns(false);

            var fakeDbCommand = A.Fake <IDbCommand>();

            A.CallTo(() => fakeDbCommand.ExecuteReader()).ReturnsNextFromSequence(fakeDbReader, fakeEmptyDbReader);

            var fakeDbConnection = A.Fake <IDbConnection>();

            A.CallTo(() => fakeDbConnection.CreateCommand()).Returns(fakeDbCommand);
            var fakeDbConnectionDisposeCall = A.CallTo(() => fakeDbConnection.Dispose());

            var fakeDbProviderFactory = A.Fake <IDbProviderFactory>();

            A.CallTo(() => fakeDbProviderFactory.CreateConnection()).Returns(fakeDbConnection);

            var fakeProcessRecordAction           = A.Fake <Action <IDataRecord, IDbOperation> >();
            var fakeProcessRecordActionInvokeCall = A.CallTo(() => fakeProcessRecordAction.Invoke(null, null)).WithAnyArguments();

            var fakeDbBehavior = A.Fake <IDbBehavior>();

            A.CallTo(() => fakeDbBehavior.UpdateLoopRetryDelays).Returns(_updateLoopRetryDelays);

            var fakeOracleDependencyManager = A.Fake <IOracleDependencyManager>();
            var fakeOracleDependencyManagerRegistryDepCall = A.CallTo(() => fakeOracleDependencyManager.RegisterDependency(null)).WithAnyArguments();

            var fakeOracleDependencyManagerRemoveRegistrationCall =
                A.CallTo(() => fakeOracleDependencyManager.RemoveRegistration(string.Empty)).WithAnyArguments();

            var fakeSignalrDbDependencyFactory = A.Fake <ISignalrDbDependencyFactory>();
            var fakeSignalrDbDependencyFactoryCreateDepCall = A.CallTo(() => fakeSignalrDbDependencyFactory.CreateDbDependency(null, false, 0, false)).WithAnyArguments();

            ObservableDbOperation dbOperation = new ObservableDbOperation(string.Empty, string.Empty, new TraceSource("ss"),
                                                                          fakeDbBehavior,
                                                                          fakeDbProviderFactory,
                                                                          fakeOracleDependencyManager,
                                                                          fakeSignalrDbDependencyFactory,
                                                                          false);

            using (var cts = new CancellationTokenSource())
            {
                Task.Run(() => dbOperation.ExecuteReaderWithUpdates(fakeProcessRecordAction),
                         cts.Token);
                Thread.Sleep(1000);
                cts.Cancel();
            }

            Thread.Sleep(1000);
            fakeOracleDependencyManagerRegistryDepCall.MustNotHaveHappened();
            fakeSignalrDbDependencyFactoryCreateDepCall.MustNotHaveHappened();
            fakeProcessRecordActionInvokeCall.MustHaveHappened();
            fakeDbReaderReadCall.MustHaveHappened(Repeated.Exactly.Times(3));
            fakeDbConnectionDisposeCall.MustHaveHappened();

            dbOperation.Dispose();

            fakeOracleDependencyManagerRemoveRegistrationCall.MustHaveHappened(Repeated.Exactly.Once);
        }