public async Task BatchNotification_ReportsOperationCount()
        {
            var store = new MobileServiceLocalStoreMock();
            var trackingContext = new StoreTrackingContext(StoreOperationSource.ServerPull, string.Empty);
            var eventManager = new MobileServiceEventManagerMock<IMobileServiceEvent>();
            var settings = new MobileServiceSyncSettingsManager(store);
            var changeTracker = new LocalStoreChangeTracker(store, trackingContext, eventManager, settings);

            EnqueueSimpleObjectResponse(store, "123", "XXX", "789");

            await changeTracker.UpsertAsync("test", new JObject() { { "id", "123" }, { "version", "2" } }, true); // Update
            await changeTracker.UpsertAsync("test", new JObject() { { "id", "456" }, { "version", "2" } }, true); // Insert
            await changeTracker.DeleteAsync("test", "789"); // Delete

            StoreOperationsBatchCompletedEvent batchEvent = null;
            eventManager.PublishAsyncFunc = e =>
            {
                batchEvent = e as StoreOperationsBatchCompletedEvent;
                return Task.FromResult(0);
            };

            changeTracker.Dispose();

            Assert.IsNotNull(batchEvent);
            Assert.AreEqual(batchEvent.Batch.OperationCount, 3);
            Assert.AreEqual(batchEvent.Batch.GetOperationCountByKind(LocalStoreOperationKind.Update), 1);
            Assert.AreEqual(batchEvent.Batch.GetOperationCountByKind(LocalStoreOperationKind.Insert), 1);
            Assert.AreEqual(batchEvent.Batch.GetOperationCountByKind(LocalStoreOperationKind.Delete), 1);
        }
예제 #2
0
        public async Task DeleteAsync_WithTableNameAndRecordIds_SendsNotification()
        {
            var store           = new MobileServiceLocalStoreMock();
            var trackingContext = new StoreTrackingContext(StoreOperationSource.Local, string.Empty);
            var eventManager    = new MobileServiceEventManagerMock <IMobileServiceEvent>();
            var settings        = new MobileServiceSyncSettingsManager(store);
            var changeTracker   = new LocalStoreChangeTracker(store, trackingContext, eventManager, settings);

            JObject item = EnqueueSimpleObjectResponse(store);

            StoreOperationCompletedEvent operationEvent = null;

            eventManager.PublishAsyncFunc = t =>
            {
                operationEvent = t as StoreOperationCompletedEvent;
                return(Task.FromResult(0));
            };

            await changeTracker.DeleteAsync("test", "123");

            Assert.IsNotNull(operationEvent);
            Assert.AreEqual(operationEvent.Operation.Kind, LocalStoreOperationKind.Delete);
            Assert.AreEqual(operationEvent.Operation.RecordId, "123");
            Assert.AreEqual(operationEvent.Operation.TableName, "test");
        }
예제 #3
0
        public async Task DeleteAsync_WithQuery_SendsNotification()
        {
            var store           = new MobileServiceLocalStoreMock();
            var trackingContext = new StoreTrackingContext(StoreOperationSource.Local, string.Empty);
            var eventManager    = new MobileServiceEventManagerMock <IMobileServiceEvent>();
            var settings        = new MobileServiceSyncSettingsManager(store);
            var changeTracker   = new LocalStoreChangeTracker(store, trackingContext, eventManager, settings);

            JObject item = EnqueueSimpleObjectResponse(store);

            StoreOperationCompletedEvent operationEvent = null;

            eventManager.PublishAsyncFunc = t =>
            {
                operationEvent = t as StoreOperationCompletedEvent;
                return(Task.FromResult(0));
            };

            MobileServiceTableQueryDescription query = new MobileServiceTableQueryDescription("test");

            query.Filter = new BinaryOperatorNode(BinaryOperatorKind.Equal, new MemberAccessNode(null, MobileServiceSystemColumns.Id), new ConstantNode("123"));

            await changeTracker.DeleteAsync(query);

            Assert.IsNotNull(operationEvent);
            Assert.AreEqual(operationEvent.Operation.Kind, LocalStoreOperationKind.Delete);
            Assert.AreEqual(operationEvent.Operation.RecordId, "123");
            Assert.AreEqual(operationEvent.Operation.TableName, "test");
        }
