public void ShouldNotAllowNewChangeSaveOperationBeforePreviousOneCompletes()
        {
            var apiShouldEnter   = new AutoResetEvent(initialState: false);
            var bulkUpdateCalled = 0;

            IDictionary <string, DocumentInfo> returnInfo = new Dictionary <string, DocumentInfo> {
                { SimpleEntity.StandardDocId, new DocumentInfo(SimpleEntity.StandardDocId, "2-cc2c5ab22cfa4a0faad27a0cb9ca7968") }
            };

            var dbApiMock = new Mock <IDatabaseApi>();

            dbApiMock
            .Setup(couchApi => couchApi.BulkUpdate(It.IsAny <Action <IBulkUpdateBatch> >()))
            .Returns <Action <IBulkUpdateBatch> >(
                updater => Task.Factory.StartNew(
                    () => {
                apiShouldEnter.WaitOne();

                Interlocked.Increment(ref bulkUpdateCalled);
                updater(Mock.Of <IBulkUpdateBatch>());

                return(returnInfo);
            },
                    TaskCreationOptions.PreferFairness
                    )
                );

            ISession sesion = new CouchSession(Default.Settings, Mock.Of <ICouchApi>(c => c.Db("testdb") == dbApiMock.Object));
            var      entity = SimpleEntity.CreateStandardWithoutRevision();

            sesion.Save(entity);
            var firstSaveChangesTask = sesion.StartSavingChanges();  // Enters API method

            Thread.Sleep(500);                                       //  Allowing first task to arrive to apiShouldEnter wating line first
            var secondSaveChangesTask = sesion.StartSavingChanges(); // Waits for first task to end

            Assert.Equal(0, bulkUpdateCalled);

            apiShouldEnter.Set();
            firstSaveChangesTask.WaitOrThrowOnTimeout();
            Assert.Equal(1, bulkUpdateCalled);


            entity.Age--;                       // Modifing entity for second save to be applicable
            apiShouldEnter.Set();               // Permitting second API method call to proceed
            secondSaveChangesTask.WaitOrThrowOnTimeout();
            Assert.Equal(2, bulkUpdateCalled);

            Assert.Equal("2-cc2c5ab22cfa4a0faad27a0cb9ca7968", entity.Revision);
        }
        public void ShouldDelegateChangesSaveToApi()
        {
            var couchApi = Mock.Of <ICouchApi>(
                c => c.Db("testdb") == Mock.Of <IDatabaseApi>(
                    d => d.BulkUpdate(It.IsAny <Action <IBulkUpdateBatch> >()) ==
                    new Dictionary <string, DocumentInfo>().ToTask <IDictionary <string, DocumentInfo> >()
                    )
                );

            ISession sesion = new CouchSession(Default.Settings, couchApi);

            sesion.Save(SimpleEntity.CreateStandardWithoutRevision());
            sesion.SaveChanges();

            Mock.Get(couchApi.Db("testdb")).Verify(dbApi => dbApi.BulkUpdate(It.IsAny <Action <IBulkUpdateBatch> >()), Times.Once());
        }
Ejemplo n.º 3
0
        public void ShouldSaveNewDocuments()
        {
            unitOfWork.AddNew(SimpleEntity.CreateStandardWithoutRevision());

            Document savedDoc = null;
            var      bulkUpdateUnitOfWorkMock = new Mock <IBulkUpdateBatch>(MockBehavior.Strict);

            bulkUpdateUnitOfWorkMock
            .Setup(u => u.Create(It.IsAny <Document>()))
            .Callback <Document>(d => { savedDoc = d; });

            unitOfWork.ApplyChanges(bulkUpdateUnitOfWorkMock.Object);

            Assert.NotNull(savedDoc);
            Assert.Equal(SimpleEntity.CreateDocumentWithoutRevision(), savedDoc);
        }
        public void ShouldAssignNewlyUpdatedRevisionsToEntities()
        {
            var couchApi = Mock.Of <ICouchApi>(
                c => c.Db("testdb") == Mock.Of <IDatabaseApi>(
                    d => d.BulkUpdate(It.IsAny <Action <IBulkUpdateBatch> >()) ==
                    new Dictionary <string, DocumentInfo> {
                { SimpleEntity.StandardDocId, new DocumentInfo(SimpleEntity.StandardDocId, "2-cc2c5ab22cfa4a0faad27a0cb9ca7968") }
            }.ToTask <IDictionary <string, DocumentInfo> >()
                    )
                );

            ISession sesion = new CouchSession(Default.Settings, couchApi);
            var      entity = SimpleEntity.CreateStandardWithoutRevision();

            sesion.Save(entity);
            sesion.SaveChanges();

            Assert.Equal("2-cc2c5ab22cfa4a0faad27a0cb9ca7968", entity.Revision);
        }
