protected void prepareEnvironmentForTest() throws IOException { // FIXME Trying to reset the device environment is crashing tests somehow deleteRosFiles(); if (BaseRealm.applicationContext != null) { // Realm was already initialized. Reset all internal state // in order to be able fully re-initialize. // This will set the 'm_metadata_manager' in 'sync_manager.cpp' to be 'null' // causing the SyncUser to remain in memory. // They're actually not persisted into disk. // move this call to 'tearDown' to clean in-memory & on-disk users // once https://github.com/realm/realm-object-store/issues/207 is resolved SyncManager.reset(); BaseRealm.applicationContext = null; // Required for Realm.init() to work } Realm.init(InstrumentationRegistry.getContext()); originalLogLevel = RealmLog.getLevel(); RealmLog.setLevel(LogLevel.DEBUG); }
@Test public void combining_trustedRootCA_and_withoutSSLVerification_willThrow() { String username = UUID.randomUUID().toString(); String password = "password"; SyncUser user = SyncUser.login(SyncCredentials.usernamePassword(username, password, true), Constants.AUTH_URL); TestHelper.TestLogger testLogger = new TestHelper.TestLogger(); int originalLevel = RealmLog.getLevel(); RealmLog.add(testLogger); RealmLog.setLevel(LogLevel.WARN); //noinspection unchecked configurationFactory.createSyncConfigurationBuilder(user, Constants.USER_REALM_SECURE) .name("useSsl") .schema(StringOnly.class) .trustedRootCA("trusted_ca.pem") .disableSSLVerification() .build(); assertEquals("SSL Verification is disabled, the provided server certificate will not be used.", testLogger.message); RealmLog.remove(testLogger); RealmLog.setLevel(originalLevel); }
@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(); }
/** * Executes a given transaction on the DynamicRealm. {@link #beginTransaction()} and * {@link #commitTransaction()} will be called automatically. If any exception is thrown * during the transaction {@link #cancelTransaction()} will be called instead of {@link #commitTransaction()}. * * @param transaction {@link io.realm.DynamicRealm.Transaction} to execute. * @throws IllegalArgumentException if the {@code transaction} is {@code null}. */ public void executeTransaction(Transaction transaction) { //noinspection ConstantConditions if (transaction == null) { throw new IllegalArgumentException("Transaction should not be null"); } beginTransaction(); try { transaction.execute(this); commitTransaction(); } catch (RuntimeException e) { if (isInTransaction()) { cancelTransaction(); } else { RealmLog.warn("Could not cancel transaction, not currently in a transaction."); } throw e; } }
/** * Executes a given transaction on the Realm. {@link #beginTransaction()} and {@link #commitTransaction()} will be * called automatically. If any exception is thrown during the transaction {@link #cancelTransaction()} will be * called instead of {@link #commitTransaction()}. * * @param transaction the {@link io.realm.Realm.Transaction} to execute. * @throws IllegalArgumentException if the {@code transaction} is {@code null}. * @throws RealmMigrationNeededException if the latest version contains incompatible schema changes. */ public void executeTransaction(Transaction transaction) { //noinspection ConstantConditions if (transaction == null) { throw new IllegalArgumentException("Transaction should not be null"); } beginTransaction(); try { transaction.execute(this); commitTransaction(); } catch (Throwable e) { if (isInTransaction()) { cancelTransaction(); } else { RealmLog.warn("Could not cancel transaction, not currently in a transaction."); } throw e; } }
@Override public void run() { while (true) { try { NativeObjectReference reference = (NativeObjectReference) referenceQueue.remove(); reference.cleanup(); } catch (InterruptedException e) { // Restores the interrupted status. Thread.currentThread().interrupt(); RealmLog.fatal("The FinalizerRunnable thread has been interrupted." + " Native resources cannot be freed anymore"); break; } } }
@Override public void onError(SyncSession session, ObjectServerError error) { if (error.getErrorCode() == ErrorCode.CLIENT_RESET) { RealmLog.error("Client Reset required for: " + session.getConfiguration().getServerUrl()); return; } String errorMsg = String.format(Locale.US, "Session Error[%s]: %s", session.getConfiguration().getServerUrl(), error.toString()); switch (error.getErrorCode().getCategory()) { case FATAL: RealmLog.error(errorMsg); break; case RECOVERABLE: RealmLog.info(errorMsg); break; default: throw new IllegalArgumentException("Unsupported error category: " + error.getErrorCode().getCategory()); } }
/** * Gets any cached {@link SyncSession} for the given {@link SyncConfiguration} or create a new one if * no one exists. * * @param syncConfiguration configuration object for the synchronized Realm. * @return the {@link SyncSession} for the specified Realm. * @throws IllegalArgumentException if syncConfiguration is {@code null}. */ public static synchronized SyncSession getSession(SyncConfiguration syncConfiguration) { // This will not create a new native (Object Store) session, this will only associate a Realm's path // with a SyncSession. Object Store's SyncManager is responsible of the life cycle (including creation) // of the native session, the provided Java wrap, helps interact with the native session, when reporting error // or requesting an access_token for example. //noinspection ConstantConditions if (syncConfiguration == null) { throw new IllegalArgumentException("A non-empty 'syncConfiguration' is required."); } SyncSession session = sessions.get(syncConfiguration.getPath()); if (session == null) { session = new SyncSession(syncConfiguration); sessions.put(syncConfiguration.getPath(), session); if (sessions.size() == 1) { RealmLog.debug("first session created add network listener"); NetworkStateReceiver.addListener(networkListener); } } return session; }
/** * Remove the wrapped Java session. * @param syncConfiguration configuration object for the synchronized Realm. */ @SuppressWarnings("unused") private static synchronized void removeSession(SyncConfiguration syncConfiguration) { //noinspection ConstantConditions if (syncConfiguration == null) { throw new IllegalArgumentException("A non-empty 'syncConfiguration' is required."); } SyncSession syncSession = sessions.remove(syncConfiguration.getPath()); if (syncSession != null) { syncSession.close(); } if (sessions.isEmpty()) { RealmLog.debug("last session dropped, remove network listener"); NetworkStateReceiver.removeListener(networkListener); } }
private void postError(final ObjectServerError error) { boolean errorHandled = false; if (callback != null) { Runnable action = new Runnable() { @Override public void run() { callback.onError(error); } }; errorHandled = handler.post(action); } if (!errorHandled) { RealmLog.error(error, "An error was thrown, but could not be handled."); } }
@Override public void onCreate() { super.onCreate(); StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build(); StrictMode.setThreadPolicy(policy); try { rootFolder = File.createTempFile(this.getClass().getSimpleName(), ""); } catch (IOException e) { RealmLog.error(e); } //noinspection ResultOfMethodCallIgnored rootFolder.delete(); //noinspection ResultOfMethodCallIgnored rootFolder.mkdir(); Realm.init(getApplicationContext()); }
@Before public void setup() { mockStatic(RealmLog.class); mockStatic(Realm.class); Realm mockRealm = PowerMockito.mock(Realm.class); when(Realm.getDefaultInstance()).thenReturn(mockRealm); this.mockRealm = mockRealm; }
@Override public void onCreate() { super.onCreate(); Realm.init(this); // Enable full log output when debugging if (BuildConfig.DEBUG) { RealmLog.setLevel(Log.DEBUG); } }
/** * Tries to restore the environment as best as possible after a test. */ protected void restoreEnvironmentAfterTest() { // Block until all users are logged out UserFactory.logoutAllUsers(); // Reset log level RealmLog.setLevel(originalLogLevel); }
public static synchronized UserFactory getInstance() { if (instance == null) { Realm realm = Realm.getInstance(configuration); UserFactoryStore store = realm.where(UserFactoryStore.class).findFirst(); if (store == null || store.getUserName() == null) { throw new IllegalStateException("Current user has not been set. Call resetInstance() first."); } instance = new UserFactory(store.getUserName()); realm.close(); } RealmLog.debug("UserFactory.getInstance, the default user is " + instance.userName + " ."); return instance; }
@Override protected void finalize() throws Throwable { if (shouldCloseSharedRealm && sharedRealm != null && !sharedRealm.isClosed()) { RealmLog.warn("Remember to call close() on all Realm instances. " + "Realm %s is being finalized without being closed, " + "this can lead to running out of native memory.", configuration.getPath() ); if (realmCache != null) { realmCache.leak(); } } super.finalize(); }
/** * To delete Realm and related temporary files. This must be called in * {@link OsObjectStore#callWithLock(RealmConfiguration, Runnable)}'s callback. * * @return {@code true} if the realm file is deleted. Temporary file deletion failure will not impact the return * value, instead, a warning will be logged. */ public static boolean deleteRealm(String canonicalPath, File realmFolder, String realmFileName) { final String management = ".management"; File managementFolder = new File(realmFolder, realmFileName + management); File realmFile = new File(canonicalPath); // Deletes files in management directory and the directory. // There is no subfolders in the management directory. File[] files = managementFolder.listFiles(); if (files != null) { for (File file : files) { boolean deleteResult = file.delete(); if (!deleteResult) { RealmLog.warn( String.format(Locale.ENGLISH,"Realm temporary file at %s cannot be deleted", file.getAbsolutePath())); } } } if (managementFolder.exists() && !managementFolder.delete()) { RealmLog.warn( String.format(Locale.ENGLISH,"Realm temporary folder at %s cannot be deleted", managementFolder.getAbsolutePath())); } boolean realmDeleted; if (realmFile.exists()) { realmDeleted = realmFile.delete(); if (!realmDeleted) { RealmLog.warn(String.format(Locale.ENGLISH,"Realm file at %s cannot be deleted", realmFile.getAbsolutePath())); } } else { realmDeleted = true; } return realmDeleted; }
public TableQuery(NativeContext context, Table table, long nativeQueryPtr) { if (DEBUG) { RealmLog.debug("New TableQuery: ptr=%x", nativeQueryPtr); } this.context = context; this.table = table; this.nativePtr = nativeQueryPtr; context.addReference(this); }
/** * The fraction of bytes transferred out of all transferable bytes. Counting from since the {@link ProgressListener} * was added. * * @return a number between {@code 0.0} and {@code 1.0}, where {@code 0.0} represents that no data has been * transferred yet, and {@code 1.0} that all data has been transferred. */ public double getFractionTransferred() { if (transferableBytes == 0) { return 1.0D; } else { double percentage = (double) transferredBytes / (double) transferableBytes; if (percentage > 1.0D) { RealmLog.error("Invalid progress state: %s", this); return 1.0D; } else { return percentage; } } }
@Override protected void finalize() throws Throwable { if (!closed) { RealmLog.warn("PermissionManager was not correctly closed before being finalized."); } super.finalize(); }
@Override public void run() { if (checkAndReportInvalidState()) { return; } if (userPermissions != null) { // Permissions already loaded notifyCallbackWithSuccess(userPermissions); } else { // TODO Right now multiple getPermission() calls will result in multiple // queries being executed. The first one to return will be the one returned // by all callbacks. loadingPermissions = permissionRealm.where(Permission.class).findAllAsync(); loadingPermissions.addChangeListener(new RealmChangeListener <RealmResults<Permission>>() { @Override public void onChange(RealmResults <Permission> loadedPermissions) { RealmLog.error(String.format("1stCallback: Size: %s, Permissions: %s", loadedPermissions.size(), Arrays.toString(loadedPermissions.toArray()))); // Don't report ready until both __permission and __management Realm are there if (loadedPermissions.size() > 1) { loadingPermissions.removeChangeListener(this); loadingPermissions = null; if (checkAndReportInvalidState()) { return; } if (userPermissions == null) { userPermissions = loadedPermissions; } notifyCallbackWithSuccess(userPermissions); } } }); } }
protected final void notifyCallbackWithError(ObjectServerError e) { RealmLog.debug("Error happened in PermissionManager for %s: %s", permissionManager.user.getIdentity(), e.toString()); try { callback.onError(e); } finally { permissionManager.activeTasks.remove(this); } }
@Override public void onChange(boolean connectionAvailable) { if (connectionAvailable) { RealmLog.debug("NetworkListener: Connection available"); // notify all sessions notifyNetworkIsBack(); } else { RealmLog.debug("NetworkListener: Connection lost"); } }
private static synchronized void notifyNetworkIsBack() { try { nativeReconnect(); } catch (Exception exception) { RealmLog.error(exception); } }
/** * All progress listener events from native Sync are reported to this method. * It costs 2 HashMap lookups for each listener triggered (one to find the session, one to * find the progress listener), but it means we don't have to cache anything on the C++ side which * can leak since we don't have control over the session lifecycle. */ @SuppressWarnings("unused") private static synchronized void notifyProgressListener(String localRealmPath, long listenerId, long transferedBytes, long transferableBytes) { SyncSession session = sessions.get(localRealmPath); if (session != null) { try { session.notifyProgressListener(listenerId, transferedBytes, transferableBytes); } catch (Exception exception) { RealmLog.error(exception); } } }
/** * This is called from the Object Store (through JNI) to request an {@code access_token} for * the session specified by sessionPath. * * This will also schedule a timer to proactively refresh the {@code access_token} regularly, before * the {@code access_token} expires. * * @throws IllegalStateException if the wrapped Java session is not found. * @param sessionPath The path to the previously Java wraped session. * @return a valid cached {@code access_token} if available or null. */ @SuppressWarnings("unused") private synchronized static String bindSessionWithConfig(String sessionPath, String refreshToken) { final SyncSession syncSession = sessions.get(sessionPath); if (syncSession == null) { RealmLog.error("Matching Java SyncSession could not be found for: " + sessionPath); } else { try { return syncSession.getAccessToken(authServer, refreshToken); } catch (Exception exception) { RealmLog.error(exception); } } return null; }
synchronized void notifyProgressListener(long listenerId, long transferredBytes, long transferableBytes) { Pair<ProgressListener, Progress> listener = listenerIdToProgressListenerMap.get(listenerId); if (listener != null) { Progress newProgressNotification = new Progress(transferredBytes, transferableBytes); if (!newProgressNotification.equals(listener.second)) { listener.second = newProgressNotification; listener.first.onChange(newProgressNotification); } } else { RealmLog.debug("Trying unknown listener failed: " + listenerId); } }
private void scheduleRefreshAccessToken(final AuthenticationServer authServer, long expireDateInMs) { // calculate the delay time before which we should refresh the access_token, // we adjust to 10 second to proactively refresh the access_token before the session // hit the expire date on the token long refreshAfter = expireDateInMs - System.currentTimeMillis() - REFRESH_MARGIN_DELAY; if (refreshAfter < 0) { // Token already expired RealmLog.debug("Expires time already reached for the access token, refresh as soon as possible"); // we avoid refreshing directly to avoid an edge case where the client clock is ahead // of the server, causing all access_token received from the server to be always // expired, we will flood the server with refresh token requests then, so adding // a bit of delay is the best effort in this case. refreshAfter = REFRESH_MARGIN_DELAY; } RealmLog.debug("Scheduling an access_token refresh in " + (refreshAfter) + " milliseconds"); if (refreshTokenTask != null) { refreshTokenTask.cancel(); } ScheduledFuture<?> task = REFRESH_TOKENS_EXECUTOR.schedule(new Runnable() { @Override public void run() { if (!isClosed && !Thread.currentThread().isInterrupted() && !refreshTokenTask.isCancelled()) { refreshAccessToken(authServer); } } }, refreshAfter, TimeUnit.MILLISECONDS); refreshTokenTask = new RealmAsyncTaskImpl(task, REFRESH_TOKENS_EXECUTOR); }
private AuthenticateResponse authenticate(URL authenticationUrl, String requestBody) throws Exception { RealmLog.debug("Network request (authenticate): " + authenticationUrl); Request request = newAuthRequest(authenticationUrl) .post(RequestBody.create(JSON, requestBody)) .build(); Call call = client.newCall(request); Response response = call.execute(); return AuthenticateResponse.from(response); }
private LogoutResponse logout(URL logoutUrl, String authToken, String requestBody) throws Exception { RealmLog.debug("Network request (logout): " + logoutUrl); Request request = newAuthRequest(logoutUrl, authToken) .post(RequestBody.create(JSON, requestBody)) .build(); Call call = client.newCall(request); Response response = call.execute(); return LogoutResponse.from(response); }
private ChangePasswordResponse changePassword(URL changePasswordUrl, String authToken, String requestBody) throws Exception { RealmLog.debug("Network request (changePassword): " + changePasswordUrl); Request request = newAuthRequest(changePasswordUrl, authToken) .put(RequestBody.create(JSON, requestBody)) .build(); Call call = client.newCall(request); Response response = call.execute(); return ChangePasswordResponse.from(response); }
private LookupUserIdResponse lookupUserId(URL lookupUserIdUrl, String authToken) throws Exception { RealmLog.debug("Network request (lookupUserId): " + lookupUserIdUrl); Request request = newAuthRequest(lookupUserIdUrl, authToken) .get() .build(); Call call = client.newCall(request); Response response = call.execute(); return LookupUserIdResponse.from(response); }
private LookupUserIdResponse(ObjectServerError error) { RealmLog.debug("LookupUserIdResponse - Error: " + error); setError(error); this.error = error; this.userId = null; this.isAdmin = null; this.metadata = new HashMap<>(); this.accounts = new HashMap<>(); }
private LookupUserIdResponse(String serverResponse) { ObjectServerError error; String userId; Boolean isAdmin; String message; Map<String, String> metadata; Map<String, String> accounts; try { JSONObject obj = new JSONObject(serverResponse); userId = obj.getString(JSON_FIELD_USER_ID); isAdmin = obj.getBoolean(JSON_FIELD_USER_IS_ADMIN); metadata = jsonToMap(obj.getJSONArray(JSON_FIELD_METADATA), "key", "value"); accounts = jsonToMap(obj.getJSONArray(JSON_FIELD_ACCOUNTS), "provider", "provider_id"); error = null; message = String.format(Locale.US, "Identity %s; Path %b", userId, isAdmin); } catch (JSONException e) { userId = null; isAdmin = null; metadata = new HashMap<>(); accounts = new HashMap<>(); error = new ObjectServerError(ErrorCode.JSON_EXCEPTION, e); message = String.format(Locale.US, "Error %s", error.getErrorMessage()); } RealmLog.debug("LookupUserIdResponse. " + message); setError(error); this.userId = userId; this.isAdmin = isAdmin; this.metadata = metadata; this.accounts = accounts; }
/** * Creates an unsuccessful authentication response. This should only happen in case of network or I/O related * issues. * * @param error the network or I/O error. */ private AuthenticateResponse(ObjectServerError error) { RealmLog.debug("AuthenticateResponse - Error: " + error); setError(error); this.accessToken = null; this.refreshToken = null; }
/** * Parses a valid (200) server response. It might still result in an unsuccessful authentication attempt, if the * JSON response could not be parsed correctly. * * @param serverResponse the server response. */ private AuthenticateResponse(String serverResponse) { ObjectServerError error; Token accessToken; Token refreshToken; String message; try { JSONObject obj = new JSONObject(serverResponse); accessToken = obj.has(JSON_FIELD_ACCESS_TOKEN) ? Token.from(obj.getJSONObject(JSON_FIELD_ACCESS_TOKEN)) : null; refreshToken = obj.has(JSON_FIELD_REFRESH_TOKEN) ? Token.from(obj.getJSONObject(JSON_FIELD_REFRESH_TOKEN)) : null; error = null; if (accessToken == null) { message = "accessToken = null"; } else { message = String.format(Locale.US, "Identity %s; Path %s", accessToken.identity(), accessToken.path()); } } catch (JSONException ex) { accessToken = null; refreshToken = null; //noinspection ThrowableInstanceNeverThrown error = new ObjectServerError(ErrorCode.JSON_EXCEPTION, ex); message = String.format(Locale.US, "Error %s", error.getErrorMessage()); } RealmLog.debug("AuthenticateResponse. " + message); setError(error); this.accessToken = accessToken; this.refreshToken = refreshToken; }
private void response(String error) { try { Message msg = Message.obtain(null, message); if (error != null) { Bundle bundle = new Bundle(); bundle.putString(BUNDLE_KEY_ERROR, error); msg.setData(bundle); } thiz.client.send(msg); } catch (RemoteException e) { RealmLog.error(e); } }
@Test public void login_appendAuthSegment() { AuthenticationServer authServer = Mockito.mock(AuthenticationServer.class); AuthenticationServer originalServer = SyncManager.getAuthServer(); SyncManager.setAuthServerImpl(authServer); String[][] urls = { {"http://ros.realm.io", "http://ros.realm.io/auth"}, {"http://ros.realm.io:8080", "http://ros.realm.io:8080/auth"}, {"http://ros.realm.io/", "http://ros.realm.io/"}, {"http://ros.realm.io/?foo=bar", "http://ros.realm.io/?foo=bar"}, {"http://ros.realm.io/auth", "http://ros.realm.io/auth"}, {"http://ros.realm.io/auth/", "http://ros.realm.io/auth/"}, {"http://ros.realm.io/custom-path/", "http://ros.realm.io/custom-path/"} }; try { for (String[] url : urls) { RealmLog.error(url[0]); String input = url[0]; String normalizedInput = url[1]; SyncCredentials credentials = SyncCredentials.accessToken("token", UUID.randomUUID().toString()); SyncUser user = SyncUser.login(credentials, input); assertEquals(normalizedInput, user.getAuthenticationUrl().toString()); user.logout(); } } finally { SyncManager.setAuthServerImpl(originalServer); } }
@Override public void onCreate() { super.onCreate(); mApp = this; Realm.init(this); RealmLog.setLevel(LogLevel.TRACE); }
/** * Init realm configuration and instance * @return * @throws Exception */ @Provides @Singleton RealmConfiguration provideRealmConfiguration(){ mockStatic(RealmCore.class); mockStatic(RealmLog.class); mockStatic(Realm.class); mockStatic(RealmConfiguration.class); Realm.init(RuntimeEnvironment.application); // TODO: Better solution would be just mock the RealmConfiguration.Builder class. But it seems there is some // problems for powermock to mock it (static inner class). We just mock the RealmCore.loadLibrary(Context) which // will be called by RealmConfiguration.Builder's constructor. doNothing().when(RealmCore.class); RealmCore.loadLibrary(any(Context.class)); final RealmConfiguration mockRealmConfig = PowerMockito.mock(RealmConfiguration.class); try { whenNew(RealmConfiguration.class).withAnyArguments().thenReturn(mockRealmConfig); } catch (Exception e) { e.printStackTrace(); } when(Realm.getDefaultConfiguration()).thenReturn(mockRealmConfig); // init mock realm Realm mockRealm = PowerMockito.mock(Realm.class);; // Anytime getInstance is called with any configuration, then return the mockRealm when(Realm.getDefaultInstance()).thenReturn(mockRealm); when(Realm.getInstance(mockRealmConfig)).thenReturn(mockRealm); return mockRealmConfig; }