예제 #4
0
        public async Task PushAsync_FeatureHeaderPresentWhenRehydrated()
        {
            var hijack = new TestHttpHandler();
            IMobileServiceClient service = new MobileServiceClient(MobileAppUriValidator.DummyMobileApp, hijack);
            var store = new MobileServiceLocalStoreMock();
            await service.SyncContext.InitializeAsync(store, new MobileServiceSyncHandler());

            IMobileServiceSyncTable table = service.GetSyncTable("someTable");
            JObject item1 = new JObject()
            {
                { "id", "abc" }
            };
            await table.InsertAsync(item1);

            // create a new service to test that operations are loaded from store
            hijack = new TestHttpHandler();
            hijack.AddResponseContent("{\"id\":\"abc\",\"String\":\"Hey\"}");

            service = new MobileServiceClient(MobileAppUriValidator.DummyMobileApp, hijack);
            await service.SyncContext.InitializeAsync(store, new MobileServiceSyncHandler());

            await service.SyncContext.PushAsync();

            Assert.Equal("TU,OL", hijack.Requests[0].Headers.GetValues("X-ZUMO-FEATURES").First());
        }
예제 #5
0
        public async Task UpdateOperationAsync_UpsertTheItemInOperation_AndDeletesTheError()
        {
            var client  = new MobileServiceClient("http://www.test.com");
            var store   = new MobileServiceLocalStoreMock();
            var context = new MobileServiceSyncContext(client);
            await context.InitializeAsync(store);

            string operationId = "abc";
            string itemId      = "def";
            string tableName   = "test";

            var item = new JObject()
            {
                { "id", itemId }, { "name", "unknown" }
            };

            store.TableMap[MobileServiceLocalSystemTables.SyncErrors] = new Dictionary <string, JObject>()
            {
                { operationId, new JObject()
                  {
                      { "id", operationId }, { "version", 1 }
                  } }
            };
            store.TableMap[MobileServiceLocalSystemTables.OperationQueue].Add(operationId, new JObject()
            {
                { "id", operationId }, { "version", 1 }, { "item", item.ToString() }, { "kind", (int)MobileServiceTableOperationKind.Delete }
            });

            // operation exists before cancel
            Assert.NotNull(await store.LookupAsync(MobileServiceLocalSystemTables.OperationQueue, operationId));
            // item does not exist
            Assert.Null(await store.LookupAsync(tableName, itemId));

            var error = new MobileServiceTableOperationError(operationId,
                                                             1,
                                                             MobileServiceTableOperationKind.Delete,
                                                             HttpStatusCode.PreconditionFailed,
                                                             tableName,
                                                             item: new JObject()
            {
                { "id", itemId }
            },
                                                             rawResult: "{}",
                                                             result: new JObject());
            var item2 = new JObject()
            {
                { "id", itemId }, { "name", "unknown" }, { "version", 2 }
            };
            await context.UpdateOperationAsync(error, item2);

            var operation = await store.LookupAsync(MobileServiceLocalSystemTables.OperationQueue, operationId);

            // operation is updated
            Assert.NotNull(operation);
            // error is deleted
            Assert.Null(await store.LookupAsync(MobileServiceLocalSystemTables.SyncErrors, operationId));

            Assert.Equal(operation.GetValue("item").ToString(), item2.ToString(Formatting.None));
        }
        public void Constructor_Throws_WhenTrackingOptionsAreInvalid()
        {
            var store = new MobileServiceLocalStoreMock();
            var trackingContext = new StoreTrackingContext(StoreOperationSource.Local, string.Empty, StoreTrackingOptions.None);
            var eventManager = new MobileServiceEventManager();
            var settings = new MobileServiceSyncSettingsManager(store);

            AssertEx.Throws<InvalidOperationException>(() => new LocalStoreChangeTracker(store, trackingContext, eventManager, settings));
        }