Ejemplo n.º 5
0
        public void ShouldNotCallCreateOrUpdateIfDocumentEntityHaveDeleted()
        {
            var persistedEntity = SimpleEntity.CreateStandard();

            unitOfWork.Attach(persistedEntity);
            var trancientEntity = SimpleEntity.CreateStandardWithoutRevision();

            unitOfWork.AddNew(trancientEntity);

            unitOfWork.MarkAsRemoved(trancientEntity);
            unitOfWork.MarkAsRemoved(persistedEntity);

            var bulkUpdateUnitOfWorkMock = new Mock <IBulkUpdateBatch>(MockBehavior.Strict);

            bulkUpdateUnitOfWorkMock
            .Setup(u => u.Delete(It.IsAny <string>(), It.IsAny <string>())).Callback <string, string>((id, rev) => { });

            //Should throw if methods other than Delete() have been called
            unitOfWork.ApplyChanges(bulkUpdateUnitOfWorkMock.Object);
        }
        public void ShouldNotAllowAnyOperationBeforeChangeSaveOperationCompletes(string operationName)
        {
            // I know this test is ginormus, but it's pretty self-contained and simple to understand

            var saveChangesOperationShouldProceed = new AutoResetEvent(initialState: false);
            var saveChangesOperationStarted       = new AutoResetEvent(initialState: false);
            var executedOperations = new List <string>();

            IDictionary <string, DocumentInfo> returnInfo = new Dictionary <string, DocumentInfo> {
                { SimpleEntity.StandardDocId, new DocumentInfo(SimpleEntity.StandardDocId, "2-cc2c5ab22cfa4a0faad27a0cb9ca7968") }
            };

            var dbApiMock = new Mock <IDatabaseApi>();

            dbApiMock
            .Setup(couchApi => couchApi.BulkUpdate(It.IsAny <Action <IBulkUpdateBatch> >()))
            .Returns <Action <IBulkUpdateBatch> >(
                updater => Task.Factory.StartNew(
                    () => {
                saveChangesOperationStarted.Set();
                saveChangesOperationShouldProceed.WaitOne();
                updater(Mock.Of <IBulkUpdateBatch>());
                return(returnInfo);
            }
                    )
                );
            dbApiMock
            .Setup(api => api.Query(It.IsAny <ViewQuery>()))
            .Returns <ViewQuery>(
                _ => {
                lock (executedOperations)
                    executedOperations.Add("Query");
                return(ViewQueryResult.Empty.ToTask());
            });
            dbApiMock
            .Setup(api => api.QueryLucene(It.IsAny <LuceneQuery>()))
            .Returns <LuceneQuery>(
                _ => {
                lock (executedOperations)
                    executedOperations.Add("QueryLucene");
                return
                (LuceneQueryResult.Empty.ToTask());
            });
            dbApiMock
            .Setup(api => api.RequestDocument(It.IsAny <string>(), It.IsAny <string>(), It.IsAny <AdditionalDocumentProperty>()))
            .Returns <string, string, AdditionalDocumentProperty>(
                (_, __, ___) => {
                lock (executedOperations)
                    executedOperations.Add("RequestDocument");
                return(SimpleEntity.CreateDocument().ToTask());
            });
            dbApiMock
            .Setup(api => api.RequestLastestDocumentRevision(It.IsAny <string>()))
            .Returns <string>(
                _ => {
                lock (executedOperations)
                    executedOperations.Add("RequestLastestDocumentRevision");
                return(SimpleEntity.StandardDocId.ToTask());
            });
            dbApiMock
            .Setup(api => api.DeleteDocument(It.IsAny <string>(), It.IsAny <string>()))
            .Returns <string, string>(
                (_, __) => {
                lock (executedOperations)
                    executedOperations.Add("DeleteDocument");
                return(SimpleEntity.StandardDocumentInfo.ToTask());
            });
            dbApiMock
            .Setup(api => api.SaveDocument(It.IsAny <Document>()))
            .Returns <Document>(
                _ => {
                lock (executedOperations)
                    executedOperations.Add("SaveDocument");
                return(SimpleEntity.StandardDocumentInfo.ToTask());
            });

            ISession sesion = new CouchSession(Default.Settings, Mock.Of <ICouchApi>(c => c.Db("testdb") == dbApiMock.Object));

            sesion.Save(SimpleEntity.CreateStandardWithoutRevision());
            var saveChangesOperation = sesion.StartSavingChanges();

            // Wating for StartSavingChanges to delegate execution to CouchAPI resetting session-wide wait handle
            saveChangesOperationStarted.WaitOne();

            var startOperationTask = Task.Factory.StartNew(
                () => {
                Task operation = null;
                switch (operationName)
                {
                case "load":
                    operation = sesion.Load <SimpleEntity>("doc1a");
                    break;

                case "query":
                    operation =
                        sesion.Query <SimpleEntity>(
                            new ViewQuery {
                        DesignDocumentName = "dd1",
                        ViewName           = "byX",
                        Key         = "key1",
                        IncludeDocs = true
                    });
                    break;

                case "fullTextQuery":
                    operation =
                        sesion.QueryLucene <SimpleEntity>(
                            new LuceneQuery
                    {
                        DesignDocumentName = "dd1",
                        IndexName          = "byX",
                        IncludeDocs        = true,
                        Query = "key1:2"
                    });
                    break;
                }
                // ReSharper disable PossibleNullReferenceException
                operation.WaitOrThrowOnTimeout();
                // ReSharper restore PossibleNullReferenceException
            });

            Assert.True(
                executedOperations.Count == 0,
                string.Join(", ", executedOperations) + " operation(s) have executed before save changes operation completes");

            saveChangesOperationShouldProceed.Set();
            saveChangesOperation.WaitOrThrowOnTimeout();

            startOperationTask.WaitOrThrowOnTimeout();
            Assert.Equal(1, executedOperations.Count);
        }
Ejemplo n.º 7
0
 public void ShouldThrowIfTransientDocumentEntityAttached()
 {
     Assert.Throws <ArgumentException>(() => unitOfWork.Attach(SimpleEntity.CreateStandardWithoutRevision()));
 }