Merge "Add DelegatingTransport which delegates all transport methods to its delegate"

This commit is contained in:
Chandan Nath
2019-09-24 08:06:25 +00:00
committed by Android (Google) Code Review
2 changed files with 800 additions and 0 deletions

View File

@@ -0,0 +1,414 @@
/*
* Copyright (C) 2019 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.backup.transport;
import android.app.backup.BackupAgent;
import android.app.backup.BackupTransport;
import android.app.backup.RestoreDescription;
import android.app.backup.RestoreSet;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import com.android.internal.backup.IBackupTransport;
/**
* Delegates all transport methods to the delegate() implemented in the derived class.
*/
public abstract class DelegatingTransport extends IBackupTransport.Stub {
protected abstract IBackupTransport getDelegate() throws RemoteException;
/**
* Ask the transport for the name under which it should be registered. This will
* typically be its host service's component name, but need not be.
*/
@Override
public String name() throws RemoteException {
return getDelegate().name();
}
/**
* Ask the transport for an Intent that can be used to launch any internal
* configuration Activity that it wishes to present. For example, the transport
* may offer a UI for allowing the user to supply login credentials for the
* transport's off-device backend.
*
* If the transport does not supply any user-facing configuration UI, it should
* return null from this method.
*
* @return An Intent that can be passed to Context.startActivity() in order to
* launch the transport's configuration UI. This method will return null
* if the transport does not offer any user-facing configuration UI.
*/
@Override
public Intent configurationIntent() throws RemoteException {
return getDelegate().configurationIntent();
}
/**
* On demand, supply a one-line string that can be shown to the user that
* describes the current backend destination. For example, a transport that
* can potentially associate backup data with arbitrary user accounts should
* include the name of the currently-active account here.
*
* @return A string describing the destination to which the transport is currently
* sending data. This method should not return null.
*/
@Override
public String currentDestinationString() throws RemoteException {
return getDelegate().currentDestinationString();
}
/**
* Ask the transport for an Intent that can be used to launch a more detailed
* secondary data management activity. For example, the configuration intent might
* be one for allowing the user to select which account they wish to associate
* their backups with, and the management intent might be one which presents a
* UI for managing the data on the backend.
*
* <p>In the Settings UI, the configuration intent will typically be invoked
* when the user taps on the preferences item labeled with the current
* destination string, and the management intent will be placed in an overflow
* menu labelled with the management label string.
*
* <p>If the transport does not supply any user-facing data management
* UI, then it should return {@code null} from this method.
*
* @return An intent that can be passed to Context.startActivity() in order to
* launch the transport's data-management UI. This method will return
* {@code null} if the transport does not offer any user-facing data
* management UI.
*/
@Override
public Intent dataManagementIntent() throws RemoteException {
return getDelegate().dataManagementIntent();
}
/**
* On demand, supply a short {@link CharSequence} that can be shown to the user as the
* label on
* an overflow menu item used to invoke the data management UI.
*
* @return A {@link CharSequence} to be used as the label for the transport's data management
* affordance. If the transport supplies a data management intent, this
* method must not return {@code null}.
*/
@Override
public CharSequence dataManagementIntentLabel() throws RemoteException {
return getDelegate().dataManagementIntentLabel();
}
/**
* Ask the transport where, on local device storage, to keep backup state blobs.
* This is per-transport so that mock transports used for testing can coexist with
* "live" backup services without interfering with the live bookkeeping. The
* returned string should be a name that is expected to be unambiguous among all
* available backup transports; the name of the class implementing the transport
* is a good choice. This MUST be constant.
*
* @return A unique name, suitable for use as a file or directory name, that the
* Backup Manager could use to disambiguate state files associated with
* different backup transports.
*/
@Override
public String transportDirName() throws RemoteException {
return getDelegate().transportDirName();
}
/**
* Verify that this is a suitable time for a backup pass. This should return zero
* if a backup is reasonable right now, some positive value otherwise. This method
* will be called outside of the {@link #startSession}/{@link #endSession} pair.
*
* <p>If this is not a suitable time for a backup, the transport should return a
* backoff delay, in milliseconds, after which the Backup Manager should try again.
*
* @return Zero if this is a suitable time for a backup pass, or a positive time delay
* in milliseconds to suggest deferring the backup pass for a while.
*/
@Override
public long requestBackupTime() throws RemoteException {
return getDelegate().requestBackupTime();
}
/**
* Initialize the server side storage for this device, erasing all stored data.
* The transport may send the request immediately, or may buffer it. After
* this is called, {@link #finishBackup} must be called to ensure the request
* is sent and received successfully.
*
* @return One of {@link BackupConstants#TRANSPORT_OK} (OK so far) or
* {@link BackupConstants#TRANSPORT_ERROR} (on network error or other failure).
*/
@Override
public int initializeDevice() throws RemoteException {
return getDelegate().initializeDevice();
}
/**
* Send one application's data to the backup destination. The transport may send
* the data immediately, or may buffer it. After this is called, {@link #finishBackup}
* must be called to ensure the data is sent and recorded successfully.
*
* @param packageInfo The identity of the application whose data is being backed up.
* This specifically includes the signature list for the package.
* @param inFd Descriptor of file with data that resulted from invoking the application's
* BackupService.doBackup() method. This may be a pipe rather than a file on
* persistent media, so it may not be seekable.
* @param flags Some of {@link BackupTransport#FLAG_USER_INITIATED}.
* @return one of {@link BackupConstants#TRANSPORT_OK} (OK so far),
* {@link BackupConstants#TRANSPORT_ERROR} (on network error or other failure), or
* {@link BackupConstants#TRANSPORT_NOT_INITIALIZED} (if the backend dataset has
* become lost due to inactive expiry or some other reason and needs re-initializing)
*/
@Override
public int performBackup(PackageInfo packageInfo,
ParcelFileDescriptor inFd, int flags) throws RemoteException {
return getDelegate().performBackup(packageInfo, inFd, flags);
}
/**
* Erase the give application's data from the backup destination. This clears
* out the given package's data from the current backup set, making it as though
* the app had never yet been backed up. After this is called, {@link finishBackup}
* must be called to ensure that the operation is recorded successfully.
*
* @return the same error codes as {@link #performBackup}.
* @param packageInfo
*/
@Override
public int clearBackupData(PackageInfo packageInfo) throws RemoteException {
return getDelegate().clearBackupData(packageInfo);
}
/**
* Finish sending application data to the backup destination. This must be
* called after {@link #performBackup} or {@link clearBackupData} to ensure that
* all data is sent. Only when this method returns true can a backup be assumed
* to have succeeded.
*
* @return the same error codes as {@link #performBackup}.
*/
@Override
public int finishBackup() throws RemoteException {
return getDelegate().finishBackup();
}
/**
* Get the set of all backups currently available over this transport.
*
* @return Descriptions of the set of restore images available for this device,
* or null if an error occurred (the attempt should be rescheduled).
**/
@Override
public RestoreSet[] getAvailableRestoreSets() throws RemoteException {
return getDelegate().getAvailableRestoreSets();
}
/**
* Get the identifying token of the backup set currently being stored from
* this device. This is used in the case of applications wishing to restore
* their last-known-good data.
*
* @return A token that can be passed to {@link #startRestore}, or 0 if there
* is no backup set available corresponding to the current device state.
*/
@Override
public long getCurrentRestoreSet() throws RemoteException {
return getDelegate().getCurrentRestoreSet();
}
/**
* Start restoring application data from backup. After calling this function,
* alternate calls to {@link #nextRestorePackage} and {@link #nextRestoreData}
* to walk through the actual application data.
*
* @param token A backup token as returned by {@link #getAvailableRestoreSets}
* or {@link #getCurrentRestoreSet}.
* @param packages List of applications to restore (if data is available).
* Application data will be restored in the order given.
* @return One of {@link BackupConstants#TRANSPORT_OK} (OK so far, call
* {@link #nextRestorePackage}) or {@link BackupConstants#TRANSPORT_ERROR}
* (an error occurred, the restore should be aborted and rescheduled).
*/
@Override
public int startRestore(long token, PackageInfo[] packages) throws RemoteException {
return getDelegate().startRestore(token, packages);
}
/**
* Get the package name of the next application with data in the backup store, plus
* a description of the structure of the restored archive: either TYPE_KEY_VALUE for
* an original-API key/value dataset, or TYPE_FULL_STREAM for a tarball-type archive stream.
*
* <p>If the package name in the returned RestoreDescription object is the singleton
* {@link RestoreDescription#NO_MORE_PACKAGES}, it indicates that no further data is available
* in the current restore session: all packages described in startRestore() have been
* processed.
*
* <p>If this method returns {@code null}, it means that a transport-level error has
* occurred and the entire restore operation should be abandoned.
*
* @return A RestoreDescription object containing the name of one of the packages
* supplied to {@link #startRestore} plus an indicator of the data type of that
* restore data; or {@link RestoreDescription#NO_MORE_PACKAGES} to indicate that
* no more packages can be restored in this session; or {@code null} to indicate
* a transport-level error.
*/
@Override
public RestoreDescription nextRestorePackage() throws RemoteException {
return getDelegate().nextRestorePackage();
}
/**
* Get the data for the application returned by {@link #nextRestorePackage}.
*
* @param outFd An open, writable file into which the backup data should be stored.
* @return the same error codes as {@link #startRestore}.
*/
@Override
public int getRestoreData(ParcelFileDescriptor outFd) throws RemoteException {
return getDelegate().getRestoreData(outFd);
}
/**
* End a restore session (aborting any in-process data transfer as necessary),
* freeing any resources and connections used during the restore process.
*/
@Override
public void finishRestore() throws RemoteException {
getDelegate().finishRestore();
}
@Override
public long requestFullBackupTime() throws RemoteException {
return getDelegate().requestFullBackupTime();
}
@Override
public int performFullBackup(PackageInfo targetPackage,
ParcelFileDescriptor socket, int flags) throws RemoteException {
return getDelegate().performFullBackup(targetPackage, socket, flags);
}
@Override
public int checkFullBackupSize(long size) throws RemoteException {
return getDelegate().checkFullBackupSize(size);
}
@Override
public int sendBackupData(int numBytes) throws RemoteException {
return getDelegate().sendBackupData(numBytes);
}
@Override
public void cancelFullBackup() throws RemoteException {
getDelegate().cancelFullBackup();
}
/**
* Ask the transport whether this app is eligible for backup.
*
* @param targetPackage The identity of the application.
* @param isFullBackup If set, transport should check if app is eligible for full data backup,
* otherwise to check if eligible for key-value backup.
* @return Whether this app is eligible for backup.
*/
@Override
public boolean isAppEligibleForBackup(PackageInfo targetPackage,
boolean isFullBackup) throws RemoteException {
return getDelegate().isAppEligibleForBackup(targetPackage, isFullBackup);
}
/**
* Ask the transport about current quota for backup size of the package.
*
* @param packageName ID of package to provide the quota.
* @param isFullBackup If set, transport should return limit for full data backup, otherwise
* for key-value backup.
* @return Current limit on full data backup size in bytes.
*/
@Override
public long getBackupQuota(String packageName, boolean isFullBackup) throws RemoteException {
return getDelegate().getBackupQuota(packageName, isFullBackup);
}
/**
* Ask the transport to provide data for the "current" package being restored. This
* is the package that was just reported by {@link #nextRestorePackage()} as having
* {@link RestoreDescription#TYPE_FULL_STREAM} data.
*
* The transport writes some data to the socket supplied to this call, and returns
* the number of bytes written. The system will then read that many bytes and
* stream them to the application's agent for restore, then will call this method again
* to receive the next chunk of the archive. This sequence will be repeated until the
* transport returns zero indicating that all of the package's data has been delivered
* (or returns a negative value indicating some sort of hard error condition at the
* transport level).
*
* <p>After this method returns zero, the system will then call
* {@link #getNextFullRestorePackage()} to begin the restore process for the next
* application, and the sequence begins again.
*
* <p>The transport should always close this socket when returning from this method.
* Do not cache this socket across multiple calls or you may leak file descriptors.
*
* @param socket The file descriptor that the transport will use for delivering the
* streamed archive. The transport must close this socket in all cases when returning
* from this method.
* @return 0 when no more data for the current package is available. A positive value
* indicates the presence of that many bytes to be delivered to the app. Any negative
* return value is treated as equivalent to {@link BackupTransport#TRANSPORT_ERROR},
* indicating a fatal error condition that precludes further restore operations
* on the current dataset.
*/
@Override
public int getNextFullRestoreDataChunk(ParcelFileDescriptor socket) throws RemoteException {
return getDelegate().getNextFullRestoreDataChunk(socket);
}
/**
* If the OS encounters an error while processing {@link RestoreDescription#TYPE_FULL_STREAM}
* data for restore, it will invoke this method to tell the transport that it should
* abandon the data download for the current package. The OS will then either call
* {@link #nextRestorePackage()} again to move on to restoring the next package in the
* set being iterated over, or will call {@link #finishRestore()} to shut down the restore
* operation.
*
* @return {@link #TRANSPORT_OK} if the transport was successful in shutting down the
* current stream cleanly, or {@link #TRANSPORT_ERROR} to indicate a serious
* transport-level failure. If the transport reports an error here, the entire restore
* operation will immediately be finished with no further attempts to restore app data.
*/
@Override
public int abortFullRestore() throws RemoteException {
return getDelegate().abortFullRestore();
}
/**
* Returns flags with additional information about the transport, which is accessible to the
* {@link BackupAgent}. This allows the agent to decide what to backup or
* restore based on properties of the transport.
*
* <p>For supported flags see {@link BackupAgent}.
*/
@Override
public int getTransportFlags() throws RemoteException {
return getDelegate().getTransportFlags();
}
}