예제 #7
0
        public void Constructor_Throws_WhenTrackingOptionsAreInvalid()
        {
            var store           = new MobileServiceLocalStoreMock();
            var trackingContext = new StoreTrackingContext(StoreOperationSource.Local, string.Empty, StoreTrackingOptions.None);
            var eventManager    = new MobileServiceEventManager();
            var settings        = new MobileServiceSyncSettingsManager(store);

            AssertEx.Throws <InvalidOperationException>(() => new LocalStoreChangeTracker(store, trackingContext, eventManager, settings));
        }
        private void AssertUntrackedStoreForSourceWithOptions(StoreOperationSource source, StoreTrackingOptions trackingOptions)
        {
            var store = new MobileServiceLocalStoreMock();
            var trackingContext = new StoreTrackingContext(StoreOperationSource.Local, string.Empty, StoreTrackingOptions.None);
            var eventManager = new MobileServiceEventManager();
            var settings = new MobileServiceSyncSettingsManager(store);

            IMobileServiceLocalStore trackedStore = StoreChangeTrackerFactory.CreateTrackedStore(store, source, trackingOptions, eventManager, settings);

            Assert.IsNotNull(trackedStore);
            Assert.IsTrue(trackedStore is LocalStoreProxy);
        }
        private void AssertUntrackedStoreForSourceWithOptions(StoreOperationSource source, StoreTrackingOptions trackingOptions)
        {
            var store           = new MobileServiceLocalStoreMock();
            var trackingContext = new StoreTrackingContext(StoreOperationSource.Local, string.Empty, StoreTrackingOptions.None);
            var eventManager    = new MobileServiceEventManager();
            var settings        = new MobileServiceSyncSettingsManager(store);

            IMobileServiceLocalStore trackedStore = StoreChangeTrackerFactory.CreateTrackedStore(store, source, trackingOptions, eventManager, settings);

            Assert.NotNull(trackedStore);
            Assert.IsType <LocalStoreProxy>(trackedStore);
        }
예제 #10
0
        public async Task CancelAndUpdateItemAsync_UpsertsTheItemInLocalStore_AndDeletesTheOperationAndError()
        {
            var client  = new MobileServiceClient(MobileAppUriValidator.DummyMobileApp);
            var store   = new MobileServiceLocalStoreMock();
            var context = new MobileServiceSyncContext(client);
            await context.InitializeAsync(store);

            string operationId = "abc";
            string itemId      = "def";
            string tableName   = "test";


            store.TableMap[MobileServiceLocalSystemTables.SyncErrors] = new Dictionary <string, JObject>()
            {
                { operationId, new JObject() }
            };
            store.TableMap[MobileServiceLocalSystemTables.OperationQueue].Add(operationId, new JObject());

            // operation exists before cancel
            Assert.NotNull(await store.LookupAsync(MobileServiceLocalSystemTables.OperationQueue, operationId));
            // item doesn't exist before upsert
            Assert.Null(await store.LookupAsync(tableName, itemId));

            var error = new MobileServiceTableOperationError(operationId,
                                                             0,
                                                             MobileServiceTableOperationKind.Update,
                                                             HttpStatusCode.Conflict,
                                                             tableName,
                                                             item: new JObject()
            {
                { "id", itemId }
            },
                                                             rawResult: "{}",
                                                             result: new JObject());

            var item = new JObject()
            {
                { "id", itemId }, { "name", "unknown" }
            };
            await context.CancelAndUpdateItemAsync(error, item);

            // operation is deleted
            Assert.Null(await store.LookupAsync(MobileServiceLocalSystemTables.OperationQueue, operationId));
            // error is deleted
            Assert.Null(await store.LookupAsync(MobileServiceLocalSystemTables.SyncErrors, operationId));

            JObject upserted = await store.LookupAsync(tableName, itemId);

            // item is upserted
            Assert.NotNull(upserted);
            Assert.Equal(item, upserted);
        }
