private void buildSyncConf() { // the rest of Sync logic ... SyncCredentials credentials = SyncCredentials.usernamePassword("username", "password"); final String urlAuth = "http://objectserver.realm.io:9080/auth"; final String url = "realm://objectserver.realm.io/default"; SyncUser.loginAsync(credentials, urlAuth, new SyncUser.Callback<SyncUser>() { @Override public void onSuccess(SyncUser user) { SyncConfiguration secureConfig = new SyncConfiguration.Builder(user, url).build(); Realm realm = Realm.getInstance(secureConfig); // ... } @Override public void onError(ObjectServerError error) {} }); }
@Test public void downloadProgressListener_changesOnly() { final CountDownLatch allChangesDownloaded = new CountDownLatch(1); SyncUser userWithData = UserFactory.createUniqueUser(Constants.AUTH_URL); SyncConfiguration userWithDataConfig = configFactory.createSyncConfigurationBuilder(userWithData, Constants.USER_REALM) .build(); URI serverUrl = createRemoteData(userWithDataConfig); SyncUser adminUser = UserFactory.createAdminUser(Constants.AUTH_URL); final SyncConfiguration config = configFactory.createSyncConfigurationBuilder(adminUser, serverUrl.toString()).build(); Realm realm = Realm.getInstance(config); SyncSession session = SyncManager.getSession(config); session.addDownloadProgressListener(ProgressMode.CURRENT_CHANGES, new ProgressListener() { @Override public void onChange(Progress progress) { if (progress.isTransferComplete()) { assertTransferComplete(progress, true); assertEquals(TEST_SIZE, getStoreTestDataSize(config)); allChangesDownloaded.countDown(); } } }); TestHelper.awaitOrFail(allChangesDownloaded); realm.close(); }
@Test public void uploadProgressListener_changesOnly() { final CountDownLatch allChangeUploaded = new CountDownLatch(1); SyncConfiguration config = createSyncConfig(); Realm realm = Realm.getInstance(config); writeSampleData(realm); SyncSession session = SyncManager.getSession(config); session.addUploadProgressListener(ProgressMode.CURRENT_CHANGES, new ProgressListener() { @Override public void onChange(Progress progress) { if (progress.isTransferComplete()) { assertTransferComplete(progress, true); allChangeUploaded.countDown(); } } }); TestHelper.awaitOrFail(allChangeUploaded); realm.close(); }
@Test public void uploadListener_keepIncreasingInSize() { SyncConfiguration config = createSyncConfig(); Realm realm = Realm.getInstance(config); SyncSession session = SyncManager.getSession(config); for (int i = 0; i < 10; i++) { final CountDownLatch changesUploaded = new CountDownLatch(1); writeSampleData(realm); final int testNo = i; session.addUploadProgressListener(ProgressMode.CURRENT_CHANGES, new ProgressListener() { @Override public void onChange(Progress progress) { RealmLog.info("Test %s -> %s", Integer.toString(testNo), progress.toString()); if (progress.isTransferComplete()) { assertTransferComplete(progress, true); changesUploaded.countDown(); } } }); TestHelper.awaitOrFail(changesUploaded); } realm.close(); }
@Override protected void run() { user = UserFactory.getInstance().loginWithDefaultUser(Constants.AUTH_URL); String realmUrl = Constants.SYNC_SERVER_URL; final SyncConfiguration syncConfig = new SyncConfiguration.Builder(user, realmUrl) .directory(getService().getRoot()) .build(); getService().setRealm(Realm.getInstance(syncConfig)); Realm realm = getService().getRealm(); realm.beginTransaction(); ProcessInfo processInfo = realm.createObject(ProcessInfo.class); processInfo.setName("Background_Process1"); processInfo.setPid(android.os.Process.myPid()); processInfo.setThreadId(Thread.currentThread().getId()); realm.commitTransaction(); // FIXME: If we close the Realm here, the data won't be able to synced to the main process. Is it a bug // in sync client which stops too early? // Realm is currently configured with stop_immediately. This means the sync session is closed as soon as // the last realm instance is closed. Not doing this would make the Realm lifecycle really // unpredictable. We should have an easy way to wait for all changes to be uploaded though. // Perhaps SyncSession.uploadAllLocalChanges() or something similar to // SyncSesson.downloadAllServerChanges() }
@Test public void addProgressListener_triggerImmediatelyWhenRegistered() { final SyncConfiguration config = createSyncConfig(); Realm realm = Realm.getInstance(config); SyncSession session = SyncManager.getSession(config); checkListener(session, ProgressMode.INDEFINITELY); checkListener(session, ProgressMode.CURRENT_CHANGES); realm.close(); }
@Test @RunTestInLooperThread @RunTestWithRemoteService(remoteService = SimpleCommitRemoteService.class, onLooperThread = true) public void expectSimpleCommit() { looperThread.runAfterTest(remoteService.afterRunnable); remoteService.createHandler(Looper.myLooper()); final SyncUser user = UserFactory.getInstance().createDefaultUser(Constants.AUTH_URL); String realmUrl = Constants.SYNC_SERVER_URL; final SyncConfiguration syncConfig = new SyncConfiguration.Builder(user,realmUrl) .directory(looperThread.getRoot()) .build(); final Realm realm = Realm.getInstance(syncConfig); final RealmResults<ProcessInfo> all = realm.where(ProcessInfo.class).findAll(); looperThread.keepStrongReference(all); all.addChangeListener(new RealmChangeListener<RealmResults<ProcessInfo>>() { @Override public void onChange(RealmResults<ProcessInfo> element) { assertEquals(1, all.size()); assertEquals("Background_Process1", all.get(0).getName()); realm.close(); user.logout(); remoteService.triggerServiceStep(SimpleCommitRemoteService.stepB_closeRealmAndLogOut); looperThread.testComplete(); } }); remoteService.triggerServiceStep(SimpleCommitRemoteService.stepA_openRealmAndCreateOneObject); }
@Override protected void run() { user = UserFactory.getInstance().loginWithDefaultUser(Constants.AUTH_URL); String realmUrl = Constants.SYNC_SERVER_URL; final SyncConfiguration syncConfig = new SyncConfiguration.Builder(user, realmUrl) .directory(getService().getRoot()) .name(UUID.randomUUID().toString() + ".realm") .build(); getService().setRealm(Realm.getInstance(syncConfig)); }
@Test public void cachedInstanceShouldNotThrowIfRefreshTokenExpires() throws InterruptedException { String username = UUID.randomUUID().toString(); String password = "password"; SyncCredentials credentials = SyncCredentials.usernamePassword(username, password, true); final SyncUser user = spy(SyncUser.login(credentials, Constants.AUTH_URL)); when(user.isValid()).thenReturn(true, false); final RealmConfiguration configuration = new SyncConfiguration.Builder(user, Constants.USER_REALM).build(); Realm realm = Realm.getInstance(configuration); assertFalse(user.isValid()); verify(user, times(2)).isValid(); final CountDownLatch backgroundThread = new CountDownLatch(1); // Should not throw when using an expired refresh_token form a different thread // It should be able to open a Realm with an expired token new Thread() { @Override public void run() { Realm instance = Realm.getInstance(configuration); instance.close(); backgroundThread.countDown(); } }.start(); backgroundThread.await(); // It should be possible to open a cached Realm with expired token Realm cachedInstance = Realm.getInstance(configuration); assertNotNull(cachedInstance); realm.close(); cachedInstance.close(); user.logout(); }
@Test public void usingConfigurationWithInvalidUserShouldThrow() { String username = UUID.randomUUID().toString(); String password = "password"; SyncCredentials credentials = SyncCredentials.usernamePassword(username, password, true); SyncUser user = SyncUser.login(credentials, Constants.AUTH_URL); RealmConfiguration configuration = new SyncConfiguration.Builder(user, Constants.USER_REALM).build(); user.logout(); assertFalse(user.isValid()); Realm instance = Realm.getInstance(configuration); instance.close(); }
@Override public void realmClosed(RealmConfiguration configuration) { // Last Thread using the specified configuration is closed // delete the wrapped Java session if (configuration instanceof SyncConfiguration) { SyncConfiguration syncConfig = (SyncConfiguration) configuration; invokeRemoveSession(syncConfig); } else { throw new IllegalArgumentException(WRONG_TYPE_OF_CONFIGURATION); } }
@Override public Object[] getUserAndServerUrl(RealmConfiguration config) { if (config instanceof SyncConfiguration) { SyncConfiguration syncConfig = (SyncConfiguration) config; SyncUser user = syncConfig.getUser(); String rosServerUrl = syncConfig.getServerUrl().toString(); String rosUserIdentity = user.getIdentity(); String syncRealmAuthUrl = user.getAuthenticationUrl().toString(); String rosSerializedUser = user.toJson(); byte sessionStopPolicy = syncConfig.getSessionStopPolicy().getNativeValue(); return new Object[]{rosUserIdentity, rosServerUrl, syncRealmAuthUrl, rosSerializedUser, syncConfig.syncClientValidateSsl(), syncConfig.getServerCertificateFilePath(), sessionStopPolicy, syncConfig.isPartialRealm()}; } else { return new Object[8]; } }
@Override public void wrapObjectStoreSessionIfRequired(OsRealmConfig config) { if (config.getRealmConfiguration() instanceof SyncConfiguration) { SyncSession session = SyncManager.getSession((SyncConfiguration) config.getRealmConfiguration()); session.setResolvedRealmURI(config.getResolvedRealmURI()); } }
@Override public String getSyncServerCertificateAssetName(RealmConfiguration configuration) { if (configuration instanceof SyncConfiguration) { SyncConfiguration syncConfig = (SyncConfiguration) configuration; return syncConfig.getServerCertificateAssetName(); } else { throw new IllegalArgumentException(WRONG_TYPE_OF_CONFIGURATION); } }
@Override public String getSyncServerCertificateFilePath(RealmConfiguration configuration) { if (configuration instanceof SyncConfiguration) { SyncConfiguration syncConfig = (SyncConfiguration) configuration; return syncConfig.getServerCertificateFilePath(); } else { throw new IllegalArgumentException(WRONG_TYPE_OF_CONFIGURATION); } }
@Override public void downloadRemoteChanges(RealmConfiguration config) { if (config instanceof SyncConfiguration) { SyncConfiguration syncConfig = (SyncConfiguration) config; if (syncConfig.shouldWaitForInitialRemoteData()) { SyncSession session = SyncManager.getSession(syncConfig); try { session.downloadAllServerChanges(); } catch (InterruptedException e) { throw new DownloadingRealmInterruptedException(syncConfig, e); } } } }
@Nonnull private SyncConfiguration createSyncConfig() { SyncUser user = UserFactory.createAdminUser(Constants.AUTH_URL); return configFactory.createSyncConfigurationBuilder(user, Constants.SYNC_SERVER_URL).build(); }
@Test public void downloadProgressListener_indefinitely() throws InterruptedException { final AtomicInteger transferCompleted = new AtomicInteger(0); final CountDownLatch allChangesDownloaded = new CountDownLatch(1); final CountDownLatch startWorker = new CountDownLatch(1); final SyncUser userWithData = UserFactory.createUniqueUser(Constants.AUTH_URL); final SyncConfiguration userWithDataConfig = configFactory.createSyncConfigurationBuilder(userWithData, Constants.USER_REALM) .name("remote") .build(); URI serverUrl = createRemoteData(userWithDataConfig); // Create worker thread that puts data into another Realm. // This is to avoid blocking one progress listener while waiting for another to complete. Thread worker = new Thread(new Runnable() { @Override public void run() { TestHelper.awaitOrFail(startWorker); createRemoteData(userWithDataConfig); } }); worker.start(); SyncUser adminUser = UserFactory.createAdminUser(Constants.AUTH_URL); final SyncConfiguration adminConfig = configFactory.createSyncConfigurationBuilder(adminUser, serverUrl.toString()) .name("local") .build(); Realm adminRealm = Realm.getInstance(adminConfig); SyncSession session = SyncManager.getSession(adminConfig); session.addDownloadProgressListener(ProgressMode.INDEFINITELY, new ProgressListener() { @Override public void onChange(Progress progress) { long objectCounts = getStoreTestDataSize(adminConfig); // The downloading progress listener could be triggered at the db version where only contains the meta // data. So we start checking from when the first 10 objects downloaded. RealmLog.warn(String.format( Locale.ENGLISH,"downloadProgressListener_indefinitely download %d/%d objects count:%d", progress.getTransferredBytes(), progress.getTransferableBytes(), objectCounts)); if (objectCounts != 0 && progress.isTransferComplete()) { switch (transferCompleted.incrementAndGet()) { case 1: { assertEquals(TEST_SIZE, objectCounts); assertTransferComplete(progress, true); startWorker.countDown(); break; } case 2: { assertTransferComplete(progress, true); assertEquals(TEST_SIZE * 2, objectCounts); allChangesDownloaded.countDown(); break; } default: fail("Transfer complete called too many times:" + transferCompleted.get()); } } } }); TestHelper.awaitOrFail(allChangesDownloaded); adminRealm.close(); // worker thread will hang if logout happens before listener triggered. worker.join(); userWithData.logout(); adminUser.logout(); }
@Test @RunTestWithRemoteService(remoteService = ALotCommitsRemoteService.class, onLooperThread = true) @RunTestInLooperThread public void expectALot() throws Throwable { looperThread.runAfterTest(remoteService.afterRunnable); remoteService.createHandler(Looper.myLooper()); final SyncUser user = UserFactory.getInstance().createDefaultUser(Constants.AUTH_URL); String realmUrl = Constants.SYNC_SERVER_URL; final SyncConfiguration syncConfig = new SyncConfiguration.Builder(user,realmUrl) .directory(looperThread.getRoot()) .build(); final Realm realm = Realm.getInstance(syncConfig); final RealmResults<TestObject> all = realm.where(TestObject.class).findAllSorted("intProp"); looperThread.keepStrongReference(all); final AtomicInteger listenerCalledCounter = new AtomicInteger(0); all.addChangeListener(new RealmChangeListener<RealmResults<TestObject>>() { @Override public void onChange(RealmResults<TestObject> element) { int counter = listenerCalledCounter.incrementAndGet(); int size = all.size(); if (size == 0) { listenerCalledCounter.decrementAndGet(); return; } assertEquals(0, size % 100); // Added 100 objects every time. assertEquals(counter * 100 - 1, all.last().getIntProp()); assertEquals("Str" + (counter * 100 - 1), all.last().getStringProp()); if (counter == 10) { remoteService.triggerServiceStep(ALotCommitsRemoteService.stepC_closeRealm); realm.close(); user.logout(); looperThread.testComplete(); } else { remoteService.triggerServiceStep(ALotCommitsRemoteService.stepB_createObjects); } } }); remoteService.triggerServiceStep(ALotCommitsRemoteService.stepA_openRealm); remoteService.triggerServiceStep(ALotCommitsRemoteService.stepB_createObjects); }
public DownloadingRealmInterruptedException(SyncConfiguration syncConfig, Throwable exception) { super("Realm was interrupted while downloading the latest changes from the server: " + syncConfig.getPath(), exception); }
public static void setActiveUser(SyncUser user) { SyncConfiguration defaultConfig = new SyncConfiguration.Builder(user, App.REALM_URL).build(); Realm.setDefaultConfiguration(defaultConfig); }
public void setRealmSyncConfiguration(User user) { SyncConfiguration configuration = new SyncConfiguration.Builder(user, SERVER_URL).build(); Realm.setDefaultConfiguration(configuration); }
/** * Gets a {@link RealmConfiguration} instance that can be used to open the backup Realm file. * * Note: This will use the default Realm module (composed of all {@link RealmModel}), and * assume no encryption should be used as well. * * @return A configuration object for the backup Realm. */ public RealmConfiguration getBackupRealmConfiguration() { return SyncConfiguration.forRecovery(path, null); }
/** * Gets a {@link RealmConfiguration} instance that can be used to open the backup Realm file. * * Note: This will use the default Realm module (composed of all {@link RealmModel}). * * @param encryptionKey Optional encryption key that was used to encrypt the original Realm file. * @return A configuration object for the backup Realm. */ public RealmConfiguration getBackupRealmConfiguration(@Nullable byte[] encryptionKey) { return SyncConfiguration.forRecovery(path, encryptionKey); }
/** * Gets a {@link RealmConfiguration} instance that can be used to open the backup Realm file. * * @param encryptionKey Optional encryption key that was used to encrypt the original Realm file. * @param modules restricts Realm schema to the provided module. * @return A configuration object for the backup Realm. */ public RealmConfiguration getBackupRealmConfiguration(@Nullable byte[] encryptionKey, Object... modules) { return SyncConfiguration.forRecovery(path, encryptionKey, modules); }