Merge "More tests for ActiveRestoreSession"

This commit is contained in:
Bernardo Rufino
2018-02-27 15:05:02 +00:00
committed by Android (Google) Code Review
7 changed files with 381 additions and 18 deletions

View File

@@ -302,7 +302,7 @@ public class BackupHandler extends Handler {
sets = transport.getAvailableRestoreSets();
// cache the result in the active session
synchronized (params.session) {
params.session.mRestoreSets = sets;
params.session.setRestoreSets(sets);
}
if (sets == null) {
EventLog.writeEvent(EventLogTags.RESTORE_TRANSPORT_FAILURE);

View File

@@ -16,6 +16,7 @@
package com.android.server.backup.params;
import android.annotation.Nullable;
import android.app.backup.IBackupManagerMonitor;
import android.app.backup.IRestoreObserver;
import android.content.pm.PackageInfo;
@@ -28,10 +29,10 @@ public class RestoreParams {
public final IRestoreObserver observer;
public final IBackupManagerMonitor monitor;
public final long token;
public final PackageInfo packageInfo;
@Nullable public final PackageInfo packageInfo;
public final int pmToken; // in post-install restore, the PM's token for this transaction
public final boolean isSystemRestore;
public final String[] filterSet;
@Nullable public final String[] filterSet;
public final OnTaskFinishedListener listener;
/**
@@ -129,10 +130,10 @@ public class RestoreParams {
IRestoreObserver observer,
IBackupManagerMonitor monitor,
long token,
PackageInfo packageInfo,
@Nullable PackageInfo packageInfo,
int pmToken,
boolean isSystemRestore,
String[] filterSet,
@Nullable String[] filterSet,
OnTaskFinishedListener listener) {
this.transportClient = transportClient;
this.observer = observer;

View File

@@ -22,6 +22,7 @@ import static com.android.server.backup.internal.BackupHandler.MSG_RESTORE_SESSI
import static com.android.server.backup.internal.BackupHandler.MSG_RUN_GET_RESTORE_SETS;
import static com.android.server.backup.internal.BackupHandler.MSG_RUN_RESTORE;
import android.annotation.Nullable;
import android.app.backup.IBackupManagerMonitor;
import android.app.backup.IRestoreObserver;
import android.app.backup.IRestoreSession;
@@ -53,13 +54,15 @@ public class ActiveRestoreSession extends IRestoreSession.Stub {
private final TransportManager mTransportManager;
private final String mTransportName;
private final BackupManagerService mBackupManagerService;
private final String mPackageName;
@Nullable private final String mPackageName;
public RestoreSet[] mRestoreSets = null;
boolean mEnded = false;
boolean mTimedOut = false;
public ActiveRestoreSession(BackupManagerService backupManagerService,
String packageName, String transportName) {
public ActiveRestoreSession(
BackupManagerService backupManagerService,
@Nullable String packageName,
String transportName) {
mBackupManagerService = backupManagerService;
mPackageName = packageName;
mTransportManager = backupManagerService.getTransportManager();
@@ -360,6 +363,10 @@ public class ActiveRestoreSession extends IRestoreSession.Stub {
}
}
public void setRestoreSets(RestoreSet[] restoreSets) {
mRestoreSets = restoreSets;
}
/**
* Returns 0 if operation sent or -1 otherwise.
*/

View File

@@ -30,6 +30,7 @@ import static com.android.server.backup.internal.BackupHandler.MSG_BACKUP_RESTOR
import static com.android.server.backup.internal.BackupHandler.MSG_RESTORE_OPERATION_TIMEOUT;
import static com.android.server.backup.internal.BackupHandler.MSG_RESTORE_SESSION_TIMEOUT;
import android.annotation.Nullable;
import android.app.ApplicationThreadConstants;
import android.app.IBackupAgent;
import android.app.backup.BackupDataInput;
@@ -158,12 +159,18 @@ public class PerformUnifiedRestoreTask implements BackupRestoreTask {
private final int mEphemeralOpToken;
// Invariant: mWakelock is already held, and this task is responsible for
// releasing it at the end of the restore operation.
public PerformUnifiedRestoreTask(BackupManagerService backupManagerService,
TransportClient transportClient, IRestoreObserver observer,
IBackupManagerMonitor monitor, long restoreSetToken, PackageInfo targetPackage,
int pmToken, boolean isFullSystemRestore, String[] filterSet,
// This task can assume that the wakelock is properly held for it and doesn't have to worry
// about releasing it.
public PerformUnifiedRestoreTask(
BackupManagerService backupManagerService,
TransportClient transportClient,
IRestoreObserver observer,
IBackupManagerMonitor monitor,
long restoreSetToken,
@Nullable PackageInfo targetPackage,
int pmToken,
boolean isFullSystemRestore,
@Nullable String[] filterSet,
OnTaskFinishedListener listener) {
this.backupManagerService = backupManagerService;
mTransportManager = backupManagerService.getTransportManager();
@@ -336,7 +343,7 @@ public class PerformUnifiedRestoreTask implements BackupRestoreTask {
*
* [ state change => FINAL ]
*
* 7. t.finishRestore(), release wakelock, etc.
* 7. t.finishRestore(), call listeners, etc.
*
*
*/

View File

@@ -25,8 +25,10 @@ import static com.google.common.truth.Truth.assertThat;
import static org.mockito.AdditionalMatchers.aryEq;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.isNull;
import static org.mockito.Mockito.doCallRealMethod;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.robolectric.Shadows.shadowOf;
@@ -39,6 +41,7 @@ import android.app.backup.IRestoreSession;
import android.app.backup.RestoreSet;
import android.os.Looper;
import android.os.PowerManager;
import android.os.RemoteException;
import android.platform.test.annotations.Presubmit;
import com.android.server.EventLogTags;
@@ -51,7 +54,9 @@ import com.android.server.backup.testing.TransportTestUtils.TransportMock;
import com.android.server.testing.FrameworkRobolectricTestRunner;
import com.android.server.testing.SystemLoaderPackages;
import com.android.server.testing.shadows.ShadowEventLog;
import com.android.server.testing.shadows.ShadowPerformUnifiedRestoreTask;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -62,8 +67,14 @@ import org.robolectric.annotation.Config;
import org.robolectric.shadows.ShadowApplication;
import org.robolectric.shadows.ShadowLooper;
import java.util.ArrayDeque;
@RunWith(FrameworkRobolectricTestRunner.class)
@Config(manifest = Config.NONE, sdk = 26, shadows = ShadowEventLog.class)
@Config(
manifest = Config.NONE,
sdk = 26,
shadows = {ShadowEventLog.class, ShadowPerformUnifiedRestoreTask.class}
)
@SystemLoaderPackages({"com.android.server.backup"})
@Presubmit
public class ActiveRestoreSessionTest {
@@ -78,6 +89,8 @@ public class ActiveRestoreSessionTest {
private ShadowApplication mShadowApplication;
private PowerManager.WakeLock mWakeLock;
private TransportData mTransport;
private long mToken1;
private long mToken2;
private RestoreSet mRestoreSet1;
private RestoreSet mRestoreSet2;
@@ -87,8 +100,10 @@ public class ActiveRestoreSessionTest {
mTransport = backupTransport();
mRestoreSet1 = new RestoreSet("name1", "device1", 1L);
mRestoreSet2 = new RestoreSet("name2", "device2", 2L);
mToken1 = 1L;
mRestoreSet1 = new RestoreSet("name1", "device1", mToken1);
mToken2 = 2L;
mRestoreSet2 = new RestoreSet("name2", "device2", mToken2);
Application application = RuntimeEnvironment.application;
mShadowApplication = shadowOf(application);
@@ -106,6 +121,12 @@ public class ActiveRestoreSessionTest {
application.getPackageManager(),
backupHandler,
mWakeLock);
when(mBackupManagerService.getPendingRestores()).thenReturn(new ArrayDeque<>());
}
@After
public void tearDown() throws Exception {
ShadowPerformUnifiedRestoreTask.reset();
}
@Test
@@ -193,12 +214,244 @@ public class ActiveRestoreSessionTest {
assertThat(mWakeLock.isHeld()).isFalse();
}
@Test
public void testRestoreAll() throws Exception {
mShadowApplication.grantPermissions(android.Manifest.permission.BACKUP);
doCallRealMethod().when(mBackupManagerService).setRestoreInProgress(anyBoolean());
when(mBackupManagerService.isRestoreInProgress()).thenCallRealMethod();
TransportMock transportMock = setUpTransport(mTransport);
IRestoreSession restoreSession =
createActiveRestoreSessionWithRestoreSets(null, mTransport, mRestoreSet1);
int result = restoreSession.restoreAll(mToken1, mObserver, mMonitor);
mShadowBackupLooper.runToEndOfTasks();
assertThat(result).isEqualTo(0);
verify(mTransportManager)
.disposeOfTransportClient(eq(transportMock.transportClient), any());
assertThat(mWakeLock.isHeld()).isFalse();
assertThat(mBackupManagerService.isRestoreInProgress()).isFalse();
// Verify it created the task properly
ShadowPerformUnifiedRestoreTask shadowTask =
ShadowPerformUnifiedRestoreTask.getLastCreated();
assertThat(shadowTask.isFullSystemRestore()).isTrue();
assertThat(shadowTask.getFilterSet()).isNull();
assertThat(shadowTask.getPackage()).isNull();
}
@Test
public void testRestoreAll_whenNoRestoreSets() throws Exception {
mShadowApplication.grantPermissions(android.Manifest.permission.BACKUP);
setUpTransport(mTransport);
IRestoreSession restoreSession = createActiveRestoreSession(null, mTransport);
int result = restoreSession.restoreAll(mToken1, mObserver, mMonitor);
mShadowBackupLooper.runToEndOfTasks();
assertThat(result).isEqualTo(-1);
assertThat(ShadowPerformUnifiedRestoreTask.getLastCreated()).isNull();
}
@Test
public void testRestoreAll_whenSinglePackageSession() throws Exception {
mShadowApplication.grantPermissions(android.Manifest.permission.BACKUP);
setUpTransport(mTransport);
IRestoreSession restoreSession =
createActiveRestoreSessionWithRestoreSets(PACKAGE_1, mTransport, mRestoreSet1);
int result = restoreSession.restoreAll(mToken1, mObserver, mMonitor);
mShadowBackupLooper.runToEndOfTasks();
assertThat(result).isEqualTo(-1);
assertThat(ShadowPerformUnifiedRestoreTask.getLastCreated()).isNull();
}
@Test
public void testRestoreAll_whenSessionEnded() throws Exception {
mShadowApplication.grantPermissions(android.Manifest.permission.BACKUP);
setUpTransport(mTransport);
IRestoreSession restoreSession =
createActiveRestoreSessionWithRestoreSets(null, mTransport, mRestoreSet1);
restoreSession.endRestoreSession();
mShadowBackupLooper.runToEndOfTasks();
expectThrows(
IllegalStateException.class,
() -> restoreSession.restoreAll(mToken1, mObserver, mMonitor));
}
@Test
public void testRestoreAll_whenTransportNotRegistered() throws Exception {
mShadowApplication.grantPermissions(android.Manifest.permission.BACKUP);
setUpTransport(mTransport.unregistered());
IRestoreSession restoreSession =
createActiveRestoreSessionWithRestoreSets(null, mTransport, mRestoreSet1);
int result = restoreSession.restoreAll(mToken1, mObserver, mMonitor);
mShadowBackupLooper.runToEndOfTasks();
assertThat(result).isEqualTo(-1);
assertThat(ShadowPerformUnifiedRestoreTask.getLastCreated()).isNull();
}
@Test
public void testRestoreAll_whenRestoreInProgress_addsToPendingRestores() throws Exception {
mShadowApplication.grantPermissions(android.Manifest.permission.BACKUP);
setUpTransport(mTransport);
when(mBackupManagerService.isRestoreInProgress()).thenReturn(true);
IRestoreSession restoreSession =
createActiveRestoreSessionWithRestoreSets(null, mTransport, mRestoreSet1);
int result = restoreSession.restoreAll(mToken1, mObserver, mMonitor);
mShadowBackupLooper.runToEndOfTasks();
assertThat(result).isEqualTo(0);
assertThat(mBackupManagerService.getPendingRestores()).hasSize(1);
}
@Test
public void testRestoreSome_for2Packages() throws Exception {
mShadowApplication.grantPermissions(android.Manifest.permission.BACKUP);
TransportMock transportMock = setUpTransport(mTransport);
IRestoreSession restoreSession =
createActiveRestoreSessionWithRestoreSets(null, mTransport, mRestoreSet1);
int result =
restoreSession.restoreSome(
mToken1, mObserver, mMonitor, new String[] {PACKAGE_1, PACKAGE_2});
mShadowBackupLooper.runToEndOfTasks();
assertThat(result).isEqualTo(0);
verify(mTransportManager)
.disposeOfTransportClient(eq(transportMock.transportClient), any());
assertThat(mWakeLock.isHeld()).isFalse();
assertThat(mBackupManagerService.isRestoreInProgress()).isFalse();
ShadowPerformUnifiedRestoreTask shadowTask =
ShadowPerformUnifiedRestoreTask.getLastCreated();
assertThat(shadowTask.getFilterSet()).asList().containsExactly(PACKAGE_1, PACKAGE_2);
assertThat(shadowTask.getPackage()).isNull();
}
@Test
public void testRestoreSome_for2Packages_createsSystemRestoreTask() throws Exception {
mShadowApplication.grantPermissions(android.Manifest.permission.BACKUP);
setUpTransport(mTransport);
IRestoreSession restoreSession =
createActiveRestoreSessionWithRestoreSets(null, mTransport, mRestoreSet1);
restoreSession.restoreSome(
mToken1, mObserver, mMonitor, new String[] {PACKAGE_1, PACKAGE_2});
mShadowBackupLooper.runToEndOfTasks();
assertThat(ShadowPerformUnifiedRestoreTask.getLastCreated().isFullSystemRestore()).isTrue();
}
@Test
public void testRestoreSome_for1Package() throws Exception {
mShadowApplication.grantPermissions(android.Manifest.permission.BACKUP);
setUpTransport(mTransport);
IRestoreSession restoreSession =
createActiveRestoreSessionWithRestoreSets(null, mTransport, mRestoreSet1);
restoreSession.restoreSome(mToken1, mObserver, mMonitor, new String[] {PACKAGE_1});
mShadowBackupLooper.runToEndOfTasks();
ShadowPerformUnifiedRestoreTask shadowTask =
ShadowPerformUnifiedRestoreTask.getLastCreated();
assertThat(shadowTask.getFilterSet()).asList().containsExactly(PACKAGE_1);
assertThat(shadowTask.getPackage()).isNull();
}
@Test
public void testRestoreSome_for1Package_createsNonSystemRestoreTask() throws Exception {
mShadowApplication.grantPermissions(android.Manifest.permission.BACKUP);
setUpTransport(mTransport);
IRestoreSession restoreSession =
createActiveRestoreSessionWithRestoreSets(null, mTransport, mRestoreSet1);
restoreSession.restoreSome(mToken1, mObserver, mMonitor, new String[] {PACKAGE_1});
mShadowBackupLooper.runToEndOfTasks();
assertThat(ShadowPerformUnifiedRestoreTask.getLastCreated().isFullSystemRestore())
.isFalse();
}
@Test
public void testRestoreSome_whenNoRestoreSets() throws Exception {
mShadowApplication.grantPermissions(android.Manifest.permission.BACKUP);
setUpTransport(mTransport);
IRestoreSession restoreSession = createActiveRestoreSession(null, mTransport);
int result =
restoreSession.restoreSome(mToken1, mObserver, mMonitor, new String[] {PACKAGE_1});
mShadowBackupLooper.runToEndOfTasks();
assertThat(result).isEqualTo(-1);
assertThat(ShadowPerformUnifiedRestoreTask.getLastCreated()).isNull();
}
@Test
public void testRestoreSome_whenSinglePackageSession() throws Exception {
mShadowApplication.grantPermissions(android.Manifest.permission.BACKUP);
setUpTransport(mTransport);
IRestoreSession restoreSession =
createActiveRestoreSessionWithRestoreSets(PACKAGE_1, mTransport, mRestoreSet1);
int result =
restoreSession.restoreSome(mToken1, mObserver, mMonitor, new String[] {PACKAGE_2});
mShadowBackupLooper.runToEndOfTasks();
assertThat(result).isEqualTo(-1);
assertThat(ShadowPerformUnifiedRestoreTask.getLastCreated()).isNull();
}
@Test
public void testRestoreSome_whenSessionEnded() throws Exception {
mShadowApplication.grantPermissions(android.Manifest.permission.BACKUP);
setUpTransport(mTransport);
IRestoreSession restoreSession =
createActiveRestoreSessionWithRestoreSets(null, mTransport, mRestoreSet1);
restoreSession.endRestoreSession();
mShadowBackupLooper.runToEndOfTasks();
expectThrows(
IllegalStateException.class,
() ->
restoreSession.restoreSome(
mToken1, mObserver, mMonitor, new String[] {PACKAGE_1}));
}
@Test
public void testRestoreSome_whenTransportNotRegistered() throws Exception {
mShadowApplication.grantPermissions(android.Manifest.permission.BACKUP);
setUpTransport(mTransport.unregistered());
IRestoreSession restoreSession =
createActiveRestoreSessionWithRestoreSets(null, mTransport, mRestoreSet1);
int result =
restoreSession.restoreSome(mToken1, mObserver, mMonitor, new String[] {PACKAGE_1});
mShadowBackupLooper.runToEndOfTasks();
assertThat(result).isEqualTo(-1);
assertThat(ShadowPerformUnifiedRestoreTask.getLastCreated()).isNull();
}
private IRestoreSession createActiveRestoreSession(
String packageName, TransportData transport) {
return new ActiveRestoreSession(
mBackupManagerService, packageName, transport.transportName);
}
private IRestoreSession createActiveRestoreSessionWithRestoreSets(
String packageName, TransportData transport, RestoreSet... restoreSets)
throws RemoteException {
ActiveRestoreSession restoreSession =
new ActiveRestoreSession(
mBackupManagerService, packageName, transport.transportName);
restoreSession.setRestoreSets(restoreSets);
return restoreSession;
}
private TransportMock setUpTransport(TransportData transport) throws Exception {
return TransportTestUtils.setUpTransport(mTransportManager, transport);
}

View File

@@ -115,6 +115,7 @@ public class TransportTestUtils {
.thenReturn(transportDirName);
when(transportManager.getTransportDirName(eq(transportComponent)))
.thenReturn(transportDirName);
when(transportManager.isTransportRegistered(eq(transportName))).thenReturn(true);
// TODO: Mock rest of description methods
} else {
// Transport not registered
@@ -127,6 +128,7 @@ public class TransportTestUtils {
.thenThrow(TransportNotRegisteredException.class);
when(transportManager.getTransportDirName(eq(transportComponent)))
.thenThrow(TransportNotRegisteredException.class);
when(transportManager.isTransportRegistered(eq(transportName))).thenReturn(false);
}
return transportMock;
}

View File

@@ -0,0 +1,93 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License
*/
package com.android.server.testing.shadows;
import android.annotation.Nullable;
import android.app.backup.IBackupManagerMonitor;
import android.app.backup.IRestoreObserver;
import android.content.pm.PackageInfo;
import com.android.server.backup.BackupManagerService;
import com.android.server.backup.internal.OnTaskFinishedListener;
import com.android.server.backup.restore.PerformUnifiedRestoreTask;
import com.android.server.backup.transport.TransportClient;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
@Implements(PerformUnifiedRestoreTask.class)
public class ShadowPerformUnifiedRestoreTask {
@Nullable private static ShadowPerformUnifiedRestoreTask sLastShadow;
/**
* Retrieves the shadow for the last {@link PerformUnifiedRestoreTask} object created.
*
* @return The shadow or {@code null} if no object created since last {@link #reset()}.
*/
@Nullable
public static ShadowPerformUnifiedRestoreTask getLastCreated() {
return sLastShadow;
}
public static void reset() {
sLastShadow = null;
}
private BackupManagerService mBackupManagerService;
@Nullable private PackageInfo mPackage;
private boolean mIsFullSystemRestore;
@Nullable private String[] mFilterSet;
private OnTaskFinishedListener mListener;
@Implementation
public void __constructor__(
BackupManagerService backupManagerService,
TransportClient transportClient,
IRestoreObserver observer,
IBackupManagerMonitor monitor,
long restoreSetToken,
@Nullable PackageInfo targetPackage,
int pmToken,
boolean isFullSystemRestore,
@Nullable String[] filterSet,
OnTaskFinishedListener listener) {
mBackupManagerService = backupManagerService;
mPackage = targetPackage;
mIsFullSystemRestore = isFullSystemRestore;
mFilterSet = filterSet;
mListener = listener;
sLastShadow = this;
}
@Implementation
public void execute() {
mBackupManagerService.setRestoreInProgress(false);
mListener.onFinished("ShadowPerformUnifiedRestoreTask.execute()");
}
public PackageInfo getPackage() {
return mPackage;
}
public String[] getFilterSet() {
return mFilterSet;
}
public boolean isFullSystemRestore() {
return mIsFullSystemRestore;
}
}