diff --git a/.gitignore b/.gitignore index 3858c294a..8a0096f1a 100644 --- a/.gitignore +++ b/.gitignore @@ -45,3 +45,4 @@ jacoco.exec # Node node_modules/ npm-debug.log +*.hprof diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 53f74c7b8..06bce3e58 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,13 +1,7 @@ # Contributing to Parse SDK for Android We want to make contributing to this project as easy and transparent as possible. -## Our Development Process -Most of our work will be done in public directly on GitHub. There may be changes done through our internal source control, but it will be rare and only as needed. - -### `master` is unsafe -Our goal is to keep `master` stable, but there may be changes that your application may not be compatible with. We'll do our best to publicize any breaking changes, but try to use our specific releases in any production environment. - -### Pull Requests +## Pull Requests We actively welcome your pull requests. When we get one, we'll run some Parse-specific integration tests on it first. From here, we'll need to get a core member to sign off on the changes and then merge the pull request. For API changes we may need to fix internal uses, which could cause some delay. We'll do our best to provide updates and feedback throughout the process. 1. Fork the repo and create your branch from `master`. @@ -16,13 +10,13 @@ We actively welcome your pull requests. When we get one, we'll run some Parse-sp 4. Ensure the test suite passes. 5. Make sure your code lints by running `./gradlew spotlessApply`. -## Bugs -Although we try to keep developing on Parse easy, you still may run into some issues. Technical questions should be asked on [Stack Overflow][stack-overflow], and for everything else we'll be using GitHub issues. +## Android API compatibility -### Known Issues -We use GitHub issues to track public bugs. We will keep a close eye on this and try to make it clear when we have an internal fix in progress. Before filing a new issue, try to make sure your problem doesn't already exist. +Consider the following to ensure a consistent Android API compatibility for the Parse Android SDK: +- Target API level: Target the latest available stable API version. +- Minimum API level: Cover at least ~90% of devices. The increment will be done only if dependencies requires it, if the statistics points that the API level covers at least ~90% of devices, or if a currently supported Android API level does not receive security updates anymore. Minimum API level changes must be marked in the release notes as breaking changes. -### Reporting New Issues +## Reporting an Issue Not all issues are SDK issues. If you're unsure whether your bug is with the SDK or backend, you can test to see if it reproduces with our [REST API][rest-api] and [Parse API Console][parse-api-console]. If it does, you can report backend bugs [here][bug-reports]. To view the REST API network requests issued by the Parse SDK and responses from the Parse backend, please check out [OkHttp Interceptors][network-debugging-tool]. With this tool, you can either log network requests/responses to Android logcat, or log them to Chrome Debugger via Stetho. @@ -41,10 +35,10 @@ This project adheres to the [Contributor Covenant Code of Conduct](https://githu ## License By contributing to Parse Android SDK, you agree that your contributions will be licensed under its license. - [stack-overflow]: http://stackoverflow.com/tags/parse.com - [bug-reports]: https://github.com/parse-community/parse-server - [rest-api]: http://docs.parseplatform.org/rest/guide/ - [network-debugging-tool]: https://github.com/square/okhttp/wiki/Interceptors - [parse-api-console]: http://blog.parseplatform.org/announcements/introducing-the-parse-api-console/ - [stacktrace-or-gtfo]: http://i.imgur.com/jacoj.jpg - [tests-dir]: /parse/src/test/java/com/parse +[stack-overflow]: http://stackoverflow.com/tags/parse.com +[bug-reports]: https://github.com/parse-community/parse-server +[rest-api]: http://docs.parseplatform.org/rest/guide/ +[network-debugging-tool]: https://github.com/square/okhttp/wiki/Interceptors +[parse-api-console]: http://blog.parseplatform.org/announcements/introducing-the-parse-api-console/ +[stacktrace-or-gtfo]: http://i.imgur.com/jacoj.jpg +[tests-dir]: /parse/src/test/java/com/parse diff --git a/README.md b/README.md index 667c3b18c..057943729 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ [![Snyk Badge](https://snyk.io/test/github/parse-community/Parse-SDK-Android/badge.svg)](https://snyk.io/test/github/parse-community/Parse-SDK-Android) [![codecov](https://codecov.io/gh/parse-community/Parse-SDK-Android/branch/master/graph/badge.svg)](https://codecov.io/gh/parse-community/Parse-SDK-Android) -[![android min api](https://img.shields.io/badge/Android_API->=16-66c718.svg)](https://github.com/parse-community/parse-dashboard/releases) +[![android min api](https://img.shields.io/badge/Android_API->=21-66c718.svg)](https://github.com/parse-community/parse-dashboard/releases) [![auto-release](https://img.shields.io/badge/%F0%9F%9A%80-auto--release-9e34eb.svg)](https://github.com/parse-community/parse-dashboard/releases) [![](https://jitpack.io/v/parse-community/Parse-SDK-Android.svg)](https://jitpack.io/#parse-community/Parse-SDK-Android) @@ -25,6 +25,7 @@ A library that gives you access to the powerful Parse Server backend from your A --- - [Getting Started](#getting-started) + - [Compatibility](#compatibility) - [Add Dependency](#add-dependency) - [Setup](#setup) - [Contributing](#contributing) @@ -32,6 +33,16 @@ A library that gives you access to the powerful Parse Server backend from your A # Getting Started +## Compatibility + +The Parse Android SDK has the following Android API and [Gradle Plugin][gradle-plugin] compatibility. + +| SDK version | Minimum API level | Targeting API level | Gradle Plugin | +|-------------|-------------------|---------------------|---------------| +| 1.26 | < API 16 | API 29 | 3.6.2 | +| 2.0 | >= API 16 | API 30 | 4.2.2 | +| 2.1 | >= API 21 | API 31 | 7.0.3 | + ## Add Dependency Add this in your root `build.gradle` file (**not** your module `build.gradle` file): @@ -46,6 +57,7 @@ allprojects { ``` Then, add the library to your project `build.gradle` + ```gradle ext { parseVersion = "latest.version.here" @@ -104,6 +116,7 @@ The custom `Application` class must be registered in `AndroidManifest.xml`: ... ``` + Note that if you are testing with a server using `http`, you will need to add `android:usesCleartextTraffic="true"` to your above `` definition, but you should only do this while testing and should use `https` for your final product. See the [guide][guide] for the rest of the SDK usage. @@ -113,6 +126,7 @@ See the [guide][guide] for the rest of the SDK usage. We want to make contributing to this project as easy and transparent as possible. Please refer to the [Contribution Guidelines](CONTRIBUTING.md). # More Parse Android Projects + These are other official libraries we made that can help you create your Parse app. - [ParseGoogleUtils](/google) - Google login/signup. @@ -131,3 +145,4 @@ As of April 5, 2017, Parse, LLC has transferred this code to the parse-community [guide]: http://docs.parseplatform.org/android/guide/ [open-collective-link]: https://opencollective.com/parse-server +[gradle-plugin]: https://developer.android.com/studio/releases/gradle-plugin diff --git a/bolts-tasks/build.gradle b/bolts-tasks/build.gradle index d07c3f3fa..79f4aefa0 100644 --- a/bolts-tasks/build.gradle +++ b/bolts-tasks/build.gradle @@ -8,7 +8,12 @@ apply plugin: 'maven-publish' dependencies { compileOnly 'com.google.android:android:4.1.1.4' - testImplementation 'junit:junit:4.13.2' + testImplementation "junit:junit:$rootProject.ext.junitVersion" +} + +java { + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 } javadoc.options.addStringOption('Xdoclint:none', '-quiet') @@ -28,6 +33,18 @@ artifacts { archives javadocJar } +//region Publishing + +afterEvaluate { + publishing { + publications { + boltsPublication(MavenPublication) { + from components.java + } + } + } +} + //endregion //region Code Coverage @@ -44,18 +61,3 @@ jacocoTestReport { } //endregion - -java { - sourceCompatibility = JavaVersion.VERSION_1_8 - targetCompatibility = JavaVersion.VERSION_1_8 -} - -afterEvaluate { - publishing { - publications { - boltsPublication(MavenPublication) { - from components.java - } - } - } -} diff --git a/bolts-tasks/src/main/java/com/parse/boltsinternal/AggregateException.java b/bolts-tasks/src/main/java/com/parse/boltsinternal/AggregateException.java index 80d39338f..4d8ca5cd2 100644 --- a/bolts-tasks/src/main/java/com/parse/boltsinternal/AggregateException.java +++ b/bolts-tasks/src/main/java/com/parse/boltsinternal/AggregateException.java @@ -8,7 +8,6 @@ import java.io.PrintStream; import java.io.PrintWriter; -import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; @@ -101,28 +100,4 @@ public void printStackTrace(PrintWriter err) { err.append("\n"); } } - - /** @deprecated Please use {@link #getInnerThrowables()} instead. */ - @Deprecated - public List getErrors() { - List errors = new ArrayList<>(); - if (innerThrowables == null) { - return errors; - } - - for (Throwable cause : innerThrowables) { - if (cause instanceof Exception) { - errors.add((Exception) cause); - } else { - errors.add(new Exception(cause)); - } - } - return errors; - } - - /** @deprecated Please use {@link #getInnerThrowables()} instead. */ - @Deprecated - public Throwable[] getCauses() { - return innerThrowables.toArray(new Throwable[0]); - } } diff --git a/bolts-tasks/src/main/java/com/parse/boltsinternal/Task.java b/bolts-tasks/src/main/java/com/parse/boltsinternal/Task.java index ccb14d779..8e73588b2 100644 --- a/bolts-tasks/src/main/java/com/parse/boltsinternal/Task.java +++ b/bolts-tasks/src/main/java/com/parse/boltsinternal/Task.java @@ -81,12 +81,6 @@ public static void setUnobservedExceptionHandler(UnobservedExceptionHandler eh) unobservedExceptionHandler = eh; } - /** @deprecated Please use {@link com.parse.boltsinternal.TaskCompletionSource ()} instead. */ - public static Task.TaskCompletionSource create() { - Task task = new Task<>(); - return task.new TaskCompletionSource(); - } - /** Creates a completed task with the given value. */ @SuppressWarnings("unchecked") public static Task forResult(TResult value) { @@ -988,11 +982,4 @@ public interface UnobservedExceptionHandler { */ void unobservedException(Task t, UnobservedTaskException e); } - - /** @deprecated Please use {@link com.parse.boltsinternal.TaskCompletionSource} instead. */ - public class TaskCompletionSource - extends com.parse.boltsinternal.TaskCompletionSource { - - /* package */ TaskCompletionSource() {} - } } diff --git a/bolts-tasks/src/test/java/com/parse/boltsinternal/TaskTest.java b/bolts-tasks/src/test/java/com/parse/boltsinternal/TaskTest.java index e77846130..adf179d1b 100644 --- a/bolts-tasks/src/test/java/com/parse/boltsinternal/TaskTest.java +++ b/bolts-tasks/src/test/java/com/parse/boltsinternal/TaskTest.java @@ -8,7 +8,6 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotSame; import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; @@ -1133,51 +1132,4 @@ public void testSetCancelledOnCompletedTask() { } // endregion - - // region deprecated - - @SuppressWarnings("deprecation") - @Test - public void testDeprecatedTaskCompletionSource() { - Task.TaskCompletionSource tcsA = Task.create(); - tcsA.setResult(null); - assertTrue(tcsA.getTask().isCompleted()); - - TaskCompletionSource tcsB = Task.create(); - tcsB.setResult(null); - assertTrue(tcsA.getTask().isCompleted()); - } - - @SuppressWarnings("deprecation") - @Test - public void testDeprecatedAggregateExceptionMethods() { - final Exception error0 = new Exception("This is an exception (0)."); - final Exception error1 = new Exception("This is an exception (1)."); - final Error error2 = new Error("This is an error."); - - List exceptions = new ArrayList<>(); - exceptions.add(error0); - exceptions.add(error1); - - // Test old functionality - AggregateException aggregate = new AggregateException(exceptions); - assertEquals("There were multiple errors.", aggregate.getMessage()); - assertEquals(2, aggregate.getErrors().size()); - assertEquals(error0, aggregate.getErrors().get(0)); - assertEquals(error1, aggregate.getErrors().get(1)); - assertEquals(2, aggregate.getCauses().length); - assertEquals(error0, aggregate.getCauses()[0]); - assertEquals(error1, aggregate.getCauses()[1]); - - // Test deprecated getErrors method returns sane results with non-Exceptions - aggregate = new AggregateException("message", new Throwable[] {error0, error1, error2}); - assertEquals("message", aggregate.getMessage()); - assertEquals(3, aggregate.getErrors().size()); - assertEquals(error0, aggregate.getErrors().get(0)); - assertEquals(error1, aggregate.getErrors().get(1)); - assertNotSame(error2, aggregate.getErrors().get(2)); - assertEquals(error2, aggregate.getErrors().get(2).getCause()); - } - - // endregion } diff --git a/build.gradle b/build.gradle index 53e066139..c78e1b983 100644 --- a/build.gradle +++ b/build.gradle @@ -6,20 +6,18 @@ buildscript { mavenCentral() } dependencies { - classpath "com.android.tools.build:gradle:4.2.2" - classpath "org.kt3k.gradle.plugin:coveralls-gradle-plugin:2.8.3" - classpath "com.github.dcendents:android-maven-gradle-plugin:2.1" + classpath "com.android.tools.build:gradle:7.0.3" classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath "org.jacoco:org.jacoco.core:$jacocoVersion" classpath "com.dicedmelon.gradle:jacoco-android:0.1.5" classpath "io.freefair.gradle:android-gradle-plugins:4.2.0-m1" - classpath "com.diffplug.spotless:spotless-plugin-gradle:5.16.0" + classpath "com.diffplug.spotless:spotless-plugin-gradle:5.17.1" } } plugins { id "com.github.ben-manes.versions" version "0.28.0" - id "com.diffplug.spotless" version "5.16.0" + id "com.diffplug.spotless" version "5.17.1" } allprojects { @@ -63,8 +61,12 @@ allprojects { } ext { - compileSdkVersion = 30 + compileSdkVersion = 31 - minSdkVersion = 16 - targetSdkVersion = 30 + minSdkVersion = 21 + targetSdkVersion = 31 + + mockitoCoreVersion = "3.12.4" + junitVersion = "4.13.2" + robolectricVersion = "4.7" } diff --git a/coroutines/build.gradle b/coroutines/build.gradle index ff9395446..79e9b12b1 100644 --- a/coroutines/build.gradle +++ b/coroutines/build.gradle @@ -40,7 +40,7 @@ android { } ext { - coroutinesVersion = "1.5.0" + coroutinesVersion = "1.5.2" } dependencies { diff --git a/facebook/build.gradle b/facebook/build.gradle index fe481cd45..0fb8594da 100644 --- a/facebook/build.gradle +++ b/facebook/build.gradle @@ -35,12 +35,13 @@ android { } dependencies { - api "com.facebook.android:facebook-login:8.2.0" + api "com.facebook.android:facebook-login:12.1.0" implementation project(":parse") - testImplementation "junit:junit:4.13.2" - testImplementation "org.mockito:mockito-core:3.9.0" - testImplementation "org.robolectric:robolectric:4.6" + testImplementation "junit:junit:$rootProject.ext.junitVersion" + testImplementation "org.mockito:mockito-core:$rootProject.ext.mockitoCoreVersion" + testImplementation "org.mockito:mockito-inline:$rootProject.ext.mockitoCoreVersion" + testImplementation "org.robolectric:robolectric:$rootProject.ext.robolectricVersion" } afterEvaluate { diff --git a/facebook/src/main/java/com/parse/facebook/FacebookController.java b/facebook/src/main/java/com/parse/facebook/FacebookController.java index efd4387c0..f353ca4d0 100644 --- a/facebook/src/main/java/com/parse/facebook/FacebookController.java +++ b/facebook/src/main/java/com/parse/facebook/FacebookController.java @@ -12,6 +12,7 @@ import android.content.Context; import android.content.Intent; import android.text.TextUtils; +import androidx.annotation.NonNull; import androidx.fragment.app.Fragment; import com.facebook.AccessToken; import com.facebook.AccessTokenSource; @@ -22,6 +23,7 @@ import com.facebook.login.LoginManager; import com.facebook.login.LoginResult; import com.parse.boltsinternal.Task; +import com.parse.boltsinternal.TaskCompletionSource; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Arrays; @@ -92,7 +94,7 @@ public Task> authenticateAsync( "Unable to authenticate when another authentication is in process")); } - final Task>.TaskCompletionSource tcs = Task.create(); + final TaskCompletionSource> tcs = new TaskCompletionSource<>(); LoginManager manager = facebookSdkDelegate.getLoginManager(); callbackManager = facebookSdkDelegate.createCallbackManager(); @@ -112,20 +114,20 @@ public void onCancel() { } @Override - public void onError(FacebookException e) { + public void onError(@NonNull FacebookException e) { tcs.trySetError(e); } }); if (LoginAuthorizationType.PUBLISH.equals(authorizationType)) { if (fragment != null) { - manager.logInWithPublishPermissions(fragment, permissions); + manager.logInWithPublishPermissions(fragment, callbackManager, permissions); } else { manager.logInWithPublishPermissions(activity, permissions); } } else { if (fragment != null) { - manager.logInWithReadPermissions(fragment, permissions); + manager.logInWithReadPermissions(fragment, callbackManager, permissions); } else { manager.logInWithReadPermissions(activity, permissions); } diff --git a/facebook/src/main/java/com/parse/facebook/ParseFacebookUtils.java b/facebook/src/main/java/com/parse/facebook/ParseFacebookUtils.java index d51970964..98e944f76 100644 --- a/facebook/src/main/java/com/parse/facebook/ParseFacebookUtils.java +++ b/facebook/src/main/java/com/parse/facebook/ParseFacebookUtils.java @@ -20,6 +20,7 @@ import com.parse.SaveCallback; import com.parse.boltsinternal.Continuation; import com.parse.boltsinternal.Task; +import com.parse.boltsinternal.TaskCompletionSource; import java.util.Collection; import java.util.Collections; import java.util.Map; @@ -565,7 +566,7 @@ private static Task callbackOnMainThreadInternalAsync( if (callback == null) { return task; } - final Task.TaskCompletionSource tcs = Task.create(); + final TaskCompletionSource tcs = new TaskCompletionSource(); task.continueWith( (Continuation) task1 -> { diff --git a/facebook/src/test/java/com/parse/facebook/FacebookControllerTest.java b/facebook/src/test/java/com/parse/facebook/FacebookControllerTest.java index 98e772cb0..df7f9d14a 100644 --- a/facebook/src/test/java/com/parse/facebook/FacebookControllerTest.java +++ b/facebook/src/test/java/com/parse/facebook/FacebookControllerTest.java @@ -314,14 +314,16 @@ public void doAuthenticateAsyncWith( verify(loginManager).logInWithPublishPermissions(activity, permissions); } if (fragment != null) { - verify(loginManager).logInWithPublishPermissions(fragment, permissions); + verify(loginManager) + .logInWithPublishPermissions(fragment, callbackManager, permissions); } } else { if (activity != null) { verify(loginManager).logInWithReadPermissions(activity, permissions); } if (fragment != null) { - verify(loginManager).logInWithReadPermissions(fragment, permissions); + verify(loginManager) + .logInWithReadPermissions(fragment, callbackManager, permissions); } } diff --git a/facebook/src/test/java/com/parse/facebook/ParseFacebookUtilsTest.java b/facebook/src/test/java/com/parse/facebook/ParseFacebookUtilsTest.java index 95bbd3c7e..9d89b66cd 100644 --- a/facebook/src/test/java/com/parse/facebook/ParseFacebookUtilsTest.java +++ b/facebook/src/test/java/com/parse/facebook/ParseFacebookUtilsTest.java @@ -16,7 +16,6 @@ import static org.mockito.ArgumentMatchers.nullable; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyInt; -import static org.mockito.Matchers.anyMapOf; import static org.mockito.Matchers.anyString; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.doThrow; @@ -56,7 +55,7 @@ public class ParseFacebookUtilsTest { @Before public void setUp() { - MockitoAnnotations.initMocks(this); + MockitoAnnotations.openMocks(this); ParseFacebookUtils.controller = controller; ParseFacebookUtils.userDelegate = userDelegate; } @@ -117,9 +116,7 @@ public void testRestoreAuthenticationFailure() throws java.text.ParseException { .registerAuthenticationCallback(eq("facebook"), callbackCaptor.capture()); AuthenticationCallback callback = callbackCaptor.getValue(); Map authData = new HashMap<>(); - doThrow(new RuntimeException()) - .when(controller) - .setAuthData(anyMapOf(String.class, String.class)); + doThrow(new RuntimeException()).when(controller).setAuthData(anyMap()); assertFalse(callback.onRestore(authData)); verify(controller).setAuthData(authData); @@ -160,7 +157,7 @@ public void testLogInWithAccessToken() { ParseFacebookUtils.isInitialized = true; ParseUser user = mock(ParseUser.class); - when(userDelegate.logInWithInBackground(anyString(), anyMapOf(String.class, String.class))) + when(userDelegate.logInWithInBackground(anyString(), anyMap())) .thenReturn(Task.forResult(user)); AccessToken token = TestUtils.newAccessToken(); Task task = ParseFacebookUtils.logInInBackground(token); @@ -225,7 +222,7 @@ private void doLogInWith( ParseFacebookUtils.isInitialized = true; ParseUser user = mock(ParseUser.class); - when(userDelegate.logInWithInBackground(anyString(), anyMapOf(String.class, String.class))) + when(userDelegate.logInWithInBackground(anyString(), anyMap())) .thenReturn(Task.forResult(user)); Task task; if (FacebookController.LoginAuthorizationType.PUBLISH.equals(type)) { @@ -266,8 +263,7 @@ public void testLinkWithAccessToken() { ParseFacebookUtils.isInitialized = true; ParseUser user = mock(ParseUser.class); - when(user.linkWithInBackground(anyString(), anyMapOf(String.class, String.class))) - .thenReturn(Task.forResult(null)); + when(user.linkWithInBackground(anyString(), anyMap())).thenReturn(Task.forResult(null)); AccessToken token = TestUtils.newAccessToken(); Task task = ParseFacebookUtils.linkInBackground(user, token); verify(controller).getAuthData(token); diff --git a/fcm/build.gradle b/fcm/build.gradle index 25209a897..41c23d2a4 100644 --- a/fcm/build.gradle +++ b/fcm/build.gradle @@ -36,7 +36,7 @@ android { } dependencies { - api "com.google.firebase:firebase-messaging:22.0.0" + api "com.google.firebase:firebase-messaging:23.0.0" implementation project(":parse") } diff --git a/google/src/main/java/com/parse/google/ParseGoogleUtils.kt b/google/src/main/java/com/parse/google/ParseGoogleUtils.kt index a03079d47..6ed42f765 100644 --- a/google/src/main/java/com/parse/google/ParseGoogleUtils.kt +++ b/google/src/main/java/com/parse/google/ParseGoogleUtils.kt @@ -13,6 +13,7 @@ import com.parse.ParseUser import com.parse.SaveCallback import com.parse.boltsinternal.Continuation import com.parse.boltsinternal.Task +import com.parse.boltsinternal.TaskCompletionSource /** * Provides a set of utilities for using Parse with Google. @@ -221,7 +222,7 @@ object ParseGoogleUtils { if (callback == null) { return task } - val tcs: Task.TaskCompletionSource = Task.create() + val tcs: TaskCompletionSource = TaskCompletionSource() task.continueWith( Continuation { task -> if (task.isCancelled && !reportCancellation) { diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 68ca99ac4..00aeb6981 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,6 @@ +#Tue Nov 16 15:15:09 EET 2021 distributionBase=GRADLE_USER_HOME +distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-bin.zip distributionPath=wrapper/dists -zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.3-bin.zip +zipStoreBase=GRADLE_USER_HOME diff --git a/parse/build.gradle b/parse/build.gradle index b362f628a..ce5602919 100644 --- a/parse/build.gradle +++ b/parse/build.gradle @@ -42,23 +42,24 @@ android { } ext { - // Note: Don't update past 3.12.x, as it sets the minSdk to Android 5.0 - okhttpVersion = "3.12.10" + okhttpVersion = "4.9.1" } dependencies { - api "androidx.annotation:annotation:1.2.0" - api "androidx.core:core:1.6.0" + api "androidx.annotation:annotation:1.3.0" + api "androidx.core:core:1.7.0" api "com.squareup.okhttp3:okhttp:$okhttpVersion" api project(':bolts-tasks') - testImplementation 'junit:junit:4.13.2' - testImplementation "org.robolectric:robolectric:4.6" testImplementation "org.skyscreamer:jsonassert:1.5.0" - testImplementation "org.mockito:mockito-core:3.9.0" + testImplementation "junit:junit:$rootProject.ext.junitVersion" + testImplementation "org.mockito:mockito-core:$rootProject.ext.mockitoCoreVersion" + testImplementation "org.robolectric:robolectric:$rootProject.ext.robolectricVersion" testImplementation "com.squareup.okhttp3:mockwebserver:$okhttpVersion" } +//region Publishing + afterEvaluate { publishing { publications { @@ -69,6 +70,8 @@ afterEvaluate { } } +//endregion + //region Code Coverage apply plugin: "com.dicedmelon.gradle.jacoco-android" @@ -92,11 +95,3 @@ jacocoAndroidUnitTestReport { } //endregion - -//region Coveralls - -apply plugin: "com.github.kt3k.coveralls" - -coveralls.jacocoReportPath = "${buildDir}/jacoco/jacoco.xml" - -//endregion diff --git a/parse/src/main/java/com/parse/OfflineStore.java b/parse/src/main/java/com/parse/OfflineStore.java index e12a44a53..accd4b78f 100644 --- a/parse/src/main/java/com/parse/OfflineStore.java +++ b/parse/src/main/java/com/parse/OfflineStore.java @@ -20,6 +20,7 @@ import com.parse.boltsinternal.Task; import com.parse.boltsinternal.TaskCompletionSource; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; import java.util.LinkedList; import java.util.List; @@ -834,9 +835,7 @@ private Task deleteObjects(final List uuids, final ParseSQLiteData } String[] placeholders = new String[uuids.size()]; - for (int i = 0; i < placeholders.length; i++) { - placeholders[i] = "?"; - } + Arrays.fill(placeholders, "?"); String where = OfflineSQLiteOpenHelper.KEY_UUID + " IN (" diff --git a/parse/src/main/java/com/parse/Parse.java b/parse/src/main/java/com/parse/Parse.java index d45f3df02..39cdc2545 100644 --- a/parse/src/main/java/com/parse/Parse.java +++ b/parse/src/main/java/com/parse/Parse.java @@ -321,15 +321,6 @@ private static boolean allParsePushIntentReceiversInternal() { return true; } - /** - * @deprecated Please use {@link #getParseCacheDir(String)} or {@link #getParseFilesDir(String)} - * instead. - */ - @Deprecated - static File getParseDir() { - return ParsePlugins.get().getParseDir(); - } - static File getParseCacheDir() { return ParsePlugins.get().getCacheDir(); } diff --git a/parse/src/main/java/com/parse/ParseCommandCache.java b/parse/src/main/java/com/parse/ParseCommandCache.java index 5d09a1823..39afa01c0 100644 --- a/parse/src/main/java/com/parse/ParseCommandCache.java +++ b/parse/src/main/java/com/parse/ParseCommandCache.java @@ -127,7 +127,7 @@ public ParseCommandCache(Context context, ParseHttpClient client) { private static File getCacheDir() { // Construct the path to the cache directory. - File cacheDir = new File(Parse.getParseDir(), "CommandCache"); + File cacheDir = new File(Parse.getParseCacheDir(), "CommandCache"); cacheDir.mkdirs(); return cacheDir; @@ -522,13 +522,11 @@ private void maybeRunAllCommandsNow(int retriesRemaining) { String localId = command.getLocalId(); Exception error = task.getError(); if (error != null) { - if (error instanceof ParseException - && ((ParseException) error) + if (!(error instanceof ParseException) + || ((ParseException) error) .getCode() - == ParseException + != ParseException .CONNECTION_FAILED) { - // do nothing - } else { if (tcs != null) { tcs.setError(error); } diff --git a/parse/src/main/java/com/parse/ParseConfig.java b/parse/src/main/java/com/parse/ParseConfig.java index 4ebfa3789..1af180194 100644 --- a/parse/src/main/java/com/parse/ParseConfig.java +++ b/parse/src/main/java/com/parse/ParseConfig.java @@ -8,6 +8,7 @@ */ package com.parse; +import androidx.annotation.NonNull; import com.parse.boltsinternal.Task; import java.util.Collections; import java.util.Date; @@ -502,6 +503,7 @@ public String getString(String key, String defaultValue) { return (value instanceof String) ? (String) value : defaultValue; } + @NonNull @Override public String toString() { return "ParseConfig[" + params.toString() + "]"; diff --git a/parse/src/main/java/com/parse/ParseCorePlugins.java b/parse/src/main/java/com/parse/ParseCorePlugins.java index e8c7deed7..01d5ed54b 100644 --- a/parse/src/main/java/com/parse/ParseCorePlugins.java +++ b/parse/src/main/java/com/parse/ParseCorePlugins.java @@ -128,7 +128,7 @@ public void registerSessionController(ParseSessionController controller) { public ParseCurrentUserController getCurrentUserController() { if (currentUserController.get() == null) { - File file = new File(Parse.getParseDir(), FILENAME_CURRENT_USER); + File file = new File(Parse.getParseFilesDir(), FILENAME_CURRENT_USER); FileObjectStore fileStore = new FileObjectStore<>(ParseUser.class, file, ParseUserCurrentCoder.get()); ParseObjectStore store = @@ -227,7 +227,7 @@ public void registerCloudCodeController(ParseCloudCodeController controller) { public ParseConfigController getConfigController() { if (configController.get() == null) { // TODO(mengyan): Do not rely on Parse global - File file = new File(ParsePlugins.get().getParseDir(), FILENAME_CURRENT_CONFIG); + File file = new File(ParsePlugins.get().getFilesDir(), FILENAME_CURRENT_CONFIG); ParseCurrentConfigController currentConfigController = new ParseCurrentConfigController(file); configController.compareAndSet( @@ -277,7 +277,7 @@ public void registerPushChannelsController(ParsePushChannelsController controlle public ParseCurrentInstallationController getCurrentInstallationController() { if (currentInstallationController.get() == null) { - File file = new File(ParsePlugins.get().getParseDir(), FILENAME_CURRENT_INSTALLATION); + File file = new File(ParsePlugins.get().getFilesDir(), FILENAME_CURRENT_INSTALLATION); FileObjectStore fileStore = new FileObjectStore<>( ParseInstallation.class, file, ParseObjectCurrentCoder.get()); @@ -338,7 +338,7 @@ public void registerDefaultACLController(ParseDefaultACLController controller) { public LocalIdManager getLocalIdManager() { if (localIdManager.get() == null) { - LocalIdManager manager = new LocalIdManager(Parse.getParseDir()); + LocalIdManager manager = new LocalIdManager(Parse.getParseFilesDir()); localIdManager.compareAndSet(null, manager); } return localIdManager.get(); diff --git a/parse/src/main/java/com/parse/ParseEventuallyQueue.java b/parse/src/main/java/com/parse/ParseEventuallyQueue.java index 0882db4dd..63192e8a4 100644 --- a/parse/src/main/java/com/parse/ParseEventuallyQueue.java +++ b/parse/src/main/java/com/parse/ParseEventuallyQueue.java @@ -86,9 +86,7 @@ protected ParseRESTCommand commandFromJSON(JSONObject json) throws JSONException ParseRESTCommand command = null; if (ParseRESTCommand.isValidCommandJSONObject(json)) { command = ParseRESTCommand.fromJSONObject(json); - } else if (ParseRESTCommand.isValidOldFormatCommandJSONObject(json)) { - // do nothing - } else { + } else if (!ParseRESTCommand.isValidOldFormatCommandJSONObject(json)) { throw new JSONException("Failed to load command from JSON."); } return command; diff --git a/parse/src/main/java/com/parse/ParseFileUtils.java b/parse/src/main/java/com/parse/ParseFileUtils.java index c1f85686b..070baa111 100644 --- a/parse/src/main/java/com/parse/ParseFileUtils.java +++ b/parse/src/main/java/com/parse/ParseFileUtils.java @@ -314,7 +314,7 @@ private static void doCopyFile( long count; while (pos < size) { final long remain = size - pos; - count = remain > FILE_COPY_BUFFER_SIZE ? FILE_COPY_BUFFER_SIZE : remain; + count = Math.min(remain, FILE_COPY_BUFFER_SIZE); final long bytesCopied = output.transferFrom(input, pos, count); if (bytesCopied == 0) { // IO-385 - can happen if file is truncated after caching the size diff --git a/parse/src/main/java/com/parse/ParseObject.java b/parse/src/main/java/com/parse/ParseObject.java index d1176d011..5407bcf3e 100644 --- a/parse/src/main/java/com/parse/ParseObject.java +++ b/parse/src/main/java/com/parse/ParseObject.java @@ -3985,6 +3985,7 @@ protected void writeToParcel(Parcel dest, ParseParcelEncoder encoder) { dest.writeStringList(new ArrayList<>(availableKeys)); } + @NonNull @Override public String toString() { return String.format( diff --git a/parse/src/main/java/com/parse/ParseObjectCurrentCoder.java b/parse/src/main/java/com/parse/ParseObjectCurrentCoder.java index 3f5de3eb4..1659426a7 100644 --- a/parse/src/main/java/com/parse/ParseObjectCurrentCoder.java +++ b/parse/src/main/java/com/parse/ParseObjectCurrentCoder.java @@ -130,17 +130,11 @@ public > T decode( } if (json.has(KEY_OLD_CREATED_AT)) { String createdAtString = json.getString(KEY_OLD_CREATED_AT); - if (createdAtString != null) { - builder.createdAt( - ParseImpreciseDateFormat.getInstance().parse(createdAtString)); - } + builder.createdAt(ParseImpreciseDateFormat.getInstance().parse(createdAtString)); } if (json.has(KEY_OLD_UPDATED_AT)) { String updatedAtString = json.getString(KEY_OLD_UPDATED_AT); - if (updatedAtString != null) { - builder.updatedAt( - ParseImpreciseDateFormat.getInstance().parse(updatedAtString)); - } + builder.updatedAt(ParseImpreciseDateFormat.getInstance().parse(updatedAtString)); } if (json.has(KEY_OLD_POINTERS)) { JSONObject newPointers = json.getJSONObject(KEY_OLD_POINTERS); diff --git a/parse/src/main/java/com/parse/ParsePlugins.java b/parse/src/main/java/com/parse/ParsePlugins.java index 35e69ea29..df8c1ebe6 100644 --- a/parse/src/main/java/com/parse/ParsePlugins.java +++ b/parse/src/main/java/com/parse/ParsePlugins.java @@ -168,24 +168,13 @@ String userAgent() { InstallationId installationId() { synchronized (lock) { if (installationId == null) { - //noinspection deprecation installationId = - new InstallationId(new File(getParseDir(), INSTALLATION_ID_LOCATION)); + new InstallationId(new File(getFilesDir(), INSTALLATION_ID_LOCATION)); } return installationId; } } - @Deprecated - File getParseDir() { - synchronized (lock) { - if (parseDir == null) { - parseDir = applicationContext.getDir("Parse", Context.MODE_PRIVATE); - } - return createFileDir(parseDir); - } - } - File getCacheDir() { synchronized (lock) { if (cacheDir == null) { diff --git a/parse/src/main/java/com/parse/ParsePolygon.java b/parse/src/main/java/com/parse/ParsePolygon.java index 4c96faa2a..915e43729 100644 --- a/parse/src/main/java/com/parse/ParsePolygon.java +++ b/parse/src/main/java/com/parse/ParsePolygon.java @@ -10,6 +10,7 @@ import android.os.Parcel; import android.os.Parcelable; +import androidx.annotation.NonNull; import java.util.List; import java.util.Locale; import org.json.JSONArray; @@ -197,6 +198,7 @@ public boolean equals(Object obj) { return isEqual; } + @NonNull @Override public String toString() { return String.format(Locale.US, "ParsePolygon: %s", coordinates); diff --git a/parse/src/main/java/com/parse/ParsePushBroadcastReceiver.java b/parse/src/main/java/com/parse/ParsePushBroadcastReceiver.java index ff9eeba91..489fa01ef 100644 --- a/parse/src/main/java/com/parse/ParsePushBroadcastReceiver.java +++ b/parse/src/main/java/com/parse/ParsePushBroadcastReceiver.java @@ -221,19 +221,7 @@ protected void onPushOpen(Context context, Intent intent) { } activityIntent.putExtras(intent.getExtras()); - /* - In order to remove dependency on android-support-library-v4 - The reason why we differentiate between versions instead of just using context.startActivity - for all devices is because in API 11 the recommended conventions for app navigation using - the back key changed. - */ - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { - TaskStackBuilderHelper.startActivities(context, cls, activityIntent); - } else { - activityIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - activityIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); - context.startActivity(activityIntent); - } + TaskStackBuilderHelper.startActivities(context, cls, activityIntent); } /** @@ -464,9 +452,7 @@ protected NotificationCompat.Builder getNotification(Context context, Intent int // from system defaults .setDefaults(Notification.DEFAULT_ALL); - if (alert != null - && alert.length() - > ParsePushBroadcastReceiver.SMALL_NOTIFICATION_MAX_CHARACTER_LIMIT) { + if (alert.length() > ParsePushBroadcastReceiver.SMALL_NOTIFICATION_MAX_CHARACTER_LIMIT) { notificationBuilder.setStyle(new NotificationCompat.BigTextStyle().bigText(alert)); } return notificationBuilder; diff --git a/parse/src/main/java/com/parse/ParseQuery.java b/parse/src/main/java/com/parse/ParseQuery.java index 8da58d89b..8c0288454 100644 --- a/parse/src/main/java/com/parse/ParseQuery.java +++ b/parse/src/main/java/com/parse/ParseQuery.java @@ -1392,7 +1392,6 @@ private interface CacheThenNetworkCallable { * values can either be actual values to compare with for equality, or instances of {@link * KeyConstraints}. */ - @SuppressWarnings("serial") /* package */ static class QueryConstraints extends HashMap { public QueryConstraints() { @@ -1409,7 +1408,6 @@ public QueryConstraints(Map map) { * special operators, such as $greaterThan or $nin. The values are the actual values to compare * against. */ - @SuppressWarnings("serial") /* package */ static class KeyConstraints extends HashMap {} /** Constraint for a $relatedTo query. */ @@ -1588,6 +1586,7 @@ public boolean ignoreACLs() { return params; } + @NonNull @Override public String toString() { return String.format( diff --git a/parse/src/main/java/com/parse/ParseSQLiteCursor.java b/parse/src/main/java/com/parse/ParseSQLiteCursor.java deleted file mode 100644 index ce6a15d77..000000000 --- a/parse/src/main/java/com/parse/ParseSQLiteCursor.java +++ /dev/null @@ -1,264 +0,0 @@ -/* - * 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 android.annotation.TargetApi; -import android.content.ContentResolver; -import android.database.CharArrayBuffer; -import android.database.ContentObserver; -import android.database.Cursor; -import android.database.DataSetObserver; -import android.net.Uri; -import android.os.Build; -import android.os.Bundle; -import com.parse.boltsinternal.Task; -import java.util.concurrent.Callable; -import java.util.concurrent.Executor; - -/** - * Wrapper class to invoke {@link Cursor#close()} on a specific thread on Android versions below - * android-14 as they require {@link Cursor#close()} to be called on the same thread the cursor was - * created in - * - *