View File

@@ -0,0 +1,386 @@
/*
* Copyright (C) 2019 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.backup.transport;
import static junit.framework.Assert.assertEquals;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
import android.app.backup.RestoreDescription;
import android.app.backup.RestoreSet;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.platform.test.annotations.Presubmit;
import androidx.test.runner.AndroidJUnit4;
import com.android.internal.backup.IBackupTransport;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
@Presubmit
@RunWith(AndroidJUnit4.class)
public class DelegatingTransportTest {
@Mock private IBackupTransport mBackupTransport;
@Mock private PackageInfo mPackageInfo;
@Mock private ParcelFileDescriptor mFd;
private final String mPackageName = "testpackage";
private final RestoreSet mRestoreSet = new RestoreSet();
private final int mFlags = 1;
private final long mRestoreToken = 10;
private final long mSize = 100;
private final int mNumBytes = 1000;
private DelegatingTransport mDelegatingTransport;
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
mDelegatingTransport = new DelegatingTransport() {
@Override
protected IBackupTransport getDelegate() {
return mBackupTransport;
}
};
}
@Test
public void testName() throws RemoteException {
String exp = "dummy";
when(mBackupTransport.name()).thenReturn(exp);
String ret = mDelegatingTransport.name();
assertEquals(exp, ret);
verify(mBackupTransport, times(1)).name();
verifyNoMoreInteractions(mBackupTransport);
}
@Test
public void testConfigurationIntent() throws RemoteException {
Intent exp = new Intent("dummy");
when(mBackupTransport.configurationIntent()).thenReturn(exp);
Intent ret = mDelegatingTransport.configurationIntent();
assertEquals(exp, ret);
verify(mBackupTransport, times(1)).configurationIntent();
verifyNoMoreInteractions(mBackupTransport);
}
@Test
public void testCurrentDestinationString() throws RemoteException {
String exp = "dummy";
when(mBackupTransport.currentDestinationString()).thenReturn(exp);
String ret = mDelegatingTransport.currentDestinationString();
assertEquals(exp, ret);
verify(mBackupTransport, times(1)).currentDestinationString();
verifyNoMoreInteractions(mBackupTransport);
}
@Test
public void testDataManagementIntent() throws RemoteException {
Intent exp = new Intent("dummy");
when(mBackupTransport.dataManagementIntent()).thenReturn(exp);
Intent ret = mDelegatingTransport.dataManagementIntent();
assertEquals(exp, ret);
verify(mBackupTransport, times(1)).dataManagementIntent();
verifyNoMoreInteractions(mBackupTransport);
}
@Test
public void testDataManagementIntentLabel() throws RemoteException {
String exp = "dummy";
when(mBackupTransport.dataManagementIntentLabel()).thenReturn(exp);
CharSequence ret = mDelegatingTransport.dataManagementIntentLabel();
assertEquals(exp, ret);
verify(mBackupTransport, times(1)).dataManagementIntentLabel();
verifyNoMoreInteractions(mBackupTransport);
}
@Test
public void testTransportDirName() throws RemoteException {
String exp = "dummy";
when(mBackupTransport.transportDirName()).thenReturn(exp);
String ret = mDelegatingTransport.transportDirName();
assertEquals(exp, ret);
verify(mBackupTransport, times(1)).transportDirName();
verifyNoMoreInteractions(mBackupTransport);
}
@Test
public void testRequestBackupTime() throws RemoteException {
long exp = 1000L;
when(mBackupTransport.requestBackupTime()).thenReturn(exp);
long ret = mDelegatingTransport.requestBackupTime();
assertEquals(exp, ret);
verify(mBackupTransport, times(1)).requestBackupTime();
verifyNoMoreInteractions(mBackupTransport);
}
@Test
public void testInitializeDevice() throws RemoteException {
int exp = 1000;
when(mBackupTransport.initializeDevice()).thenReturn(exp);
long ret = mDelegatingTransport.initializeDevice();
assertEquals(exp, ret);
verify(mBackupTransport, times(1)).initializeDevice();
verifyNoMoreInteractions(mBackupTransport);
}
@Test
public void testPerformBackup() throws RemoteException {
int exp = 1000;
when(mBackupTransport.performBackup(mPackageInfo, mFd, mFlags)).thenReturn(exp);
int ret = mDelegatingTransport.performBackup(mPackageInfo, mFd, mFlags);
assertEquals(exp, ret);
verify(mBackupTransport, times(1)).performBackup(mPackageInfo, mFd, mFlags);
verifyNoMoreInteractions(mBackupTransport);
}
@Test
public void testClearBackupData() throws RemoteException {
int exp = 1000;
when(mBackupTransport.clearBackupData(mPackageInfo)).thenReturn(exp);
int ret = mDelegatingTransport.clearBackupData(mPackageInfo);
assertEquals(exp, ret);
verify(mBackupTransport, times(1)).clearBackupData(mPackageInfo);
verifyNoMoreInteractions(mBackupTransport);
}
@Test
public void testFinishBackup() throws RemoteException {
int exp = 1000;
when(mBackupTransport.finishBackup()).thenReturn(exp);
int ret = mDelegatingTransport.finishBackup();
assertEquals(exp, ret);
verify(mBackupTransport, times(1)).finishBackup();
verifyNoMoreInteractions(mBackupTransport);
}
@Test
public void testGetAvailableRestoreSets() throws RemoteException {
RestoreSet[] exp = new RestoreSet[] {mRestoreSet};
when(mBackupTransport.getAvailableRestoreSets()).thenReturn(exp);
RestoreSet[] ret = mDelegatingTransport.getAvailableRestoreSets();
assertEquals(exp, ret);
verify(mBackupTransport, times(1)).getAvailableRestoreSets();
verifyNoMoreInteractions(mBackupTransport);
}
@Test
public void testGetCurrentRestoreSet() throws RemoteException {
long exp = 1000;
when(mBackupTransport.getCurrentRestoreSet()).thenReturn(exp);
long ret = mDelegatingTransport.getCurrentRestoreSet();
assertEquals(exp, ret);
verify(mBackupTransport, times(1)).getCurrentRestoreSet();
verifyNoMoreInteractions(mBackupTransport);
}
@Test
public void testStartRestore() throws RemoteException {
int exp = 1000;
PackageInfo[] packageInfos = {mPackageInfo};
when(mBackupTransport.startRestore(mRestoreToken, packageInfos)).thenReturn(exp);
int ret = mDelegatingTransport.startRestore(mRestoreToken, packageInfos);
assertEquals(exp, ret);
verify(mBackupTransport, times(1)).startRestore(mRestoreToken, packageInfos);
verifyNoMoreInteractions(mBackupTransport);
}
@Test
public void testNextRestorePackage() throws RemoteException {
RestoreDescription exp = new RestoreDescription(mPackageName, 1);
when(mBackupTransport.nextRestorePackage()).thenReturn(exp);
RestoreDescription ret = mDelegatingTransport.nextRestorePackage();
assertEquals(exp, ret);
verify(mBackupTransport, times(1)).nextRestorePackage();
verifyNoMoreInteractions(mBackupTransport);
}
@Test
public void testGetRestoreData() throws RemoteException {
int exp = 1000;
when(mBackupTransport.getRestoreData(mFd)).thenReturn(exp);
int ret = mDelegatingTransport.getRestoreData(mFd);
assertEquals(exp, ret);
verify(mBackupTransport, times(1)).getRestoreData(mFd);
verifyNoMoreInteractions(mBackupTransport);
}
@Test
public void tesFinishRestore() throws RemoteException {
mDelegatingTransport.finishRestore();
verify(mBackupTransport, times(1)).finishRestore();
verifyNoMoreInteractions(mBackupTransport);
}
@Test
public void testRequestFullBackupTime() throws RemoteException {
long exp = 1000L;
when(mBackupTransport.requestFullBackupTime()).thenReturn(exp);
long ret = mDelegatingTransport.requestFullBackupTime();
assertEquals(exp, ret);
verify(mBackupTransport, times(1)).requestFullBackupTime();
verifyNoMoreInteractions(mBackupTransport);
}
@Test
public void testPerformFullBackup() throws RemoteException {
int exp = 1000;
when(mBackupTransport.performFullBackup(mPackageInfo, mFd, mFlags)).thenReturn(exp);
int ret = mDelegatingTransport.performFullBackup(mPackageInfo, mFd, mFlags);
assertEquals(exp, ret);
verify(mBackupTransport, times(1)).performFullBackup(mPackageInfo, mFd, mFlags);
verifyNoMoreInteractions(mBackupTransport);
}
@Test
public void testCheckFullBackupSize() throws RemoteException {
int exp = 1000;
when(mBackupTransport.checkFullBackupSize(mSize)).thenReturn(exp);
int ret = mDelegatingTransport.checkFullBackupSize(mSize);
assertEquals(exp, ret);
verify(mBackupTransport, times(1)).checkFullBackupSize(mSize);
verifyNoMoreInteractions(mBackupTransport);
}
@Test
public void testSendBackupData() throws RemoteException {
int exp = 1000;
when(mBackupTransport.sendBackupData(mNumBytes)).thenReturn(exp);
int ret = mDelegatingTransport.sendBackupData(mNumBytes);
assertEquals(exp, ret);
verify(mBackupTransport, times(1)).sendBackupData(mNumBytes);
verifyNoMoreInteractions(mBackupTransport);
}
@Test
public void testCancelFullBackup() throws RemoteException {
mDelegatingTransport.cancelFullBackup();
verify(mBackupTransport, times(1)).cancelFullBackup();
verifyNoMoreInteractions(mBackupTransport);
}
@Test
public void testIsAppEligibleForBackup() throws RemoteException {
boolean exp = true;
when(mBackupTransport.isAppEligibleForBackup(mPackageInfo, true)).thenReturn(exp);
boolean ret = mDelegatingTransport.isAppEligibleForBackup(mPackageInfo, true);
assertEquals(exp, ret);
verify(mBackupTransport, times(1)).isAppEligibleForBackup(mPackageInfo, true);
verifyNoMoreInteractions(mBackupTransport);
}
@Test
public void testGetBackupQuota() throws RemoteException {
long exp = 1000;
when(mBackupTransport.getBackupQuota(mPackageName, true)).thenReturn(exp);
long ret = mDelegatingTransport.getBackupQuota(mPackageName, true);
assertEquals(exp, ret);
verify(mBackupTransport, times(1)).getBackupQuota(mPackageName, true);
verifyNoMoreInteractions(mBackupTransport);
}
@Test
public void testGetNextFullRestoreDataChunk() throws RemoteException {
int exp = 1000;
when(mBackupTransport.getNextFullRestoreDataChunk(mFd)).thenReturn(exp);
int ret = mDelegatingTransport.getNextFullRestoreDataChunk(mFd);
assertEquals(exp, ret);
verify(mBackupTransport, times(1)).getNextFullRestoreDataChunk(mFd);
verifyNoMoreInteractions(mBackupTransport);
}
@Test
public void testAbortFullRestore() throws RemoteException {
int exp = 1000;
when(mBackupTransport.abortFullRestore()).thenReturn(exp);
int ret = mDelegatingTransport.abortFullRestore();
assertEquals(exp, ret);
verify(mBackupTransport, times(1)).abortFullRestore();
verifyNoMoreInteractions(mBackupTransport);
}
@Test
public void testGetTransportFlags() throws RemoteException {
int exp = 1000;
when(mBackupTransport.getTransportFlags()).thenReturn(exp);
int ret = mDelegatingTransport.getTransportFlags();
assertEquals(exp, ret);
verify(mBackupTransport, times(1)).getTransportFlags();
verifyNoMoreInteractions(mBackupTransport);
}
}