diff options
10 files changed, 233 insertions, 74 deletions
diff --git a/core/java/android/app/backup/BackupAgent.java b/core/java/android/app/backup/BackupAgent.java index 097dd9c00aca..62332d605145 100644 --- a/core/java/android/app/backup/BackupAgent.java +++ b/core/java/android/app/backup/BackupAgent.java @@ -126,6 +126,11 @@ public abstract class BackupAgent extends ContextWrapper { private static final boolean DEBUG = false; /** @hide */ + public static final int RESULT_SUCCESS = 0; + /** @hide */ + public static final int RESULT_ERROR = -1; + + /** @hide */ public static final int TYPE_EOF = 0; /** @@ -955,8 +960,10 @@ public abstract class BackupAgent extends ContextWrapper { BackupDataOutput output = new BackupDataOutput( data.getFileDescriptor(), quotaBytes, transportFlags); + long result = RESULT_ERROR; try { BackupAgent.this.onBackup(oldState, output, newState); + result = RESULT_SUCCESS; } catch (IOException ex) { Log.d(TAG, "onBackup (" + BackupAgent.this.getClass().getName() + ") threw", ex); throw new RuntimeException(ex); @@ -971,7 +978,7 @@ public abstract class BackupAgent extends ContextWrapper { Binder.restoreCallingIdentity(ident); try { - callbackBinder.operationComplete(0); + callbackBinder.operationComplete(result); } catch (RemoteException e) { // we'll time out anyway, so we're safe } diff --git a/services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupReporter.java b/services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupReporter.java index d397962141b1..2f32775a84a3 100644 --- a/services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupReporter.java +++ b/services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupReporter.java @@ -52,11 +52,9 @@ import java.util.List; // verify calls to this object. Add these and more assertions to the test of this class. @VisibleForTesting public class KeyValueBackupReporter { - @VisibleForTesting - static final String TAG = "KeyValueBackupTask"; + @VisibleForTesting static final String TAG = "KeyValueBackupTask"; private static final boolean DEBUG = BackupManagerService.DEBUG; - @VisibleForTesting - static final boolean MORE_DEBUG = BackupManagerService.MORE_DEBUG || true; + @VisibleForTesting static final boolean MORE_DEBUG = BackupManagerService.MORE_DEBUG || true; static void onNewThread(String threadName) { if (DEBUG) { @@ -357,6 +355,14 @@ public class KeyValueBackupReporter { null, BackupManagerMonitor.EXTRA_LOG_CANCEL_ALL, true)); } + void onAgentResultError(@Nullable PackageInfo packageInfo) { + String packageName = getPackageName(packageInfo); + BackupObserverUtils.sendBackupOnPackageResult( + mObserver, packageName, BackupManager.ERROR_AGENT_FAILURE); + EventLog.writeEvent(EventLogTags.BACKUP_AGENT_FAILURE, packageName, "result error"); + Slog.w(TAG, "Agent " + packageName + " error in onBackup()"); + } + private String getPackageName(@Nullable PackageInfo packageInfo) { return (packageInfo != null) ? packageInfo.packageName : "no_package_yet"; } diff --git a/services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupTask.java b/services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupTask.java index 55b970ab1a3d..fbe0d6f6d21c 100644 --- a/services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupTask.java +++ b/services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupTask.java @@ -251,15 +251,15 @@ public class KeyValueBackupTask implements BackupRestoreTask, Runnable { @Nullable private final DataChangedJournal mJournal; @Nullable private PerformFullTransportBackupTask mFullBackupTask; - private IBackupAgent mAgentBinder; - private PackageInfo mCurrentPackage; - private File mSavedStateFile; - private File mBackupDataFile; - private File mNewStateFile; - private ParcelFileDescriptor mSavedState; - private ParcelFileDescriptor mBackupData; - private ParcelFileDescriptor mNewState; private int mStatus; + @Nullable private IBackupAgent mAgentBinder; + @Nullable private PackageInfo mCurrentPackage; + @Nullable private File mSavedStateFile; + @Nullable private File mBackupDataFile; + @Nullable private File mNewStateFile; + @Nullable private ParcelFileDescriptor mSavedState; + @Nullable private ParcelFileDescriptor mBackupData; + @Nullable private ParcelFileDescriptor mNewState; /** * This {@link ConditionVariable} is used to signal that the cancel operation has been @@ -344,23 +344,32 @@ public class KeyValueBackupTask implements BackupRestoreTask, Runnable { } /** Returns whether to consume next queue package. */ - private boolean handleAgentResult(RemoteResult result) { + private boolean handleAgentResult(@Nullable PackageInfo packageInfo, RemoteResult result) { if (result == RemoteResult.FAILED_THREAD_INTERRUPTED) { // Not an explicit cancel, we need to flag it. mCancelled = true; - handleAgentCancelled(); + mReporter.onAgentCancelled(packageInfo); + errorCleanup(); return false; } if (result == RemoteResult.FAILED_CANCELLED) { - handleAgentCancelled(); + mReporter.onAgentCancelled(packageInfo); + errorCleanup(); return false; } if (result == RemoteResult.FAILED_TIMED_OUT) { - handleAgentTimeout(); + mReporter.onAgentTimedOut(packageInfo); + errorCleanup(); + return true; + } + Preconditions.checkState(result.isPresent()); + long agentResult = result.get(); + if (agentResult == BackupAgent.RESULT_ERROR) { + mReporter.onAgentResultError(packageInfo); + errorCleanup(); return true; } - Preconditions.checkState(result.succeeded()); - return sendDataToTransport(result.get()); + return sendDataToTransport(); } @Override @@ -463,7 +472,7 @@ public class KeyValueBackupTask implements BackupRestoreTask, Runnable { } Preconditions.checkNotNull(agentResult); - return handleAgentResult(agentResult); + return handleAgentResult(mCurrentPackage, agentResult); } /** Returns whether to consume next queue package. */ @@ -543,7 +552,8 @@ public class KeyValueBackupTask implements BackupRestoreTask, Runnable { return false; } - return handleAgentResult(agentResult); + Preconditions.checkNotNull(agentResult); + return handleAgentResult(mCurrentPackage, agentResult); } private void finishTask() { @@ -790,7 +800,7 @@ public class KeyValueBackupTask implements BackupRestoreTask, Runnable { } /** Returns whether to consume next queue package. */ - private boolean sendDataToTransport(long agentResult) { + private boolean sendDataToTransport() { Preconditions.checkState(mBackupData != null); String packageName = mCurrentPackage.packageName; @@ -994,16 +1004,6 @@ public class KeyValueBackupTask implements BackupRestoreTask, Runnable { mCancelAcknowledged.block(); } - private void handleAgentTimeout() { - mReporter.onAgentTimedOut(mCurrentPackage); - errorCleanup(); - } - - private void handleAgentCancelled() { - mReporter.onAgentCancelled(mCurrentPackage); - errorCleanup(); - } - private void revertTask() { mReporter.onRevertTask(); long delay; diff --git a/services/backup/java/com/android/server/backup/remote/FutureBackupCallback.java b/services/backup/java/com/android/server/backup/remote/FutureBackupCallback.java index 1445cc3065b8..1ea4249aabbc 100644 --- a/services/backup/java/com/android/server/backup/remote/FutureBackupCallback.java +++ b/services/backup/java/com/android/server/backup/remote/FutureBackupCallback.java @@ -23,7 +23,7 @@ import java.util.concurrent.CompletableFuture; /** * An implementation of {@link IBackupCallback} that completes the {@link CompletableFuture} - * provided in the constructor with a successful {@link RemoteResult}. + * provided in the constructor with a present {@link RemoteResult}. */ public class FutureBackupCallback extends IBackupCallback.Stub { private final CompletableFuture<RemoteResult> mFuture; @@ -34,6 +34,6 @@ public class FutureBackupCallback extends IBackupCallback.Stub { @Override public void operationComplete(long result) throws RemoteException { - mFuture.complete(RemoteResult.successful(result)); + mFuture.complete(RemoteResult.of(result)); } } diff --git a/services/backup/java/com/android/server/backup/remote/RemoteCall.java b/services/backup/java/com/android/server/backup/remote/RemoteCall.java index ac848113f08f..b3e802ed3be4 100644 --- a/services/backup/java/com/android/server/backup/remote/RemoteCall.java +++ b/services/backup/java/com/android/server/backup/remote/RemoteCall.java @@ -83,7 +83,7 @@ public class RemoteCall { * * <ul> * <li>The callback passed to {@link RemoteCallable} is called with the result. We return a - * successful {@link RemoteResult} with the result. + * present {@link RemoteResult} with the result. * <li>Time-out happens. We return {@link RemoteResult#FAILED_TIMED_OUT}. * <li>Someone calls {@link #cancel()} on this object. We return {@link * RemoteResult#FAILED_CANCELLED}. diff --git a/services/backup/java/com/android/server/backup/remote/RemoteResult.java b/services/backup/java/com/android/server/backup/remote/RemoteResult.java index 7f4f4696395e..63c79dba584a 100644 --- a/services/backup/java/com/android/server/backup/remote/RemoteResult.java +++ b/services/backup/java/com/android/server/backup/remote/RemoteResult.java @@ -29,7 +29,7 @@ import java.util.Objects; * #FAILED_CANCELLED}, {@link #FAILED_THREAD_INTERRUPTED} or a successful result, in which case * {@link #get()} returns its value. * - * <p>Use {@link #succeeded()} to check for successful result, or direct identity comparison to + * <p>Use {@link #isPresent()} to check for successful result, or direct identity comparison to * check for specific failures, like {@code result == RemoteResult.FAILED_CANCELLED}. */ public class RemoteResult { @@ -38,7 +38,7 @@ public class RemoteResult { public static final RemoteResult FAILED_THREAD_INTERRUPTED = new RemoteResult(Type.FAILED_THREAD_INTERRUPTED, 0); - public static RemoteResult successful(long value) { + public static RemoteResult of(long value) { return new RemoteResult(Type.SUCCESS, value); } @@ -50,7 +50,7 @@ public class RemoteResult { mValue = value; } - public boolean succeeded() { + public boolean isPresent() { return mType == Type.SUCCESS; } @@ -60,7 +60,7 @@ public class RemoteResult { * @throws IllegalStateException in case this is not a successful result. */ public long get() { - Preconditions.checkState(succeeded(), "Can't obtain value of failed result"); + Preconditions.checkState(isPresent(), "Can't obtain value of failed result"); return mValue; } @@ -79,8 +79,9 @@ public class RemoteResult { return "FAILED_CANCELLED"; case Type.FAILED_THREAD_INTERRUPTED: return "FAILED_THREAD_INTERRUPTED"; + default: + throw new AssertionError("Unknown type"); } - throw new AssertionError("Unknown type"); } @Override diff --git a/services/robotests/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java b/services/robotests/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java index 63b0ea882826..9fae43a46d51 100644 --- a/services/robotests/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java +++ b/services/robotests/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java @@ -62,6 +62,7 @@ import static org.mockito.Mockito.verifyZeroInteractions; import static org.mockito.Mockito.when; import static org.robolectric.Shadows.shadowOf; import static org.robolectric.shadow.api.Shadow.extract; +import static org.testng.Assert.fail; import static java.nio.file.StandardCopyOption.REPLACE_EXISTING; import static java.util.Collections.emptyList; @@ -106,6 +107,7 @@ import com.android.server.backup.PackageManagerBackupAgent; import com.android.server.backup.TransportManager; import com.android.server.backup.internal.BackupHandler; import com.android.server.backup.internal.OnTaskFinishedListener; +import com.android.server.backup.remote.RemoteCall; import com.android.server.backup.testing.PackageData; import com.android.server.backup.testing.TestUtils.ThrowingRunnable; import com.android.server.backup.testing.TransportData; @@ -704,14 +706,13 @@ public class KeyValueBackupTaskTest { } /** - * For local agents the exception is thrown in our stack, so it hits the catch clause around - * invocation earlier than the {@link KeyValueBackupTask#operationComplete(long)} code-path, - * invalidating the latter. Note that this happens because {@link - * BackupManagerService#opComplete(int, long)} schedules the actual execution to the backup - * handler. + * For local agents the exception is thrown in our stack, before {@link RemoteCall} has a chance + * to complete cleanly. */ + // TODO: When RemoteCall spins up a new thread the assertions on this method should be the same + // as the methods below (non-local call). @Test - public void testRunTask_whenLocalAgentOnBackupThrows() throws Exception { + public void testRunTask_whenLocalAgentOnBackupThrows_setsNullWorkSource() throws Exception { TransportMock transportMock = setUpInitializedTransport(mTransport); AgentMock agentMock = setUpAgent(PACKAGE_1); agentOnBackupDo( @@ -724,16 +725,119 @@ public class KeyValueBackupTaskTest { runTask(task); verify(mBackupManagerService).setWorkSource(null); + } + + @Test + public void testRunTask_whenLocalAgentOnBackupThrows_reportsCorrectly() throws Exception { + TransportMock transportMock = setUpInitializedTransport(mTransport); + AgentMock agentMock = setUpAgent(PACKAGE_1); + agentOnBackupDo( + agentMock, + (oldState, dataOutput, newState) -> { + throw new RuntimeException(); + }); + KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1); + + runTask(task); + verify(mObserver).onResult(PACKAGE_1.packageName, ERROR_AGENT_FAILURE); verify(mObserver).backupFinished(SUCCESS); + verify(mReporter) + .onCallAgentDoBackupError( + eq(PACKAGE_1.packageName), eq(true), any(RuntimeException.class)); assertEventLogged( EventLogTags.BACKUP_AGENT_FAILURE, PACKAGE_1.packageName, new RuntimeException().toString()); + } + + @Test + public void testRunTask_whenLocalAgentOnBackupThrows_doesNotUpdateBookkeping() + throws Exception { + TransportMock transportMock = setUpInitializedTransport(mTransport); + AgentMock agentMock = setUpAgent(PACKAGE_1); + agentOnBackupDo( + agentMock, + (oldState, dataOutput, newState) -> { + throw new RuntimeException(); + }); + KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1); + + runTask(task); + assertBackupPendingFor(PACKAGE_1); } @Test + public void testRunTask_whenAgentOnBackupThrows_reportsCorrectly() throws Exception { + TransportMock transportMock = setUpInitializedTransport(mTransport); + AgentMock agentMock = setUpAgent(PACKAGE_1); + remoteAgentOnBackupThrows( + agentMock, + (oldState, dataOutput, newState) -> { + throw new RuntimeException(); + }); + KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1); + + runTask(task); + + verify(mReporter).onAgentResultError(argThat(packageInfo(PACKAGE_1))); + } + + @Test + public void testRunTask_whenAgentOnBackupThrows_updatesBookkeeping() throws Exception { + TransportMock transportMock = setUpInitializedTransport(mTransport); + AgentMock agentMock = setUpAgent(PACKAGE_1); + remoteAgentOnBackupThrows( + agentMock, + (oldState, dataOutput, newState) -> { + throw new RuntimeException(); + }); + KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1); + + runTask(task); + + assertBackupNotPendingFor(PACKAGE_1); + } + + @Test + public void testRunTask_whenAgentOnBackupThrows_doesNotCallTransport() throws Exception { + TransportMock transportMock = setUpInitializedTransport(mTransport); + AgentMock agentMock = setUpAgent(PACKAGE_1); + remoteAgentOnBackupThrows( + agentMock, + (oldState, dataOutput, newState) -> { + throw new RuntimeException(); + }); + KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1); + + runTask(task); + + verify(transportMock.transport, never()) + .performBackup(argThat(packageInfo(PACKAGE_1)), any(), anyInt()); + } + + @Test + public void testRunTask_whenAgentOnBackupThrows_updatesAndCleansUpFiles() throws Exception { + TransportMock transportMock = setUpInitializedTransport(mTransport); + AgentMock agentMock = setUpAgent(PACKAGE_1); + remoteAgentOnBackupThrows( + agentMock, + (oldState, dataOutput, newState) -> { + throw new RuntimeException(); + }); + KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1); + Files.write(getStateFile(mTransport, PACKAGE_1), "oldState".getBytes()); + + runTask(task); + + assertThat(Files.readAllBytes(getStateFile(mTransport, PACKAGE_1))) + .isEqualTo("oldState".getBytes()); + assertThat(Files.exists(getTemporaryStateFile(mTransport, PACKAGE_1))).isFalse(); + assertThat(Files.exists(getStagingFile(PACKAGE_1))).isFalse(); + } + + @Test public void testRunTask_whenTransportProvidesFlags_passesThemToTheAgent() throws Exception { TransportMock transportMock = setUpInitializedTransport(mTransport); int flags = BackupAgent.FLAG_CLIENT_SIDE_ENCRYPTION_ENABLED; @@ -2130,6 +2234,10 @@ public class KeyValueBackupTaskTest { * Implements {@code function} for {@link BackupAgent#onBackup(ParcelFileDescriptor, * BackupDataOutput, ParcelFileDescriptor)} of {@code agentMock} and populates {@link * AgentMock#oldState}. + * + * <p>Note that for throwing agents this will simulate a local agent (the exception will be + * thrown in our stack), use {@link #remoteAgentOnBackupThrows(AgentMock, BackupAgentOnBackup)} + * if you want to simulate a remote agent. */ private static void agentOnBackupDo(AgentMock agentMock, BackupAgentOnBackup function) throws Exception { @@ -2150,6 +2258,33 @@ public class KeyValueBackupTaskTest { } /** + * Use this method to simulate a remote agent throwing. We catch the exception thrown, thus + * simulating a one-way call. It also populates {@link AgentMock#oldState}. + * + * @param agentMock The Agent mock. + * @param function A function that throws, otherwise the test will fail. + */ + // TODO: Remove when RemoteCall spins up a dedicated thread for calls + private static void remoteAgentOnBackupThrows(AgentMock agentMock, BackupAgentOnBackup function) + throws Exception { + agentOnBackupDo(agentMock, function); + doAnswer( + invocation -> { + try { + invocation.callRealMethod(); + fail("Agent method expected to throw"); + } catch (RuntimeException e) { + // This silences the exception just like a one-way call would, the + // normal completion via IBackupCallback binder still happens, check + // finally() block of IBackupAgent.doBackup(). + } + return null; + }) + .when(agentMock.agentBinder) + .doBackup(any(), any(), any(), anyLong(), any(), anyInt()); + } + + /** * Returns an {@link Answer} that can be used for mocking {@link * IBackupTransport#performBackup(PackageInfo, ParcelFileDescriptor, int)} that copies the * backup data received to {@code backupDataPath} and returns {@code result}. diff --git a/services/robotests/src/com/android/server/backup/remote/FutureBackupCallbackTest.java b/services/robotests/src/com/android/server/backup/remote/FutureBackupCallbackTest.java index aec207d2fea6..f3621e282179 100644 --- a/services/robotests/src/com/android/server/backup/remote/FutureBackupCallbackTest.java +++ b/services/robotests/src/com/android/server/backup/remote/FutureBackupCallbackTest.java @@ -41,6 +41,6 @@ public class FutureBackupCallbackTest { callback.operationComplete(7); - assertThat(future.get()).isEqualTo(RemoteResult.successful(7)); + assertThat(future.get()).isEqualTo(RemoteResult.of(7)); } } diff --git a/services/robotests/src/com/android/server/backup/remote/RemoteCallTest.java b/services/robotests/src/com/android/server/backup/remote/RemoteCallTest.java index 55db6160481a..6434c4f4e8e9 100644 --- a/services/robotests/src/com/android/server/backup/remote/RemoteCallTest.java +++ b/services/robotests/src/com/android/server/backup/remote/RemoteCallTest.java @@ -161,7 +161,7 @@ public class RemoteCallTest { } @Test - public void testCall_whenCallbackIsCalledBeforeTimeOut_returnsSuccess() throws Exception { + public void testCall_whenCallbackIsCalledBeforeTimeOut_returnsResult() throws Exception { ConditionVariable scheduled = new ConditionVariable(false); RemoteCall remoteCall = new RemoteCall( @@ -176,11 +176,11 @@ public class RemoteCallTest { scheduled.block(); runToEndOfTasks(Looper.getMainLooper()); - assertThat(result.get()).isEqualTo(RemoteResult.successful(3)); + assertThat(result.get()).isEqualTo(RemoteResult.of(3)); } @Test - public void testCall_whenCallbackIsCalledBeforeCancel_returnsSuccess() throws Exception { + public void testCall_whenCallbackIsCalledBeforeCancel_returnsResult() throws Exception { CompletableFuture<IBackupCallback> callbackFuture = new CompletableFuture<>(); RemoteCall remoteCall = new RemoteCall(callbackFuture::complete, 1000); @@ -191,7 +191,7 @@ public class RemoteCallTest { IBackupCallback callback = callbackFuture.get(); callback.operationComplete(3); remoteCall.cancel(); - assertThat(result.get()).isEqualTo(RemoteResult.successful(3)); + assertThat(result.get()).isEqualTo(RemoteResult.of(3)); } @Test diff --git a/services/robotests/src/com/android/server/backup/remote/RemoteResultTest.java b/services/robotests/src/com/android/server/backup/remote/RemoteResultTest.java index f1c4f27bc38e..7f6fd5785b65 100644 --- a/services/robotests/src/com/android/server/backup/remote/RemoteResultTest.java +++ b/services/robotests/src/com/android/server/backup/remote/RemoteResultTest.java @@ -35,28 +35,38 @@ import org.robolectric.annotation.Config; @Presubmit public class RemoteResultTest { @Test - public void testSucceeded_whenSuccessfulResult_returnsTrue() { - RemoteResult result = RemoteResult.successful(3); + public void testIsPresent_whenNonFailedResult_returnsTrue() { + RemoteResult result = RemoteResult.of(3); - boolean succeeded = result.succeeded(); + boolean isPresent = result.isPresent(); - assertThat(succeeded).isTrue(); + assertThat(isPresent).isTrue(); } @Test - public void testSucceeded_whenFailedResults_returnsFalse() { - boolean timeOutSucceeded = RemoteResult.FAILED_TIMED_OUT.succeeded(); - boolean cancelledSucceeded = RemoteResult.FAILED_CANCELLED.succeeded(); - boolean threadInterruptedSucceeded = RemoteResult.FAILED_THREAD_INTERRUPTED.succeeded(); - - assertThat(timeOutSucceeded).isFalse(); - assertThat(cancelledSucceeded).isFalse(); - assertThat(threadInterruptedSucceeded).isFalse(); + public void testIsPresent_whenTimeOutResult_returnsFalse() { + boolean timeOutIsPresent = RemoteResult.FAILED_TIMED_OUT.isPresent(); + + assertThat(timeOutIsPresent).isFalse(); + } + + @Test + public void testIsPresent_whenCancelledResult_returnsFalse() { + boolean cancelledIsPresent = RemoteResult.FAILED_CANCELLED.isPresent(); + + assertThat(cancelledIsPresent).isFalse(); + } + + @Test + public void testIsPresent_whenThreadInterruptedResult_returnsFalse() { + boolean threadInterruptedIsPresent = RemoteResult.FAILED_THREAD_INTERRUPTED.isPresent(); + + assertThat(threadInterruptedIsPresent).isFalse(); } @Test public void testGet_whenSuccessfulResult_returnsValue() { - RemoteResult result = RemoteResult.successful(7); + RemoteResult result = RemoteResult.of(7); long value = result.get(); @@ -72,7 +82,7 @@ public class RemoteResultTest { @Test public void testToString() { - assertThat(RemoteResult.successful(3).toString()).isEqualTo("RemoteResult{3}"); + assertThat(RemoteResult.of(3).toString()).isEqualTo("RemoteResult{3}"); assertThat(RemoteResult.FAILED_TIMED_OUT.toString()) .isEqualTo("RemoteResult{FAILED_TIMED_OUT}"); assertThat(RemoteResult.FAILED_CANCELLED.toString()) @@ -83,14 +93,14 @@ public class RemoteResultTest { @Test public void testEquals() { - assertThat(RemoteResult.successful(3).equals(RemoteResult.successful(3))).isTrue(); - assertThat(RemoteResult.successful(3).equals(RemoteResult.successful(7))).isFalse(); - assertThat(RemoteResult.successful(-1).equals(RemoteResult.successful(1))).isFalse(); - assertThat(RemoteResult.successful(Long.MAX_VALUE).equals(RemoteResult.successful(-1))) + assertThat(RemoteResult.of(3).equals(RemoteResult.of(3))).isTrue(); + assertThat(RemoteResult.of(3).equals(RemoteResult.of(7))).isFalse(); + assertThat(RemoteResult.of(-1).equals(RemoteResult.of(1))).isFalse(); + assertThat(RemoteResult.of(Long.MAX_VALUE).equals(RemoteResult.of(-1))) .isFalse(); - assertThat(RemoteResult.successful(3).equals(RemoteResult.FAILED_TIMED_OUT)).isFalse(); - assertThat(RemoteResult.successful(3).equals("3")).isFalse(); - assertThat(RemoteResult.successful(3).equals(null)).isFalse(); + assertThat(RemoteResult.of(3).equals(RemoteResult.FAILED_TIMED_OUT)).isFalse(); + assertThat(RemoteResult.of(3).equals("3")).isFalse(); + assertThat(RemoteResult.of(3).equals(null)).isFalse(); assertThat(RemoteResult.FAILED_TIMED_OUT.equals(RemoteResult.FAILED_TIMED_OUT)).isTrue(); assertThat(RemoteResult.FAILED_TIMED_OUT.equals(RemoteResult.FAILED_CANCELLED)).isFalse(); } @@ -98,9 +108,9 @@ public class RemoteResultTest { /** @see Object#hashCode() */ @Test public void testHashCode() { - RemoteResult result3 = RemoteResult.successful(3); + RemoteResult result3 = RemoteResult.of(3); assertThat(result3.hashCode()).isEqualTo(result3.hashCode()); - assertThat(result3.hashCode()).isEqualTo(RemoteResult.successful(3).hashCode()); + assertThat(result3.hashCode()).isEqualTo(RemoteResult.of(3).hashCode()); assertThat(RemoteResult.FAILED_TIMED_OUT.hashCode()) .isEqualTo(RemoteResult.FAILED_TIMED_OUT.hashCode()); assertThat(RemoteResult.FAILED_CANCELLED.hashCode()) |