Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 34607a0f authored by Bernardo Rufino's avatar Bernardo Rufino
Browse files

Tests for BMS.requestBackup()

Test: m -j RunFrameworksServicesRoboTests
Change-Id: I71f377a2ce16ece08e7d2ebbf2af31c0d1594703
parent b671b241
Loading
Loading
Loading
Loading
+1 −1
Original line number Original line Diff line number Diff line
@@ -177,7 +177,7 @@ public class TransportManager {
    }
    }


    @Nullable
    @Nullable
    String getCurrentTransportName() {
    public String getCurrentTransportName() {
        return mCurrentTransportName;
        return mCurrentTransportName;
    }
    }


+19 −1
Original line number Original line Diff line number Diff line
@@ -16,11 +16,12 @@


package com.android.server.backup.internal;
package com.android.server.backup.internal;


import java.util.Objects;

/**
/**
 * Set of backup services that have pending changes.
 * Set of backup services that have pending changes.
 */
 */
public class BackupRequest {
public class BackupRequest {

    public String packageName;
    public String packageName;


    public BackupRequest(String pkgName) {
    public BackupRequest(String pkgName) {
@@ -30,4 +31,21 @@ public class BackupRequest {
    public String toString() {
    public String toString() {
        return "BackupRequest{pkg=" + packageName + "}";
        return "BackupRequest{pkg=" + packageName + "}";
    }
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (!(o instanceof BackupRequest)) {
            return false;
        }
        BackupRequest that = (BackupRequest) o;
        return Objects.equals(packageName, that.packageName);
    }

    @Override
    public int hashCode() {
        return Objects.hash(packageName);
    }
}
}
+181 −30
Original line number Original line Diff line number Diff line
@@ -22,7 +22,9 @@ import static com.android.server.backup.testing.TransportData.d2dTransport;
import static com.android.server.backup.testing.TransportData.localTransport;
import static com.android.server.backup.testing.TransportData.localTransport;
import static com.android.server.backup.testing.TransportTestUtils.setUpCurrentTransport;
import static com.android.server.backup.testing.TransportTestUtils.setUpCurrentTransport;
import static com.android.server.backup.testing.TransportTestUtils.setUpTransports;
import static com.android.server.backup.testing.TransportTestUtils.setUpTransports;

import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertThat;

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.eq;
@@ -34,6 +36,7 @@ import static org.robolectric.Shadows.shadowOf;
import static org.testng.Assert.expectThrows;
import static org.testng.Assert.expectThrows;


import android.app.backup.BackupManager;
import android.app.backup.BackupManager;
import android.app.backup.IBackupObserver;
import android.app.backup.ISelectBackupTransportCallback;
import android.app.backup.ISelectBackupTransportCallback;
import android.content.ComponentName;
import android.content.ComponentName;
import android.content.Context;
import android.content.Context;
@@ -43,18 +46,16 @@ import android.os.HandlerThread;
import android.platform.test.annotations.Presubmit;
import android.platform.test.annotations.Presubmit;
import android.provider.Settings;
import android.provider.Settings;


import com.android.server.testing.shadows.ShadowAppBackupUtils;
import com.android.server.backup.internal.BackupRequest;
import com.android.server.testing.shadows.ShadowBackupPolicyEnforcer;
import com.android.server.backup.testing.TransportData;
import com.android.server.backup.testing.TransportData;
import com.android.server.backup.testing.TransportTestUtils.TransportMock;
import com.android.server.backup.testing.TransportTestUtils.TransportMock;
import com.android.server.backup.transport.TransportNotRegisteredException;
import com.android.server.backup.transport.TransportNotRegisteredException;
import com.android.server.testing.FrameworkRobolectricTestRunner;
import com.android.server.testing.FrameworkRobolectricTestRunner;
import com.android.server.testing.SystemLoaderPackages;
import com.android.server.testing.SystemLoaderPackages;
import com.android.server.testing.shadows.ShadowAppBackupUtils;
import com.android.server.testing.shadows.ShadowBackupPolicyEnforcer;
import com.android.server.testing.shadows.ShadowPerformBackupTask;


import java.io.File;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.junit.After;
import org.junit.After;
import org.junit.Before;
import org.junit.Before;
import org.junit.Test;
import org.junit.Test;
@@ -70,6 +71,9 @@ import org.robolectric.shadows.ShadowPackageManager;
import org.robolectric.shadows.ShadowSettings;
import org.robolectric.shadows.ShadowSettings;
import org.robolectric.shadows.ShadowSystemClock;
import org.robolectric.shadows.ShadowSystemClock;


import java.io.File;
import java.util.List;

@RunWith(FrameworkRobolectricTestRunner.class)
@RunWith(FrameworkRobolectricTestRunner.class)
@Config(
@Config(
    manifest = Config.NONE,
    manifest = Config.NONE,
@@ -80,6 +84,8 @@ import org.robolectric.shadows.ShadowSystemClock;
@Presubmit
@Presubmit
public class BackupManagerServiceTest {
public class BackupManagerServiceTest {
    private static final String TAG = "BMSTest";
    private static final String TAG = "BMSTest";
    private static final String PACKAGE_1 = "some.package.1";
    private static final String PACKAGE_2 = "some.package.2";


    @Mock private TransportManager mTransportManager;
    @Mock private TransportManager mTransportManager;
    private HandlerThread mBackupThread;
    private HandlerThread mBackupThread;
@@ -90,6 +96,7 @@ public class BackupManagerServiceTest {
    private Context mContext;
    private Context mContext;
    private TransportData mTransport;
    private TransportData mTransport;
    private String mTransportName;
    private String mTransportName;
    private ShadowPackageManager mShadowPackageManager;


    @Before
    @Before
    public void setUp() throws Exception {
    public void setUp() throws Exception {
@@ -102,6 +109,7 @@ public class BackupManagerServiceTest {
        mShadowBackupLooper = shadowOf(mBackupThread.getLooper());
        mShadowBackupLooper = shadowOf(mBackupThread.getLooper());


        ContextWrapper context = RuntimeEnvironment.application;
        ContextWrapper context = RuntimeEnvironment.application;
        mShadowPackageManager = shadowOf(context.getPackageManager());
        mContext = context;
        mContext = context;
        mShadowContext = shadowOf(context);
        mShadowContext = shadowOf(context);


@@ -167,57 +175,54 @@ public class BackupManagerServiceTest {
    /* Tests for app eligibility */
    /* Tests for app eligibility */


    @Test
    @Test
    public void testIsAppEligibleForBackup_whenAppEligible() throws Exception {
    public void testIsAppEligibleForBackup_whenAppNotEligible() throws Exception {
        mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
        mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
        TransportMock transportMock = setUpCurrentTransport(mTransportManager, backupTransport());
        setUpCurrentTransport(mTransportManager, mTransport);
        ShadowAppBackupUtils.sAppIsRunningAndEligibleForBackupWithTransport = p -> true;
        BackupManagerService backupManagerService = createInitializedBackupManagerService();
        BackupManagerService backupManagerService = createInitializedBackupManagerService();


        boolean result = backupManagerService.isAppEligibleForBackup("app.package");
        boolean result = backupManagerService.isAppEligibleForBackup(PACKAGE_1);

        assertThat(result).isTrue();


        verify(mTransportManager)
        assertThat(result).isFalse();
                .disposeOfTransportClient(eq(transportMock.transportClient), any());
    }
    }


    @Test
    @Test
    public void testIsAppEligibleForBackup_whenAppNotEligible() throws Exception {
    public void testIsAppEligibleForBackup_whenAppEligible() throws Exception {
        mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
        mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
        setUpCurrentTransport(mTransportManager, mTransport);
        TransportMock transportMock = setUpCurrentTransport(mTransportManager, backupTransport());
        ShadowAppBackupUtils.sAppIsRunningAndEligibleForBackupWithTransport = p -> false;
        ShadowAppBackupUtils.setAppRunningAndEligibleForBackupWithTransport(PACKAGE_1);
        BackupManagerService backupManagerService = createInitializedBackupManagerService();
        BackupManagerService backupManagerService = createInitializedBackupManagerService();


        boolean result = backupManagerService.isAppEligibleForBackup("app.package");
        boolean result = backupManagerService.isAppEligibleForBackup(PACKAGE_1);


        assertThat(result).isFalse();
        assertThat(result).isTrue();
        verify(mTransportManager)
                .disposeOfTransportClient(eq(transportMock.transportClient), any());
    }
    }


    @Test
    @Test
    public void testIsAppEligibleForBackup_withoutPermission() throws Exception {
    public void testIsAppEligibleForBackup_withoutPermission() throws Exception {
        mShadowContext.denyPermissions(android.Manifest.permission.BACKUP);
        mShadowContext.denyPermissions(android.Manifest.permission.BACKUP);
        setUpCurrentTransport(mTransportManager, mTransport);
        setUpCurrentTransport(mTransportManager, mTransport);
        ShadowAppBackupUtils.setAppRunningAndEligibleForBackupWithTransport(PACKAGE_1);
        BackupManagerService backupManagerService = createInitializedBackupManagerService();
        BackupManagerService backupManagerService = createInitializedBackupManagerService();


        expectThrows(
        expectThrows(
                SecurityException.class,
                SecurityException.class,
                () -> backupManagerService.isAppEligibleForBackup("app.package"));
                () -> backupManagerService.isAppEligibleForBackup(PACKAGE_1));
    }
    }


    @Test
    @Test
    public void testFilterAppsEligibleForBackup() throws Exception {
    public void testFilterAppsEligibleForBackup() throws Exception {
        mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
        mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
        TransportMock transportMock = setUpCurrentTransport(mTransportManager, mTransport);
        TransportMock transportMock = setUpCurrentTransport(mTransportManager, mTransport);
        Map<String, Boolean> packagesMap = new HashMap<>();
        ShadowAppBackupUtils.setAppRunningAndEligibleForBackupWithTransport(PACKAGE_1);
        packagesMap.put("package.a", true);
        packagesMap.put("package.b", false);
        ShadowAppBackupUtils.sAppIsRunningAndEligibleForBackupWithTransport = packagesMap::get;
        BackupManagerService backupManagerService = createInitializedBackupManagerService();
        BackupManagerService backupManagerService = createInitializedBackupManagerService();
        String[] packages = packagesMap.keySet().toArray(new String[packagesMap.size()]);


        String[] filtered = backupManagerService.filterAppsEligibleForBackup(packages);
        String[] filtered =
                backupManagerService.filterAppsEligibleForBackup(
                        new String[] {PACKAGE_1, PACKAGE_2});


        assertThat(filtered).asList().containsExactly("package.a");
        assertThat(filtered).asList().containsExactly(PACKAGE_1);
        verify(mTransportManager)
        verify(mTransportManager)
                .disposeOfTransportClient(eq(transportMock.transportClient), any());
                .disposeOfTransportClient(eq(transportMock.transportClient), any());
    }
    }
@@ -225,12 +230,11 @@ public class BackupManagerServiceTest {
    @Test
    @Test
    public void testFilterAppsEligibleForBackup_whenNoneIsEligible() throws Exception {
    public void testFilterAppsEligibleForBackup_whenNoneIsEligible() throws Exception {
        mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
        mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
        ShadowAppBackupUtils.sAppIsRunningAndEligibleForBackupWithTransport = p -> false;
        BackupManagerService backupManagerService = createInitializedBackupManagerService();
        BackupManagerService backupManagerService = createInitializedBackupManagerService();


        String[] filtered =
        String[] filtered =
                backupManagerService.filterAppsEligibleForBackup(
                backupManagerService.filterAppsEligibleForBackup(
                        new String[] {"package.a", "package.b"});
                        new String[] {PACKAGE_1, PACKAGE_2});


        assertThat(filtered).isEmpty();
        assertThat(filtered).isEmpty();
    }
    }
@@ -245,7 +249,7 @@ public class BackupManagerServiceTest {
                SecurityException.class,
                SecurityException.class,
                () ->
                () ->
                        backupManagerService.filterAppsEligibleForBackup(
                        backupManagerService.filterAppsEligibleForBackup(
                                new String[] {"package.a", "package.b"}));
                                new String[] {PACKAGE_1, PACKAGE_2}));
    }
    }


    /* Tests for select transport */
    /* Tests for select transport */
@@ -608,6 +612,153 @@ public class BackupManagerServiceTest {
                                "dataManagementLabel"));
                                "dataManagementLabel"));
    }
    }


    /* Tests for request backup */

    @Mock private IBackupObserver mObserver;

    private void setUpForRequestBackup(String... packages) throws Exception {
        mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
        for (String packageName : packages) {
            mShadowPackageManager.addPackage(packageName);
            ShadowAppBackupUtils.setAppRunningAndEligibleForBackupWithTransport(packageName);
        }
        setUpCurrentTransport(mTransportManager, mTransport);
    }

    private void tearDownForRequestBackup() {
        ShadowPerformBackupTask.reset();
    }

    @Test
    public void testRequestBackup_whenPermissionDenied() throws Exception {
        mShadowContext.denyPermissions(android.Manifest.permission.BACKUP);
        BackupManagerService backupManagerService = createInitializedBackupManagerService();

        expectThrows(
                SecurityException.class,
                () -> backupManagerService.requestBackup(new String[] {PACKAGE_1}, mObserver, 0));
    }

    @Test
    public void testRequestBackup_whenPackagesNull() throws Exception {
        mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
        BackupManagerService backupManagerService = createInitializedBackupManagerService();

        expectThrows(
                IllegalArgumentException.class,
                () -> backupManagerService.requestBackup(null, mObserver, 0));
        verify(mObserver).backupFinished(BackupManager.ERROR_TRANSPORT_ABORTED);
    }

    @Test
    public void testRequestBackup_whenPackagesEmpty() throws Exception {
        mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
        BackupManagerService backupManagerService = createInitializedBackupManagerService();

        expectThrows(
                IllegalArgumentException.class,
                () -> backupManagerService.requestBackup(new String[0], mObserver, 0));
        verify(mObserver).backupFinished(BackupManager.ERROR_TRANSPORT_ABORTED);
    }

    @Test
    public void testRequestBackup_whenBackupDisabled() throws Exception {
        mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
        BackupManagerService backupManagerService = createInitializedBackupManagerService();
        backupManagerService.setEnabled(false);

        int result = backupManagerService.requestBackup(new String[] {PACKAGE_1}, mObserver, 0);

        assertThat(result).isEqualTo(BackupManager.ERROR_BACKUP_NOT_ALLOWED);
        verify(mObserver).backupFinished(BackupManager.ERROR_BACKUP_NOT_ALLOWED);
    }

    @Test
    public void testRequestBackup_whenNotProvisioned() throws Exception {
        mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
        BackupManagerService backupManagerService = createInitializedBackupManagerService();
        backupManagerService.setProvisioned(false);

        int result = backupManagerService.requestBackup(new String[] {PACKAGE_1}, mObserver, 0);

        assertThat(result).isEqualTo(BackupManager.ERROR_BACKUP_NOT_ALLOWED);
        verify(mObserver).backupFinished(BackupManager.ERROR_BACKUP_NOT_ALLOWED);
    }

    @Test
    public void testRequestBackup_whenTransportNotRegistered() throws Exception {
        mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
        setUpCurrentTransport(mTransportManager, mTransport.unregistered());
        BackupManagerService backupManagerService = createInitializedBackupManagerService();
        backupManagerService.setEnabled(true);
        backupManagerService.setProvisioned(true);

        int result = backupManagerService.requestBackup(new String[] {PACKAGE_1}, mObserver, 0);

        assertThat(result).isEqualTo(BackupManager.ERROR_TRANSPORT_ABORTED);
        verify(mObserver).backupFinished(BackupManager.ERROR_TRANSPORT_ABORTED);
    }

    @Test
    public void testRequestBackup_whenAppNotEligibleForBackup() throws Exception {
        mShadowContext.grantPermissions(android.Manifest.permission.BACKUP);
        mShadowPackageManager.addPackage(PACKAGE_1);
        setUpCurrentTransport(mTransportManager, mTransport);
        BackupManagerService backupManagerService = createInitializedBackupManagerService();
        backupManagerService.setEnabled(true);
        backupManagerService.setProvisioned(true);
        // Haven't set PACKAGE_1 as eligible

        int result = backupManagerService.requestBackup(new String[] {PACKAGE_1}, mObserver, 0);

        assertThat(result).isEqualTo(BackupManager.SUCCESS);
        verify(mObserver).onResult(PACKAGE_1, BackupManager.ERROR_BACKUP_NOT_ALLOWED);
        // TODO: We probably don't need to kick-off PerformBackupTask when list is empty
        tearDownForRequestBackup();
    }

    @Test
    @Config(shadows = ShadowPerformBackupTask.class)
    public void testRequestBackup_whenPackageIsKeyValue() throws Exception {
        setUpForRequestBackup(PACKAGE_1);
        BackupManagerService backupManagerService = createBackupManagerServiceForRequestBackup();

        int result = backupManagerService.requestBackup(new String[] {PACKAGE_1}, mObserver, 0);

        mShadowBackupLooper.runToEndOfTasks();
        assertThat(result).isEqualTo(BackupManager.SUCCESS);
        ShadowPerformBackupTask shadowTask = ShadowPerformBackupTask.getLastCreated();
        assertThat(shadowTask.getQueue()).containsExactly(new BackupRequest(PACKAGE_1));
        assertThat(shadowTask.getPendingFullBackups()).isEmpty();
        // TODO: Assert more about PerformBackupTask
        tearDownForRequestBackup();
    }

    @Test
    @Config(shadows = ShadowPerformBackupTask.class)
    public void testRequestBackup_whenPackageIsFullBackup() throws Exception {
        setUpForRequestBackup(PACKAGE_1);
        ShadowAppBackupUtils.setAppGetsFullBackup(PACKAGE_1);
        BackupManagerService backupManagerService = createBackupManagerServiceForRequestBackup();

        int result = backupManagerService.requestBackup(new String[] {PACKAGE_1}, mObserver, 0);

        mShadowBackupLooper.runToEndOfTasks();
        assertThat(result).isEqualTo(BackupManager.SUCCESS);
        ShadowPerformBackupTask shadowTask = ShadowPerformBackupTask.getLastCreated();
        assertThat(shadowTask.getQueue()).isEmpty();
        assertThat(shadowTask.getPendingFullBackups()).containsExactly(PACKAGE_1);
        // TODO: Assert more about PerformBackupTask
        tearDownForRequestBackup();
    }

    private BackupManagerService createBackupManagerServiceForRequestBackup() {
        BackupManagerService backupManagerService = createInitializedBackupManagerService();
        backupManagerService.setEnabled(true);
        backupManagerService.setProvisioned(true);
        return backupManagerService;
    }

    /* Miscellaneous tests */
    /* Miscellaneous tests */


    @Test
    @Test
+13 −2
Original line number Original line Diff line number Diff line
@@ -79,10 +79,21 @@ public class TransportTestUtils {
    /** {@code transportName} has to be in the {@link ComponentName} format (with '/') */
    /** {@code transportName} has to be in the {@link ComponentName} format (with '/') */
    public static TransportMock setUpCurrentTransport(
    public static TransportMock setUpCurrentTransport(
            TransportManager transportManager, TransportData transport) throws Exception {
            TransportManager transportManager, TransportData transport) throws Exception {
        TransportMock transportMock = setUpTransports(transportManager, transport).get(0);
        TransportMock transportMock = setUpTransport(transportManager, transport);
        if (transportMock.transportClient != null) {
        int status = transport.transportStatus;
        when(transportManager.getCurrentTransportName()).thenReturn(transport.transportName);
        if (status == TransportStatus.REGISTERED_AVAILABLE
                || status == TransportStatus.REGISTERED_UNAVAILABLE) {
            // Transport registered
            when(transportManager.getCurrentTransportClient(any()))
            when(transportManager.getCurrentTransportClient(any()))
                    .thenReturn(transportMock.transportClient);
                    .thenReturn(transportMock.transportClient);
            when(transportManager.getCurrentTransportClientOrThrow(any()))
                    .thenReturn(transportMock.transportClient);
        } else {
            // Transport not registered
            when(transportManager.getCurrentTransportClient(any())).thenReturn(null);
            when(transportManager.getCurrentTransportClientOrThrow(any()))
                    .thenThrow(TransportNotRegisteredException.class);
        }
        }
        return transportMock;
        return transportMock;
    }
    }
+35 −6
Original line number Original line Diff line number Diff line
@@ -17,6 +17,8 @@
package com.android.server.testing.shadows;
package com.android.server.testing.shadows;


import android.annotation.Nullable;
import android.annotation.Nullable;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager;


import com.android.server.backup.transport.TransportClient;
import com.android.server.backup.transport.TransportClient;
@@ -25,22 +27,49 @@ import com.android.server.backup.utils.AppBackupUtils;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
import org.robolectric.annotation.Implements;


import java.util.function.Function;
import java.util.HashSet;
import java.util.Set;


@Implements(AppBackupUtils.class)
@Implements(AppBackupUtils.class)
public class ShadowAppBackupUtils {
public class ShadowAppBackupUtils {
    public static Function<String, Boolean> sAppIsRunningAndEligibleForBackupWithTransport;
    private static final Set<String> sAppsRunningAndEligibleForBackupWithTransport =
    static {
            new HashSet<>();
        reset();
    private static final Set<String> sAppsEligibleForBackup = new HashSet<>();
    private static final Set<String> sAppsGetFullBackup = new HashSet<>();

    public static void setAppRunningAndEligibleForBackupWithTransport(String packageName) {
        sAppsEligibleForBackup.add(packageName);
        sAppsRunningAndEligibleForBackupWithTransport.add(packageName);
    }

    public static void setAppEligibleForBackup(String packageName) {
        sAppsEligibleForBackup.add(packageName);
    }

    /** By default the app will be key-value. */
    public static void setAppGetsFullBackup(String packageName) {
        sAppsGetFullBackup.add(packageName);
    }
    }


    @Implementation
    @Implementation
    public static boolean appIsRunningAndEligibleForBackupWithTransport(
    public static boolean appIsRunningAndEligibleForBackupWithTransport(
            @Nullable TransportClient transportClient, String packageName, PackageManager pm) {
            @Nullable TransportClient transportClient, String packageName, PackageManager pm) {
        return sAppIsRunningAndEligibleForBackupWithTransport.apply(packageName);
        return sAppsRunningAndEligibleForBackupWithTransport.contains(packageName);
    }

    @Implementation
    public static boolean appIsEligibleForBackup(ApplicationInfo app, PackageManager pm) {
        return sAppsEligibleForBackup.contains(app.packageName);
    }

    @Implementation
    public static boolean appGetsFullBackup(PackageInfo packageInfo) {
        return sAppsGetFullBackup.contains(packageInfo.packageName);
    }
    }


    public static void reset() {
    public static void reset() {
        sAppIsRunningAndEligibleForBackupWithTransport = p -> true;
        sAppsRunningAndEligibleForBackupWithTransport.clear();
        sAppsEligibleForBackup.clear();
        sAppsGetFullBackup.clear();
    }
    }
}
}
Loading