예제 #11
0
        public async Task PushAsync_ExecutesThePendingOperations_InOrder()
        {
            var hijack = new TestHttpHandler();
            IMobileServiceClient service = new MobileServiceClient(MobileAppUriValidator.DummyMobileApp, hijack);
            var store = new MobileServiceLocalStoreMock();
            await service.SyncContext.InitializeAsync(store, new MobileServiceSyncHandler());

            IMobileServiceSyncTable table = service.GetSyncTable("someTable");

            JObject item1 = new JObject()
            {
                { "id", "abc" }
            }, item2 = new JObject()
            {
                { "id", "def" }
            };

            await table.InsertAsync(item1);

            await table.InsertAsync(item2);

            Assert.Empty(hijack.Requests);

            // create a new service to test that operations are loaded from store
            hijack = new TestHttpHandler();
            hijack.AddResponseContent("{\"id\":\"abc\",\"String\":\"Hey\"}");
            hijack.AddResponseContent("{\"id\":\"def\",\"String\":\"What\"}");

            service = new MobileServiceClient(MobileAppUriValidator.DummyMobileApp, hijack);
            await service.SyncContext.InitializeAsync(store, new MobileServiceSyncHandler());

            Assert.Empty(hijack.Requests);
            await service.SyncContext.PushAsync();

            Assert.Equal(2, hijack.Requests.Count);

            Assert.Equal(item1.ToString(Formatting.None), hijack.RequestContents[0]);
            Assert.Equal("TU,OL", hijack.Requests[0].Headers.GetValues("X-ZUMO-FEATURES").First());
            Assert.Equal(item2.ToString(Formatting.None), hijack.RequestContents[1]);
            Assert.Equal("TU,OL", hijack.Requests[1].Headers.GetValues("X-ZUMO-FEATURES").First());

            // create yet another service to make sure the old items were purged from queue
            hijack = new TestHttpHandler();
            hijack.AddResponseContent("{\"id\":\"abc\",\"String\":\"Hey\"}");
            service = new MobileServiceClient(MobileAppUriValidator.DummyMobileApp, hijack);
            await service.SyncContext.InitializeAsync(store, new MobileServiceSyncHandler());

            Assert.Empty(hijack.Requests);
            await service.SyncContext.PushAsync();

            Assert.Empty(hijack.Requests);
        }
예제 #12
0
        public async Task UpdateOperationAsync_UpsertsTheItemInLocalStore_AndDeletesTheError_FromSyncHandler()
        {
            // Arrange
            string itemId = "abc";
            var    hijack = new TestHttpHandler();

            hijack.Responses.Add(new HttpResponseMessage(HttpStatusCode.InternalServerError));

            var handler = new MobileServiceSyncHandlerMock();

            handler.PushCompleteAction = async pushCompletionResult =>
            {
                foreach (var error in pushCompletionResult.Errors)
                {
                    await error.UpdateOperationAsync(JObject.Parse("{\"id\":\"abc\",\"__version\":\"Hey\"}"));
                }
            };
            var store = new MobileServiceLocalStoreMock();
            IMobileServiceClient service = new MobileServiceClient("http://www.test.com", hijack);
            await service.SyncContext.InitializeAsync(store, handler);

            IMobileServiceSyncTable table = service.GetSyncTable("someTable");

            await table.InsertAsync(new JObject()
            {
                { "id", "abc" }, { "__version", "Wow" }
            });

            // Act
            await(service.SyncContext as MobileServiceSyncContext).PushAsync(CancellationToken.None, MobileServiceTableKind.Table);


            // Assert
            var     syncError = store.TableMap[MobileServiceLocalSystemTables.SyncErrors].Values;
            var     operation = store.TableMap[MobileServiceLocalSystemTables.OperationQueue].Values.FirstOrDefault();
            var     item      = JObject.Parse("{\"id\":\"abc\",\"__version\":\"Hey\"}");
            JObject upserted  = await store.LookupAsync("someTable", itemId);

            // item is upserted
            Assert.NotNull(upserted);

            // verify if the record was updated
            Assert.Equal(item.ToString(), upserted.ToString());

            // verify if the errors were cleared
            Assert.Empty(syncError);

            // Verify operation is still present
            Assert.Equal(operation.Value <string>("itemId"), itemId);
        }