https://github.com/android/platform_frameworks_base/commit/6f37f83a4802a0d411395f3abc5f24a2cfec025d - */ -class ParseSQLiteCursor implements Cursor { - - private final Cursor cursor; - private final Executor executor; - - private ParseSQLiteCursor(Cursor cursor, Executor executor) { - this.cursor = cursor; - this.executor = executor; - } - - public static Cursor create(Cursor cursor, Executor executor) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { - return cursor; - } - return new ParseSQLiteCursor(cursor, executor); - } - - @Override - public int getCount() { - return cursor.getCount(); - } - - @Override - public int getPosition() { - return cursor.getPosition(); - } - - @Override - public boolean move(int offset) { - return cursor.move(offset); - } - - @Override - public boolean moveToPosition(int position) { - return cursor.moveToPosition(position); - } - - @Override - public boolean moveToFirst() { - return cursor.moveToFirst(); - } - - @Override - public boolean moveToLast() { - return cursor.moveToLast(); - } - - @Override - public boolean moveToNext() { - return cursor.moveToNext(); - } - - @Override - public boolean moveToPrevious() { - return cursor.moveToPrevious(); - } - - @Override - public boolean isFirst() { - return cursor.isFirst(); - } - - @Override - public boolean isLast() { - return cursor.isLast(); - } - - @Override - public boolean isBeforeFirst() { - return cursor.isBeforeFirst(); - } - - @Override - public boolean isAfterLast() { - return cursor.isAfterLast(); - } - - @Override - public int getColumnIndex(String columnName) { - return cursor.getColumnIndex(columnName); - } - - @Override - public int getColumnIndexOrThrow(String columnName) throws IllegalArgumentException { - return cursor.getColumnIndexOrThrow(columnName); - } - - @Override - public String getColumnName(int columnIndex) { - return cursor.getColumnName(columnIndex); - } - - @Override - public String[] getColumnNames() { - return cursor.getColumnNames(); - } - - @Override - public int getColumnCount() { - return cursor.getColumnCount(); - } - - @Override - public byte[] getBlob(int columnIndex) { - return cursor.getBlob(columnIndex); - } - - @Override - public String getString(int columnIndex) { - return cursor.getString(columnIndex); - } - - @Override - public void copyStringToBuffer(int columnIndex, CharArrayBuffer buffer) { - cursor.copyStringToBuffer(columnIndex, buffer); - } - - @Override - public short getShort(int columnIndex) { - return cursor.getShort(columnIndex); - } - - @Override - public int getInt(int columnIndex) { - return cursor.getInt(columnIndex); - } - - @Override - public long getLong(int columnIndex) { - return cursor.getLong(columnIndex); - } - - @Override - public float getFloat(int columnIndex) { - return cursor.getFloat(columnIndex); - } - - @Override - public double getDouble(int columnIndex) { - return cursor.getDouble(columnIndex); - } - - @TargetApi(Build.VERSION_CODES.HONEYCOMB) - @Override - public int getType(int columnIndex) { - return cursor.getType(columnIndex); - } - - @Override - public boolean isNull(int columnIndex) { - return cursor.isNull(columnIndex); - } - - @Override - @Deprecated - public void deactivate() { - cursor.deactivate(); - } - - @Override - @Deprecated - public boolean requery() { - return cursor.requery(); - } - - @Override - public void close() { - // Basically close _eventually_. - Task.call( - (Callable) - () -> { - cursor.close(); - return null; - }, - executor); - } - - @Override - public boolean isClosed() { - return cursor.isClosed(); - } - - @Override - public void registerContentObserver(ContentObserver observer) { - cursor.registerContentObserver(observer); - } - - @Override - public void unregisterContentObserver(ContentObserver observer) { - cursor.unregisterContentObserver(observer); - } - - @Override - public void registerDataSetObserver(DataSetObserver observer) { - cursor.registerDataSetObserver(observer); - } - - @Override - public void unregisterDataSetObserver(DataSetObserver observer) { - cursor.unregisterDataSetObserver(observer); - } - - @Override - public void setNotificationUri(ContentResolver cr, Uri uri) { - cursor.setNotificationUri(cr, uri); - } - - @TargetApi(Build.VERSION_CODES.KITKAT) - @Override - public Uri getNotificationUri() { - return cursor.getNotificationUri(); - } - - @Override - public boolean getWantsAllOnMoveCalls() { - return cursor.getWantsAllOnMoveCalls(); - } - - @Override - public Bundle getExtras() { - return cursor.getExtras(); - } - - @TargetApi(Build.VERSION_CODES.M) - @Override - public void setExtras(Bundle bundle) { - cursor.setExtras(bundle); - } - - @Override - public Bundle respond(Bundle extras) { - return cursor.respond(extras); - } -} diff --git a/parse/src/main/java/com/parse/ParseSQLiteDatabase.java b/parse/src/main/java/com/parse/ParseSQLiteDatabase.java index 6dd7ff969..dc1f667ac 100644 --- a/parse/src/main/java/com/parse/ParseSQLiteDatabase.java +++ b/parse/src/main/java/com/parse/ParseSQLiteDatabase.java @@ -217,9 +217,7 @@ public Task queryAsync( dbExecutor) .onSuccess( task12 -> { - Cursor cursor = - ParseSQLiteCursor.create( - task12.getResult(), dbExecutor); + Cursor cursor = task12.getResult(); /* Ensure the cursor window is filled on the dbExecutor thread. We need to do this because * the cursor cannot be filled from a different thread than it was created on. */ @@ -335,9 +333,7 @@ public Task rawQueryAsync(final String sql, final String[] args) { current.onSuccess(task13 -> db.rawQuery(sql, args), dbExecutor) .onSuccess( task12 -> { - Cursor cursor = - ParseSQLiteCursor.create( - task12.getResult(), dbExecutor); + Cursor cursor = task12.getResult(); // Ensure the cursor window is filled on the dbExecutor // thread. We need to do this because // the cursor cannot be filled from a different thread than diff --git a/parse/src/main/java/com/parse/ParseTaskUtils.java b/parse/src/main/java/com/parse/ParseTaskUtils.java index 6cd25d444..a76326743 100644 --- a/parse/src/main/java/com/parse/ParseTaskUtils.java +++ b/parse/src/main/java/com/parse/ParseTaskUtils.java @@ -98,7 +98,7 @@ static Task callbackOnMainThreadAsync( if (callback == null) { return task; } - final TaskCompletionSource tcs = new TaskCompletionSource(); + final TaskCompletionSource tcs = new TaskCompletionSource<>(); task.continueWith( (Continuation) task1 -> { diff --git a/parse/src/main/java/com/parse/PushRouter.java b/parse/src/main/java/com/parse/PushRouter.java index 56acac628..305f76096 100644 --- a/parse/src/main/java/com/parse/PushRouter.java +++ b/parse/src/main/java/com/parse/PushRouter.java @@ -29,7 +29,6 @@ */ public class PushRouter { private static final String TAG = "com.parse.ParsePushRouter"; - private static final String LEGACY_STATE_LOCATION = "pushState"; private static final String STATE_LOCATION = "push"; private static final int MAX_HISTORY_LENGTH = 10; @@ -45,8 +44,7 @@ private PushRouter(File diskState, PushHistory history) { public static synchronized PushRouter getInstance() { if (instance == null) { File diskState = new File(ParsePlugins.get().getFilesDir(), STATE_LOCATION); - File oldDiskState = new File(ParsePlugins.get().getParseDir(), LEGACY_STATE_LOCATION); - instance = pushRouterFromState(diskState, oldDiskState, MAX_HISTORY_LENGTH); + instance = pushRouterFromState(diskState, MAX_HISTORY_LENGTH); } return instance; @@ -59,33 +57,11 @@ static synchronized void resetInstance() { } /* package for tests */ - static PushRouter pushRouterFromState(File diskState, File oldDiskState, int maxHistoryLength) { + static PushRouter pushRouterFromState(File diskState, int maxHistoryLength) { JSONObject state = readJSONFileQuietly(diskState); JSONObject historyJSON = (state != null) ? state.optJSONObject("history") : null; PushHistory history = new PushHistory(maxHistoryLength, historyJSON); - - // If the deserialized push history object doesn't have a last timestamp, we might have to - // migrate the last timestamp from the legacy pushState file instead. - boolean didMigrate = false; - if (history.getLastReceivedTimestamp() == null) { - JSONObject oldState = readJSONFileQuietly(oldDiskState); - if (oldState != null) { - String lastTime = oldState.optString("lastTime", null); - if (lastTime != null) { - history.setLastReceivedTimestamp(lastTime); - } - didMigrate = true; - } - } - - PushRouter router = new PushRouter(diskState, history); - - if (didMigrate) { - router.saveStateToDisk(); - ParseFileUtils.deleteQuietly(oldDiskState); - } - - return router; + return new PushRouter(diskState, history); } private static JSONObject readJSONFileQuietly(File file) { diff --git a/parse/src/test/java/com/parse/ParseAnalyticsTest.java b/parse/src/test/java/com/parse/ParseAnalyticsTest.java index 97697cede..94fa856f9 100644 --- a/parse/src/test/java/com/parse/ParseAnalyticsTest.java +++ b/parse/src/test/java/com/parse/ParseAnalyticsTest.java @@ -12,7 +12,7 @@ import static org.junit.Assert.assertNull; import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; -import static org.mockito.Matchers.anyMapOf; +import static org.mockito.ArgumentMatchers.anyMap; import static org.mockito.Matchers.anyString; import static org.mockito.Matchers.eq; import static org.mockito.Matchers.isNull; @@ -53,11 +53,10 @@ public void setUp() { // Mock ParseAnalyticsController controller = mock(ParseAnalyticsController.class); - when(controller.trackEventInBackground( - anyString(), anyMapOf(String.class, String.class), anyString())) - .thenReturn(Task.forResult(null)); + when(controller.trackEventInBackground(anyString(), anyMap(), anyString())) + .thenReturn(Task.forResult(null)); when(controller.trackAppOpenedInBackground(anyString(), anyString())) - .thenReturn(Task.forResult(null)); + .thenReturn(Task.forResult(null)); ParseCorePlugins.getInstance().registerAnalyticsController(controller); } @@ -94,8 +93,7 @@ public void testTrackEventInBackgroundNormalName() throws Exception { ParseTaskUtils.wait(ParseAnalytics.trackEventInBackground("test")); verify(controller, times(1)) - .trackEventInBackground( - eq("test"), Matchers.>eq(null), isNull(String.class)); + .trackEventInBackground(eq("test"), Matchers.eq(null), isNull(String.class)); } @Test @@ -104,8 +102,7 @@ public void testTrackEventInBackgroundNullParameters() throws Exception { ParseAnalytics.trackEventInBackground("test", (Map) null)); verify(controller, times(1)) - .trackEventInBackground( - eq("test"), Matchers.>eq(null), isNull(String.class)); + .trackEventInBackground(eq("test"), Matchers.eq(null), isNull(String.class)); } @Test @@ -169,8 +166,7 @@ public void testTrackEventInBackgroundNormalCallback() throws Exception { // Make sure the callback is called assertTrue(doneAgain.tryAcquire(1, 10, TimeUnit.SECONDS)); verify(controller, times(1)) - .trackEventInBackground( - eq("test"), Matchers.>eq(null), isNull(String.class)); + .trackEventInBackground(eq("test"), Matchers.eq(null), isNull(String.class)); } // endregion diff --git a/parse/src/test/java/com/parse/ParseTestUtils.java b/parse/src/test/java/com/parse/ParseTestUtils.java index ce5b15bf2..b5c08192c 100644 --- a/parse/src/test/java/com/parse/ParseTestUtils.java +++ b/parse/src/test/java/com/parse/ParseTestUtils.java @@ -69,7 +69,7 @@ static ParsePlugins mockParsePlugins(Parse.Configuration configuration) { File parseDir = createFileDir(applicationContext.getDir("Parse", Context.MODE_PRIVATE)); when(parsePlugins.installationId()) .thenReturn(new InstallationId(new File(parseDir, "installationId"))); - when(parsePlugins.getParseDir()).thenReturn(parseDir); + when(parsePlugins.getFilesDir()).thenReturn(parseDir); when(parsePlugins.getCacheDir()) .thenReturn(createFileDir(new File(applicationContext.getCacheDir(), "com.parse"))); when(parsePlugins.getFilesDir()) diff --git a/parse/src/test/java/com/parse/ParseUserTest.java b/parse/src/test/java/com/parse/ParseUserTest.java index fcb1f69a0..8920e5832 100644 --- a/parse/src/test/java/com/parse/ParseUserTest.java +++ b/parse/src/test/java/com/parse/ParseUserTest.java @@ -14,12 +14,12 @@ import static org.junit.Assert.assertNull; import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.ArgumentMatchers.anyMap; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.nullable; -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.anyBoolean; -import static org.mockito.Matchers.anyMapOf; -import static org.mockito.Matchers.anyString; -import static org.mockito.Matchers.eq; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; @@ -51,7 +51,6 @@ import org.junit.rules.ExpectedException; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; -import org.mockito.Matchers; import org.robolectric.RobolectricTestRunner; import org.robolectric.RuntimeEnvironment; import org.robolectric.Shadows; @@ -155,8 +154,7 @@ public void testParcelableState() { public void testSignUpAsyncWithNoUserName() throws Exception { // Register a mock currentUserController to make getCurrentUser work ParseCurrentUserController currentUserController = mock(ParseCurrentUserController.class); - when(currentUserController.getAsync(anyBoolean())) - .thenReturn(Task.forResult(null)); + when(currentUserController.getAsync(anyBoolean())).thenReturn(Task.forResult(null)); ParseCorePlugins.getInstance().registerCurrentUserController(currentUserController); ParseUser user = new ParseUser(); @@ -164,15 +162,14 @@ public void testSignUpAsyncWithNoUserName() throws Exception { thrown.expect(IllegalArgumentException.class); thrown.expectMessage("Username cannot be missing or blank"); - ParseTaskUtils.wait(user.signUpAsync(Task.forResult(null))); + ParseTaskUtils.wait(user.signUpAsync(Task.forResult(null))); } @Test public void testSignUpAsyncWithNoPassword() throws Exception { // Register a mock currentUserController to make getCurrentUser work ParseCurrentUserController currentUserController = mock(ParseCurrentUserController.class); - when(currentUserController.getAsync(anyBoolean())) - .thenReturn(Task.forResult(null)); + when(currentUserController.getAsync(anyBoolean())).thenReturn(Task.forResult(null)); ParseCorePlugins.getInstance().registerCurrentUserController(currentUserController); ParseUser user = new ParseUser(); @@ -181,15 +178,14 @@ public void testSignUpAsyncWithNoPassword() throws Exception { thrown.expect(IllegalArgumentException.class); thrown.expectMessage("Password cannot be missing or blank"); - ParseTaskUtils.wait(user.signUpAsync(Task.forResult(null))); + ParseTaskUtils.wait(user.signUpAsync(Task.forResult(null))); } @Test public void testSignUpAsyncWithObjectIdSetAndAuthDataNotSet() throws Exception { // Register a mock currentUserController to make getCurrentUser work ParseCurrentUserController currentUserController = mock(ParseCurrentUserController.class); - when(currentUserController.getAsync(anyBoolean())) - .thenReturn(Task.forResult(null)); + when(currentUserController.getAsync(anyBoolean())).thenReturn(Task.forResult(null)); ParseCorePlugins.getInstance().registerCurrentUserController(currentUserController); ParseUser.State userState = new ParseUser.State.Builder().objectId("test").build(); @@ -200,7 +196,7 @@ public void testSignUpAsyncWithObjectIdSetAndAuthDataNotSet() throws Exception { thrown.expect(IllegalArgumentException.class); thrown.expectMessage("Cannot sign up a user that has already signed up."); - ParseTaskUtils.wait(user.signUpAsync(Task.forResult(null))); + ParseTaskUtils.wait(user.signUpAsync(Task.forResult(null))); } @Test @@ -222,22 +218,19 @@ public void testSignUpAsyncWithObjectIdSetAndAuthDataSet() throws Exception { user.setPassword("password"); // TODO (mengyan): Avoid using partial mock after we have ParseObjectInstanceController ParseUser partialMockUser = spy(user); - doReturn(Task.forResult(null)) - .when(partialMockUser) - .saveAsync(anyString(), Matchers.>any()); + doReturn(Task.forResult(null)).when(partialMockUser).saveAsync(anyString(), any()); - ParseTaskUtils.wait(partialMockUser.signUpAsync(Task.forResult(null))); + ParseTaskUtils.wait(partialMockUser.signUpAsync(Task.forResult(null))); // Verify user is saved - verify(partialMockUser, times(1)).saveAsync(eq("sessionToken"), Matchers.>any()); + verify(partialMockUser, times(1)).saveAsync(eq("sessionToken"), any()); } @Test public void testSignUpAsyncWithAnotherSignUpAlreadyRunning() throws Exception { // Register a mock currentUserController to make getCurrentUser work ParseCurrentUserController currentUserController = mock(ParseCurrentUserController.class); - when(currentUserController.getAsync(anyBoolean())) - .thenReturn(Task.forResult(null)); + when(currentUserController.getAsync(anyBoolean())).thenReturn(Task.forResult(null)); ParseCorePlugins.getInstance().registerCurrentUserController(currentUserController); ParseUser user = new ParseUser(); @@ -248,7 +241,7 @@ public void testSignUpAsyncWithAnotherSignUpAlreadyRunning() throws Exception { thrown.expect(IllegalArgumentException.class); thrown.expectMessage("Cannot sign up a user that is already signing up."); - ParseTaskUtils.wait(user.signUpAsync(Task.forResult(null))); + ParseTaskUtils.wait(user.signUpAsync(Task.forResult(null))); } @Test @@ -268,7 +261,7 @@ public void testSignUpAsyncWithSignUpSameAnonymousUser() throws Exception { thrown.expect(IllegalArgumentException.class); thrown.expectMessage("Attempt to merge currentUser with itself."); - ParseTaskUtils.wait(user.signUpAsync(Task.forResult(null))); + ParseTaskUtils.wait(user.signUpAsync(Task.forResult(null))); } @Test @@ -281,8 +274,7 @@ public void testSignUpAsyncWithMergeInDiskAnonymousUser() throws Exception { when(currentUser.isLinked(ParseAnonymousUtils.AUTH_TYPE)).thenReturn(true); when(currentUser.getSessionToken()).thenReturn("oldSessionToken"); when(currentUser.getAuthData()).thenReturn(new HashMap<>()); - when(currentUser.saveAsync(anyString(), eq(false), Matchers.>any())) - .thenReturn(Task.forResult(null)); + when(currentUser.saveAsync(anyString(), eq(false), any())).thenReturn(Task.forResult(null)); ParseUser.State state = new ParseUser.State.Builder().put("oldKey", "oldValue").build(); when(currentUser.getState()).thenReturn(state); ParseCurrentUserController currentUserController = mock(ParseCurrentUserController.class); @@ -296,7 +288,7 @@ public void testSignUpAsyncWithMergeInDiskAnonymousUser() throws Exception { anonymousAuthData.put("key", "token"); user.putAuthData(ParseAnonymousUtils.AUTH_TYPE, anonymousAuthData); - Task signUpTask = user.signUpAsync(Task.forResult(null)); + Task signUpTask = user.signUpAsync(Task.forResult(null)); signUpTask.waitForCompletion(); // Make sure currentUser copy changes from user @@ -305,8 +297,7 @@ public void testSignUpAsyncWithMergeInDiskAnonymousUser() throws Exception { verify(currentUser, times(1)).setUsername("userName"); verify(currentUser, times(1)).setPassword("password"); // Make sure we save currentUser - verify(currentUser, times(1)) - .saveAsync(eq("oldSessionToken"), eq(false), Matchers.>any()); + verify(currentUser, times(1)).saveAsync(eq("oldSessionToken"), eq(false), any()); // Make sure we merge currentUser with user after save assertEquals("oldValue", user.get("oldKey")); // Make sure set currentUser @@ -328,7 +319,7 @@ public void testSignUpAsyncWithMergeInDiskAnonymousUserSaveFailure() throws Exce ParseException saveException = new ParseException(ParseException.OTHER_CAUSE, ""); doReturn(Task.forError(saveException)) .when(partialMockCurrentUser) - .saveAsync(anyString(), eq(false), Matchers.>any()); + .saveAsync(anyString(), eq(false), any()); ParseCurrentUserController currentUserController = mock(ParseCurrentUserController.class); when(currentUserController.getAsync(anyBoolean())) .thenReturn(Task.forResult(partialMockCurrentUser)); @@ -341,7 +332,7 @@ public void testSignUpAsyncWithMergeInDiskAnonymousUserSaveFailure() throws Exce anonymousAuthData.put("key", "token"); user.putAuthData(ParseAnonymousUtils.AUTH_TYPE, anonymousAuthData); - Task signUpTask = user.signUpAsync(Task.forResult(null)); + Task signUpTask = user.signUpAsync(Task.forResult(null)); signUpTask.waitForCompletion(); // Make sure we update currentUser username and password @@ -350,8 +341,7 @@ public void testSignUpAsyncWithMergeInDiskAnonymousUserSaveFailure() throws Exce // Make sure we sync user with currentUser verify(partialMockCurrentUser, times(1)).copyChangesFrom(eq(user)); // Make sure we save currentUser - verify(partialMockCurrentUser, times(1)) - .saveAsync(eq("oldSessionToken"), eq(false), Matchers.>any()); + verify(partialMockCurrentUser, times(1)).saveAsync(eq("oldSessionToken"), eq(false), any()); // Make sure we restore old username and password after save fails verify(partialMockCurrentUser, times(1)).setUsername("oldUserName"); verify(partialMockCurrentUser, times(1)).setPassword("oldPassword"); @@ -367,8 +357,7 @@ public void testSignUpAsyncWithMergeInDiskAnonymousUserSaveFailure() throws Exce public void testSignUpAsyncWithNoCurrentUserAndSignUpSuccess() throws Exception { // Register a mock currentUserController to make getCurrentUser work ParseCurrentUserController currentUserController = mock(ParseCurrentUserController.class); - when(currentUserController.getAsync(anyBoolean())) - .thenReturn(Task.forResult(null)); + when(currentUserController.getAsync(anyBoolean())).thenReturn(Task.forResult(null)); ParseCorePlugins.getInstance().registerCurrentUserController(currentUserController); // Register a mock userController to make logIn work ParseUserController userController = mock(ParseUserController.class); @@ -388,7 +377,7 @@ public void testSignUpAsyncWithNoCurrentUserAndSignUpSuccess() throws Exception user.setUsername("userName"); user.setPassword("password"); - ParseTaskUtils.wait(user.signUpAsync(Task.forResult(null))); + ParseTaskUtils.wait(user.signUpAsync(Task.forResult(null))); // Make sure we sign up the user verify(userController, times(1)) @@ -412,8 +401,7 @@ public void testSignUpAsyncWithNoCurrentUserAndSignUpSuccess() throws Exception public void testSignUpAsyncWithNoCurrentUserAndSignUpFailure() { // Register a mock currentUserController to make getCurrentUser work ParseCurrentUserController currentUserController = mock(ParseCurrentUserController.class); - when(currentUserController.getAsync(anyBoolean())) - .thenReturn(Task.forResult(null)); + when(currentUserController.getAsync(anyBoolean())).thenReturn(Task.forResult(null)); ParseCorePlugins.getInstance().registerCurrentUserController(currentUserController); // Register a mock userController to make logIn work ParseUserController userController = mock(ParseUserController.class); @@ -422,7 +410,7 @@ public void testSignUpAsyncWithNoCurrentUserAndSignUpFailure() { any(ParseUser.State.class), any(ParseOperationSet.class), nullable(String.class))) - .thenReturn(Task.forError(signUpException)); + .thenReturn(Task.forError(signUpException)); ParseCorePlugins.getInstance().registerUserController(userController); ParseUser user = new ParseUser(); @@ -430,7 +418,7 @@ public void testSignUpAsyncWithNoCurrentUserAndSignUpFailure() { user.setUsername("userName"); user.setPassword("password"); - Task signUpTask = user.signUpAsync(Task.forResult(null)); + Task signUpTask = user.signUpAsync(Task.forResult(null)); // Make sure we sign up the user verify(userController, times(1)) @@ -450,9 +438,8 @@ public void testSignUpAsyncWithNoCurrentUserAndSignUpFailure() { @Test public void testLoginWithAsyncWithoutExistingLazyUser() throws ParseException { ParseCurrentUserController currentUserController = mock(ParseCurrentUserController.class); - when(currentUserController.getAsync(false)).thenReturn(Task.forResult(null)); - when(currentUserController.setAsync(any(ParseUser.class))) - .thenReturn(Task.forResult(null)); + when(currentUserController.getAsync(false)).thenReturn(Task.forResult(null)); + when(currentUserController.setAsync(any(ParseUser.class))).thenReturn(Task.forResult(null)); ParseUser.State userState = mock(ParseUser.State.class); when(userState.className()).thenReturn("_User"); @@ -460,7 +447,7 @@ public void testLoginWithAsyncWithoutExistingLazyUser() throws ParseException { when(userState.isComplete()).thenReturn(true); ParseUserController userController = mock(ParseUserController.class); - when(userController.logInAsync(anyString(), anyMapOf(String.class, String.class))) + when(userController.logInAsync(anyString(), anyMap())) .thenReturn(Task.forResult(userState)); ParseCorePlugins.getInstance().registerCurrentUserController(currentUserController); @@ -490,7 +477,7 @@ public void testLoginWithAsyncWithLinkedLazyUser() throws Exception { when(partialMockCurrentUser.getSessionToken()).thenReturn("oldSessionToken"); doReturn(Task.forResult(null)) .when(partialMockCurrentUser) - .resolveLazinessAsync(Matchers.>any()); + .resolveLazinessAsync(any()); ParseCurrentUserController currentUserController = mock(ParseCurrentUserController.class); when(currentUserController.getAsync(false)) .thenReturn(Task.forResult(partialMockCurrentUser)); @@ -507,7 +494,7 @@ public void testLoginWithAsyncWithLinkedLazyUser() throws Exception { // Make sure we update authData assertEquals(authData, userAfterLogin.getAuthData().get("facebook")); // Make sure we resolveLaziness - verify(partialMockCurrentUser, times(1)).resolveLazinessAsync(Matchers.>any()); + verify(partialMockCurrentUser, times(1)).resolveLazinessAsync(any()); } @Test @@ -521,7 +508,7 @@ public void testLoginWithAsyncWithLinkedLazyUseAndResolveLazinessFailure() throw when(partialMockCurrentUser.getSessionToken()).thenReturn("oldSessionToken"); doReturn(Task.forError(new Exception())) .when(partialMockCurrentUser) - .resolveLazinessAsync(Matchers.>any()); + .resolveLazinessAsync(any()); ParseCurrentUserController currentUserController = mock(ParseCurrentUserController.class); when(currentUserController.getAsync(false)) .thenReturn(Task.forResult(partialMockCurrentUser)); @@ -535,7 +522,7 @@ public void testLoginWithAsyncWithLinkedLazyUseAndResolveLazinessFailure() throw loginTask.waitForCompletion(); // Make sure we try to resolveLaziness - verify(partialMockCurrentUser, times(1)).resolveLazinessAsync(Matchers.>any()); + verify(partialMockCurrentUser, times(1)).resolveLazinessAsync(any()); // Make sure we do not save new authData assertNull(partialMockCurrentUser.getAuthData().get("facebook")); // Make sure we restore anonymity after resolve laziness failure @@ -558,7 +545,7 @@ public void testLoginWithAsyncWithLinkedNotLazyUser() throws Exception { ParseUser partialMockCurrentUser = spy(currentUser); // ParseUser.mutex doReturn(Task.forResult(null)) .when(partialMockCurrentUser) - .linkWithInBackground(anyString(), Matchers.>any()); + .linkWithInBackground(anyString(), anyMap()); ParseCurrentUserController currentUserController = mock(ParseCurrentUserController.class); when(currentUserController.getAsync()).thenReturn(Task.forResult(partialMockCurrentUser)); when(currentUserController.getAsync(anyBoolean())) @@ -586,7 +573,7 @@ public void testLoginWithAsyncWithLinkedNotLazyUserLinkFailure() throws Exceptio .put("newKey", "newValue") .sessionToken("newSessionToken") .build(); - when(userController.logInAsync(anyString(), Matchers.>any())) + when(userController.logInAsync(anyString(), anyMap())) .thenReturn(Task.forResult(newUserState)); ParseCorePlugins.getInstance().registerUserController(userController); // Register a mock currentUserController to make getCurrentUser work @@ -599,12 +586,11 @@ public void testLoginWithAsyncWithLinkedNotLazyUserLinkFailure() throws Exceptio new ParseException(ParseException.ACCOUNT_ALREADY_LINKED, "Account already linked"); doReturn(Task.forError(linkException)) .when(partialMockCurrentUser) - .linkWithInBackground(anyString(), Matchers.>any()); + .linkWithInBackground(anyString(), anyMap()); ParseCurrentUserController currentUserController = mock(ParseCurrentUserController.class); when(currentUserController.getAsync(false)) .thenReturn(Task.forResult(partialMockCurrentUser)); - when(currentUserController.setAsync(any(ParseUser.class))) - .thenReturn(Task.forResult(null)); + when(currentUserController.setAsync(any(ParseUser.class))).thenReturn(Task.forResult(null)); ParseCorePlugins.getInstance().registerCurrentUserController(currentUserController); String authType = "facebook"; @@ -637,14 +623,13 @@ public void testLoginWithAsyncWithNoCurrentUser() throws Exception { .put("newKey", "newValue") .sessionToken("newSessionToken") .build(); - when(userController.logInAsync(anyString(), Matchers.>any())) + when(userController.logInAsync(anyString(), anyMap())) .thenReturn(Task.forResult(newUserState)); ParseCorePlugins.getInstance().registerUserController(userController); // Register a mock currentUserController to make getCurrentUser work ParseCurrentUserController currentUserController = mock(ParseCurrentUserController.class); - when(currentUserController.getAsync(false)).thenReturn(Task.forResult(null)); - when(currentUserController.setAsync(any(ParseUser.class))) - .thenReturn(Task.forResult(null)); + when(currentUserController.getAsync(false)).thenReturn(Task.forResult(null)); + when(currentUserController.setAsync(any(ParseUser.class))).thenReturn(Task.forResult(null)); ParseCorePlugins.getInstance().registerCurrentUserController(currentUserController); String authType = "facebook"; @@ -667,14 +652,12 @@ public void testLoginWithAsyncWithNoCurrentUser() throws Exception { public void testlinkWithInBackgroundWithSaveAsyncSuccess() throws Exception { // Register a mock currentUserController to make setCurrentUser work ParseCurrentUserController currentUserController = mock(ParseCurrentUserController.class); - when(currentUserController.getCurrentSessionTokenAsync()) - .thenReturn(Task.forResult(null)); - when(currentUserController.getAsync(anyBoolean())) - .thenReturn(Task.forResult(null)); + when(currentUserController.getCurrentSessionTokenAsync()).thenReturn(Task.forResult(null)); + when(currentUserController.getAsync(anyBoolean())).thenReturn(Task.forResult(null)); ParseCorePlugins.getInstance().registerCurrentUserController(currentUserController); // Register mock callbacks AuthenticationCallback callbacks = mock(AuthenticationCallback.class); - when(callbacks.onRestore(Matchers.>any())).thenReturn(true); + when(callbacks.onRestore(anyMap())).thenReturn(true); ParseUser.registerAuthenticationCallback("facebook", callbacks); ParseUser user = new ParseUser(); @@ -686,7 +669,7 @@ public void testlinkWithInBackgroundWithSaveAsyncSuccess() throws Exception { ParseUser partialMockUser = spy(user); doReturn(Task.forResult(null)) .when(partialMockUser) - .saveAsync(anyString(), eq(false), Matchers.>any()); + .saveAsync(anyString(), eq(false), any()); doReturn("sessionTokenAgain").when(partialMockUser).getSessionToken(); Map authData = new HashMap<>(); authData.put("token", "test"); @@ -698,8 +681,7 @@ public void testlinkWithInBackgroundWithSaveAsyncSuccess() throws Exception { // Make sure new authData is added assertSame(authData, partialMockUser.getAuthData().get("facebook")); // Make sure we save the user - verify(partialMockUser, times(1)) - .saveAsync(eq("sessionTokenAgain"), eq(false), Matchers.>any()); + verify(partialMockUser, times(1)).saveAsync(eq("sessionTokenAgain"), eq(false), any()); // Make sure synchronizeAuthData() is called verify(callbacks, times(1)).onRestore(authData); } @@ -726,7 +708,7 @@ public void testlinkWithInBackgroundWithSaveAsyncFailure() throws Exception { Exception saveException = new Exception(); doReturn(Task.forError(saveException)) .when(partialMockUser) - .saveAsync(anyString(), eq(false), Matchers.>any()); + .saveAsync(anyString(), eq(false), any()); doReturn("sessionTokenAgain").when(partialMockUser).getSessionToken(); String authType = "facebook"; Map authData = new HashMap<>(); @@ -736,8 +718,7 @@ public void testlinkWithInBackgroundWithSaveAsyncFailure() throws Exception { linkTask.waitForCompletion(); // Make sure we save the user - verify(partialMockUser, times(1)) - .saveAsync(eq("sessionTokenAgain"), eq(false), Matchers.>any()); + verify(partialMockUser, times(1)).saveAsync(eq("sessionTokenAgain"), eq(false), any()); // Make sure old authData is restored assertSame( anonymousAuthData, @@ -766,11 +747,10 @@ public void testResolveLazinessAsyncWithAuthDataAndNotNewUser() throws Exception ParseCorePlugins.getInstance().registerUserController(userController); // Register a mock currentUserController to make getCurrentUser work ParseCurrentUserController currentUserController = mock(ParseCurrentUserController.class); - when(currentUserController.setAsync(any(ParseUser.class))) - .thenReturn(Task.forResult(null)); + when(currentUserController.setAsync(any(ParseUser.class))).thenReturn(Task.forResult(null)); ParseCorePlugins.getInstance().registerCurrentUserController(currentUserController); - ParseTaskUtils.wait(user.resolveLazinessAsync(Task.forResult(null))); + ParseTaskUtils.wait(user.resolveLazinessAsync(Task.forResult(null))); ArgumentCaptor userAfterResolveLazinessCaptor = ArgumentCaptor.forClass(ParseUser.class); @@ -810,7 +790,7 @@ public void testResolveLazinessAsyncWithAuthDataAndNewUser() throws Exception { ParseCurrentUserController currentUserController = mock(ParseCurrentUserController.class); ParseCorePlugins.getInstance().registerCurrentUserController(currentUserController); - ParseTaskUtils.wait(user.resolveLazinessAsync(Task.forResult(null))); + ParseTaskUtils.wait(user.resolveLazinessAsync(Task.forResult(null))); // Make sure we logIn the lazy user verify(userController, times(1)) @@ -848,13 +828,12 @@ public void testResolveLazinessAsyncWithAuthDataAndNotNewUserAndLDSEnabled() thr ParseCorePlugins.getInstance().registerUserController(userController); // Register a mock currentUserController to make getCurrentUser work ParseCurrentUserController currentUserController = mock(ParseCurrentUserController.class); - when(currentUserController.setAsync(any(ParseUser.class))) - .thenReturn(Task.forResult(null)); + when(currentUserController.setAsync(any(ParseUser.class))).thenReturn(Task.forResult(null)); ParseCorePlugins.getInstance().registerCurrentUserController(currentUserController); // Enable LDS Parse.enableLocalDatastore(null); - ParseTaskUtils.wait(user.resolveLazinessAsync(Task.forResult(null))); + ParseTaskUtils.wait(user.resolveLazinessAsync(Task.forResult(null))); ArgumentCaptor userAfterResolveLazinessCaptor = ArgumentCaptor.forClass(ParseUser.class); @@ -941,8 +920,7 @@ public void testValidateSaveWithLDSNotEnabledAndCurrentUserNotMatch() { public void testSaveAsyncWithLazyAndCurrentUser() throws Exception { // Register a mock currentUserController to make setCurrentUser work ParseCurrentUserController currentUserController = mock(ParseCurrentUserController.class); - when(currentUserController.setAsync(any(ParseUser.class))) - .thenReturn(Task.forResult(null)); + when(currentUserController.setAsync(any(ParseUser.class))).thenReturn(Task.forResult(null)); ParseCorePlugins.getInstance().registerCurrentUserController(currentUserController); // Set facebook authData to null to verify cleanAuthData() @@ -952,11 +930,9 @@ public void testSaveAsyncWithLazyAndCurrentUser() throws Exception { setLazy(user); user.setIsCurrentUser(true); ParseUser partialMockUser = spy(user); - doReturn(Task.forResult(null)) - .when(partialMockUser) - .resolveLazinessAsync(Matchers.>any()); + doReturn(Task.forResult(null)).when(partialMockUser).resolveLazinessAsync(any()); - ParseTaskUtils.wait(partialMockUser.saveAsync("sessionToken", Task.forResult(null))); + ParseTaskUtils.wait(partialMockUser.saveAsync("sessionToken", Task.forResult(null))); // Make sure we clean authData assertFalse(partialMockUser.getState().authData().containsKey("facebook")); @@ -975,8 +951,7 @@ public void testSaveAsyncWithLazyAndCurrentUser() throws Exception { public void testSaveAsyncWithLazyAndNotCurrentUser() throws Exception { // Register a mock currentUserController to make setCurrentUser work ParseCurrentUserController currentUserController = mock(ParseCurrentUserController.class); - when(currentUserController.setAsync(any(ParseUser.class))) - .thenReturn(Task.forResult(null)); + when(currentUserController.setAsync(any(ParseUser.class))).thenReturn(Task.forResult(null)); ParseCorePlugins.getInstance().registerCurrentUserController(currentUserController); // Set facebook authData to null to verify cleanAuthData() @@ -986,11 +961,9 @@ public void testSaveAsyncWithLazyAndNotCurrentUser() throws Exception { setLazy(user); user.setIsCurrentUser(false); ParseUser partialMockUser = spy(user); - doReturn(Task.forResult(null)) - .when(partialMockUser) - .resolveLazinessAsync(Matchers.>any()); + doReturn(Task.forResult(null)).when(partialMockUser).resolveLazinessAsync(any()); - ParseTaskUtils.wait(partialMockUser.saveAsync("sessionToken", Task.forResult(null))); + ParseTaskUtils.wait(partialMockUser.saveAsync("sessionToken", Task.forResult(null))); // Make sure we do not clean authData assertTrue(partialMockUser.getAuthData().containsKey("facebook")); @@ -1006,10 +979,10 @@ public void testSaveAsyncWithLazyAndNotCurrentUser() throws Exception { public void testLogOutAsync() throws Exception { // Register a mock sessionController to verify revokeAsync() NetworkSessionController sessionController = mock(NetworkSessionController.class); - when(sessionController.revokeAsync(anyString())).thenReturn(Task.forResult(null)); + when(sessionController.revokeAsync(anyString())).thenReturn(Task.forResult(null)); ParseCorePlugins.getInstance().registerSessionController(sessionController); ParseAuthenticationManager manager = mock(ParseAuthenticationManager.class); - when(manager.deauthenticateAsync(anyString())).thenReturn(Task.forResult(null)); + when(manager.deauthenticateAsync(anyString())).thenReturn(Task.forResult(null)); ParseCorePlugins.getInstance().registerAuthenticationManager(manager); // Set user initial state @@ -1057,8 +1030,7 @@ public void testEnableRevocableSessionInBackgroundWithNoCurrentUser() throws Exc ParsePlugins.set(mockPlugins); // Register a mock currentUserController to verify setAsync ParseCurrentUserController currentUserController = mock(ParseCurrentUserController.class); - when(currentUserController.getAsync(anyBoolean())) - .thenReturn(Task.forResult(null)); + when(currentUserController.getAsync(anyBoolean())).thenReturn(Task.forResult(null)); ParseCorePlugins.getInstance().registerCurrentUserController(currentUserController); ParseTaskUtils.wait(ParseUser.enableRevocableSessionInBackground()); @@ -1161,16 +1133,14 @@ public void testUnlinkFromAsyncWithAuthType() throws Exception { .build(); ParseUser user = ParseObject.from(userState); ParseUser partialMockUser = spy(user); - doReturn(Task.forResult(null)) - .when(partialMockUser) - .saveAsync(anyString(), Matchers.>any()); + doReturn(Task.forResult(null)).when(partialMockUser).saveAsync(anyString(), any()); ParseTaskUtils.wait(partialMockUser.unlinkFromInBackground(authType)); // Verify we delete authData assertNull(user.getAuthData().get("facebook")); // Verify we save the user - verify(partialMockUser, times(1)).saveAsync(eq("sessionToken"), Matchers.>any()); + verify(partialMockUser, times(1)).saveAsync(eq("sessionToken"), any()); } @Test @@ -1193,8 +1163,7 @@ public void testLogInWithNoPassword() throws Exception { public void testLogIn() throws Exception { // Register a mock currentUserController to make setCurrentUser work ParseCurrentUserController currentUserController = mock(ParseCurrentUserController.class); - when(currentUserController.setAsync(any(ParseUser.class))) - .thenReturn(Task.forResult(null)); + when(currentUserController.setAsync(any(ParseUser.class))).thenReturn(Task.forResult(null)); ParseCorePlugins.getInstance().registerCurrentUserController(currentUserController); // Register a mock userController to make logIn work ParseUserController userController = mock(ParseUserController.class); @@ -1226,8 +1195,7 @@ public void testLogIn() throws Exception { public void testLogInWithCallback() throws Exception { // Register a mock currentUserController to make setCurrentUser work ParseCurrentUserController currentUserController = mock(ParseCurrentUserController.class); - when(currentUserController.setAsync(any(ParseUser.class))) - .thenReturn(Task.forResult(null)); + when(currentUserController.setAsync(any(ParseUser.class))).thenReturn(Task.forResult(null)); ParseCorePlugins.getInstance().registerCurrentUserController(currentUserController); // Register a mock userController to make logIn work ParseUserController userController = mock(ParseUserController.class); @@ -1273,8 +1241,7 @@ public void testBecomeWithNoSessionToken() throws Exception { public void testBecome() throws Exception { // Register a mock currentUserController to make setCurrentUser work ParseCurrentUserController currentUserController = mock(ParseCurrentUserController.class); - when(currentUserController.setAsync(any(ParseUser.class))) - .thenReturn(Task.forResult(null)); + when(currentUserController.setAsync(any(ParseUser.class))).thenReturn(Task.forResult(null)); ParseCorePlugins.getInstance().registerCurrentUserController(currentUserController); // Register a mock userController to make getUsreAsync work ParseUserController userController = mock(ParseUserController.class); @@ -1305,8 +1272,7 @@ public void testBecome() throws Exception { public void testBecomeWithCallback() { // Register a mock currentUserController to make setCurrentUser work ParseCurrentUserController currentUserController = mock(ParseCurrentUserController.class); - when(currentUserController.setAsync(any(ParseUser.class))) - .thenReturn(Task.forResult(null)); + when(currentUserController.setAsync(any(ParseUser.class))).thenReturn(Task.forResult(null)); ParseCorePlugins.getInstance().registerCurrentUserController(currentUserController); // Register a mock userController to make getUsreAsync work ParseUserController userController = mock(ParseUserController.class); @@ -1404,7 +1370,7 @@ public void testSynchronizeAuthData() throws Exception { ParseCorePlugins.getInstance().registerCurrentUserController(currentUserController); // Register mock callbacks AuthenticationCallback callbacks = mock(AuthenticationCallback.class); - when(callbacks.onRestore(Matchers.>any())).thenReturn(true); + when(callbacks.onRestore(any())).thenReturn(true); ParseUser.registerAuthenticationCallback("facebook", callbacks); // Set user initial state @@ -1435,7 +1401,7 @@ public void testSynchronizeAllAuthData() throws Exception { ParseCorePlugins.getInstance().registerCurrentUserController(currentUserController); // Register mock callbacks AuthenticationCallback callbacks = mock(AuthenticationCallback.class); - when(callbacks.onRestore(Matchers.>any())).thenReturn(true); + when(callbacks.onRestore(any())).thenReturn(true); ParseUser.registerAuthenticationCallback("facebook", callbacks); // Set user initial state @@ -1495,7 +1461,7 @@ public void testPinCurrentUserIfNeededAsync() { currentUser.setObjectId("test"); CachedCurrentUserController currentUserController = mock(CachedCurrentUserController.class); when(currentUserController.setIfNeededAsync(any(ParseUser.class))) - .thenReturn(Task.forResult(null)); + .thenReturn(Task.forResult(null)); ParseCorePlugins.getInstance().registerCurrentUserController(currentUserController); ParseUser user = new ParseUser(); diff --git a/rxjava/build.gradle b/rxjava/build.gradle index 047030f65..6d7c9995f 100644 --- a/rxjava/build.gradle +++ b/rxjava/build.gradle @@ -42,7 +42,7 @@ android { dependencies { api "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" - api "io.reactivex.rxjava3:rxjava:3.0.4" + api "io.reactivex.rxjava3:rxjava:3.1.0" implementation project(":parse") } diff --git a/twitter/build.gradle b/twitter/build.gradle index b8dd37321..135397656 100644 --- a/twitter/build.gradle +++ b/twitter/build.gradle @@ -40,8 +40,8 @@ dependencies { api "se.akerfeldt:okhttp-signpost:1.1.0" implementation project(":parse") - testImplementation "junit:junit:4.13.2" - testImplementation "org.mockito:mockito-core:3.9.0" + testImplementation "junit:junit:$rootProject.ext.junitVersion" + testImplementation "org.mockito:mockito-core:$rootProject.ext.mockitoCoreVersion" } afterEvaluate { diff --git a/twitter/src/main/java/com/parse/twitter/ParseTwitterUtils.java b/twitter/src/main/java/com/parse/twitter/ParseTwitterUtils.java index 4b4d91786..76707cb6f 100644 --- a/twitter/src/main/java/com/parse/twitter/ParseTwitterUtils.java +++ b/twitter/src/main/java/com/parse/twitter/ParseTwitterUtils.java @@ -17,6 +17,7 @@ import com.parse.boltsinternal.AggregateException; import com.parse.boltsinternal.Continuation; import com.parse.boltsinternal.Task; +import com.parse.boltsinternal.TaskCompletionSource; import java.util.Map; import java.util.concurrent.CancellationException; @@ -128,15 +129,6 @@ public static Task linkInBackground(Context context, final ParseUser user) .onSuccessTask(task -> user.linkWithInBackground(AUTH_TYPE, task.getResult())); } - /** - * @deprecated Please use {@link ParseTwitterUtils#linkInBackground(Context, ParseUser)} - * instead. - */ - @Deprecated - public static void link(ParseUser user, Context context) { - link(user, context, null); - } - /** * Links a ParseUser to a Twitter account, allowing you to use Twitter for authentication, and * providing access to Twitter data for the user. A dialog will be shown to the user for Twitter @@ -177,20 +169,6 @@ public static Task linkInBackground( return user.linkWithInBackground(AUTH_TYPE, authData); } - /** - * @deprecated Please use {@link ParseTwitterUtils#linkInBackground(ParseUser, String, String, - * String, String)} instead. - */ - @Deprecated - public static void link( - ParseUser user, - String twitterId, - String screenName, - String authToken, - String authTokenSecret) { - link(user, twitterId, screenName, authToken, authTokenSecret, null); - } - /** * Links a ParseUser to a Twitter account, allowing you to use Twitter for authentication, and * providing access to Twitter data for the user. This method allows you to handle getting the @@ -391,7 +369,7 @@ private static Task callbackOnMainThreadInternalAsync( if (callback == null) { return task; } - final Task.TaskCompletionSource tcs = Task.create(); + final TaskCompletionSource tcs = new TaskCompletionSource(); task.continueWith( (Continuation) task1 -> { diff --git a/twitter/src/main/java/com/parse/twitter/Twitter.java b/twitter/src/main/java/com/parse/twitter/Twitter.java index 15db35b45..b2067ffe4 100644 --- a/twitter/src/main/java/com/parse/twitter/Twitter.java +++ b/twitter/src/main/java/com/parse/twitter/Twitter.java @@ -10,9 +10,12 @@ import android.content.Context; import android.net.Uri; -import android.os.AsyncTask; -import android.webkit.CookieSyncManager; +import android.os.Handler; +import android.os.Looper; +import android.webkit.CookieManager; import com.parse.twitter.OAuth1FlowDialog.FlowResultHandler; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; import oauth.signpost.http.HttpParameters; import se.akerfeldt.okhttp.signpost.OkHttpOAuthConsumer; import se.akerfeldt.okhttp.signpost.OkHttpOAuthProvider; @@ -107,114 +110,132 @@ public void authorize(final Context context, final AsyncCallback callback) { final OkHttpOAuthConsumer consumer = new OkHttpOAuthConsumer(getConsumerKey(), getConsumerSecret()); - AsyncTask task = - new AsyncTask() { - private Throwable error; - - @Override - protected String doInBackground(Void... params) { - try { - return provider.retrieveRequestToken(consumer, callbackUrl); - } catch (Throwable e) { - error = e; - } - return null; - } + final ExecutorService executor = Executors.newSingleThreadExecutor(); + final Handler handler = new Handler(Looper.getMainLooper()); + + executor.execute( + () -> { + Throwable error = null; + String requestToken = null; - @Override - protected void onPostExecute(String result) { - super.onPostExecute(result); - if (error != null) { - callback.onFailure(error); - return; - } - CookieSyncManager.createInstance(context); - OAuth1FlowDialog dialog = - new OAuth1FlowDialog( - context, - result, - callbackUrl, - "api.twitter", - new FlowResultHandler() { - - @Override - public void onError( - int errorCode, - String description, - String failingUrl) { - callback.onFailure( - new OAuth1FlowException( - errorCode, - description, - failingUrl)); - } - - @Override - public void onComplete(String callbackUrl) { - CookieSyncManager.getInstance().sync(); - Uri uri = Uri.parse(callbackUrl); - final String verifier = - uri.getQueryParameter(VERIFIER_PARAM); - if (verifier == null) { - callback.onCancel(); - return; - } - AsyncTask getTokenTask = - new AsyncTask< - Void, Void, HttpParameters>() { - private Throwable error; - - @Override - protected HttpParameters doInBackground( - Void... params) { - try { - provider.retrieveAccessToken( - consumer, verifier); - } catch (Throwable e) { - error = e; - } - return provider - .getResponseParameters(); - } - - @Override - protected void onPostExecute( - HttpParameters result) { - super.onPostExecute(result); - if (error != null) { - callback.onFailure(error); - return; - } - try { - setAuthToken( - consumer.getToken()); - setAuthTokenSecret( - consumer - .getTokenSecret()); - setScreenName( - result.getFirst( - SCREEN_NAME_PARAM)); - setUserId( - result.getFirst( - USER_ID_PARAM)); - } catch (Throwable e) { - callback.onFailure(e); - return; - } - callback.onSuccess(Twitter.this); - } - }; - getTokenTask.execute(); - } - - @Override - public void onCancel() { - callback.onCancel(); - } - }); - dialog.show(); + try { + requestToken = provider.retrieveRequestToken(consumer, callbackUrl); + } catch (Throwable e) { + error = e; } - }; - task.execute(); + + final Throwable finalError = error; + final String finalRequestToken = requestToken; + + handler.post( + () -> { + if (finalError != null) { + callback.onFailure(finalError); + return; + } + + OAuth1FlowDialog dialog = + new OAuth1FlowDialog( + context, + finalRequestToken, + callbackUrl, + "api.twitter", + new FlowResultHandler() { + + @Override + public void onError( + int errorCode, + String description, + String failingUrl) { + callback.onFailure( + new OAuth1FlowException( + errorCode, + description, + failingUrl)); + } + + @Override + public void onComplete(String callbackUrl) { + CookieManager.getInstance().flush(); + final Uri uri = Uri.parse(callbackUrl); + final String verifier = + uri.getQueryParameter( + VERIFIER_PARAM); + if (verifier == null) { + callback.onCancel(); + return; + } + + executor.execute( + () -> { + Throwable error = null; + HttpParameters parameters = + null; + + try { + provider + .retrieveAccessToken( + consumer, + verifier); + parameters = + provider + .getResponseParameters(); + } catch (Throwable e) { + error = e; + } + + final Throwable finalError = + error; + final HttpParameters + finalParameters = + parameters; + + handler.post( + () -> { + if (finalError + != null) { + callback + .onFailure( + finalError); + return; + } + try { + setAuthToken( + consumer + .getToken()); + setAuthTokenSecret( + consumer + .getTokenSecret()); + setScreenName( + finalParameters + .getFirst( + SCREEN_NAME_PARAM)); + setUserId( + finalParameters + .getFirst( + USER_ID_PARAM)); + } catch ( + Throwable + e) { + callback + .onFailure( + e); + return; + } + callback.onSuccess( + Twitter + .this); + }); + }); + } + + @Override + public void onCancel() { + callback.onCancel(); + } + }); + dialog.show(); + }); + }); } } diff --git a/twitter/src/main/java/com/parse/twitter/TwitterController.java b/twitter/src/main/java/com/parse/twitter/TwitterController.java index 9df087667..bf8ad0704 100644 --- a/twitter/src/main/java/com/parse/twitter/TwitterController.java +++ b/twitter/src/main/java/com/parse/twitter/TwitterController.java @@ -11,6 +11,7 @@ import android.content.Context; import com.parse.ParseException; import com.parse.boltsinternal.Task; +import com.parse.boltsinternal.TaskCompletionSource; import java.util.HashMap; import java.util.Map; @@ -25,7 +26,7 @@ class TwitterController { private static final String AUTH_TOKEN_SECRET_KEY = "auth_token_secret"; private final Twitter twitter; - private Task>.TaskCompletionSource currentTcs; + private TaskCompletionSource> currentTcs; TwitterController() { this(new Twitter("", "", "")); @@ -44,7 +45,7 @@ public Twitter getTwitter() { } public Task> authenticateAsync(Context context) { - final Task>.TaskCompletionSource tcs = Task.create(); + final TaskCompletionSource> tcs = new TaskCompletionSource<>(); if (currentTcs != null) { handleCancel(currentTcs); } @@ -100,7 +101,7 @@ public void onSuccess(Object result) { return tcs.getTask(); } - private void handleCancel(Task>.TaskCompletionSource callback) { + private void handleCancel(TaskCompletionSource> callback) { // Ensure that the operation being cancelled is actually the current // operation (so that if one had already been cancelled but still // invokes this method, it doesn't cancel the "real" current operation). diff --git a/twitter/src/test/java/com/parse/twitter/ParseTwitterUtilsTest.java b/twitter/src/test/java/com/parse/twitter/ParseTwitterUtilsTest.java index 49588d0e0..e16510057 100644 --- a/twitter/src/test/java/com/parse/twitter/ParseTwitterUtilsTest.java +++ b/twitter/src/test/java/com/parse/twitter/ParseTwitterUtilsTest.java @@ -10,8 +10,8 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.anyMap; import static org.mockito.Matchers.any; -import static org.mockito.Matchers.anyMapOf; import static org.mockito.Matchers.anyString; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.doThrow; @@ -32,7 +32,7 @@ import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; -import org.mockito.runners.MockitoJUnitRunner; +import org.mockito.junit.MockitoJUnitRunner; @RunWith(MockitoJUnitRunner.class) public class ParseTwitterUtilsTest { @@ -84,9 +84,7 @@ public void testRestoreAuthenticationFailure() { ArgumentCaptor.forClass(AuthenticationCallback.class); verify(userDelegate).registerAuthenticationCallback(eq("twitter"), captor.capture()); - doThrow(new RuntimeException()) - .when(controller) - .setAuthData(anyMapOf(String.class, String.class)); + doThrow(new RuntimeException()).when(controller).setAuthData(anyMap()); AuthenticationCallback callback = captor.getValue(); Map authData = new HashMap<>(); assertFalse(callback.onRestore(authData)); @@ -111,7 +109,7 @@ public void testIsLinked() { public void testLogInWithToken() { ParseTwitterUtils.isInitialized = true; ParseUser user = mock(ParseUser.class); - when(userDelegate.logInWithInBackground(anyString(), anyMapOf(String.class, String.class))) + when(userDelegate.logInWithInBackground(anyString(), anyMap())) .thenReturn(Task.forResult(user)); String twitterId = "test_id"; @@ -121,8 +119,7 @@ public void testLogInWithToken() { Task task = ParseTwitterUtils.logInInBackground(twitterId, screenName, authToken, authSecret); verify(controller).getAuthData(twitterId, screenName, authToken, authSecret); - verify(userDelegate) - .logInWithInBackground(eq("twitter"), anyMapOf(String.class, String.class)); + verify(userDelegate).logInWithInBackground(eq("twitter"), anyMap()); assertTrue(task.isCompleted()); } @@ -133,7 +130,7 @@ public void testLogInWithContext() { ParseUser user = mock(ParseUser.class); Map authData = new HashMap<>(); when(controller.authenticateAsync(any(Context.class))).thenReturn(Task.forResult(authData)); - when(userDelegate.logInWithInBackground(anyString(), anyMapOf(String.class, String.class))) + when(userDelegate.logInWithInBackground(anyString(), anyMap())) .thenReturn(Task.forResult(user)); Context context = mock(Context.class); @@ -153,8 +150,7 @@ public void testLinkWithToken() { ParseTwitterUtils.isInitialized = true; ParseUser user = mock(ParseUser.class); - when(user.linkWithInBackground(anyString(), anyMapOf(String.class, String.class))) - .thenReturn(Task.forResult(null)); + when(user.linkWithInBackground(anyString(), anyMap())).thenReturn(Task.forResult(null)); String twitterId = "test_id"; String screenName = "test_screen_name"; String authToken = "test_token"; @@ -163,7 +159,7 @@ public void testLinkWithToken() { ParseTwitterUtils.linkInBackground( user, twitterId, screenName, authToken, authSecret); verify(controller).getAuthData(twitterId, screenName, authToken, authSecret); - verify(user).linkWithInBackground(eq("twitter"), anyMapOf(String.class, String.class)); + verify(user).linkWithInBackground(eq("twitter"), anyMap()); assertTrue(task.isCompleted()); } @@ -176,8 +172,7 @@ public void testLinkWithContext() { Context context = mock(Context.class); ParseUser user = mock(ParseUser.class); - when(user.linkWithInBackground(anyString(), anyMapOf(String.class, String.class))) - .thenReturn(Task.forResult(null)); + when(user.linkWithInBackground(anyString(), any())).thenReturn(Task.forResult(null)); Task task = ParseTwitterUtils.linkInBackground(context, user); verify(controller).authenticateAsync(context); verify(user).linkWithInBackground("twitter", authData); @@ -190,7 +185,7 @@ public void testLinkWithContext() { public void testUnlink() { ParseTwitterUtils.isInitialized = true; ParseUser user = mock(ParseUser.class); - when(user.unlinkFromInBackground(anyString())).thenReturn(Task.forResult(null)); + when(user.unlinkFromInBackground(anyString())).thenReturn(Task.forResult(null)); Task task = ParseTwitterUtils.unlinkInBackground(user); verify(user).unlinkFromInBackground("twitter"); verifyNoMoreInteractions(user); diff --git a/twitter/src/test/java/com/parse/twitter/TwitterControllerTest.java b/twitter/src/test/java/com/parse/twitter/TwitterControllerTest.java index 2be1e9857..f11803906 100644 --- a/twitter/src/test/java/com/parse/twitter/TwitterControllerTest.java +++ b/twitter/src/test/java/com/parse/twitter/TwitterControllerTest.java @@ -27,7 +27,7 @@ import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; -import org.mockito.runners.MockitoJUnitRunner; +import org.mockito.junit.MockitoJUnitRunner; @RunWith(MockitoJUnitRunner.class) public class TwitterControllerTest {