/* * Copyright (c) 2015-present, Parse, LLC. * All rights reserved. * * This source code is licensed under the BSD-style license found in the * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. */ package com.parse; import org.junit.After; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; import org.junit.rules.TemporaryFolder; import java.util.Arrays; import java.util.Collections; import bolts.Task; import static junit.framework.Assert.assertNotNull; import static junit.framework.Assert.assertSame; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyBoolean; import static org.mockito.Matchers.anyList; import static org.mockito.Matchers.anyString; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; public class OfflineObjectStoreTest { private static final String PIN_NAME = "test"; @Rule public TemporaryFolder temporaryFolder = new TemporaryFolder(); @Rule public ExpectedException thrown = ExpectedException.none(); @Before public void setUp() { ParseObject.registerSubclass(ParseUser.class); } @After public void tearDown() { ParseObject.unregisterSubclass(ParseUser.class); Parse.setLocalDatastore(null); ParseCorePlugins.getInstance().reset(); } @Test public void testSetAsync() throws Exception { OfflineStore lds = mock(OfflineStore.class); when(lds.unpinAllObjectsAsync(anyString())).thenReturn(Task.<Void>forResult(null)); when(lds.pinAllObjectsAsync(anyString(), anyList(), anyBoolean())) .thenReturn(Task.forResult(null)); Parse.setLocalDatastore(lds); OfflineObjectStore<ParseUser> store = new OfflineObjectStore<>(ParseUser.class, PIN_NAME, null); ParseUser user = mock(ParseUser.class); ParseTaskUtils.wait(store.setAsync(user)); verify(lds, times(1)).unpinAllObjectsAsync(PIN_NAME); verify(user, times(1)).pinInBackground(PIN_NAME, false); } //region getAsync @Test public void testGetAsyncFromLDS() throws Exception { Parse.enableLocalDatastore(null); ParseUser user = mock(ParseUser.class); ParseQueryController queryController = mock(ParseQueryController.class); //noinspection unchecked when(queryController.findAsync( any(ParseQuery.State.class), any(ParseUser.class), any(Task.class)) ).thenReturn(Task.forResult(Collections.singletonList(user))); ParseCorePlugins.getInstance().registerQueryController(queryController); OfflineObjectStore<ParseUser> store = new OfflineObjectStore<>(ParseUser.class, PIN_NAME, null); ParseUser userAgain = ParseTaskUtils.wait(store.getAsync()); //noinspection unchecked verify(queryController, times(1)) .findAsync(any(ParseQuery.State.class), any(ParseUser.class), any(Task.class)); assertSame(user, userAgain); } @Test public void testGetAsyncFromLDSWithTooManyObjects() throws Exception { Parse.enableLocalDatastore(null); ParseQueryController queryController = mock(ParseQueryController.class); //noinspection unchecked when(queryController.findAsync( any(ParseQuery.State.class), any(ParseUser.class), any(Task.class)) ).thenReturn(Task.forResult(Arrays.asList(mock(ParseUser.class), mock(ParseUser.class)))); ParseCorePlugins.getInstance().registerQueryController(queryController); OfflineStore lds = mock(OfflineStore.class); when(lds.unpinAllObjectsAsync(anyString())).thenReturn(Task.<Void>forResult(null)); Parse.setLocalDatastore(lds); @SuppressWarnings("unchecked") ParseObjectStore<ParseUser> legacy = mock(ParseObjectStore.class); when(legacy.getAsync()).thenReturn(Task.<ParseUser>forResult(null)); OfflineObjectStore<ParseUser> store = new OfflineObjectStore<>(ParseUser.class, PIN_NAME, legacy); ParseUser user = ParseTaskUtils.wait(store.getAsync()); //noinspection unchecked verify(queryController, times(1)) .findAsync(any(ParseQuery.State.class), any(ParseUser.class), any(Task.class)); verify(lds, times(1)).unpinAllObjectsAsync(PIN_NAME); assertNull(user); } @Test public void testGetAsyncMigrate() throws Exception { Parse.enableLocalDatastore(null); ParseQueryController queryController = mock(ParseQueryController.class); //noinspection unchecked when(queryController.findAsync( any(ParseQuery.State.class), any(ParseUser.class), any(Task.class)) ).thenReturn(Task.forResult(null)); ParseCorePlugins.getInstance().registerQueryController(queryController); OfflineStore lds = mock(OfflineStore.class); when(lds.pinAllObjectsAsync(anyString(), anyList(), anyBoolean())) .thenReturn(Task.forResult(null)); when(lds.unpinAllObjectsAsync(anyString())).thenReturn(Task.<Void>forResult(null)); when(lds.pinAllObjectsAsync(anyString(), anyList(), anyBoolean())) .thenReturn(Task.<Void>forResult(null)); Parse.setLocalDatastore(lds); ParseUser user = mock(ParseUser.class); when(user.pinInBackground(anyString(), anyBoolean())).thenReturn(Task.<Void>forResult(null)); @SuppressWarnings("unchecked") ParseObjectStore<ParseUser> legacy = mock(ParseObjectStore.class); when(legacy.getAsync()).thenReturn(Task.forResult(user)); when(legacy.deleteAsync()).thenReturn(Task.<Void>forResult(null)); OfflineObjectStore<ParseUser> store = new OfflineObjectStore<>(ParseUser.class, PIN_NAME, legacy); ParseUser userAgain = ParseTaskUtils.wait(store.getAsync()); //noinspection unchecked verify(queryController, times(1)) .findAsync(any(ParseQuery.State.class), any(ParseUser.class), any(Task.class)); verify(legacy, times(1)).getAsync(); verify(legacy, times(1)).deleteAsync(); verify(lds, times(1)).unpinAllObjectsAsync(PIN_NAME); verify(user, times(1)).pinInBackground(PIN_NAME, false); assertNotNull(userAgain); assertSame(user, userAgain); } //endregion //region existsAsync @Test public void testExistsAsyncLDS() throws Exception { Parse.enableLocalDatastore(null); ParseQueryController queryController = mock(ParseQueryController.class); //noinspection unchecked when(queryController.countAsync( any(ParseQuery.State.class), any(ParseUser.class), any(Task.class)) ).thenReturn(Task.forResult(1)); ParseCorePlugins.getInstance().registerQueryController(queryController); OfflineObjectStore<ParseUser> store = new OfflineObjectStore<>(ParseUser.class, PIN_NAME, null); assertTrue(ParseTaskUtils.wait(store.existsAsync())); //noinspection unchecked verify(queryController, times(1)).countAsync( any(ParseQuery.State.class), any(ParseUser.class), any(Task.class)); } @Test public void testExistsAsyncLegacy() throws Exception { Parse.enableLocalDatastore(null); ParseQueryController queryController = mock(ParseQueryController.class); //noinspection unchecked when(queryController.countAsync( any(ParseQuery.State.class), any(ParseUser.class), any(Task.class)) ).thenReturn(Task.forResult(0)); ParseCorePlugins.getInstance().registerQueryController(queryController); @SuppressWarnings("unchecked") ParseObjectStore<ParseUser> legacy = mock(ParseObjectStore.class); when(legacy.existsAsync()).thenReturn(Task.forResult(true)); OfflineObjectStore<ParseUser> store = new OfflineObjectStore<>(ParseUser.class, PIN_NAME, legacy); assertTrue(ParseTaskUtils.wait(store.existsAsync())); //noinspection unchecked verify(queryController, times(1)).countAsync( any(ParseQuery.State.class), any(ParseUser.class), any(Task.class)); } //endregion //region deleteAsync @Test public void testDeleteAsync() throws Exception { OfflineStore lds = mock(OfflineStore.class); when(lds.unpinAllObjectsAsync(anyString())).thenReturn(Task.<Void>forResult(null)); Parse.setLocalDatastore(lds); @SuppressWarnings("unchecked") ParseObjectStore<ParseUser> legacy = mock(ParseObjectStore.class); when(legacy.deleteAsync()).thenReturn(Task.<Void>forResult(null)); OfflineObjectStore<ParseUser> store = new OfflineObjectStore<>(ParseUser.class, PIN_NAME, legacy); ParseTaskUtils.wait(store.deleteAsync()); verify(legacy, times(1)).deleteAsync(); verify(lds, times(1)).unpinAllObjectsAsync(PIN_NAME); } @Test public void testDeleteAsyncFailure() throws Exception { OfflineStore lds = mock(OfflineStore.class); when(lds.unpinAllObjectsAsync(anyString())) .thenReturn(Task.<Void>forError(new RuntimeException("failure"))); Parse.setLocalDatastore(lds); @SuppressWarnings("unchecked") ParseObjectStore<ParseUser> legacy = mock(ParseObjectStore.class); when(legacy.deleteAsync()).thenReturn(Task.<Void>forResult(null)); OfflineObjectStore<ParseUser> store = new OfflineObjectStore<>(ParseUser.class, PIN_NAME, legacy); thrown.expect(RuntimeException.class); ParseTaskUtils.wait(store.deleteAsync()); verify(legacy, times(1)).deleteAsync(); } //endregion }