예제 #13
0
        private async Task ConflictOperation_WithNotificationsEnabled_UsesTheCorrectStoreOperationSource(Func <MobileServiceSyncContext, MobileServiceTableOperationError, Task> handler)
        {
            var client           = new MobileServiceClient(MobileAppUriValidator.DummyMobileApp);
            var store            = new MobileServiceLocalStoreMock();
            var context          = new MobileServiceSyncContext(client);
            var manualResetEvent = new ManualResetEventSlim();

            await context.InitializeAsync(store, StoreTrackingOptions.NotifyLocalConflictResolutionOperations);

            string operationId = "abc";
            string itemId      = string.Empty;
            string tableName   = "test";

            store.TableMap[MobileServiceLocalSystemTables.OperationQueue].Add(operationId, new JObject()
            {
                { "version", 1 }
            });


            var error = new MobileServiceTableOperationError(operationId,
                                                             1,
                                                             MobileServiceTableOperationKind.Update,
                                                             HttpStatusCode.Conflict,
                                                             tableName,
                                                             item: new JObject()
            {
                { "id", itemId }
            },
                                                             rawResult: "{}",
                                                             result: new JObject());


            bool        sourceIsLocalConflict = false;
            IDisposable subscription          = client.EventManager.Subscribe <StoreOperationCompletedEvent>(o =>
            {
                sourceIsLocalConflict = o.Operation.Source == StoreOperationSource.LocalConflictResolution;
                manualResetEvent.Set();
            });

            await handler(context, error);

            bool resetEventSignaled = manualResetEvent.Wait(1000);

            subscription.Dispose();

            Assert.True(resetEventSignaled);
            Assert.True(sourceIsLocalConflict);
        }
예제 #14
0
        private IEnumerable <JObject> EnqueueSimpleObjectResponse(MobileServiceLocalStoreMock store, params string[] ids)
        {
            var results = new List <JObject>();

            foreach (var id in ids)
            {
                var item = new JObject()
                {
                    { "id", id }, { "version", "1" }
                };
                store.ReadResponses.Enqueue(string.Format("[{0}]", item.ToString()));

                results.Add(item);
            }

            return(results);
        }
        public void Disposing_CompletesBatch()
        {
            var store = new MobileServiceLocalStoreMock();
            var trackingContext = new StoreTrackingContext(StoreOperationSource.ServerPull, string.Empty);
            var eventManager = new MobileServiceEventManagerMock<IMobileServiceEvent>();
            var settings = new MobileServiceSyncSettingsManager(store);

            StoreOperationsBatchCompletedEvent batchEvent = null;
            eventManager.PublishAsyncFunc = e =>
            {
                batchEvent = e as StoreOperationsBatchCompletedEvent;
                return Task.FromResult(0);
            };

            var changeTracker = new LocalStoreChangeTracker(store, trackingContext, eventManager, settings);
            changeTracker.Dispose();

            Assert.IsNotNull(batchEvent);
        }
예제 #16
0
        public async Task PushAsync_ReplaysStoredErrors_IfTheyAreInStore()
        {
            var error = new MobileServiceTableOperationError("abc",
                                                             1,
                                                             MobileServiceTableOperationKind.Update,
                                                             HttpStatusCode.PreconditionFailed,
                                                             "test",
                                                             new JObject(),
                                                             "{}",
                                                             new JObject());
            var store = new MobileServiceLocalStoreMock();
            await store.UpsertAsync(MobileServiceLocalSystemTables.SyncErrors, error.Serialize(), fromServer : false);

            var hijack = new TestHttpHandler();
            IMobileServiceClient service = new MobileServiceClient(MobileAppUriValidator.DummyMobileApp, hijack);
            await service.SyncContext.InitializeAsync(store, new MobileServiceSyncHandler());

            await Assert.ThrowsAsync <MobileServicePushFailedException>(() => service.SyncContext.PushAsync());
        }
