Java tutorial
/* Copyright (c) Microsoft Open Technologies, Inc. All Rights Reserved Apache 2.0 License Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. See the Apache Version 2.0 License for specific language governing permissions and limitations under the License. */ package com.microsoft.windowsazure.mobileservices.sdk.testapp.test; import android.test.InstrumentationTestCase; import com.google.common.base.Function; import com.google.common.util.concurrent.ListenableFuture; import com.google.gson.GsonBuilder; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.microsoft.windowsazure.mobileservices.MobileServiceClient; import com.microsoft.windowsazure.mobileservices.MobileServiceException; import com.microsoft.windowsazure.mobileservices.http.HttpConstants; import com.microsoft.windowsazure.mobileservices.http.NextServiceFilterCallback; import com.microsoft.windowsazure.mobileservices.http.ServiceFilter; import com.microsoft.windowsazure.mobileservices.http.ServiceFilterRequest; import com.microsoft.windowsazure.mobileservices.http.ServiceFilterResponse; import com.microsoft.windowsazure.mobileservices.sdk.testapp.framework.filters.ServiceFilterRequestMock; import com.microsoft.windowsazure.mobileservices.sdk.testapp.framework.filters.ServiceFilterResponseMock; import com.microsoft.windowsazure.mobileservices.sdk.testapp.framework.mocks.MobileServiceLocalStoreMock; import com.microsoft.windowsazure.mobileservices.sdk.testapp.framework.mocks.MobileServiceSyncHandlerMock; import com.microsoft.windowsazure.mobileservices.sdk.testapp.test.helpers.EncodingUtilities; import com.microsoft.windowsazure.mobileservices.sdk.testapp.test.types.CustomFunctionTwoParameters; import com.microsoft.windowsazure.mobileservices.sdk.testapp.test.types.IdPropertyTestClasses.StringIdType; import com.microsoft.windowsazure.mobileservices.table.MobileServiceExceptionBase; import com.microsoft.windowsazure.mobileservices.table.query.Query; import com.microsoft.windowsazure.mobileservices.table.query.QueryOperations; import com.microsoft.windowsazure.mobileservices.table.query.QueryOrder; import com.microsoft.windowsazure.mobileservices.table.sync.MobileServiceJsonSyncTable; import com.microsoft.windowsazure.mobileservices.table.sync.MobileServiceSyncTable; import com.microsoft.windowsazure.mobileservices.table.sync.operations.TableOperationError; import com.microsoft.windowsazure.mobileservices.table.sync.operations.TableOperationKind; import com.microsoft.windowsazure.mobileservices.table.sync.push.MobileServicePushFailedException; import com.microsoft.windowsazure.mobileservices.table.sync.push.MobileServicePushStatus; import com.microsoft.windowsazure.mobileservices.table.sync.queue.OperationErrorList; import com.microsoft.windowsazure.mobileservices.table.sync.synchandler.SimpleSyncHandler; import com.squareup.okhttp.Protocol; import com.squareup.okhttp.internal.http.StatusLine; import java.io.IOException; import java.net.MalformedURLException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.LinkedHashMap; import java.util.List; import java.util.Locale; import java.util.TimeZone; import java.util.concurrent.ExecutionException; public class MobileServiceSyncTableTests extends InstrumentationTestCase { String appUrl = ""; String appKey = ""; GsonBuilder gsonBuilder; String OperationQueue = "__operations"; String SyncErrors = "__errors"; protected void setUp() throws Exception { appUrl = "http://myapp.com/"; appKey = "qwerty"; gsonBuilder = new GsonBuilder(); super.setUp(); } protected void tearDown() throws Exception { super.tearDown(); } public void testPushExecutesThePendingOperationsInOrder() throws InterruptedException, ExecutionException, MalformedURLException { MobileServiceLocalStoreMock store = new MobileServiceLocalStoreMock(); ServiceFilterContainer serviceFilterContainer1 = new ServiceFilterContainer(); MobileServiceClient client1 = new MobileServiceClient(appUrl, getInstrumentation().getTargetContext()); client1 = client1.withFilter(getTestFilter(serviceFilterContainer1, "")); client1.getSyncContext().initialize(store, new SimpleSyncHandler()).get(); MobileServiceJsonSyncTable table = client1.getSyncTable("someTable"); JsonObject item1 = new JsonObject(); item1.addProperty("id", "abc"); JsonObject item2 = new JsonObject(); item2.addProperty("id", "def"); table.insert(item1).get(); table.insert(item2).get(); assertEquals(serviceFilterContainer1.Requests.size(), 0); // create a new service to test that operations are loaded from store ServiceFilterContainer serviceFilterContainer2 = new ServiceFilterContainer(); MobileServiceClient client2 = new MobileServiceClient(appUrl, getInstrumentation().getTargetContext()); client2 = client2.withFilter(getTestFilter(serviceFilterContainer2, "{\"id\":\"abc\",\"String\":\"Hey\"}", "{\"id\":\"def\",\"String\":\"What\"}")); client2.getSyncContext().initialize(store, new SimpleSyncHandler()).get(); assertEquals(serviceFilterContainer2.Requests.size(), 0); client2.getSyncContext().push().get(); assertEquals(serviceFilterContainer2.Requests.size(), 2); assertEquals(serviceFilterContainer2.Requests.get(0).Content, item1.toString()); // Assert.AreEqual(hijack.Requests[0].Headers.GetValues("X-ZUMO-FEATURES").First(), // "OL"); assertEquals(serviceFilterContainer2.Requests.get(1).Content, item2.toString()); // Assert.AreEqual(hijack.Requests[1].Headers.GetValues("X-ZUMO-FEATURES").First(), // "OL"); // create yet another service to make sure the old items were purged // from queue ServiceFilterContainer serviceFilterContainer3 = new ServiceFilterContainer(); MobileServiceClient client3 = new MobileServiceClient(appUrl, getInstrumentation().getTargetContext()); client3 = client3.withFilter(getTestFilter(serviceFilterContainer3, "{\"id\":\"abc\",\"String\":\"Hey\"}")); client3.getSyncContext().initialize(store, new SimpleSyncHandler()).get(); assertEquals(serviceFilterContainer3.Requests.size(), 0); client3.getSyncContext().push().get(); assertEquals(serviceFilterContainer3.Requests.size(), 0); } public void testPullThrowsWhenPushThrows() throws MalformedURLException, InterruptedException, ExecutionException { MobileServiceLocalStoreMock store = new MobileServiceLocalStoreMock(); ServiceFilterContainer serviceFilterContainer = new ServiceFilterContainer(); MobileServiceClient client = new MobileServiceClient(appUrl, getInstrumentation().getTargetContext()); client.getSyncContext().initialize(store, new SimpleSyncHandler()).get(); client = client.withFilter(getTestFilter(serviceFilterContainer, 401, "")); // for // push client.getSyncContext().initialize(store, new SimpleSyncHandler()).get(); // insert an item but don't push MobileServiceJsonSyncTable table = client.getSyncTable("someTable"); JsonObject jsonObject = new JsonObject(); jsonObject.addProperty("id", "abc"); table.insert(jsonObject).get(); assertEquals(store.Tables.get(table.getName().toLowerCase(Locale.getDefault())).size(), 1); // item // is // inserted // this should trigger a push try { table.pull(null).get(); fail("MobileServicePushFailedException expected"); return; } catch (Exception ex) { if (ex.getCause() instanceof MobileServicePushFailedException) { MobileServicePushFailedException mobileServicePushFailedException = (MobileServicePushFailedException) ex .getCause(); assertEquals(mobileServicePushFailedException.getPushCompletionResult().getOperationErrors().size(), 0); assertEquals(serviceFilterContainer.Requests.size(), 1); } else { fail("MobileServicePushFailedException expected"); } } } public void testPullDoesNotPurgeWhenItemIsMissing() throws InterruptedException, ExecutionException, MalformedURLException { MobileServiceLocalStoreMock store = new MobileServiceLocalStoreMock(); ServiceFilterContainer serviceFilterContainer = new ServiceFilterContainer(); MobileServiceClient client = new MobileServiceClient(appUrl, getInstrumentation().getTargetContext()); client = client.withFilter(getTestFilter(serviceFilterContainer, false, "{\"id\":\"abc\",\"String\":\"Hey\"}", "[{\"id\":\"def\",\"String\":\"World\"}]")); client.getSyncContext().initialize(store, new SimpleSyncHandler()).get(); MobileServiceJsonSyncTable table = client.getSyncTable("someTable"); JsonObject jsonObject = new JsonObject(); jsonObject.addProperty("id", "abc"); table.insert(jsonObject).get(); // insert an item client.getSyncContext().push().get(); // push to clear the queue // now pull table.pull(null).get(); assertEquals(store.Tables.get(table.getName().toLowerCase(Locale.getDefault())).size(), 2); // 1 // from // remote // and // 1 // from // local assertEquals(serviceFilterContainer.Requests.size(), 3); } public void testPullDoesNotTriggerPushWhenThereIsNoOperationInTable() throws InterruptedException, ExecutionException, MalformedURLException { MobileServiceLocalStoreMock store = new MobileServiceLocalStoreMock(); ServiceFilterContainer serviceFilterContainer = new ServiceFilterContainer(); store.ReadResponses.add("[{\"id\":\"abc\",\"String\":\"Hey\"},{\"id\":\"def\",\"String\":\"World\"}]"); // for // pull MobileServiceClient client = new MobileServiceClient(appUrl, getInstrumentation().getTargetContext()); client = client .withFilter(getTestFilter(serviceFilterContainer, false, "{\"id\":\"abc\",\"String\":\"Hey\"}", "[{\"id\":\"abc\",\"String\":\"Hey\"},{\"id\":\"def\",\"String\":\"World\"}]")); client.getSyncContext().initialize(store, new SimpleSyncHandler()).get(); // insert item in pull table MobileServiceJsonSyncTable table1 = client.getSyncTable("someTable"); JsonObject jsonObject = new JsonObject(); jsonObject.addProperty("id", "abc"); table1.insert(jsonObject).get(); // insert an item // but push to clear the queue client.getSyncContext().push().get(); assertEquals(store.Tables.get(table1.getName().toLowerCase(Locale.getDefault())).size(), 1); // item // is // inserted assertEquals(serviceFilterContainer.Requests.size(), 1); // first push // then insert item in other table MobileServiceSyncTable<StringIdType> table2 = client.getSyncTable(StringIdType.class); StringIdType item = new StringIdType(); item.Id = "an id"; item.String = "what?"; table2.insert(item).get(); table1.pull(null).get(); assertEquals(store.Tables.get(table1.getName().toLowerCase(Locale.getDefault())).size(), 2); // table // should // contain // 2 // pulled // items assertEquals(serviceFilterContainer.Requests.size(), 3); // 1 for push // and 1 for // pull assertEquals(store.Tables.get(table2.getName().toLowerCase(Locale.getDefault())).size(), 1); // this // table // should // not // be // touched } public void testPullTriggersPushWhenThereIsOperationInTable() throws InterruptedException, ExecutionException, MalformedURLException { MobileServiceLocalStoreMock store = new MobileServiceLocalStoreMock(); ServiceFilterContainer serviceFilterContainer = new ServiceFilterContainer(); store.ReadResponses.add("[{\"id\":\"abc\",\"String\":\"Hey\"},{\"id\":\"def\",\"String\":\"World\"}]"); // for // pull MobileServiceClient client = new MobileServiceClient(appUrl, getInstrumentation().getTargetContext()); client = client .withFilter(getTestFilter(serviceFilterContainer, false, "{\"id\":\"abc\",\"String\":\"Hey\"}", // for // insert "[{\"id\":\"abc\",\"String\":\"Hey\"},{\"id\":\"def\",\"String\":\"World\"}]" // remote // item )); client.getSyncContext().initialize(store, new SimpleSyncHandler()).get(); // insert an item but don't push MobileServiceJsonSyncTable table1 = client.getSyncTable("someTable"); JsonObject jsonObject = new JsonObject(); jsonObject.addProperty("id", "abc"); table1.insert(jsonObject).get(); // insert an item assertEquals(store.Tables.get(table1.getName().toLowerCase(Locale.getDefault())).size(), 1); // item // is // inserted // this should trigger a push table1.pull(null).get(); assertEquals(serviceFilterContainer.Requests.size(), 3); // 1 for push // and 2 for // pull assertEquals(store.Tables.get(table1.getName().toLowerCase(Locale.getDefault())).size(), 2); // table // is // populated } // REVISAR EL TEMA DE LOS HANDLERS Y LAS EXCEPCIONES // public void testPullThrowsWhenPushThrows() // throws MalformedURLException, InterruptedException, // ExecutionException { // MobileServiceLocalStoreMock store = new MobileServiceLocalStoreMock(); // // MobileServiceClient client = null; // // client = new MobileServiceClient(appUrl, getInstrumentation() // .getTargetContext()); // // client = client.withFilter(getTestFilter(404)); // for push // // client.getSyncContext().initialize(store, new SimpleSyncHandler()) // .get(); // // // insert an item but don't push // MobileServiceJsonSyncTable table = client.getSyncTable("someTable"); // // JsonObject jsonObject = new JsonObject(); // jsonObject.addProperty("id", "abc"); // // table.insert(jsonObject).get(); // insert an item // // assertEquals(store.Tables.get(table.getName().toLowerCase()).size(), 1); // // item // // is // // inserted // // try { // table.pull(null).get(); // } catch (Throwable throwable) { // // if (throwable instanceof MobileServicePushFailedException) { // MobileServicePushFailedException ex = (MobileServicePushFailedException) // throwable; // assertEquals(ex.getPushCompletionResult().getOperationErrors() // .size(), 1); // } // } // // // Assert.AreEqual(hijack.Requests.Count, 1); // 1 for push // } public void testPullSucceds() throws MalformedURLException, InterruptedException, ExecutionException, MobileServiceException { MobileServiceLocalStoreMock store = new MobileServiceLocalStoreMock(); ServiceFilterContainer serviceFilterContainer = new ServiceFilterContainer(); MobileServiceClient client = new MobileServiceClient(appUrl, getInstrumentation().getTargetContext()); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"); sdf.setTimeZone(TimeZone.getTimeZone("UTC")); String updatedAt = sdf.format(new Date()); client = client.withFilter(getTestFilter(serviceFilterContainer, false, "{\"count\":\"2\",\"results\":[{\"id\":\"abc\",\"String\":\"Hey\",\"updatedAt\":\"" + updatedAt + "\"},{\"id\":\"def\",\"String\":\"World\",\"updatedAt\":\"" + updatedAt + "\"}]}"// remote // item )); client.getSyncContext().initialize(store, new SimpleSyncHandler()).get(); MobileServiceSyncTable<StringIdType> table = client.getSyncTable(StringIdType.class); Query query = QueryOperations.tableName(table.getName()).skip(5).top(3).field("String").eq("world") .orderBy("Id", QueryOrder.Descending).includeInlineCount().select("String"); table.pull(query).get(); assertEquals(serviceFilterContainer.Requests.get(0).Url, EncodingUtilities.percentEncodeSpaces( "http://myapp.com/tables/stringidtype?$filter=String%20eq%20(%27world%27)&$top=3&$skip=5&$orderby=Id%20desc&__includeDeleted=true")); } public void testPullNoSkipSucceds() throws MalformedURLException, InterruptedException, ExecutionException, MobileServiceException { MobileServiceLocalStoreMock store = new MobileServiceLocalStoreMock(); ServiceFilterContainer serviceFilterContainer = new ServiceFilterContainer(); MobileServiceClient client = new MobileServiceClient(appUrl, getInstrumentation().getTargetContext()); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"); sdf.setTimeZone(TimeZone.getTimeZone("UTC")); String updatedAt = sdf.format(new Date()); client = client.withFilter(getTestFilter(serviceFilterContainer, false, "{\"count\":\"2\",\"results\":[{\"id\":\"abc\",\"String\":\"Hey\",\"updatedAt\":\"" + updatedAt + "\"},{\"id\":\"def\",\"String\":\"World\",\"updatedAt\":\"" + updatedAt + "\"}]}"// remote // item )); client.getSyncContext().initialize(store, new SimpleSyncHandler()).get(); MobileServiceSyncTable<StringIdType> table = client.getSyncTable(StringIdType.class); Query query = QueryOperations.tableName(table.getName()).top(3).field("String").eq("world") .orderBy("Id", QueryOrder.Descending).includeInlineCount().select("String"); table.pull(query).get(); assertEquals(serviceFilterContainer.Requests.get(0).Url, EncodingUtilities.percentEncodeSpaces( "http://myapp.com/tables/stringidtype?$filter=String%20eq%20(%27world%27)&$top=3&$skip=0&$orderby=Id%20desc&__includeDeleted=true")); } public void testPullSuccedsNoTopNoOrderBy() throws MalformedURLException, InterruptedException, ExecutionException, MobileServiceException { MobileServiceLocalStoreMock store = new MobileServiceLocalStoreMock(); ServiceFilterContainer serviceFilterContainer = new ServiceFilterContainer(); MobileServiceClient client = new MobileServiceClient(appUrl, getInstrumentation().getTargetContext()); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"); sdf.setTimeZone(TimeZone.getTimeZone("UTC")); String updatedAt = sdf.format(new Date()); client = client.withFilter(getTestFilter(serviceFilterContainer, false, "{\"count\":\"2\",\"results\":[{\"id\":\"abc\",\"String\":\"Hey\",\"updatedAt\":\"" + updatedAt + "\"},{\"id\":\"def\",\"String\":\"World\",\"updatedAt\":\"" + updatedAt + "\"}]}"// remote // item )); client.getSyncContext().initialize(store, new SimpleSyncHandler()).get(); MobileServiceSyncTable<StringIdType> table = client.getSyncTable(StringIdType.class); Query query = QueryOperations.tableName(table.getName()).field("String").eq("world") .orderBy("Id", QueryOrder.Descending).includeInlineCount().select("String"); table.pull(query).get(); assertEquals(serviceFilterContainer.Requests.get(0).Url, EncodingUtilities.percentEncodeSpaces( "http://myapp.com/tables/stringidtype?$filter=String%20eq%20(%27world%27)&$top=50&$skip=0&$orderby=Id%20desc&__includeDeleted=true")); } public void testIncrementalPullSucceds() throws MalformedURLException, InterruptedException, ExecutionException, MobileServiceException { MobileServiceLocalStoreMock store = new MobileServiceLocalStoreMock(); ServiceFilterContainer serviceFilterContainer = new ServiceFilterContainer(); String queryKey = "QueryKey"; MobileServiceClient client = new MobileServiceClient(appUrl, getInstrumentation().getTargetContext()); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"); sdf.setTimeZone(TimeZone.getTimeZone("UTC")); String updatedAt1 = sdf.format(new Date()); String updatedAt2 = sdf.format(new Date()); client = client.withFilter(getTestFilter(serviceFilterContainer, false, "{\"count\":\"4\",\"results\":[{\"id\":\"abc\",\"String\":\"Hey\",\"updatedAt\":\"" + updatedAt1 + "\"},{\"id\":\"def\",\"String\":\"World\",\"updatedAt\":\"" + updatedAt1 + "\"}]}", "[{\"id\":\"abc\",\"String\":\"Hey\",\"updatedAt\":\"" + updatedAt2 + "\"},{\"id\":\"def\",\"String\":\"World\",\"updatedAt\":\"" + updatedAt2 + "\"}]" // remote // item )); client.getSyncContext().initialize(store, new SimpleSyncHandler()).get(); MobileServiceSyncTable<StringIdType> table = client.getSyncTable(StringIdType.class); Query query = QueryOperations.field("String").eq("noMatch"); table.pull(query, "QueryKey").get(); assertEquals(serviceFilterContainer.Requests.get(0).Url, EncodingUtilities.percentEncodeSpaces( "http://myapp.com/tables/stringidtype?$filter=String%20eq%20(%27noMatch%27)&$top=50&$orderby=updatedAt%20asc&__includeDeleted=true")); assertEquals(serviceFilterContainer.Requests.get(1).Url, EncodingUtilities.percentEncodeSpaces( "http://myapp.com/tables/stringidtype?$filter=String%20eq%20(%27noMatch%27)%20and%20" + "(updatedAt%20ge%20(datetimeoffset%27" + updatedAt1 + "%27))&$top=50&$orderby=updatedAt%20asc&__includeDeleted=true")); } public void testIncrementalPullSaveLastUpdatedAtDate() throws MalformedURLException, InterruptedException, ExecutionException, MobileServiceException { MobileServiceLocalStoreMock store = new MobileServiceLocalStoreMock(); ServiceFilterContainer serviceFilterContainer = new ServiceFilterContainer(); String queryKey = "QueryKey"; String incrementalPullStrategyTable = "__incrementalPullData"; MobileServiceClient client = new MobileServiceClient(appUrl, getInstrumentation().getTargetContext()); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"); sdf.setTimeZone(TimeZone.getTimeZone("UTC")); String updatedAt1 = sdf.format(new Date()); String updatedAt2 = sdf.format(new Date()); client = client.withFilter(getTestFilter(serviceFilterContainer, false, "{\"count\":\"4\",\"results\":[{\"id\":\"abc\",\"String\":\"Hey\",\"updatedAt\":\"" + updatedAt1 + "\"},{\"id\":\"def\",\"String\":\"World\",\"updatedAt\":\"" + updatedAt1 + "\"}]}", "[{\"id\":\"abc\",\"String\":\"Hey\",\"updatedAt\":\"" + updatedAt2 + "\"},{\"id\":\"def\",\"String\":\"World\",\"updatedAt\":\"" + updatedAt2 + "\"}]" // remote // item )); client.getSyncContext().initialize(store, new SimpleSyncHandler()).get(); MobileServiceSyncTable<StringIdType> table = client.getSyncTable(StringIdType.class); Query query = QueryOperations.tableName(table.getName()).top(2); table.pull(query, queryKey).get(); LinkedHashMap<String, JsonObject> tableContent = store.Tables.get(incrementalPullStrategyTable); JsonElement result = tableContent.get(table.getName().toLowerCase() + "_" + queryKey); String stringMaxUpdatedDate = result.getAsJsonObject().get("maxupdateddate").getAsString(); assertEquals(updatedAt2, stringMaxUpdatedDate); } public void testincrementalSyncUsesSkipWhenMaxUpdateAtIsSame() throws MalformedURLException, InterruptedException, ExecutionException, MobileServiceException { MobileServiceLocalStoreMock store = new MobileServiceLocalStoreMock(); ServiceFilterContainer serviceFilterContainer = new ServiceFilterContainer(); String queryKey = "QueryKey"; String incrementalPullStrategyTable = "__incrementalPullData"; MobileServiceClient client = new MobileServiceClient(appUrl, getInstrumentation().getTargetContext()); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"); sdf.setTimeZone(TimeZone.getTimeZone("UTC")); Date d = new Date(); String updatedAt1 = sdf.format(d); d.setTime(d.getTime() + 1000L); String updatedAt2 = sdf.format(d); client = client.withFilter(getTestFilter(serviceFilterContainer, false, "[{\"id\":\"abc\",\"String\":\"Hey\",\"updatedAt\":\"" + updatedAt1 + "\"}," + "{\"id\":\"def\",\"String\":\"World\",\"updatedAt\":\"" + updatedAt1 + "\"}]", "[{\"id\":\"abc\",\"String\":\"Hey\",\"updatedAt\":\"" + updatedAt1 + "\"}," + "{\"id\":\"def\",\"String\":\"World\",\"updatedAt\":\"" + updatedAt1 + "\"}]", "[{\"id\":\"abc\",\"String\":\"Hey\",\"updatedAt\":\"" + updatedAt2 + "\"}," + "{\"id\":\"def\",\"String\":\"World\",\"updatedAt\":\"" + updatedAt2 + "\"}]")); client.getSyncContext().initialize(store, new SimpleSyncHandler()).get(); MobileServiceSyncTable<StringIdType> table = client.getSyncTable(StringIdType.class); Query query = QueryOperations.field("String").eq("Hey"); table.pull(query, queryKey).get(); // Skip added assertEquals(serviceFilterContainer.Requests.get(2).Url, EncodingUtilities.percentEncodeSpaces( "http://myapp.com/tables/stringidtype?$filter=String%20eq%20(%27Hey%27)%20and%20(updatedAt%20ge%20(datetimeoffset%27" + updatedAt1 + "%27))" + "&$top=50&$skip=2&" + "$orderby=updatedAt%20asc&__includeDeleted=true")); // Skip removed assertEquals(serviceFilterContainer.Requests.get(3).Url, EncodingUtilities.percentEncodeSpaces( "http://myapp.com/tables/stringidtype?$filter=String%20eq%20(%27Hey%27)%20and%20(updatedAt%20ge%20(datetimeoffset%27" + updatedAt2 + "%27))" + "&$top=50&$orderby=updatedAt%20asc&__includeDeleted=true")); } public void testPurgeDoesNotThrowExceptionWhenThereIsNoOperationInTable() throws MalformedURLException, InterruptedException, ExecutionException { MobileServiceLocalStoreMock store = new MobileServiceLocalStoreMock(); ServiceFilterContainer serviceFilterContainer = new ServiceFilterContainer(); MobileServiceClient client = new MobileServiceClient(appUrl, getInstrumentation().getTargetContext()); client = client.withFilter(getTestFilter(serviceFilterContainer, "{\"id\":\"abc\",\"String\":\"Hey\"}")); client.getSyncContext().initialize(store, new SimpleSyncHandler()).get(); // insert item in purge table MobileServiceJsonSyncTable table1 = client.getSyncTable("someTable"); JsonObject jsonObject = new JsonObject(); jsonObject.addProperty("id", "abc"); table1.insert(jsonObject).get(); // but push to clear the queue client.getSyncContext().push().get(); assertEquals(store.Tables.get(table1.getName().toLowerCase(Locale.getDefault())).size(), 1);// item // is // inserted // then insert item in other table MobileServiceSyncTable<StringIdType> table2 = client.getSyncTable(StringIdType.class); StringIdType item = new StringIdType(); item.Id = "an id"; item.String = "what?"; table2.insert(item).get(); // try purge on first table now table1.purge(null).get(); assertEquals(store.DeleteQueries.get(0).getTableName(), SyncErrors); // push // deletes // all // sync // erros assertEquals(store.DeleteQueries.get(1).getTableName(), table1.getName().toLowerCase(Locale.getDefault())); // purged table assertEquals(serviceFilterContainer.Requests.size(), 1); // still 1 // means no // other // push happened assertEquals(store.Tables.get(table2.getName().toLowerCase(Locale.getDefault())).size(), 1); // this // table // should // not // be // touched } public void testPurgeThrowsExceptionWhenThereIsOperationInTable() throws InterruptedException, ExecutionException, MalformedURLException { MobileServiceLocalStoreMock store = new MobileServiceLocalStoreMock(); ServiceFilterContainer serviceFilterContainer = new ServiceFilterContainer(); MobileServiceClient client = new MobileServiceClient(appUrl, getInstrumentation().getTargetContext()); client = client.withFilter(getTestFilter(serviceFilterContainer, "{\"id\":\"abc\",\"String\":\"Hey\"}")); client.getSyncContext().initialize(store, new SimpleSyncHandler()).get(); // insert an item but don't push MobileServiceJsonSyncTable table1 = client.getSyncTable("someTable"); JsonObject jsonObject = new JsonObject(); jsonObject.addProperty("id", "abc"); table1.insert(jsonObject).get(); assertEquals(store.Tables.get(table1.getName().toLowerCase(Locale.getDefault())).size(), 1); // item // is // inserted try { // this should throw an exception table1.purge(null).get(); } catch (Throwable throwable) { if (throwable.getCause() instanceof MobileServiceException) { assertEquals(store.DeleteQueries.size(), 0); // no purge queries return; } } fail("MobileServiceException expected"); } public void testPushExecutesThePendingOperations() throws InterruptedException, ExecutionException, MalformedURLException { MobileServiceLocalStoreMock store = new MobileServiceLocalStoreMock(); ServiceFilterContainer serviceFilterContainer = new ServiceFilterContainer(); MobileServiceClient client = new MobileServiceClient(appUrl, getInstrumentation().getTargetContext()); client = client.withFilter(getTestFilter(serviceFilterContainer, "{\"id\":\"abc\",\"String\":\"Hey\"}")); client.getSyncContext().initialize(store, new SimpleSyncHandler()).get(); MobileServiceSyncTable<StringIdType> table = client.getSyncTable(StringIdType.class); StringIdType item = new StringIdType(); item.Id = "an id"; item.String = "what?"; table.insert(item).get(); assertEquals(store.Tables.get(table.getName().toLowerCase(Locale.getDefault())).size(), 1); client.getSyncContext().push().get(); } public void testDeleteDoesNotUpsertResultOnStoreWhenOperationIsPushed() throws InterruptedException, ExecutionException, MalformedURLException { MobileServiceLocalStoreMock store = new MobileServiceLocalStoreMock(); ServiceFilterContainer serviceFilterContainer = new ServiceFilterContainer(); MobileServiceClient client = null; client = new MobileServiceClient(appUrl, getInstrumentation().getTargetContext()); client = client.withFilter(getTestFilter(serviceFilterContainer, "{\"id\":\"abc\",\"String\":\"Hey\"}", // for // insert "{\"id\":\"abc\",\"String\":\"Hey\"}"// for delete )); client.getSyncContext().initialize(store, new SimpleSyncHandler()).get(); MobileServiceSyncTable<StringIdType> table = client.getSyncTable(StringIdType.class); StringIdType item = new StringIdType(); item.Id = "abc"; item.String = "what?"; // first add an item table.insert(item).get(); assertEquals(store.Tables.get(table.getName().toLowerCase(Locale.getDefault())).size(), 1); // for good measure also push it client.getSyncContext().push().get(); table.delete(item).get(); assertEquals(store.Tables.get(table.getName().toLowerCase(Locale.getDefault())).size(), 0); // now play it on server client.getSyncContext().push().get(); // wait we don't want to upsert the result back because its delete // operation assertEquals(store.Tables.get(table.getName().toLowerCase(Locale.getDefault())).size(), 0); // looks good } public void testDeleteCancelsAllWhenInsertIsInQueue() throws Throwable { MobileServiceLocalStoreMock store = new MobileServiceLocalStoreMock(); ServiceFilterContainer serviceFilterContainer = new ServiceFilterContainer(); MobileServiceClient client = null; client = new MobileServiceClient(appUrl, getInstrumentation().getTargetContext()); client = client.withFilter(getTestFilter(serviceFilterContainer, "[{\"id\":\"abc\",\"String\":\"Hey\"}]")); client.getSyncContext().initialize(store, new SimpleSyncHandler()).get(); MobileServiceSyncTable<StringIdType> table = client.getSyncTable(StringIdType.class); StringIdType item = new StringIdType(); item.Id = "abc"; item.String = "what?"; table.insert(item).get(); assertEquals(client.getSyncContext().getPendingOperations(), 1); table.delete(item).get(); assertEquals(client.getSyncContext().getPendingOperations(), 0); client.getSyncContext().push().get(); assertEquals(client.getSyncContext().getPendingOperations(), 0); } public void testOperationErrorLoadCorrectly() throws Throwable { MobileServiceLocalStoreMock store = new MobileServiceLocalStoreMock(); OperationErrorList operationErrorList = OperationErrorList.load(store); TableOperationError tableOperationError = new TableOperationError("Id1", TableOperationKind.Update, "Table1", "ItemId", null, "Message", 400, null, null); operationErrorList.add(tableOperationError); //Load with the previous inserted operation OperationErrorList.load(store); } public void testCancelAndDiscardItem() throws Throwable { MobileServiceLocalStoreMock store = new MobileServiceLocalStoreMock(); final ServiceFilterContainer serviceFilterContainer = new ServiceFilterContainer(); final ThrownExceptionFlag thrownExceptionFlag = new ThrownExceptionFlag(); thrownExceptionFlag.Thrown = true; MobileServiceClient client = new MobileServiceClient(appUrl, getInstrumentation().getTargetContext()); Function<ServiceFilterRequest, Void> onHandleRequest = new Function<ServiceFilterRequest, Void>() { public Void apply(ServiceFilterRequest request) { try { if (thrownExceptionFlag.Thrown) { throw new Exception(); } } catch (Exception e) { serviceFilterContainer.Exception = e; } return null; } }; client = client.withFilter( getTestFilter(serviceFilterContainer, onHandleRequest, "{\"id\":\"abc\",\"String\":\"Hey\"}")); client.getSyncContext().initialize(store, new SimpleSyncHandler()).get(); MobileServiceSyncTable<StringIdType> table = client.getSyncTable(StringIdType.class); StringIdType item = new StringIdType(); item.Id = "abc"; item.String = "what?"; table.insert(item).get(); assertEquals(client.getSyncContext().getPendingOperations(), 1); try { client.getSyncContext().push().get(); } catch (Exception ex) { MobileServicePushFailedException mspfe = (MobileServicePushFailedException) ex.getCause(); assertEquals(mspfe.getPushCompletionResult().getStatus(), MobileServicePushStatus.InternalError); assertEquals(mspfe.getPushCompletionResult().getOperationErrors().size(), 1); assertEquals(client.getSyncContext().getPendingOperations(), 1); TableOperationError tableOperationError = mspfe.getPushCompletionResult().getOperationErrors().get(0); client.getSyncContext().cancelAndDiscardItem(tableOperationError); assertEquals(client.getSyncContext().getPendingOperations(), 0); StringIdType result = table.lookUp(item.Id).get(); assertEquals(null, result); return; } assertTrue(false); } public void testCancelAndUpdateItem() throws Throwable { MobileServiceLocalStoreMock store = new MobileServiceLocalStoreMock(); final ServiceFilterContainer serviceFilterContainer = new ServiceFilterContainer(); final ThrownExceptionFlag thrownExceptionFlag = new ThrownExceptionFlag(); thrownExceptionFlag.Thrown = true; MobileServiceClient client = new MobileServiceClient(appUrl, getInstrumentation().getTargetContext()); final JsonObject serverItem = new JsonObject(); serverItem.addProperty("id", "abc"); serverItem.addProperty("String", "fooo"); Function<ServiceFilterRequest, Void> onHandleRequest = new Function<ServiceFilterRequest, Void>() { public Void apply(ServiceFilterRequest request) { try { if (thrownExceptionFlag.Thrown) { throw new MobileServiceExceptionBase(new MobileServiceException(new Exception()), serverItem); } } catch (Exception e) { serviceFilterContainer.Exception = e; } return null; } }; client = client.withFilter( getTestFilter(serviceFilterContainer, onHandleRequest, "{\"id\":\"abc\",\"String\":\"Hey\"}")); client.getSyncContext().initialize(store, new SimpleSyncHandler()).get(); MobileServiceSyncTable<StringIdType> table = client.getSyncTable(StringIdType.class); StringIdType item = new StringIdType(); item.Id = "abc"; item.String = "what?"; table.insert(item).get(); assertEquals(client.getSyncContext().getPendingOperations(), 1); try { client.getSyncContext().push().get(); } catch (Exception ex) { MobileServicePushFailedException mspfe = (MobileServicePushFailedException) ex.getCause(); assertEquals(mspfe.getPushCompletionResult().getStatus(), MobileServicePushStatus.InternalError); assertEquals(mspfe.getPushCompletionResult().getOperationErrors().size(), 1); assertEquals(client.getSyncContext().getPendingOperations(), 1); TableOperationError tableOperationError = mspfe.getPushCompletionResult().getOperationErrors().get(0); client.getSyncContext().cancelAndUpdateItem(tableOperationError); assertEquals(client.getSyncContext().getPendingOperations(), 0); StringIdType result = table.lookUp(item.Id).get(); assertEquals(item.Id, result.Id); assertEquals("fooo", result.String); return; } assertTrue(false); } public void testPushAbortOnNewtorkError() throws Throwable { MobileServiceLocalStoreMock store = new MobileServiceLocalStoreMock(); final ServiceFilterContainer serviceFilterContainer = new ServiceFilterContainer(); final ThrownExceptionFlag thrownExceptionFlag = new ThrownExceptionFlag(); thrownExceptionFlag.Thrown = true; MobileServiceClient client = new MobileServiceClient(appUrl, getInstrumentation().getTargetContext()); final MobileServiceException innerException = new MobileServiceException(new IOException()); Function<ServiceFilterRequest, Void> onHandleRequest = new Function<ServiceFilterRequest, Void>() { public Void apply(ServiceFilterRequest request) { try { if (thrownExceptionFlag.Thrown) { throw innerException; } } catch (Exception e) { serviceFilterContainer.Exception = e; } return null; } }; client = client.withFilter( getTestFilter(serviceFilterContainer, onHandleRequest, "{\"id\":\"abc\",\"String\":\"Hey\"}")); client.getSyncContext().initialize(store, new SimpleSyncHandler()).get(); MobileServiceSyncTable<StringIdType> table = client.getSyncTable(StringIdType.class); StringIdType item = new StringIdType(); item.Id = "abc"; item.String = "what?"; table.insert(item).get(); assertEquals(client.getSyncContext().getPendingOperations(), 1); try { client.getSyncContext().push().get(); } catch (Exception ex) { MobileServicePushFailedException mspfe = (MobileServicePushFailedException) ex.getCause(); assertEquals(mspfe.getPushCompletionResult().getStatus(), MobileServicePushStatus.CancelledByNetworkError); assertEquals(mspfe.getPushCompletionResult().getOperationErrors().size(), 0); assertEquals(client.getSyncContext().getPendingOperations(), 1); thrownExceptionFlag.Thrown = false; client.getSyncContext().push().get(); assertEquals(client.getSyncContext().getPendingOperations(), 0); assertEquals(serviceFilterContainer.Requests.get(1).Method, HttpConstants.PostMethod); return; } assertTrue(false); } public void testPushAbortOnAuthentication() throws Throwable { MobileServiceLocalStoreMock store = new MobileServiceLocalStoreMock(); final ServiceFilterContainer serviceFilterContainer = new ServiceFilterContainer(); final ThrownExceptionFlag thrownExceptionFlag = new ThrownExceptionFlag(); thrownExceptionFlag.Thrown = true; MobileServiceClient client = new MobileServiceClient(appUrl, getInstrumentation().getTargetContext()); ServiceFilterResponseMock response = new ServiceFilterResponseMock(); response.setStatus(new StatusLine(Protocol.HTTP_2, 401, "")); final MobileServiceException innerException = new MobileServiceException("", response); Function<ServiceFilterRequest, Void> onHandleRequest = new Function<ServiceFilterRequest, Void>() { public Void apply(ServiceFilterRequest request) { try { if (thrownExceptionFlag.Thrown) { throw innerException; } } catch (Exception e) { serviceFilterContainer.Exception = e; } return null; } }; client = client.withFilter( getTestFilter(serviceFilterContainer, onHandleRequest, "{\"id\":\"abc\",\"String\":\"Hey\"}")); client.getSyncContext().initialize(store, new SimpleSyncHandler()).get(); MobileServiceSyncTable<StringIdType> table = client.getSyncTable(StringIdType.class); StringIdType item = new StringIdType(); item.Id = "abc"; item.String = "what?"; table.insert(item).get(); assertEquals(client.getSyncContext().getPendingOperations(), 1); try { client.getSyncContext().push().get(); } catch (Exception ex) { MobileServicePushFailedException mspfe = (MobileServicePushFailedException) ex.getCause(); assertEquals(mspfe.getPushCompletionResult().getStatus(), MobileServicePushStatus.CancelledByAuthenticationError); assertEquals(mspfe.getPushCompletionResult().getOperationErrors().size(), 0); assertEquals(client.getSyncContext().getPendingOperations(), 1); thrownExceptionFlag.Thrown = false; client.getSyncContext().push().get(); assertEquals(client.getSyncContext().getPendingOperations(), 0); assertEquals(serviceFilterContainer.Requests.get(1).Method, HttpConstants.PostMethod); return; } assertTrue(false); } public void testPushAbortOnOperationError() throws Throwable { MobileServiceLocalStoreMock store = new MobileServiceLocalStoreMock(); final ServiceFilterContainer serviceFilterContainer = new ServiceFilterContainer(); final ThrownExceptionFlag thrownExceptionFlag = new ThrownExceptionFlag(); thrownExceptionFlag.Thrown = true; MobileServiceClient client = new MobileServiceClient(appUrl, getInstrumentation().getTargetContext()); Function<ServiceFilterRequest, Void> onHandleRequest = new Function<ServiceFilterRequest, Void>() { public Void apply(ServiceFilterRequest request) { try { if (thrownExceptionFlag.Thrown) { throw new Exception(); } } catch (Exception e) { serviceFilterContainer.Exception = e; } return null; } }; client = client.withFilter( getTestFilter(serviceFilterContainer, onHandleRequest, "{\"id\":\"abc\",\"String\":\"Hey\"}")); client.getSyncContext().initialize(store, new SimpleSyncHandler()).get(); MobileServiceSyncTable<StringIdType> table = client.getSyncTable(StringIdType.class); StringIdType item = new StringIdType(); item.Id = "abc"; item.String = "what?"; table.insert(item).get(); assertEquals(client.getSyncContext().getPendingOperations(), 1); try { client.getSyncContext().push().get(); } catch (Exception ex) { MobileServicePushFailedException mspfe = (MobileServicePushFailedException) ex.getCause(); assertEquals(mspfe.getPushCompletionResult().getStatus(), MobileServicePushStatus.InternalError); assertEquals(mspfe.getPushCompletionResult().getOperationErrors().size(), 1); assertEquals(client.getSyncContext().getPendingOperations(), 1); thrownExceptionFlag.Thrown = false; client.getSyncContext().push().get(); assertEquals(client.getSyncContext().getPendingOperations(), 0); assertEquals(serviceFilterContainer.Requests.get(1).Method, HttpConstants.PostMethod); return; } assertTrue(false); } //Test Collapse Login on Operation Error public void testInsertThrowsWhenInsertIsInQueueOnNewtorkError() throws Throwable { MobileServiceLocalStoreMock store = new MobileServiceLocalStoreMock(); final ServiceFilterContainer serviceFilterContainer = new ServiceFilterContainer(); final ThrownExceptionFlag thrownExceptionFlag = new ThrownExceptionFlag(); thrownExceptionFlag.Thrown = true; MobileServiceClient client = new MobileServiceClient(appUrl, getInstrumentation().getTargetContext()); final MobileServiceException innerException = new MobileServiceException(new IOException()); Function<ServiceFilterRequest, Void> onHandleRequest = new Function<ServiceFilterRequest, Void>() { public Void apply(ServiceFilterRequest request) { try { if (thrownExceptionFlag.Thrown) { throw innerException; } } catch (Exception e) { serviceFilterContainer.Exception = e; } return null; } }; client = client.withFilter( getTestFilter(serviceFilterContainer, onHandleRequest, "{\"id\":\"abc\",\"String\":\"Hey\"}")); client.getSyncContext().initialize(store, new SimpleSyncHandler()).get(); MobileServiceSyncTable<StringIdType> table = client.getSyncTable(StringIdType.class); StringIdType item = new StringIdType(); item.Id = "abc"; item.String = "what?"; table.insert(item).get(); assertEquals(client.getSyncContext().getPendingOperations(), 1); try { client.getSyncContext().push().get(); } catch (Exception ex) { try { table.insert(item).get(); } catch (Exception ex2) { assertEquals(client.getSyncContext().getPendingOperations(), 1); assertEquals(serviceFilterContainer.Requests.get(0).Method, HttpConstants.PostMethod); assertEquals(ex2.getMessage(), "java.lang.IllegalStateException: An insert operation on the item is already in the queue."); return; } } assertTrue(false); } public void testInsertThrowsWhenInsertIsInQueueOnAuthenticationError() throws Throwable { MobileServiceLocalStoreMock store = new MobileServiceLocalStoreMock(); final ServiceFilterContainer serviceFilterContainer = new ServiceFilterContainer(); final ThrownExceptionFlag thrownExceptionFlag = new ThrownExceptionFlag(); thrownExceptionFlag.Thrown = true; MobileServiceClient client = new MobileServiceClient(appUrl, getInstrumentation().getTargetContext()); ServiceFilterResponseMock response = new ServiceFilterResponseMock(); response.setStatus(new StatusLine(Protocol.HTTP_2, 401, "")); final MobileServiceException innerException = new MobileServiceException("", response); Function<ServiceFilterRequest, Void> onHandleRequest = new Function<ServiceFilterRequest, Void>() { public Void apply(ServiceFilterRequest request) { try { if (thrownExceptionFlag.Thrown) { throw innerException; } } catch (Exception e) { serviceFilterContainer.Exception = e; } return null; } }; client = client.withFilter( getTestFilter(serviceFilterContainer, onHandleRequest, "{\"id\":\"abc\",\"String\":\"Hey\"}")); client.getSyncContext().initialize(store, new SimpleSyncHandler()).get(); MobileServiceSyncTable<StringIdType> table = client.getSyncTable(StringIdType.class); StringIdType item = new StringIdType(); item.Id = "abc"; item.String = "what?"; table.insert(item).get(); assertEquals(client.getSyncContext().getPendingOperations(), 1); try { client.getSyncContext().push().get(); } catch (Exception ex) { try { table.insert(item).get(); } catch (Exception ex2) { assertEquals(client.getSyncContext().getPendingOperations(), 1); assertEquals(serviceFilterContainer.Requests.get(0).Method, HttpConstants.PostMethod); assertEquals(ex2.getMessage(), "java.lang.IllegalStateException: An insert operation on the item is already in the queue."); return; } } assertTrue(false); } public void testInsertThrowsWhenInsertIsInQueueOnOperationError() throws Throwable { MobileServiceLocalStoreMock store = new MobileServiceLocalStoreMock(); final ServiceFilterContainer serviceFilterContainer = new ServiceFilterContainer(); final ThrownExceptionFlag thrownExceptionFlag = new ThrownExceptionFlag(); thrownExceptionFlag.Thrown = true; MobileServiceClient client = new MobileServiceClient(appUrl, getInstrumentation().getTargetContext()); Function<ServiceFilterRequest, Void> onHandleRequest = new Function<ServiceFilterRequest, Void>() { public Void apply(ServiceFilterRequest request) { try { if (thrownExceptionFlag.Thrown) { throw new Exception(); } } catch (Exception e) { serviceFilterContainer.Exception = e; } return null; } }; client = client.withFilter( getTestFilter(serviceFilterContainer, onHandleRequest, "{\"id\":\"abc\",\"String\":\"Hey\"}")); client.getSyncContext().initialize(store, new SimpleSyncHandler()).get(); MobileServiceSyncTable<StringIdType> table = client.getSyncTable(StringIdType.class); StringIdType item = new StringIdType(); item.Id = "abc"; item.String = "what?"; table.insert(item).get(); assertEquals(client.getSyncContext().getPendingOperations(), 1); try { client.getSyncContext().push().get(); } catch (Exception ex) { try { table.insert(item).get(); } catch (Exception ex2) { assertEquals(client.getSyncContext().getPendingOperations(), 1); assertEquals(serviceFilterContainer.Requests.get(0).Method, HttpConstants.PostMethod); assertEquals(ex2.getMessage(), "java.lang.IllegalStateException: An insert operation on the item is already in the queue."); return; } } assertTrue(false); } public void testDeleteNoCollapseInsertWhenFailedInsertIsInQueueOnNewtorkError() throws Throwable { MobileServiceLocalStoreMock store = new MobileServiceLocalStoreMock(); final ServiceFilterContainer serviceFilterContainer = new ServiceFilterContainer(); final ThrownExceptionFlag thrownExceptionFlag = new ThrownExceptionFlag(); String expectedUrl = "http://myapp.com/tables/stringidtype/abc"; thrownExceptionFlag.Thrown = true; MobileServiceClient client = new MobileServiceClient(appUrl, getInstrumentation().getTargetContext()); final MobileServiceException innerException = new MobileServiceException(new IOException()); Function<ServiceFilterRequest, Void> onHandleRequest = new Function<ServiceFilterRequest, Void>() { public Void apply(ServiceFilterRequest request) { try { if (thrownExceptionFlag.Thrown) { throw innerException; } } catch (Exception e) { serviceFilterContainer.Exception = e; } return null; } }; client = client.withFilter( getTestFilter(serviceFilterContainer, onHandleRequest, "{\"id\":\"abc\",\"String\":\"Hey\"}")); client.getSyncContext().initialize(store, new SimpleSyncHandler()).get(); MobileServiceSyncTable<StringIdType> table = client.getSyncTable(StringIdType.class); StringIdType item = new StringIdType(); item.Id = "abc"; item.String = "what?"; table.insert(item).get(); assertEquals(client.getSyncContext().getPendingOperations(), 1); try { client.getSyncContext().push().get(); } catch (Exception ex) { table.delete(item).get(); assertEquals(client.getSyncContext().getPendingOperations(), 1); thrownExceptionFlag.Thrown = false; client.getSyncContext().push().get(); assertEquals(client.getSyncContext().getPendingOperations(), 0); assertEquals(serviceFilterContainer.Requests.get(1).Url, expectedUrl); assertEquals(serviceFilterContainer.Requests.get(1).Method, HttpConstants.DeleteMethod); return; } assertTrue(false); } public void testDeleteNoCollapseInsertWhenFailedInsertIsInQueueOnAuthentication() throws Throwable { MobileServiceLocalStoreMock store = new MobileServiceLocalStoreMock(); final ServiceFilterContainer serviceFilterContainer = new ServiceFilterContainer(); final ThrownExceptionFlag thrownExceptionFlag = new ThrownExceptionFlag(); String expectedUrl = "http://myapp.com/tables/stringidtype/abc"; thrownExceptionFlag.Thrown = true; MobileServiceClient client = new MobileServiceClient(appUrl, getInstrumentation().getTargetContext()); ServiceFilterResponseMock response = new ServiceFilterResponseMock(); response.setStatus(new StatusLine(Protocol.HTTP_2, 401, "")); final MobileServiceException innerException = new MobileServiceException("", response); Function<ServiceFilterRequest, Void> onHandleRequest = new Function<ServiceFilterRequest, Void>() { public Void apply(ServiceFilterRequest request) { try { if (thrownExceptionFlag.Thrown) { throw innerException; } } catch (Exception e) { serviceFilterContainer.Exception = e; } return null; } }; client = client.withFilter( getTestFilter(serviceFilterContainer, onHandleRequest, "{\"id\":\"abc\",\"String\":\"Hey\"}")); client.getSyncContext().initialize(store, new SimpleSyncHandler()).get(); MobileServiceSyncTable<StringIdType> table = client.getSyncTable(StringIdType.class); StringIdType item = new StringIdType(); item.Id = "abc"; item.String = "what?"; table.insert(item).get(); assertEquals(client.getSyncContext().getPendingOperations(), 1); try { client.getSyncContext().push().get(); } catch (Exception ex) { table.delete(item).get(); assertEquals(client.getSyncContext().getPendingOperations(), 1); thrownExceptionFlag.Thrown = false; client.getSyncContext().push().get(); assertEquals(client.getSyncContext().getPendingOperations(), 0); assertEquals(serviceFilterContainer.Requests.get(1).Url, expectedUrl); assertEquals(serviceFilterContainer.Requests.get(1).Method, HttpConstants.DeleteMethod); return; } assertTrue(false); } public void testDeleteNoCollapseInsertWhenFailedInsertIsInQueueOnOperationError() throws Throwable { MobileServiceLocalStoreMock store = new MobileServiceLocalStoreMock(); final ServiceFilterContainer serviceFilterContainer = new ServiceFilterContainer(); final ThrownExceptionFlag thrownExceptionFlag = new ThrownExceptionFlag(); String expectedUrl = "http://myapp.com/tables/stringidtype/abc"; thrownExceptionFlag.Thrown = true; MobileServiceClient client = new MobileServiceClient(appUrl, getInstrumentation().getTargetContext()); Function<ServiceFilterRequest, Void> onHandleRequest = new Function<ServiceFilterRequest, Void>() { public Void apply(ServiceFilterRequest request) { try { if (thrownExceptionFlag.Thrown) { throw new Exception(); } } catch (Exception e) { serviceFilterContainer.Exception = e; } return null; } }; client = client.withFilter( getTestFilter(serviceFilterContainer, onHandleRequest, "{\"id\":\"abc\",\"String\":\"Hey\"}")); client.getSyncContext().initialize(store, new SimpleSyncHandler()).get(); MobileServiceSyncTable<StringIdType> table = client.getSyncTable(StringIdType.class); StringIdType item = new StringIdType(); item.Id = "abc"; item.String = "what?"; table.insert(item).get(); assertEquals(client.getSyncContext().getPendingOperations(), 1); try { client.getSyncContext().push().get(); } catch (Exception ex) { table.delete(item).get(); assertEquals(client.getSyncContext().getPendingOperations(), 1); thrownExceptionFlag.Thrown = false; client.getSyncContext().push().get(); assertEquals(client.getSyncContext().getPendingOperations(), 0); assertEquals(serviceFilterContainer.Requests.get(1).Url, expectedUrl); assertEquals(serviceFilterContainer.Requests.get(1).Method, HttpConstants.DeleteMethod); return; } assertTrue(false); } public void testUpdateCollapseWhenInsertIsInQueueOnNewtorkError() throws Throwable { MobileServiceLocalStoreMock store = new MobileServiceLocalStoreMock(); final ServiceFilterContainer serviceFilterContainer = new ServiceFilterContainer(); final ThrownExceptionFlag thrownExceptionFlag = new ThrownExceptionFlag(); final String expectedUpdateContent = "{\"String\":\"fooo\",\"id\":\"abc\"}"; thrownExceptionFlag.Thrown = true; MobileServiceClient client = new MobileServiceClient(appUrl, getInstrumentation().getTargetContext()); final MobileServiceException innerException = new MobileServiceException(new IOException()); Function<ServiceFilterRequest, Void> onHandleRequest = new Function<ServiceFilterRequest, Void>() { public Void apply(ServiceFilterRequest request) { try { if (thrownExceptionFlag.Thrown) { throw innerException; } } catch (Exception e) { serviceFilterContainer.Exception = e; } return null; } }; client = client.withFilter( getTestFilter(serviceFilterContainer, onHandleRequest, "{\"id\":\"abc\",\"String\":\"Hey\"}")); client.getSyncContext().initialize(store, new SimpleSyncHandler()).get(); MobileServiceSyncTable<StringIdType> table = client.getSyncTable(StringIdType.class); StringIdType item = new StringIdType(); item.Id = "abc"; item.String = "what?"; table.insert(item).get(); assertEquals(client.getSyncContext().getPendingOperations(), 1); try { client.getSyncContext().push().get(); } catch (Exception ex) { StringIdType itemUpdated = new StringIdType(); itemUpdated.Id = "abc"; itemUpdated.String = "fooo"; table.update(itemUpdated).get(); thrownExceptionFlag.Thrown = false; client.getSyncContext().push().get(); assertEquals(client.getSyncContext().getPendingOperations(), 0); assertEquals(serviceFilterContainer.Requests.get(0).Method, HttpConstants.PostMethod); assertEquals(serviceFilterContainer.Requests.get(1).Method, HttpConstants.PostMethod); assertEquals(serviceFilterContainer.Requests.get(1).Content, expectedUpdateContent); return; } assertTrue(false); } public void testUpdateCollapseWhenInsertIsInQueueOnAuthenticationError() throws Throwable { MobileServiceLocalStoreMock store = new MobileServiceLocalStoreMock(); final ServiceFilterContainer serviceFilterContainer = new ServiceFilterContainer(); final ThrownExceptionFlag thrownExceptionFlag = new ThrownExceptionFlag(); final String expectedUpdateContent = "{\"String\":\"fooo\",\"id\":\"abc\"}"; thrownExceptionFlag.Thrown = true; MobileServiceClient client = new MobileServiceClient(appUrl, getInstrumentation().getTargetContext()); ServiceFilterResponseMock response = new ServiceFilterResponseMock(); response.setStatus(new StatusLine(Protocol.HTTP_2, 401, "")); final MobileServiceException innerException = new MobileServiceException("", response); Function<ServiceFilterRequest, Void> onHandleRequest = new Function<ServiceFilterRequest, Void>() { public Void apply(ServiceFilterRequest request) { try { if (thrownExceptionFlag.Thrown) { throw innerException; } } catch (Exception e) { serviceFilterContainer.Exception = e; } return null; } }; client = client.withFilter( getTestFilter(serviceFilterContainer, onHandleRequest, "{\"id\":\"abc\",\"String\":\"Hey\"}")); client.getSyncContext().initialize(store, new SimpleSyncHandler()).get(); MobileServiceSyncTable<StringIdType> table = client.getSyncTable(StringIdType.class); StringIdType item = new StringIdType(); item.Id = "abc"; item.String = "what?"; table.insert(item).get(); assertEquals(client.getSyncContext().getPendingOperations(), 1); try { client.getSyncContext().push().get(); } catch (Exception ex) { StringIdType itemUpdated = new StringIdType(); itemUpdated.Id = "abc"; itemUpdated.String = "fooo"; table.update(itemUpdated).get(); thrownExceptionFlag.Thrown = false; client.getSyncContext().push().get(); assertEquals(client.getSyncContext().getPendingOperations(), 0); assertEquals(serviceFilterContainer.Requests.get(0).Method, HttpConstants.PostMethod); assertEquals(serviceFilterContainer.Requests.get(1).Method, HttpConstants.PostMethod); assertEquals(serviceFilterContainer.Requests.get(1).Content, expectedUpdateContent); return; } assertTrue(false); } public void testUpdateCollapseWhenInsertIsInQueueOnOperationError() throws Throwable { MobileServiceLocalStoreMock store = new MobileServiceLocalStoreMock(); final ServiceFilterContainer serviceFilterContainer = new ServiceFilterContainer(); final ThrownExceptionFlag thrownExceptionFlag = new ThrownExceptionFlag(); final String expectedUpdateContent = "{\"String\":\"fooo\",\"id\":\"abc\"}"; thrownExceptionFlag.Thrown = true; MobileServiceClient client = new MobileServiceClient(appUrl, getInstrumentation().getTargetContext()); final MobileServiceException innerException = new MobileServiceException(new IOException()); Function<ServiceFilterRequest, Void> onHandleRequest = new Function<ServiceFilterRequest, Void>() { public Void apply(ServiceFilterRequest request) { try { if (thrownExceptionFlag.Thrown) { throw new Exception(); } } catch (Exception e) { serviceFilterContainer.Exception = e; } return null; } }; client = client.withFilter( getTestFilter(serviceFilterContainer, onHandleRequest, "{\"id\":\"abc\",\"String\":\"Hey\"}")); client.getSyncContext().initialize(store, new SimpleSyncHandler()).get(); MobileServiceSyncTable<StringIdType> table = client.getSyncTable(StringIdType.class); StringIdType item = new StringIdType(); item.Id = "abc"; item.String = "what?"; table.insert(item).get(); assertEquals(client.getSyncContext().getPendingOperations(), 1); try { client.getSyncContext().push().get(); } catch (Exception ex) { StringIdType itemUpdated = new StringIdType(); itemUpdated.Id = "abc"; itemUpdated.String = "fooo"; table.update(itemUpdated).get(); thrownExceptionFlag.Thrown = false; client.getSyncContext().push().get(); assertEquals(client.getSyncContext().getPendingOperations(), 0); assertEquals(serviceFilterContainer.Requests.get(0).Method, HttpConstants.PostMethod); assertEquals(serviceFilterContainer.Requests.get(1).Method, HttpConstants.PostMethod); assertEquals(serviceFilterContainer.Requests.get(1).Content, expectedUpdateContent); return; } assertTrue(false); } public void testUpdateCollapseWhenUpdateIsInQueueOnNewtorkError() throws Throwable { MobileServiceLocalStoreMock store = new MobileServiceLocalStoreMock(); final ServiceFilterContainer serviceFilterContainer = new ServiceFilterContainer(); final ThrownExceptionFlag thrownExceptionFlag = new ThrownExceptionFlag(); final String expectedUpdateContent = "{\"String\":\"fooo\",\"id\":\"abc\"}"; thrownExceptionFlag.Thrown = true; MobileServiceClient client = new MobileServiceClient(appUrl, getInstrumentation().getTargetContext()); final MobileServiceException innerException = new MobileServiceException(new IOException()); Function<ServiceFilterRequest, Void> onHandleRequest = new Function<ServiceFilterRequest, Void>() { public Void apply(ServiceFilterRequest request) { try { if (thrownExceptionFlag.Thrown) { throw innerException; } } catch (Exception e) { serviceFilterContainer.Exception = e; } return null; } }; client = client.withFilter( getTestFilter(serviceFilterContainer, onHandleRequest, "{\"id\":\"abc\",\"String\":\"Hey\"}")); client.getSyncContext().initialize(store, new SimpleSyncHandler()).get(); MobileServiceSyncTable<StringIdType> table = client.getSyncTable(StringIdType.class); StringIdType item = new StringIdType(); item.Id = "abc"; item.String = "what?"; table.update(item).get(); assertEquals(client.getSyncContext().getPendingOperations(), 1); try { client.getSyncContext().push().get(); } catch (Exception ex) { StringIdType itemUpdated = new StringIdType(); itemUpdated.Id = "abc"; itemUpdated.String = "fooo"; table.update(itemUpdated).get(); thrownExceptionFlag.Thrown = false; client.getSyncContext().push().get(); assertEquals(client.getSyncContext().getPendingOperations(), 0); assertEquals(serviceFilterContainer.Requests.get(0).Method, HttpConstants.PatchMethod); assertEquals(serviceFilterContainer.Requests.get(1).Method, HttpConstants.PatchMethod); assertEquals(serviceFilterContainer.Requests.get(1).Content, expectedUpdateContent); return; } assertTrue(false); } public void testUpdateCollapseWhenUpdateIsInQueueOnAuthentication() throws Throwable { MobileServiceLocalStoreMock store = new MobileServiceLocalStoreMock(); final ServiceFilterContainer serviceFilterContainer = new ServiceFilterContainer(); final ThrownExceptionFlag thrownExceptionFlag = new ThrownExceptionFlag(); final String expectedUpdateContent = "{\"String\":\"fooo\",\"id\":\"abc\"}"; thrownExceptionFlag.Thrown = true; MobileServiceClient client = new MobileServiceClient(appUrl, getInstrumentation().getTargetContext()); ServiceFilterResponseMock response = new ServiceFilterResponseMock(); response.setStatus(new StatusLine(Protocol.HTTP_2, 401, "")); final MobileServiceException innerException = new MobileServiceException("", response); Function<ServiceFilterRequest, Void> onHandleRequest = new Function<ServiceFilterRequest, Void>() { public Void apply(ServiceFilterRequest request) { try { if (thrownExceptionFlag.Thrown) { throw innerException; } } catch (Exception e) { serviceFilterContainer.Exception = e; } return null; } }; client = client.withFilter( getTestFilter(serviceFilterContainer, onHandleRequest, "{\"id\":\"abc\",\"String\":\"Hey\"}")); client.getSyncContext().initialize(store, new SimpleSyncHandler()).get(); MobileServiceSyncTable<StringIdType> table = client.getSyncTable(StringIdType.class); StringIdType item = new StringIdType(); item.Id = "abc"; item.String = "what?"; table.update(item).get(); assertEquals(client.getSyncContext().getPendingOperations(), 1); try { client.getSyncContext().push().get(); } catch (Exception ex) { StringIdType itemUpdated = new StringIdType(); itemUpdated.Id = "abc"; itemUpdated.String = "fooo"; table.update(itemUpdated).get(); thrownExceptionFlag.Thrown = false; client.getSyncContext().push().get(); assertEquals(client.getSyncContext().getPendingOperations(), 0); assertEquals(serviceFilterContainer.Requests.get(0).Method, HttpConstants.PatchMethod); assertEquals(serviceFilterContainer.Requests.get(1).Method, HttpConstants.PatchMethod); assertEquals(serviceFilterContainer.Requests.get(1).Content, expectedUpdateContent); return; } assertTrue(false); } public void testUpdateCollapseWhenUpdateIsInQueueOnOperationError() throws Throwable { MobileServiceLocalStoreMock store = new MobileServiceLocalStoreMock(); final ServiceFilterContainer serviceFilterContainer = new ServiceFilterContainer(); final ThrownExceptionFlag thrownExceptionFlag = new ThrownExceptionFlag(); final String expectedUpdateContent = "{\"String\":\"fooo\",\"id\":\"abc\"}"; thrownExceptionFlag.Thrown = true; MobileServiceClient client = new MobileServiceClient(appUrl, getInstrumentation().getTargetContext()); Function<ServiceFilterRequest, Void> onHandleRequest = new Function<ServiceFilterRequest, Void>() { public Void apply(ServiceFilterRequest request) { try { if (thrownExceptionFlag.Thrown) { throw new Exception(); } } catch (Exception e) { serviceFilterContainer.Exception = e; } return null; } }; client = client.withFilter( getTestFilter(serviceFilterContainer, onHandleRequest, "{\"id\":\"abc\",\"String\":\"Hey\"}")); client.getSyncContext().initialize(store, new SimpleSyncHandler()).get(); MobileServiceSyncTable<StringIdType> table = client.getSyncTable(StringIdType.class); StringIdType item = new StringIdType(); item.Id = "abc"; item.String = "what?"; table.update(item).get(); assertEquals(client.getSyncContext().getPendingOperations(), 1); try { client.getSyncContext().push().get(); } catch (Exception ex) { StringIdType itemUpdated = new StringIdType(); itemUpdated.Id = "abc"; itemUpdated.String = "fooo"; table.update(itemUpdated).get(); thrownExceptionFlag.Thrown = false; client.getSyncContext().push().get(); assertEquals(client.getSyncContext().getPendingOperations(), 0); assertEquals(serviceFilterContainer.Requests.get(0).Method, HttpConstants.PatchMethod); assertEquals(serviceFilterContainer.Requests.get(1).Method, HttpConstants.PatchMethod); assertEquals(serviceFilterContainer.Requests.get(1).Content, expectedUpdateContent); return; } assertTrue(false); } public void testDeleteCollapseUpdateWhenUpdateIsInQueueOnNewtorkError() throws Throwable { MobileServiceLocalStoreMock store = new MobileServiceLocalStoreMock(); final ServiceFilterContainer serviceFilterContainer = new ServiceFilterContainer(); final ThrownExceptionFlag thrownExceptionFlag = new ThrownExceptionFlag(); thrownExceptionFlag.Thrown = true; MobileServiceClient client = new MobileServiceClient(appUrl, getInstrumentation().getTargetContext()); final MobileServiceException innerException = new MobileServiceException(new IOException()); Function<ServiceFilterRequest, Void> onHandleRequest = new Function<ServiceFilterRequest, Void>() { public Void apply(ServiceFilterRequest request) { try { if (thrownExceptionFlag.Thrown) { throw innerException; } } catch (Exception e) { serviceFilterContainer.Exception = e; } return null; } }; client = client.withFilter( getTestFilter(serviceFilterContainer, onHandleRequest, "{\"id\":\"abc\",\"String\":\"Hey\"}")); client.getSyncContext().initialize(store, new SimpleSyncHandler()).get(); MobileServiceSyncTable<StringIdType> table = client.getSyncTable(StringIdType.class); StringIdType item = new StringIdType(); item.Id = "abc"; item.String = "what?"; table.update(item).get(); assertEquals(client.getSyncContext().getPendingOperations(), 1); try { client.getSyncContext().push().get(); } catch (Exception ex) { table.delete(item).get(); thrownExceptionFlag.Thrown = false; client.getSyncContext().push().get(); assertEquals(client.getSyncContext().getPendingOperations(), 0); assertEquals(serviceFilterContainer.Requests.get(0).Method, HttpConstants.PatchMethod); assertEquals(serviceFilterContainer.Requests.get(1).Method, HttpConstants.DeleteMethod); return; } assertTrue(false); } public void testDeleteCollapseUpdateWhenUpdateIsInQueueOnAuthenticationError() throws Throwable { MobileServiceLocalStoreMock store = new MobileServiceLocalStoreMock(); final ServiceFilterContainer serviceFilterContainer = new ServiceFilterContainer(); final ThrownExceptionFlag thrownExceptionFlag = new ThrownExceptionFlag(); thrownExceptionFlag.Thrown = true; MobileServiceClient client = new MobileServiceClient(appUrl, getInstrumentation().getTargetContext()); ServiceFilterResponseMock response = new ServiceFilterResponseMock(); response.setStatus((new StatusLine(Protocol.HTTP_2, 401, ""))); final MobileServiceException innerException = new MobileServiceException("", response); Function<ServiceFilterRequest, Void> onHandleRequest = new Function<ServiceFilterRequest, Void>() { public Void apply(ServiceFilterRequest request) { try { if (thrownExceptionFlag.Thrown) { throw innerException; } } catch (Exception e) { serviceFilterContainer.Exception = e; } return null; } }; client = client.withFilter( getTestFilter(serviceFilterContainer, onHandleRequest, "{\"id\":\"abc\",\"String\":\"Hey\"}")); client.getSyncContext().initialize(store, new SimpleSyncHandler()).get(); MobileServiceSyncTable<StringIdType> table = client.getSyncTable(StringIdType.class); StringIdType item = new StringIdType(); item.Id = "abc"; item.String = "what?"; table.update(item).get(); assertEquals(client.getSyncContext().getPendingOperations(), 1); try { client.getSyncContext().push().get(); } catch (Exception ex) { table.delete(item).get(); thrownExceptionFlag.Thrown = false; client.getSyncContext().push().get(); assertEquals(client.getSyncContext().getPendingOperations(), 0); assertEquals(serviceFilterContainer.Requests.get(0).Method, HttpConstants.PatchMethod); assertEquals(serviceFilterContainer.Requests.get(1).Method, HttpConstants.DeleteMethod); return; } assertTrue(false); } public void testDeleteCollapseUpdateWhenUpdateIsInQueueOnOperationError() throws Throwable { MobileServiceLocalStoreMock store = new MobileServiceLocalStoreMock(); final ServiceFilterContainer serviceFilterContainer = new ServiceFilterContainer(); final ThrownExceptionFlag thrownExceptionFlag = new ThrownExceptionFlag(); thrownExceptionFlag.Thrown = true; MobileServiceClient client = new MobileServiceClient(appUrl, getInstrumentation().getTargetContext()); Function<ServiceFilterRequest, Void> onHandleRequest = new Function<ServiceFilterRequest, Void>() { public Void apply(ServiceFilterRequest request) { try { if (thrownExceptionFlag.Thrown) { throw new Exception(); } } catch (Exception e) { serviceFilterContainer.Exception = e; } return null; } }; client = client.withFilter( getTestFilter(serviceFilterContainer, onHandleRequest, "{\"id\":\"abc\",\"String\":\"Hey\"}")); client.getSyncContext().initialize(store, new SimpleSyncHandler()).get(); MobileServiceSyncTable<StringIdType> table = client.getSyncTable(StringIdType.class); StringIdType item = new StringIdType(); item.Id = "abc"; item.String = "what?"; table.update(item).get(); assertEquals(client.getSyncContext().getPendingOperations(), 1); try { client.getSyncContext().push().get(); } catch (Exception ex) { table.delete(item).get(); thrownExceptionFlag.Thrown = false; client.getSyncContext().push().get(); assertEquals(client.getSyncContext().getPendingOperations(), 0); assertEquals(serviceFilterContainer.Requests.get(0).Method, HttpConstants.PatchMethod); assertEquals(serviceFilterContainer.Requests.get(1).Method, HttpConstants.DeleteMethod); return; } assertTrue(false); } public void testInsertThrowsWhenUpdateIsInQueueOnNewtorkError() throws Throwable { MobileServiceLocalStoreMock store = new MobileServiceLocalStoreMock(); final ServiceFilterContainer serviceFilterContainer = new ServiceFilterContainer(); final ThrownExceptionFlag thrownExceptionFlag = new ThrownExceptionFlag(); thrownExceptionFlag.Thrown = true; MobileServiceClient client = new MobileServiceClient(appUrl, getInstrumentation().getTargetContext()); final MobileServiceException innerException = new MobileServiceException(new IOException()); Function<ServiceFilterRequest, Void> onHandleRequest = new Function<ServiceFilterRequest, Void>() { public Void apply(ServiceFilterRequest request) { try { if (thrownExceptionFlag.Thrown) { throw innerException; } } catch (Exception e) { serviceFilterContainer.Exception = e; } return null; } }; client = client.withFilter( getTestFilter(serviceFilterContainer, onHandleRequest, "{\"id\":\"abc\",\"String\":\"Hey\"}")); client.getSyncContext().initialize(store, new SimpleSyncHandler()).get(); MobileServiceSyncTable<StringIdType> table = client.getSyncTable(StringIdType.class); StringIdType item = new StringIdType(); item.Id = "abc"; item.String = "what?"; table.update(item).get(); assertEquals(client.getSyncContext().getPendingOperations(), 1); try { client.getSyncContext().push().get(); } catch (Exception ex) { try { table.insert(item).get(); } catch (Exception ex2) { assertEquals(client.getSyncContext().getPendingOperations(), 1); assertEquals(serviceFilterContainer.Requests.get(0).Method, HttpConstants.PatchMethod); assertEquals(ex2.getMessage(), "java.lang.IllegalStateException: An update operation on the item is already in the queue."); return; } } assertTrue(false); } public void testInsertThrowsWhenUpdateIsInQueueOnAuthenticationError() throws Throwable { MobileServiceLocalStoreMock store = new MobileServiceLocalStoreMock(); final ServiceFilterContainer serviceFilterContainer = new ServiceFilterContainer(); final ThrownExceptionFlag thrownExceptionFlag = new ThrownExceptionFlag(); thrownExceptionFlag.Thrown = true; MobileServiceClient client = new MobileServiceClient(appUrl, getInstrumentation().getTargetContext()); ServiceFilterResponseMock response = new ServiceFilterResponseMock(); response.setStatus(new StatusLine(Protocol.HTTP_2, 401, "")); final MobileServiceException innerException = new MobileServiceException("", response); Function<ServiceFilterRequest, Void> onHandleRequest = new Function<ServiceFilterRequest, Void>() { public Void apply(ServiceFilterRequest request) { try { if (thrownExceptionFlag.Thrown) { throw innerException; } } catch (Exception e) { serviceFilterContainer.Exception = e; } return null; } }; client = client.withFilter( getTestFilter(serviceFilterContainer, onHandleRequest, "{\"id\":\"abc\",\"String\":\"Hey\"}")); client.getSyncContext().initialize(store, new SimpleSyncHandler()).get(); MobileServiceSyncTable<StringIdType> table = client.getSyncTable(StringIdType.class); StringIdType item = new StringIdType(); item.Id = "abc"; item.String = "what?"; table.update(item).get(); assertEquals(client.getSyncContext().getPendingOperations(), 1); try { client.getSyncContext().push().get(); } catch (Exception ex) { try { table.insert(item).get(); } catch (Exception ex2) { assertEquals(client.getSyncContext().getPendingOperations(), 1); assertEquals(serviceFilterContainer.Requests.get(0).Method, HttpConstants.PatchMethod); assertEquals(ex2.getMessage(), "java.lang.IllegalStateException: An update operation on the item is already in the queue."); return; } } assertTrue(false); } public void testInsertThrowsWhenUpdateIsInQueueOnOperationError() throws Throwable { MobileServiceLocalStoreMock store = new MobileServiceLocalStoreMock(); final ServiceFilterContainer serviceFilterContainer = new ServiceFilterContainer(); final ThrownExceptionFlag thrownExceptionFlag = new ThrownExceptionFlag(); thrownExceptionFlag.Thrown = true; MobileServiceClient client = new MobileServiceClient(appUrl, getInstrumentation().getTargetContext()); Function<ServiceFilterRequest, Void> onHandleRequest = new Function<ServiceFilterRequest, Void>() { public Void apply(ServiceFilterRequest request) { try { if (thrownExceptionFlag.Thrown) { throw new Exception(); } } catch (Exception e) { serviceFilterContainer.Exception = e; } return null; } }; client = client.withFilter( getTestFilter(serviceFilterContainer, onHandleRequest, "{\"id\":\"abc\",\"String\":\"Hey\"}")); client.getSyncContext().initialize(store, new SimpleSyncHandler()).get(); MobileServiceSyncTable<StringIdType> table = client.getSyncTable(StringIdType.class); StringIdType item = new StringIdType(); item.Id = "abc"; item.String = "what?"; table.update(item).get(); assertEquals(client.getSyncContext().getPendingOperations(), 1); try { client.getSyncContext().push().get(); } catch (Exception ex) { try { table.insert(item).get(); } catch (Exception ex2) { assertEquals(client.getSyncContext().getPendingOperations(), 1); assertEquals(serviceFilterContainer.Requests.get(0).Method, HttpConstants.PatchMethod); assertEquals(ex2.getMessage(), "java.lang.IllegalStateException: An update operation on the item is already in the queue."); return; } } assertTrue(false); } public void testDeleteThrowsWhenDeleteIsInQueueOnNewtorkError() throws Throwable { MobileServiceLocalStoreMock store = new MobileServiceLocalStoreMock(); final ServiceFilterContainer serviceFilterContainer = new ServiceFilterContainer(); final ThrownExceptionFlag thrownExceptionFlag = new ThrownExceptionFlag(); thrownExceptionFlag.Thrown = true; MobileServiceClient client = new MobileServiceClient(appUrl, getInstrumentation().getTargetContext()); final MobileServiceException innerException = new MobileServiceException(new IOException()); Function<ServiceFilterRequest, Void> onHandleRequest = new Function<ServiceFilterRequest, Void>() { public Void apply(ServiceFilterRequest request) { try { if (thrownExceptionFlag.Thrown) { throw innerException; } } catch (Exception e) { serviceFilterContainer.Exception = e; } return null; } }; client = client.withFilter( getTestFilter(serviceFilterContainer, onHandleRequest, "{\"id\":\"abc\",\"String\":\"Hey\"}")); client.getSyncContext().initialize(store, new SimpleSyncHandler()).get(); MobileServiceSyncTable<StringIdType> table = client.getSyncTable(StringIdType.class); StringIdType item = new StringIdType(); item.Id = "abc"; item.String = "what?"; table.delete(item).get(); assertEquals(client.getSyncContext().getPendingOperations(), 1); try { client.getSyncContext().push().get(); } catch (Exception ex) { try { table.delete(item).get(); } catch (Exception ex2) { assertEquals(client.getSyncContext().getPendingOperations(), 1); assertEquals(serviceFilterContainer.Requests.get(0).Method, HttpConstants.DeleteMethod); assertEquals(ex2.getMessage(), "java.lang.IllegalStateException: A delete operation on the item is already in the queue."); return; } } assertTrue(false); } public void testDeleteThrowsWhenDeleteIsInQueueOnAuthenticationError() throws Throwable { MobileServiceLocalStoreMock store = new MobileServiceLocalStoreMock(); final ServiceFilterContainer serviceFilterContainer = new ServiceFilterContainer(); final ThrownExceptionFlag thrownExceptionFlag = new ThrownExceptionFlag(); thrownExceptionFlag.Thrown = true; MobileServiceClient client = new MobileServiceClient(appUrl, getInstrumentation().getTargetContext()); ServiceFilterResponseMock response = new ServiceFilterResponseMock(); response.setStatus(new StatusLine(Protocol.HTTP_2, 401, "")); final MobileServiceException innerException = new MobileServiceException("", response); Function<ServiceFilterRequest, Void> onHandleRequest = new Function<ServiceFilterRequest, Void>() { public Void apply(ServiceFilterRequest request) { try { if (thrownExceptionFlag.Thrown) { throw innerException; } } catch (Exception e) { serviceFilterContainer.Exception = e; } return null; } }; client = client.withFilter( getTestFilter(serviceFilterContainer, onHandleRequest, "{\"id\":\"abc\",\"String\":\"Hey\"}")); client.getSyncContext().initialize(store, new SimpleSyncHandler()).get(); MobileServiceSyncTable<StringIdType> table = client.getSyncTable(StringIdType.class); StringIdType item = new StringIdType(); item.Id = "abc"; item.String = "what?"; table.delete(item).get(); assertEquals(client.getSyncContext().getPendingOperations(), 1); try { client.getSyncContext().push().get(); } catch (Exception ex) { try { table.delete(item).get(); } catch (Exception ex2) { assertEquals(client.getSyncContext().getPendingOperations(), 1); assertEquals(serviceFilterContainer.Requests.get(0).Method, HttpConstants.DeleteMethod); assertEquals(ex2.getMessage(), "java.lang.IllegalStateException: A delete operation on the item is already in the queue."); return; } } assertTrue(false); } public void testDeleteThrowsWhenDeleteIsInQueueOnOperationError() throws Throwable { MobileServiceLocalStoreMock store = new MobileServiceLocalStoreMock(); final ServiceFilterContainer serviceFilterContainer = new ServiceFilterContainer(); final ThrownExceptionFlag thrownExceptionFlag = new ThrownExceptionFlag(); thrownExceptionFlag.Thrown = true; MobileServiceClient client = new MobileServiceClient(appUrl, getInstrumentation().getTargetContext()); Function<ServiceFilterRequest, Void> onHandleRequest = new Function<ServiceFilterRequest, Void>() { public Void apply(ServiceFilterRequest request) { try { if (thrownExceptionFlag.Thrown) { throw new Exception(); } } catch (Exception e) { serviceFilterContainer.Exception = e; } return null; } }; client = client.withFilter( getTestFilter(serviceFilterContainer, onHandleRequest, "{\"id\":\"abc\",\"String\":\"Hey\"}")); client.getSyncContext().initialize(store, new SimpleSyncHandler()).get(); MobileServiceSyncTable<StringIdType> table = client.getSyncTable(StringIdType.class); StringIdType item = new StringIdType(); item.Id = "abc"; item.String = "what?"; table.delete(item).get(); assertEquals(client.getSyncContext().getPendingOperations(), 1); try { client.getSyncContext().push().get(); } catch (Exception ex) { try { table.delete(item).get(); } catch (Exception ex2) { assertEquals(client.getSyncContext().getPendingOperations(), 1); assertEquals(serviceFilterContainer.Requests.get(0).Method, HttpConstants.DeleteMethod); assertEquals(ex2.getMessage(), "java.lang.IllegalStateException: A delete operation on the item is already in the queue."); return; } } assertTrue(false); } public void testInsertThrowsWhenDeleteIsInQueueOnNewtorkError() throws Throwable { MobileServiceLocalStoreMock store = new MobileServiceLocalStoreMock(); final ServiceFilterContainer serviceFilterContainer = new ServiceFilterContainer(); final ThrownExceptionFlag thrownExceptionFlag = new ThrownExceptionFlag(); thrownExceptionFlag.Thrown = true; MobileServiceClient client = new MobileServiceClient(appUrl, getInstrumentation().getTargetContext()); final MobileServiceException innerException = new MobileServiceException(new IOException()); Function<ServiceFilterRequest, Void> onHandleRequest = new Function<ServiceFilterRequest, Void>() { public Void apply(ServiceFilterRequest request) { try { if (thrownExceptionFlag.Thrown) { throw innerException; } } catch (Exception e) { serviceFilterContainer.Exception = e; } return null; } }; client = client.withFilter( getTestFilter(serviceFilterContainer, onHandleRequest, "{\"id\":\"abc\",\"String\":\"Hey\"}")); client.getSyncContext().initialize(store, new SimpleSyncHandler()).get(); MobileServiceSyncTable<StringIdType> table = client.getSyncTable(StringIdType.class); StringIdType item = new StringIdType(); item.Id = "abc"; item.String = "what?"; table.delete(item).get(); assertEquals(client.getSyncContext().getPendingOperations(), 1); try { client.getSyncContext().push().get(); } catch (Exception ex) { try { table.insert(item).get(); } catch (Exception ex2) { assertEquals(client.getSyncContext().getPendingOperations(), 1); assertEquals(serviceFilterContainer.Requests.get(0).Method, HttpConstants.DeleteMethod); assertEquals(ex2.getMessage(), "java.lang.IllegalStateException: A delete operation on the item is already in the queue."); return; } } assertTrue(false); } public void testInsertThrowsWhenDeleteIsInQueueOnAuthenticationError() throws Throwable { MobileServiceLocalStoreMock store = new MobileServiceLocalStoreMock(); final ServiceFilterContainer serviceFilterContainer = new ServiceFilterContainer(); final ThrownExceptionFlag thrownExceptionFlag = new ThrownExceptionFlag(); thrownExceptionFlag.Thrown = true; MobileServiceClient client = new MobileServiceClient(appUrl, getInstrumentation().getTargetContext()); ServiceFilterResponseMock response = new ServiceFilterResponseMock(); response.setStatus((new StatusLine(Protocol.HTTP_2, 401, ""))); final MobileServiceException innerException = new MobileServiceException("", response); Function<ServiceFilterRequest, Void> onHandleRequest = new Function<ServiceFilterRequest, Void>() { public Void apply(ServiceFilterRequest request) { try { if (thrownExceptionFlag.Thrown) { throw innerException; } } catch (Exception e) { serviceFilterContainer.Exception = e; } return null; } }; client = client.withFilter( getTestFilter(serviceFilterContainer, onHandleRequest, "{\"id\":\"abc\",\"String\":\"Hey\"}")); client.getSyncContext().initialize(store, new SimpleSyncHandler()).get(); MobileServiceSyncTable<StringIdType> table = client.getSyncTable(StringIdType.class); StringIdType item = new StringIdType(); item.Id = "abc"; item.String = "what?"; table.delete(item).get(); assertEquals(client.getSyncContext().getPendingOperations(), 1); try { client.getSyncContext().push().get(); } catch (Exception ex) { try { table.insert(item).get(); } catch (Exception ex2) { assertEquals(client.getSyncContext().getPendingOperations(), 1); assertEquals(serviceFilterContainer.Requests.get(0).Method, HttpConstants.DeleteMethod); assertEquals(ex2.getMessage(), "java.lang.IllegalStateException: A delete operation on the item is already in the queue."); return; } } assertTrue(false); } public void testInsertThrowsWhenDeleteIsInQueueOnOperationError() throws Throwable { MobileServiceLocalStoreMock store = new MobileServiceLocalStoreMock(); final ServiceFilterContainer serviceFilterContainer = new ServiceFilterContainer(); final ThrownExceptionFlag thrownExceptionFlag = new ThrownExceptionFlag(); thrownExceptionFlag.Thrown = true; MobileServiceClient client = new MobileServiceClient(appUrl, getInstrumentation().getTargetContext()); Function<ServiceFilterRequest, Void> onHandleRequest = new Function<ServiceFilterRequest, Void>() { public Void apply(ServiceFilterRequest request) { try { if (thrownExceptionFlag.Thrown) { throw new Exception(); } } catch (Exception e) { serviceFilterContainer.Exception = e; } return null; } }; client = client.withFilter( getTestFilter(serviceFilterContainer, onHandleRequest, "{\"id\":\"abc\",\"String\":\"Hey\"}")); client.getSyncContext().initialize(store, new SimpleSyncHandler()).get(); MobileServiceSyncTable<StringIdType> table = client.getSyncTable(StringIdType.class); StringIdType item = new StringIdType(); item.Id = "abc"; item.String = "what?"; table.delete(item).get(); assertEquals(client.getSyncContext().getPendingOperations(), 1); try { client.getSyncContext().push().get(); } catch (Exception ex) { try { table.insert(item).get(); } catch (Exception ex2) { assertEquals(client.getSyncContext().getPendingOperations(), 1); assertEquals(serviceFilterContainer.Requests.get(0).Method, HttpConstants.DeleteMethod); assertEquals(ex2.getMessage(), "java.lang.IllegalStateException: A delete operation on the item is already in the queue."); return; } } assertTrue(false); } public void testUpdateThrowsWhenDeleteIsInQueueOnNewtorkError() throws Throwable { MobileServiceLocalStoreMock store = new MobileServiceLocalStoreMock(); final ServiceFilterContainer serviceFilterContainer = new ServiceFilterContainer(); final ThrownExceptionFlag thrownExceptionFlag = new ThrownExceptionFlag(); thrownExceptionFlag.Thrown = true; MobileServiceClient client = new MobileServiceClient(appUrl, getInstrumentation().getTargetContext()); final MobileServiceException innerException = new MobileServiceException(new IOException()); Function<ServiceFilterRequest, Void> onHandleRequest = new Function<ServiceFilterRequest, Void>() { public Void apply(ServiceFilterRequest request) { try { if (thrownExceptionFlag.Thrown) { throw innerException; } } catch (Exception e) { serviceFilterContainer.Exception = e; } return null; } }; client = client.withFilter( getTestFilter(serviceFilterContainer, onHandleRequest, "{\"id\":\"abc\",\"String\":\"Hey\"}")); client.getSyncContext().initialize(store, new SimpleSyncHandler()).get(); MobileServiceSyncTable<StringIdType> table = client.getSyncTable(StringIdType.class); StringIdType item = new StringIdType(); item.Id = "abc"; item.String = "what?"; table.delete(item).get(); assertEquals(client.getSyncContext().getPendingOperations(), 1); try { client.getSyncContext().push().get(); } catch (Exception ex) { try { table.update(item).get(); } catch (Exception ex2) { assertEquals(client.getSyncContext().getPendingOperations(), 1); assertEquals(serviceFilterContainer.Requests.get(0).Method, HttpConstants.DeleteMethod); assertEquals(ex2.getMessage(), "java.lang.IllegalStateException: A delete operation on the item is already in the queue."); return; } } assertTrue(false); } public void testUpdateThrowsWhenDeleteIsInQueueOnAuthenticationError() throws Throwable { MobileServiceLocalStoreMock store = new MobileServiceLocalStoreMock(); final ServiceFilterContainer serviceFilterContainer = new ServiceFilterContainer(); final ThrownExceptionFlag thrownExceptionFlag = new ThrownExceptionFlag(); thrownExceptionFlag.Thrown = true; MobileServiceClient client = new MobileServiceClient(appUrl, getInstrumentation().getTargetContext()); ServiceFilterResponseMock response = new ServiceFilterResponseMock(); response.setStatus((new StatusLine(Protocol.HTTP_2, 401, ""))); final MobileServiceException innerException = new MobileServiceException("", response); Function<ServiceFilterRequest, Void> onHandleRequest = new Function<ServiceFilterRequest, Void>() { public Void apply(ServiceFilterRequest request) { try { if (thrownExceptionFlag.Thrown) { throw innerException; } } catch (Exception e) { serviceFilterContainer.Exception = e; } return null; } }; client = client.withFilter( getTestFilter(serviceFilterContainer, onHandleRequest, "{\"id\":\"abc\",\"String\":\"Hey\"}")); client.getSyncContext().initialize(store, new SimpleSyncHandler()).get(); MobileServiceSyncTable<StringIdType> table = client.getSyncTable(StringIdType.class); StringIdType item = new StringIdType(); item.Id = "abc"; item.String = "what?"; table.delete(item).get(); assertEquals(client.getSyncContext().getPendingOperations(), 1); try { client.getSyncContext().push().get(); } catch (Exception ex) { try { table.update(item).get(); } catch (Exception ex2) { assertEquals(client.getSyncContext().getPendingOperations(), 1); assertEquals(serviceFilterContainer.Requests.get(0).Method, HttpConstants.DeleteMethod); assertEquals(ex2.getMessage(), "java.lang.IllegalStateException: A delete operation on the item is already in the queue."); return; } } assertTrue(false); } public void testUpdateThrowsWhenDeleteIsInQueueOnOperationError() throws Throwable { MobileServiceLocalStoreMock store = new MobileServiceLocalStoreMock(); final ServiceFilterContainer serviceFilterContainer = new ServiceFilterContainer(); final ThrownExceptionFlag thrownExceptionFlag = new ThrownExceptionFlag(); thrownExceptionFlag.Thrown = true; MobileServiceClient client = new MobileServiceClient(appUrl, getInstrumentation().getTargetContext()); Function<ServiceFilterRequest, Void> onHandleRequest = new Function<ServiceFilterRequest, Void>() { public Void apply(ServiceFilterRequest request) { try { if (thrownExceptionFlag.Thrown) { throw new Exception(); } } catch (Exception e) { serviceFilterContainer.Exception = e; } return null; } }; client = client.withFilter( getTestFilter(serviceFilterContainer, onHandleRequest, "{\"id\":\"abc\",\"String\":\"Hey\"}")); client.getSyncContext().initialize(store, new SimpleSyncHandler()).get(); MobileServiceSyncTable<StringIdType> table = client.getSyncTable(StringIdType.class); StringIdType item = new StringIdType(); item.Id = "abc"; item.String = "what?"; table.delete(item).get(); assertEquals(client.getSyncContext().getPendingOperations(), 1); try { client.getSyncContext().push().get(); } catch (Exception ex) { try { table.update(item).get(); } catch (Exception ex2) { assertEquals(client.getSyncContext().getPendingOperations(), 1); assertEquals(serviceFilterContainer.Requests.get(0).Method, HttpConstants.DeleteMethod); assertEquals(ex2.getMessage(), "java.lang.IllegalStateException: A delete operation on the item is already in the queue."); return; } } assertTrue(false); } //Test collapse login public void testDeleteCancelsUpdateWhenUpdateIsInQueue() throws Throwable { CustomFunctionTwoParameters<MobileServiceSyncTable<StringIdType>, StringIdType, Void> firstOperationOnItem1 = new CustomFunctionTwoParameters<MobileServiceSyncTable<StringIdType>, StringIdType, Void>() { @Override public Void apply(MobileServiceSyncTable<StringIdType> table, StringIdType item) throws Exception { try { table.update(item).get(); } catch (Exception e) { throw e; } return null; } }; CustomFunctionTwoParameters<MobileServiceSyncTable<StringIdType>, StringIdType, Void> operationOnItem2 = new CustomFunctionTwoParameters<MobileServiceSyncTable<StringIdType>, StringIdType, Void>() { @Override public Void apply(MobileServiceSyncTable<StringIdType> table, StringIdType item) throws Exception { try { table.insert(item).get(); } catch (Exception e) { throw e; } return null; } }; CustomFunctionTwoParameters<MobileServiceSyncTable<StringIdType>, StringIdType, Void> secondOperationOnItem1 = new CustomFunctionTwoParameters<MobileServiceSyncTable<StringIdType>, StringIdType, Void>() { @Override public Void apply(MobileServiceSyncTable<StringIdType> table, StringIdType item) throws Exception { try { table.delete(item).get(); } catch (Exception e) { throw e; } return null; } }; CustomFunctionTwoParameters<ServiceFilterRequest, Integer, Void> assertRequest = new CustomFunctionTwoParameters<ServiceFilterRequest, Integer, Void>() { @Override public Void apply(ServiceFilterRequest serviceFilterRequest, Integer executed) { if (executed == 1) // order is maintained by doing insert first // and delete after that. This means first // update was cancelled, not the second one. { assertEquals(serviceFilterRequest.getMethod(), HttpConstants.PostMethod); } else { assertEquals(serviceFilterRequest.getMethod(), HttpConstants.DeleteMethod); } return null; } }; this.TestCollapseCancel(firstOperationOnItem1, operationOnItem2, secondOperationOnItem1, assertRequest); } public void testDeleteThrowsWhenDeleteIsInQueue() throws Throwable { CustomFunctionTwoParameters<MobileServiceSyncTable<StringIdType>, StringIdType, Void> firstOperation = new CustomFunctionTwoParameters<MobileServiceSyncTable<StringIdType>, StringIdType, Void>() { @Override public Void apply(MobileServiceSyncTable<StringIdType> table, StringIdType item) throws Exception { try { table.delete(item).get(); } catch (Exception e) { throw e; } return null; } }; CustomFunctionTwoParameters<MobileServiceSyncTable<StringIdType>, StringIdType, Void> secondOperation = new CustomFunctionTwoParameters<MobileServiceSyncTable<StringIdType>, StringIdType, Void>() { @Override public Void apply(MobileServiceSyncTable<StringIdType> table, StringIdType item) throws Exception { try { table.delete(item).get(); } catch (Exception e) { throw e; } return null; } }; this.TestCollapseThrow(firstOperation, secondOperation); } public void testInsertThrowsWhenUpdateIsInQueue() throws Throwable { CustomFunctionTwoParameters<MobileServiceSyncTable<StringIdType>, StringIdType, Void> firstOperation = new CustomFunctionTwoParameters<MobileServiceSyncTable<StringIdType>, StringIdType, Void>() { @Override public Void apply(MobileServiceSyncTable<StringIdType> table, StringIdType item) throws Exception { try { table.update(item).get(); } catch (Exception e) { throw e; } return null; } }; CustomFunctionTwoParameters<MobileServiceSyncTable<StringIdType>, StringIdType, Void> secondOperation = new CustomFunctionTwoParameters<MobileServiceSyncTable<StringIdType>, StringIdType, Void>() { @Override public Void apply(MobileServiceSyncTable<StringIdType> table, StringIdType item) throws Exception { try { table.insert(item).get(); } catch (Exception e) { throw e; } return null; } }; this.TestCollapseThrow(firstOperation, secondOperation); } public void testInsertThrowsWhenInsertIsInQueue() throws Throwable { CustomFunctionTwoParameters<MobileServiceSyncTable<StringIdType>, StringIdType, Void> firstOperation = new CustomFunctionTwoParameters<MobileServiceSyncTable<StringIdType>, StringIdType, Void>() { @Override public Void apply(MobileServiceSyncTable<StringIdType> table, StringIdType item) throws Exception { try { table.insert(item).get(); } catch (Exception e) { throw e; } return null; } }; CustomFunctionTwoParameters<MobileServiceSyncTable<StringIdType>, StringIdType, Void> secondOperation = new CustomFunctionTwoParameters<MobileServiceSyncTable<StringIdType>, StringIdType, Void>() { @Override public Void apply(MobileServiceSyncTable<StringIdType> table, StringIdType item) throws Exception { try { table.insert(item).get(); } catch (Exception e) { throw e; } return null; } }; this.TestCollapseThrow(firstOperation, secondOperation); } public void testUpdateThrowsWhenDeleteIsInQueue() throws Throwable { CustomFunctionTwoParameters<MobileServiceSyncTable<StringIdType>, StringIdType, Void> firstOperation = new CustomFunctionTwoParameters<MobileServiceSyncTable<StringIdType>, StringIdType, Void>() { @Override public Void apply(MobileServiceSyncTable<StringIdType> table, StringIdType item) throws Exception { try { table.delete(item).get(); } catch (Exception e) { throw e; } return null; } }; CustomFunctionTwoParameters<MobileServiceSyncTable<StringIdType>, StringIdType, Void> secondOperation = new CustomFunctionTwoParameters<MobileServiceSyncTable<StringIdType>, StringIdType, Void>() { @Override public Void apply(MobileServiceSyncTable<StringIdType> table, StringIdType item) throws Exception { try { table.update(item).get(); } catch (Exception e) { throw e; } return null; } }; this.TestCollapseThrow(firstOperation, secondOperation); } public void testUpdateCancelsSecondUpdateWhenInsertIsInQueue() throws Throwable { CustomFunctionTwoParameters<MobileServiceSyncTable<StringIdType>, StringIdType, Void> firstOperationOnItem1 = new CustomFunctionTwoParameters<MobileServiceSyncTable<StringIdType>, StringIdType, Void>() { @Override public Void apply(MobileServiceSyncTable<StringIdType> table, StringIdType item) throws Exception { try { table.insert(item).get(); } catch (Exception e) { throw e; } return null; } }; CustomFunctionTwoParameters<MobileServiceSyncTable<StringIdType>, StringIdType, Void> operationOnItem2 = new CustomFunctionTwoParameters<MobileServiceSyncTable<StringIdType>, StringIdType, Void>() { @Override public Void apply(MobileServiceSyncTable<StringIdType> table, StringIdType item) throws Exception { try { table.delete(item).get(); } catch (Exception e) { throw e; } return null; } }; CustomFunctionTwoParameters<MobileServiceSyncTable<StringIdType>, StringIdType, Void> secondOperationOnItem1 = new CustomFunctionTwoParameters<MobileServiceSyncTable<StringIdType>, StringIdType, Void>() { @Override public Void apply(MobileServiceSyncTable<StringIdType> table, StringIdType item) throws Exception { try { table.update(item).get(); } catch (Exception e) { throw e; } return null; } }; CustomFunctionTwoParameters<ServiceFilterRequest, Integer, Void> assertRequest = new CustomFunctionTwoParameters<ServiceFilterRequest, Integer, Void>() { @Override public Void apply(ServiceFilterRequest serviceFilterRequest, Integer executed) { if (executed == 1) // order is maintained by doing insert first // and delete after that. This means first // update was cancelled, not the second one. { assertEquals(serviceFilterRequest.getMethod(), HttpConstants.PostMethod); } else { assertEquals(serviceFilterRequest.getMethod(), HttpConstants.DeleteMethod); } return null; } }; this.TestCollapseCancel(firstOperationOnItem1, operationOnItem2, secondOperationOnItem1, assertRequest); } public void testPushIsAbortedOnNetworkError() throws Throwable { this.TestPushAbort(new IOException(), MobileServicePushStatus.CancelledByNetworkError); } public void testPushIsAbortedOnAuthenticationError() throws Throwable { // Create a mock response simulating an error ServiceFilterResponseMock response = new ServiceFilterResponseMock(); response.setStatus((new StatusLine(Protocol.HTTP_2, 401, ""))); MobileServiceException authError = new MobileServiceException("", response); TestPushAbort(authError, MobileServicePushStatus.CancelledByAuthenticationError); } private void TestCollapseCancel( CustomFunctionTwoParameters<MobileServiceSyncTable<StringIdType>, StringIdType, Void> firstOperationOnItem1, CustomFunctionTwoParameters<MobileServiceSyncTable<StringIdType>, StringIdType, Void> operationOnItem2, CustomFunctionTwoParameters<MobileServiceSyncTable<StringIdType>, StringIdType, Void> secondOperationOnItem1, final CustomFunctionTwoParameters<ServiceFilterRequest, Integer, Void> assertRequest) throws Throwable { MobileServiceLocalStoreMock store = new MobileServiceLocalStoreMock(); final ServiceFilterContainer serviceFilterContainer = new ServiceFilterContainer(); MobileServiceClient client = new MobileServiceClient(appUrl, getInstrumentation().getTargetContext()); Function<ServiceFilterRequest, Void> onHandleRequest = new Function<ServiceFilterRequest, Void>() { public Void apply(ServiceFilterRequest request) { try { assertRequest.apply(request, serviceFilterContainer.Requests.size()); } catch (Exception e) { // throw e; } return null; } }; client = client.withFilter( getTestFilter(serviceFilterContainer, onHandleRequest, "{\"id\":\"abc\",\"String\":\"Hey\"}")); client.getSyncContext().initialize(store, new SimpleSyncHandler()).get(); StringIdType item1 = new StringIdType(); item1.Id = "an id"; item1.String = "what?"; StringIdType item2 = new StringIdType(); item2.Id = "two"; item2.String = "this"; MobileServiceSyncTable<StringIdType> table = client.getSyncTable(StringIdType.class); firstOperationOnItem1.apply(table, item1); assertEquals(client.getSyncContext().getPendingOperations(), 1); operationOnItem2.apply(table, item2); assertEquals(client.getSyncContext().getPendingOperations(), 2); secondOperationOnItem1.apply(table, item1); assertEquals(client.getSyncContext().getPendingOperations(), 2); client.getSyncContext().push().get(); assertEquals(client.getSyncContext().getPendingOperations(), 0); assertEquals(serviceFilterContainer.Requests.size(), 2); // total two // operations // executed } private void TestCollapseThrow( CustomFunctionTwoParameters<MobileServiceSyncTable<StringIdType>, StringIdType, Void> firstOperation, CustomFunctionTwoParameters<MobileServiceSyncTable<StringIdType>, StringIdType, Void> secondOperation) throws Throwable { MobileServiceLocalStoreMock store = new MobileServiceLocalStoreMock(); MobileServiceClient client = new MobileServiceClient(appUrl, getInstrumentation().getTargetContext()); client = client.withFilter(getTestFilter()); client.getSyncContext().initialize(store, new SimpleSyncHandler()).get(); StringIdType item = new StringIdType(); item.Id = "an id"; item.String = "what?"; MobileServiceSyncTable<StringIdType> table = client.getSyncTable(StringIdType.class); firstOperation.apply(table, item); assertEquals(client.getSyncContext().getPendingOperations(), 1); try { secondOperation.apply(table, item); } catch (Exception e) { e.printStackTrace(); assertEquals(client.getSyncContext().getPendingOperations(), 1); return; } fail("Exception expected"); } private void TestPushAbort(final Exception toThrow, MobileServicePushStatus expectedStatus) throws Throwable { MobileServiceSyncHandlerMock operationHandler = new MobileServiceSyncHandlerMock(); final ThrownExceptionFlag thrownExceptionFlag = new ThrownExceptionFlag(); thrownExceptionFlag.Thrown = false; MobileServiceLocalStoreMock store = new MobileServiceLocalStoreMock(); final ServiceFilterContainer serviceFilterContainer = new ServiceFilterContainer(); MobileServiceClient client = new MobileServiceClient(appUrl, getInstrumentation().getTargetContext()); Function<ServiceFilterRequest, Void> onHandleRequest = new Function<ServiceFilterRequest, Void>() { public Void apply(ServiceFilterRequest request) { try { if (!thrownExceptionFlag.Thrown) { thrownExceptionFlag.Thrown = true; throw toThrow; } } catch (Exception e) { serviceFilterContainer.Exception = e; } return null; } }; client = client.withFilter( getTestFilter(serviceFilterContainer, onHandleRequest, "{\"id\":\"abc\",\"String\":\"Hey\"}")); client.getSyncContext().initialize(store, operationHandler).get(); StringIdType item = new StringIdType(); item.Id = "an id"; item.String = "what?"; MobileServiceSyncTable<StringIdType> table = client.getSyncTable(StringIdType.class); table.insert(item).get(); assertEquals(client.getSyncContext().getPendingOperations(), 1); try { client.getSyncContext().push().get(); fail("MobileServicePushFailedException expected"); return; } catch (Exception ex) { if (ex.getCause() instanceof MobileServicePushFailedException) { MobileServicePushFailedException mobileServicePushFailedException = (MobileServicePushFailedException) ex .getCause(); assertEquals(mobileServicePushFailedException.getPushCompletionResult().getStatus(), expectedStatus); assertEquals(mobileServicePushFailedException.getPushCompletionResult().getOperationErrors().size(), 0); } else { fail("MobileServicePushFailedException expected"); } } assertEquals(operationHandler.PushCompletionResult.getStatus(), expectedStatus); // the insert operation is still in queue assertEquals(client.getSyncContext().getPendingOperations(), 1); client.getSyncContext().push().get(); assertEquals(client.getSyncContext().getPendingOperations(), 0); assertEquals(operationHandler.PushCompletionResult.getStatus(), MobileServicePushStatus.Complete); } // Test Filter private ServiceFilter getTestFilter(String... content) { return getTestFilter(new ServiceFilterContainer(), 200, content); } // Test Filter private ServiceFilter getTestFilter(ServiceFilterContainer serviceFilterContainer, Function<ServiceFilterRequest, Void> onHandleRequest, String... content) { return getTestFilter(serviceFilterContainer, 200, onHandleRequest, true, content); } // Test Filter private ServiceFilter getTestFilter(ServiceFilterContainer serviceFilterContainer, String... content) { return getTestFilter(serviceFilterContainer, 200, content); } // Test Filter private ServiceFilter getTestFilter(ServiceFilterContainer serviceFilterContainer, final boolean getLastContentAsDefault, String... content) { return getTestFilter(serviceFilterContainer, 200, null, getLastContentAsDefault, content); } // Test Filter private ServiceFilter getTestFilter(ServiceFilterContainer serviceFilterContainer, int statusCode, String... content) { return getTestFilter(serviceFilterContainer, statusCode, null, true, content); } // Test Filter private ServiceFilter getTestFilter(final ServiceFilterContainer serviceFilterContainer, final int statusCode, final Function<ServiceFilterRequest, Void> onHandleRequest, final boolean getLastContentAsDefault, final String... contents) { return new ServiceFilter() { @Override public ListenableFuture<ServiceFilterResponse> handleRequest(ServiceFilterRequest request, NextServiceFilterCallback nextServiceFilterCallback) { // Create a mock response simulating an error ServiceFilterResponseMock response = new ServiceFilterResponseMock(); response.setStatus((new StatusLine(Protocol.HTTP_2, statusCode, ""))); String content = ""; if (contents.length > serviceFilterContainer.Requests.size()) { content = contents[serviceFilterContainer.Requests.size()]; } else { if (getLastContentAsDefault) { content = contents[contents.length - 1]; } else { content = "[]"; } } response.setContent(content); ServiceFilterRequestData serviceFilterRequestData = new ServiceFilterRequestData(); serviceFilterRequestData.Headers = request.getHeaders(); serviceFilterRequestData.Content = request.getContent(); serviceFilterRequestData.Url = request.getUrl(); serviceFilterRequestData.Method = request.getMethod(); serviceFilterContainer.Url = request.getUrl(); serviceFilterContainer.Requests.add(serviceFilterRequestData); if (onHandleRequest != null) { onHandleRequest.apply(request); } // create a mock request to replace the existing one ServiceFilterRequestMock requestMock = new ServiceFilterRequestMock(response); if (serviceFilterContainer.Exception != null) { requestMock.setExceptionToThrow(serviceFilterContainer.Exception); requestMock.setHasErrorOnExecute(true); // used exception serviceFilterContainer.Exception = null; } return nextServiceFilterCallback.onNext(requestMock); } }; } public class ServiceFilterContainer { public String Url; public List<ServiceFilterRequestData> Requests = new ArrayList<ServiceFilterRequestData>(); public Exception Exception; } public class ThrownExceptionFlag { public boolean Thrown; } public class ServiceFilterRequestData { public com.squareup.okhttp.Headers Headers; public String Content; public String Url; public String Method; public int Count; public String getHeaderValue(String headerName) { return this.Headers.get(headerName); } } }