public async Task WhenLeasesHaveContinuationTokenNullReturn0()
        {
            // Cleanup the test collection to avoid other tests' documents causing issues with StartFromBeginning
            await this.ResetTestCollection();

            int documentCount  = 1;
            int partitionCount = await IntegrationTestsHelper.GetPartitionCount(this.ClassData.monitoredCollectionInfo);

            int openedCount = 0, processedCount = 0;
            var allObserversStarted = new ManualResetEvent(false);
            var allDocsProcessed    = new ManualResetEvent(false);

            var observerFactory = new TestObserverFactory(
                context =>
            {
                int newCount = Interlocked.Increment(ref openedCount);
                if (newCount == partitionCount)
                {
                    allObserversStarted.Set();
                }
                return(Task.CompletedTask);
            },
                null,
                (ChangeFeedObserverContext context, IReadOnlyList <Document> docs) =>
            {
                int newCount = Interlocked.Add(ref processedCount, docs.Count);
                if (newCount == documentCount)
                {
                    allDocsProcessed.Set();
                }
                return(Task.CompletedTask);
            });

            var hostName = Guid.NewGuid().ToString();

            // We create a host to initialize the leases with ContinuationToken null
            var host = new ChangeFeedEventHost(
                hostName,
                this.ClassData.monitoredCollectionInfo,
                this.LeaseCollectionInfo,
                new ChangeFeedOptions {
                StartFromBeginning = false
            },
                new ChangeFeedHostOptions());

            // Initialize leases
            await host.RegisterObserverFactoryAsync(observerFactory);

            // Stop host, this leaves the leases with ContinuationToken null state
            await host.UnregisterObserversAsync();

            // Since the leases have ContinuationToken null state, the estimator will use StartFromBeginning and pick-up the changes that happened from the start
            long estimation = await host.GetEstimatedRemainingWork();

            Assert.Equal(0, estimation);
        }
        public async Task WhenNoLeasesExistReturn1()
        {
            var hostName = Guid.NewGuid().ToString();

            var host = new ChangeFeedEventHost(
                hostName,
                this.MonitoredCollectionInfo,
                this.LeaseCollectionInfo,
                new ChangeFeedOptions {
                StartFromBeginning = false
            },
                new ChangeFeedHostOptions());

            // Verify that 1 is returned on an uninitialized collection
            long estimation = await host.GetEstimatedRemainingWork();

            Assert.Equal(1, estimation);
        }
        public async Task WhenNoLeasesExistReturn1()
        {
            // Cleanup the test collection to avoid other tests' documents causing issues with StartFromBeginning
            await this.ResetTestCollection();

            var hostName = Guid.NewGuid().ToString();

            var host = new ChangeFeedEventHost(
                hostName,
                this.ClassData.monitoredCollectionInfo,
                this.LeaseCollectionInfo,
                new ChangeFeedOptions {
                StartFromBeginning = false
            },
                new ChangeFeedHostOptions());

            // Verify that 1 is returned on an uninitialized collection
            long estimation = await host.GetEstimatedRemainingWork();

            Assert.Equal(1, estimation);
        }
        public async Task CountPendingDocuments()
        {
            int documentCount  = 1;
            int partitionCount = await IntegrationTestsHelper.GetPartitionCount(this.MonitoredCollectionInfo);

            int openedCount = 0, processedCount = 0;
            var allObserversStarted = new ManualResetEvent(false);
            var allDocsProcessed    = new ManualResetEvent(false);

            var observerFactory = new TestObserverFactory(
                context =>
            {
                int newCount = Interlocked.Increment(ref openedCount);
                if (newCount == partitionCount)
                {
                    allObserversStarted.Set();
                }
                return(Task.CompletedTask);
            },
                null,
                (ChangeFeedObserverContext context, IReadOnlyList <Document> docs) =>
            {
                int newCount = Interlocked.Add(ref processedCount, docs.Count);
                if (newCount == documentCount)
                {
                    allDocsProcessed.Set();
                }
                return(Task.CompletedTask);
            });

            var hostName = Guid.NewGuid().ToString();

            var host = new ChangeFeedEventHost(
                hostName,
                this.MonitoredCollectionInfo,
                this.LeaseCollectionInfo,
                new ChangeFeedOptions {
                StartFromBeginning = false
            },
                new ChangeFeedHostOptions());

            // Initialize leases
            await host.RegisterObserverFactoryAsync(observerFactory);

            // Verify that 0 is returned on empty collection
            long estimation = await host.GetEstimatedRemainingWork();

            Assert.Equal(0, estimation);

            using (var client = new DocumentClient(this.MonitoredCollectionInfo.Uri, this.MonitoredCollectionInfo.MasterKey, this.MonitoredCollectionInfo.ConnectionPolicy))
            {
                await IntegrationTestsHelper.CreateDocumentsAsync(
                    client,
                    UriFactory.CreateDocumentCollectionUri(this.MonitoredCollectionInfo.DatabaseName, this.MonitoredCollectionInfo.CollectionName),
                    1);

                var isStartOk = allObserversStarted.WaitOne(IntegrationTest.changeWaitTimeout + IntegrationTest.changeWaitTimeout);
                Assert.True(isStartOk, "Timed out waiting for observer to start");

                allDocsProcessed.WaitOne(IntegrationTest.changeWaitTimeout);

                // Halt the processor temporarily
                await host.UnregisterObserversAsync();

                estimation = await host.GetEstimatedRemainingWork();

                Assert.Equal(0, estimation);

                await IntegrationTestsHelper.CreateDocumentsAsync(
                    client,
                    UriFactory.CreateDocumentCollectionUri(this.MonitoredCollectionInfo.DatabaseName, this.MonitoredCollectionInfo.CollectionName),
                    1);

                estimation = await host.GetEstimatedRemainingWork();

                Assert.Equal(1, estimation);

                await IntegrationTestsHelper.CreateDocumentsAsync(
                    client,
                    UriFactory.CreateDocumentCollectionUri(this.MonitoredCollectionInfo.DatabaseName, this.MonitoredCollectionInfo.CollectionName),
                    10);

                estimation = await host.GetEstimatedRemainingWork();

                Assert.Equal(11, estimation);

                // Create a new host to process pending changes
                var newHost = new ChangeFeedEventHost(
                    hostName,
                    this.MonitoredCollectionInfo,
                    this.LeaseCollectionInfo,
                    new ChangeFeedOptions {
                    StartFromBeginning = false
                },
                    new ChangeFeedHostOptions());

                openedCount    = 0;
                processedCount = 0;
                allObserversStarted.Reset();
                allDocsProcessed.Reset();

                await newHost.RegisterObserverFactoryAsync(observerFactory);

                isStartOk = allObserversStarted.WaitOne(IntegrationTest.changeWaitTimeout + IntegrationTest.changeWaitTimeout);
                Assert.True(isStartOk, "Timed out waiting for observer to start");

                allDocsProcessed.WaitOne(IntegrationTest.changeWaitTimeout);

                try
                {
                    estimation = await newHost.GetEstimatedRemainingWork();

                    Assert.Equal(0, estimation);
                }
                finally
                {
                    await newHost.UnregisterObserversAsync();
                }
            }
        }