예제 #17
0
        public void Disposing_CompletesBatch()
        {
            var store           = new MobileServiceLocalStoreMock();
            var trackingContext = new StoreTrackingContext(StoreOperationSource.ServerPull, string.Empty);
            var eventManager    = new MobileServiceEventManagerMock <IMobileServiceEvent>();
            var settings        = new MobileServiceSyncSettingsManager(store);

            StoreOperationsBatchCompletedEvent batchEvent = null;

            eventManager.PublishAsyncFunc = e =>
            {
                batchEvent = e as StoreOperationsBatchCompletedEvent;
                return(Task.FromResult(0));
            };

            var changeTracker = new LocalStoreChangeTracker(store, trackingContext, eventManager, settings);

            changeTracker.Dispose();

            Assert.IsNotNull(batchEvent);
        }
예제 #18
0
        private async Task TestOperationModifiedException(bool operationExists, Func <MobileServiceTableOperationError, MobileServiceSyncContext, Task> action, String errorMessage)
        {
            var client  = new MobileServiceClient(MobileAppUriValidator.DummyMobileApp);
            var store   = new MobileServiceLocalStoreMock();
            var context = new MobileServiceSyncContext(client);
            await context.InitializeAsync(store);

            string operationId = "abc";
            string itemId      = "def";
            string tableName   = "test";

            if (operationExists)
            {
                store.TableMap[MobileServiceLocalSystemTables.OperationQueue].Add(operationId, new JObject()
                {
                    { "version", 3 }
                });
            }
            else
            {
                // operation exists before cancel
                Assert.Null(await store.LookupAsync(MobileServiceLocalSystemTables.OperationQueue, operationId));
            }

            var error = new MobileServiceTableOperationError(operationId,
                                                             1,
                                                             MobileServiceTableOperationKind.Update,
                                                             HttpStatusCode.Conflict,
                                                             tableName,
                                                             item: new JObject()
            {
                { "id", itemId }
            },
                                                             rawResult: "{}",
                                                             result: new JObject());

            InvalidOperationException ex = await Assert.ThrowsAsync <InvalidOperationException>(() => action(error, context));

            Assert.Equal(errorMessage, ex.Message);
        }
예제 #19
0
        public async Task BatchNotification_ReportsOperationCount()
        {
            var store           = new MobileServiceLocalStoreMock();
            var trackingContext = new StoreTrackingContext(StoreOperationSource.ServerPull, string.Empty);
            var eventManager    = new MobileServiceEventManagerMock <IMobileServiceEvent>();
            var settings        = new MobileServiceSyncSettingsManager(store);
            var changeTracker   = new LocalStoreChangeTracker(store, trackingContext, eventManager, settings);

            EnqueueSimpleObjectResponse(store, "123", "XXX", "789");

            await changeTracker.UpsertAsync("test", new JObject()
            {
                { "id", "123" }, { "version", "2" }
            }, true);                                                                                             // Update

            await changeTracker.UpsertAsync("test", new JObject()
            {
                { "id", "456" }, { "version", "2" }
            }, true);                                       // Insert

            await changeTracker.DeleteAsync("test", "789"); // Delete

            StoreOperationsBatchCompletedEvent batchEvent = null;

            eventManager.PublishAsyncFunc = e =>
            {
                batchEvent = e as StoreOperationsBatchCompletedEvent;
                return(Task.FromResult(0));
            };

            changeTracker.Dispose();

            Assert.IsNotNull(batchEvent);
            Assert.AreEqual(batchEvent.Batch.OperationCount, 3);
            Assert.AreEqual(batchEvent.Batch.GetOperationCountByKind(LocalStoreOperationKind.Update), 1);
            Assert.AreEqual(batchEvent.Batch.GetOperationCountByKind(LocalStoreOperationKind.Insert), 1);
            Assert.AreEqual(batchEvent.Batch.GetOperationCountByKind(LocalStoreOperationKind.Delete), 1);
        }
