private async Task AbortPushDuringSync(SyncAbortLocation whereToAbort) { await ClearStore(); SyncAbortLocation abortLocation = whereToAbort; DateTime now = DateTime.UtcNow; int seed = now.Year * 10000 + now.Month * 100 + now.Day; Log("Using random seed: {0}", seed); Random rndGen = new Random(seed); var offlineReadyClient = CreateClient(); var items = Enumerable.Range(0, 10).Select(_ => new OfflineReadyItem(rndGen)).ToArray(); foreach (var item in items) { item.Id = Guid.NewGuid().ToString("D"); } int abortIndex = abortLocation == SyncAbortLocation.Start ? 0 : (abortLocation == SyncAbortLocation.End ? items.Length - 1 : rndGen.Next(1, items.Length - 1)); var idToAbort = items[abortIndex].Id; Log("Will send {0} items, aborting when id = {1}", items.Length, idToAbort); var localStore = new MobileServiceSQLiteStore(StoreFileName); Log("Defined the table on the local store"); localStore.DefineTable <OfflineReadyItem>(); var syncHandler = new AbortingSyncHandler(this, id => id == idToAbort); await offlineReadyClient.SyncContext.InitializeAsync(localStore, syncHandler); Log("Initialized the store and sync context"); var localTable = offlineReadyClient.GetSyncTable <OfflineReadyItem>(); var remoteTable = offlineReadyClient.GetTable <OfflineReadyItem>(); try { foreach (var item in items) { await localTable.InsertAsync(item); } Log("Inserted {0} items in the local table. Now pushing those"); try { await offlineReadyClient.SyncContext.PushAsync(); Assert.Fail("Error, push call should have failed"); } catch (MobileServicePushFailedException ex) { Log("Caught (expected) exception: {0}", ex); } var expectedOperationQueueSize = items.Length - abortIndex; Log("Current operation queue size: {0}", offlineReadyClient.SyncContext.PendingOperations); if (expectedOperationQueueSize != offlineReadyClient.SyncContext.PendingOperations) { Assert.Fail(string.Format("Error, expected {0} items in the queue", expectedOperationQueueSize)); } foreach (var allItemsPushed in new bool[] { false, true }) { HashSet <OfflineReadyItem> itemsInServer, itemsNotInServer; if (allItemsPushed) { itemsInServer = new HashSet <OfflineReadyItem>(items.ToArray()); itemsNotInServer = new HashSet <OfflineReadyItem>(Enumerable.Empty <OfflineReadyItem>()); } else { itemsInServer = new HashSet <OfflineReadyItem>(items.Where((item, index) => index < abortIndex)); itemsNotInServer = new HashSet <OfflineReadyItem>(items.Where((item, index) => index >= abortIndex)); } foreach (var item in items) { var itemFromServer = (await remoteTable.Where(i => i.Id == item.Id).Take(1).ToEnumerableAsync()).FirstOrDefault(); Log("Item with id = {0} from server: {1}", item.Id, itemFromServer == null ? "<<null>>" : itemFromServer.ToString()); if (itemsInServer.Contains(item) && itemFromServer == null) { Assert.Fail(string.Format("Error, the item {0} should have made to the server", item.Id)); } else if (itemsNotInServer.Contains(item) && itemFromServer != null) { Assert.Fail(string.Format("Error, the item {0} should not have made to the server", item.Id)); } } if (!allItemsPushed) { Log("Changing the handler so that it doesn't abort anymore."); syncHandler.AbortCondition = _ => false; Log("Pushing again"); await offlineReadyClient.SyncContext.PushAsync(); Log("Finished pushing all elements"); } } Log("Changing the handler so that it doesn't abort anymore."); syncHandler.AbortCondition = _ => false; Log("Cleaning up"); foreach (var item in items) { await localTable.DeleteAsync(item); } await offlineReadyClient.SyncContext.PushAsync(); Log("Done"); } finally { localStore.Dispose(); ClearStore().Wait(); } }
private async Task AbortPushDuringSync(SyncAbortLocation whereToAbort) { ClearStore(); SyncAbortLocation abortLocation = whereToAbort; DateTime now = DateTime.UtcNow; int seed = now.Year * 10000 + now.Month * 100 + now.Day; Random rndGen = new Random(seed); var offlineReadyClient = CreateClient(); var items = Enumerable.Range(0, 10).Select(_ => new OfflineReadyItem(rndGen)).ToArray(); foreach (var item in items) { item.Id = Guid.NewGuid().ToString("D"); } int abortIndex = abortLocation == SyncAbortLocation.Start ? 0 : (abortLocation == SyncAbortLocation.End ? items.Length - 1 : rndGen.Next(1, items.Length - 1)); var idToAbort = items[abortIndex].Id; var localStore = new MobileServiceSQLiteStore(StoreFileName); localStore.DefineTable <OfflineReadyItem>(); var syncHandler = new AbortingSyncHandler(this, id => id == idToAbort); await offlineReadyClient.SyncContext.InitializeAsync(localStore, syncHandler); var localTable = offlineReadyClient.GetSyncTable <OfflineReadyItem>(); var remoteTable = offlineReadyClient.GetTable <OfflineReadyItem>(); try { foreach (var item in items) { await localTable.InsertAsync(item); } await Assert.ThrowsAsync <MobileServicePushFailedException>(() => offlineReadyClient.SyncContext.PushAsync()); var expectedOperationQueueSize = items.Length - abortIndex; Assert.False(expectedOperationQueueSize != offlineReadyClient.SyncContext.PendingOperations); foreach (var allItemsPushed in new bool[] { false, true }) { HashSet <OfflineReadyItem> itemsInServer, itemsNotInServer; if (allItemsPushed) { itemsInServer = new HashSet <OfflineReadyItem>(items.ToArray()); itemsNotInServer = new HashSet <OfflineReadyItem>(Enumerable.Empty <OfflineReadyItem>()); } else { itemsInServer = new HashSet <OfflineReadyItem>(items.Where((item, index) => index < abortIndex)); itemsNotInServer = new HashSet <OfflineReadyItem>(items.Where((item, index) => index >= abortIndex)); } foreach (var item in items) { var itemFromServer = (await remoteTable.Where(i => i.Id == item.Id).Take(1).ToEnumerableAsync()).FirstOrDefault(); Assert.False(itemsInServer.Contains(item) && itemFromServer == null); Assert.False(itemsNotInServer.Contains(item) && itemFromServer != null); } if (!allItemsPushed) { syncHandler.AbortCondition = _ => false; await offlineReadyClient.SyncContext.PushAsync(); } } syncHandler.AbortCondition = _ => false; foreach (var item in items) { await localTable.DeleteAsync(item); } await offlineReadyClient.SyncContext.PushAsync(); } finally { localStore.Dispose(); ClearStore(); } }