private static ZumoTest CreateSyncConflictTest(bool autoResolve) { var testName = "Offline - dealing with conflicts - " + (autoResolve ? "client resolves conflicts" : "push fails after conflicts"); bool resolveConflictsOnClient = autoResolve; return(new ZumoTest(testName, async delegate(ZumoTest test) { DateTime now = DateTime.UtcNow; int seed = now.Year * 10000 + now.Month * 100 + now.Day; test.AddLog("Using random seed: {0}", seed); Random rndGen = new Random(seed); var offlineReadyClient = CreateClient(); var localStore = new MobileServiceSQLiteStore(StoreFileName); test.AddLog("Defined the table on the local store"); localStore.DefineTable <OfflineReadyItem>(); ConflictResolvingSyncHandler <OfflineReadyItem> .ConflictResolution conflictHandlingPolicy; conflictHandlingPolicy = (client, server) => new OfflineReadyItem { Id = client.Id, Age = Math.Max(client.Age, server.Age), Date = client.Date > server.Date ? client.Date : server.Date, Flag = client.Flag || server.Flag, FloatingNumber = Math.Max(client.FloatingNumber, server.FloatingNumber), Name = client.Name }; if (resolveConflictsOnClient) { var handler = new ConflictResolvingSyncHandler <OfflineReadyItem>(test, offlineReadyClient, conflictHandlingPolicy); await offlineReadyClient.SyncContext.InitializeAsync(localStore, handler); } else { await offlineReadyClient.SyncContext.InitializeAsync(localStore); } test.AddLog("Initialized the store and sync context"); var localTable = offlineReadyClient.GetSyncTable <OfflineReadyItem>(); var remoteTable = offlineReadyClient.GetTable <OfflineReadyItem>(); await localTable.PurgeAsync(); test.AddLog("Removed all items from the local table"); var item = new OfflineReadyItem(rndGen); await remoteTable.InsertAsync(item); test.AddLog("Inserted the item to the remote store:", item); var pullQuery = "$filter=id eq '" + item.Id + "'"; await localTable.PullAsync(null, pullQuery); test.AddLog("Changing the item on the server"); item.Age++; await remoteTable.UpdateAsync(item); test.AddLog("Updated the item: {0}", item); var localItem = await localTable.LookupAsync(item.Id); test.AddLog("Retrieved the item from the local table, now updating it"); localItem.Date = localItem.Date.AddDays(1); await localTable.UpdateAsync(localItem); test.AddLog("Updated the item on the local table"); test.AddLog("Now trying to pull changes from the server (will trigger a push)"); bool testResult = true; try { await localTable.PullAsync(null, pullQuery); if (!autoResolve) { test.AddLog("Error, pull (push) should have caused a conflict, but none happened."); testResult = false; } else { var expectedMergedItem = conflictHandlingPolicy(localItem, item); var localMergedItem = await localTable.LookupAsync(item.Id); if (localMergedItem.Equals(expectedMergedItem)) { test.AddLog("Item was merged correctly."); } else { test.AddLog("Error, item not merged correctly. Expected: {0}, Actual: {1}", expectedMergedItem, localMergedItem); testResult = false; } } } catch (MobileServicePushFailedException ex) { test.AddLog("Push exception: {0}", ex); if (autoResolve) { test.AddLog("Error, push should have succeeded."); testResult = false; } else { test.AddLog("Expected exception was thrown."); } } test.AddLog("Cleaning up"); await localTable.DeleteAsync(item); test.AddLog("Local table cleaned up. Now sync'ing once more"); await offlineReadyClient.SyncContext.PushAsync(); test.AddLog("Done"); return testResult; }, ZumoTestGlobals.RuntimeFeatureNames.STRING_ID_TABLES)); }
private async Task CreateSyncConflict(bool autoResolve) { await ClearStore(); bool resolveConflictsOnClient = autoResolve; 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 localStore = new MobileServiceSQLiteStore(StoreFileName); Log("Defined the table on the local store"); localStore.DefineTable <OfflineReadyItem>(); ConflictResolvingSyncHandler <OfflineReadyItem> .ConflictResolution conflictHandlingPolicy; conflictHandlingPolicy = (client, server) => new OfflineReadyItem { Id = client.Id, Age = Math.Max(client.Age, server.Age), Date = client.Date > server.Date ? client.Date : server.Date, Flag = client.Flag || server.Flag, FloatingNumber = Math.Max(client.FloatingNumber, server.FloatingNumber), Name = client.Name }; if (resolveConflictsOnClient) { var handler = new ConflictResolvingSyncHandler <OfflineReadyItem>(this, offlineReadyClient, conflictHandlingPolicy); await offlineReadyClient.SyncContext.InitializeAsync(localStore, handler); } else { await offlineReadyClient.SyncContext.InitializeAsync(localStore); } Log("Initialized the store and sync context"); var localTable = offlineReadyClient.GetSyncTable <OfflineReadyItem>(); var remoteTable = offlineReadyClient.GetTable <OfflineReadyItem>(); await localTable.PurgeAsync(); Log("Removed all items from the local table"); var item = new OfflineReadyItem(rndGen); await remoteTable.InsertAsync(item); Log("Inserted the item to the remote store:", item); var pullQuery = "$filter=id eq '" + item.Id + "'"; await localTable.PullAsync(null, pullQuery); Log("Changing the item on the server"); item.Age++; await remoteTable.UpdateAsync(item); Log("Updated the item: {0}", item); var localItem = await localTable.LookupAsync(item.Id); Log("Retrieved the item from the local table, now updating it"); localItem.Date = localItem.Date.AddDays(1); await localTable.UpdateAsync(localItem); Log("Updated the item on the local table"); Log("Now trying to pull changes from the server (will trigger a push)"); string errorMessage = string.Empty; try { await localTable.PullAsync(null, pullQuery); if (!autoResolve) { errorMessage = "Error, pull (push) should have caused a conflict, but none happened."; } else { var expectedMergedItem = conflictHandlingPolicy(localItem, item); var localMergedItem = await localTable.LookupAsync(item.Id); if (localMergedItem.Equals(expectedMergedItem)) { Log("Item was merged correctly."); } else { errorMessage = string.Format("Error, item not merged correctly. Expected: {0}, Actual: {1}", expectedMergedItem, localMergedItem); } } } catch (MobileServicePushFailedException ex) { Log("Push exception: {0}", ex); if (autoResolve) { errorMessage = "Error, push should have succeeded."; } else { Log("Expected exception was thrown."); } } Log("Cleaning up"); await localTable.DeleteAsync(item); Log("Local table cleaned up. Now sync'ing once more"); await offlineReadyClient.SyncContext.PushAsync(); Log("Done"); localStore.Dispose(); await ClearStore(); if (!String.IsNullOrEmpty(errorMessage)) { Assert.Fail(errorMessage); } }
private async Task CreateSyncConflict(bool autoResolve) { ClearStore(); bool resolveConflictsOnClient = autoResolve; DateTime now = DateTime.UtcNow; int seed = now.Year * 10000 + now.Month * 100 + now.Day; Random rndGen = new Random(seed); var offlineReadyClient = CreateClient(); var localStore = new MobileServiceSQLiteStore(StoreFileName); localStore.DefineTable <OfflineReadyItem>(); ConflictResolvingSyncHandler <OfflineReadyItem> .ConflictResolution conflictHandlingPolicy; conflictHandlingPolicy = (client, server) => new OfflineReadyItem { Id = client.Id, Age = Math.Max(client.Age, server.Age), Date = client.Date > server.Date ? client.Date : server.Date, Flag = client.Flag || server.Flag, FloatingNumber = Math.Max(client.FloatingNumber, server.FloatingNumber), Name = client.Name }; if (resolveConflictsOnClient) { var handler = new ConflictResolvingSyncHandler <OfflineReadyItem>(this, offlineReadyClient, conflictHandlingPolicy); await offlineReadyClient.SyncContext.InitializeAsync(localStore, handler); } else { await offlineReadyClient.SyncContext.InitializeAsync(localStore); } var localTable = offlineReadyClient.GetSyncTable <OfflineReadyItem>(); var remoteTable = offlineReadyClient.GetTable <OfflineReadyItem>(); await localTable.PurgeAsync(); var item = new OfflineReadyItem(rndGen); await remoteTable.InsertAsync(item); var pullQuery = "$filter=id eq '" + item.Id + "'"; await localTable.PullAsync(null, pullQuery); item.Age++; await remoteTable.UpdateAsync(item); var localItem = await localTable.LookupAsync(item.Id); localItem.Date = localItem.Date.AddDays(1); await localTable.UpdateAsync(localItem); string errorMessage = string.Empty; try { await localTable.PullAsync(null, pullQuery); if (!autoResolve) { errorMessage = "Error, pull (push) should have caused a conflict, but none happened."; } else { var expectedMergedItem = conflictHandlingPolicy(localItem, item); var localMergedItem = await localTable.LookupAsync(item.Id); Assert.Equal(expectedMergedItem, localMergedItem); } } catch (MobileServicePushFailedException) { if (autoResolve) { errorMessage = "Error, push should have succeeded."; } } await localTable.DeleteAsync(item); await offlineReadyClient.SyncContext.PushAsync(); localStore.Dispose(); ClearStore(); Assert.True(String.IsNullOrEmpty(errorMessage)); }