예제 #20
0
        private async Task AssertNotificationResultWithMatchingLocalRecordVersion(StoreOperationSource[] operationSources, bool shouldNotify)
        {
            foreach (var operationSource in operationSources)
            {
                var store           = new MobileServiceLocalStoreMock();
                var trackingContext = new StoreTrackingContext(operationSource, string.Empty);
                var eventManager    = new MobileServiceEventManagerMock <IMobileServiceEvent>();
                var settings        = new MobileServiceSyncSettingsManager(store);
                var changeTracker   = new LocalStoreChangeTracker(store, trackingContext, eventManager, settings);

                JObject item = EnqueueSimpleObjectResponse(store);

                bool notificationSent = false;
                eventManager.PublishAsyncFunc = t =>
                {
                    notificationSent = true;
                    return(Task.FromResult(0));
                };

                await changeTracker.UpsertAsync("test", item, true);

                Assert.AreEqual(notificationSent, shouldNotify, string.Format("Incorrect notification result with source {0}", operationSource));
            }
        }
        public async Task DeleteAsync_WithTableNameAndRecordIds_SendsNotification()
        {
            var store = new MobileServiceLocalStoreMock();
            var trackingContext = new StoreTrackingContext(StoreOperationSource.Local, string.Empty);
            var eventManager = new MobileServiceEventManagerMock<IMobileServiceEvent>();
            var settings = new MobileServiceSyncSettingsManager(store);
            var changeTracker = new LocalStoreChangeTracker(store, trackingContext, eventManager, settings);

            JObject item = EnqueueSimpleObjectResponse(store);

            StoreOperationCompletedEvent operationEvent = null;
            eventManager.PublishAsyncFunc = t =>
            {
                operationEvent = t as StoreOperationCompletedEvent;
                return Task.FromResult(0);
            };

            await changeTracker.DeleteAsync("test", "123");

            Assert.IsNotNull(operationEvent);
            Assert.AreEqual(operationEvent.Operation.Kind, LocalStoreOperationKind.Delete);
            Assert.AreEqual(operationEvent.Operation.RecordId, "123");
            Assert.AreEqual(operationEvent.Operation.TableName, "test");
        }
        public async Task DeleteAsync_WithQuery_SendsNotification()
        {
            var store = new MobileServiceLocalStoreMock();
            var trackingContext = new StoreTrackingContext(StoreOperationSource.Local, string.Empty);
            var eventManager = new MobileServiceEventManagerMock<IMobileServiceEvent>();
            var settings = new MobileServiceSyncSettingsManager(store);
            var changeTracker = new LocalStoreChangeTracker(store, trackingContext, eventManager, settings);

            JObject item = EnqueueSimpleObjectResponse(store);

            StoreOperationCompletedEvent operationEvent = null;
            eventManager.PublishAsyncFunc = t =>
            {
                operationEvent = t as StoreOperationCompletedEvent;
                return Task.FromResult(0);
            };

            MobileServiceTableQueryDescription query = new MobileServiceTableQueryDescription("test");
            query.Filter = new BinaryOperatorNode(BinaryOperatorKind.Equal, new MemberAccessNode(null, MobileServiceSystemColumns.Id), new ConstantNode("123"));

            await changeTracker.DeleteAsync(query);

            Assert.IsNotNull(operationEvent);
            Assert.AreEqual(operationEvent.Operation.Kind, LocalStoreOperationKind.Delete);
            Assert.AreEqual(operationEvent.Operation.RecordId, "123");
            Assert.AreEqual(operationEvent.Operation.TableName, "test");
        }
        private async Task AssertNotificationResultWithMatchingLocalRecordVersion(StoreOperationSource[] operationSources, bool shouldNotify)
        {
            foreach (var operationSource in operationSources)
            {
                var store = new MobileServiceLocalStoreMock();
                var trackingContext = new StoreTrackingContext(operationSource, string.Empty);
                var eventManager = new MobileServiceEventManagerMock<IMobileServiceEvent>();
                var settings = new MobileServiceSyncSettingsManager(store);
                var changeTracker = new LocalStoreChangeTracker(store, trackingContext, eventManager, settings);

                JObject item = EnqueueSimpleObjectResponse(store);

                bool notificationSent = false;
                eventManager.PublishAsyncFunc = t =>
                {
                    notificationSent = true;
                    return Task.FromResult(0);
                };

                await changeTracker.UpsertAsync("test", item, true);

                Assert.AreEqual(notificationSent, shouldNotify, string.Format("Incorrect notification result with source {0}", operationSource));
            }
        }
 private JObject EnqueueSimpleObjectResponse(MobileServiceLocalStoreMock store)
 {
     return EnqueueSimpleObjectResponse(store, "123").First();
 }
        private IEnumerable<JObject> EnqueueSimpleObjectResponse(MobileServiceLocalStoreMock store, params string[] ids)
        {
            var results = new List<JObject>();
            foreach (var id in ids)
            {
                var item = new JObject() { { "id", id }, { "version", "1" } };
                store.ReadResponses.Enqueue(string.Format("[{0}]", item.ToString()));

                results.Add(item);
            }
            
            return results;
        }
예제 #26
0
 private JObject EnqueueSimpleObjectResponse(MobileServiceLocalStoreMock store)
 {
     return(EnqueueSimpleObjectResponse(store, "123").First());
 }
예제 #27
0
        private async Task UpdateOperationAsync_ConflictOperation_WithNotificationsEnabled_UsesTheCorrectStoreSource()
        {
            var client  = new MobileServiceClient("http://www.test.com");
            var store   = new MobileServiceLocalStoreMock();
            var context = new MobileServiceSyncContext(client);
            await context.InitializeAsync(store, StoreTrackingOptions.NotifyLocalConflictResolutionOperations);

            var manualResetEvent = new ManualResetEventSlim();

            string operationId = "abc";
            string itemId      = "def";
            string tableName   = "test";


            store.TableMap[MobileServiceLocalSystemTables.SyncErrors] = new Dictionary <string, JObject>()
            {
                { operationId, new JObject()
                  {
                      { "id", operationId }, { "version", 1 }
                  } }
            };
            store.TableMap[MobileServiceLocalSystemTables.OperationQueue].Add(operationId, new JObject()
            {
                { "id", operationId }, { "version", 1 }
            });
            store.TableMap.Add(tableName, new Dictionary <string, JObject>()
            {
                { itemId, new JObject() }
            });

            // operation exists before cancel
            Assert.NotNull(await store.LookupAsync(MobileServiceLocalSystemTables.OperationQueue, operationId));
            // item exists before upsert
            Assert.NotNull(await store.LookupAsync(tableName, itemId));


            var error = new MobileServiceTableOperationError(operationId,
                                                             1,
                                                             MobileServiceTableOperationKind.Update,
                                                             HttpStatusCode.Conflict,
                                                             tableName,
                                                             item: new JObject()
            {
                { "id", itemId }
            },
                                                             rawResult: "{}",
                                                             result: new JObject());
            var item = new JObject()
            {
                { "id", itemId }, { "name", "unknown" }
            };

            bool        sourceIsLocalConflict = false;
            IDisposable subscription          = client.EventManager.Subscribe <StoreOperationCompletedEvent>(o =>
            {
                sourceIsLocalConflict = o.Operation.Source == StoreOperationSource.LocalConflictResolution;
                manualResetEvent.Set();
            });

            await context.UpdateOperationAsync(error, item);

            bool resetEventSignaled = manualResetEvent.Wait(1000);

            subscription.Dispose();

            Assert.True(resetEventSignaled);
            Assert.True(sourceIsLocalConflict);
        }